From b55cd9aad0835a96a790e61f9f89edc2fae1be9f Mon Sep 17 00:00:00 2001
From: 刘帅 <rr.iii@qq.com>
Date: 星期二, 29 九月 2026 01:26:37 +0800
Subject: [PATCH] 注释优化、格式优化

---
 cloud-server-other/src/main/java/com/dsh/other/mapper/QrLinkMapper.java                                             |   12 +
 cloud-server-management/src/main/webapp/static/modular/system/appGuide/appGuide.js                                  |  121 +++++++++++-
 cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideConfig.java                                           |   75 ++++++-
 cloud-server-other/src/main/java/com/dsh/other/service/SysAccountAuditLogService.java                               |   11 +
 cloud-server-management/src/main/java/cn/mb/cloud/common/sentinel/fallback/DefaultFeignFallback.java                |   14 
 cloud-server-other/src/main/java/com/dsh/other/controller/AppGuideController.java                                   |   68 +++++-
 cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/AppGuideManagementController.java |   64 ++++++
 cloud-server-management/src/main/java/com/dsh/guns/modular/system/util/ExcelUtil.java                               |    8 
 cloud-server-management/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java                               |   22 +-
 cloud-server-other/src/main/java/com/dsh/other/mapper/SysAccountAuditLogMapper.java                                 |    5 
 cloud-server-account/src/main/java/com/dsh/privacy/UnmaskedSensitiveData.java                                       |    4 
 cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideBanner.java                                           |   28 ++
 cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideBannerMapper.java                                     |   12 +
 cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java                                |   16 
 cloud-server-account/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java                                  |    4 
 cloud-server-other/src/main/java/com/dsh/other/feignclient/account/AppUserClient.java                               |    2 
 cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideConfigMapper.java                                     |   12 +
 cloud-server-other/src/main/java/com/dsh/other/entity/QrLink.java                                                   |   60 +++++-
 cloud-server-management/src/main/java/com/dsh/course/feignClient/account/AppUserClient.java                         |    4 
 19 files changed, 443 insertions(+), 99 deletions(-)

diff --git a/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java b/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java
index d8b3fbe..69e1c50 100644
--- a/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java
+++ b/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java
@@ -247,10 +247,9 @@
     }
 
     /**
-     * Internal-only data source for the management sensitive-data query.  The
-     * caller is authenticated and authorised by the management service; its
-     * Feign interceptor adds the header that permits the response to remain
-     * unmasked for that single request.
+     * 仅供管理端敏感信息查询使用的内部数据接口。
+     * 调用方由管理服务完成认证和授权;其 Feign 拦截器会添加请求头,
+     * 以允许本次响应不进行脱敏。
      */
     @PostMapping("/internal/sensitive/app-user/{id}")
     public Map<String, Object> sensitiveAppUser(@PathVariable("id") Integer id,
@@ -269,9 +268,8 @@
     }
 
     /**
-     * Internal data source used when an APP booking submits its displayed,
-     * masked phone number.  Limit the response to the single field needed for
-     * that booking; callers must use the internal sensitive-data header.
+     * APP 订场提交页面展示的脱敏手机号时使用的内部数据接口。
+     * 仅返回该预约所需的手机号字段;调用方必须携带内部敏感数据访问请求头。
      */
     @PostMapping("/internal/sensitive/site-booking/app-user/{id}/phone")
     public Map<String, Object> siteBookingPhone(@PathVariable("id") Integer id,
@@ -883,8 +881,8 @@
     public void updateAppUser(@RequestBody TAppUser appUser) {
         try {
             TAppUser appUser1 = appUserService.getById(appUser.getId());
-            // A management edit form may contain the displayed masked value.
-            // Never persist that display value over the original identifier.
+            // 管理端编辑表单可能携带页面展示的脱敏值。
+            // 不得使用该展示值覆盖原始证件或联系方式。
             if (appUser.getPhone() != null && appUser.getPhone().contains("*")) appUser.setPhone(appUser1.getPhone());
             if (appUser.getIdCard() != null && appUser.getIdCard().contains("*")) appUser.setIdCard(appUser1.getIdCard());
             appUserService.updateById(appUser);
diff --git a/cloud-server-account/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java b/cloud-server-account/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java
index d19eeef..b9fde6f 100644
--- a/cloud-server-account/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java
+++ b/cloud-server-account/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java
@@ -57,8 +57,8 @@
 
     private void mask(Object value, IdentityHashMap<Object, Boolean> visited) {
         if (value == null || value instanceof String || value.getClass().isEnum() || visited.put(value, Boolean.TRUE) != null) return;
-        // Path 的实现类(如 sun.nio.fs.UnixPath)本身是 Iterable;遍历其子路径会不断创建新对象,
-        // IdentityHashMap 无法识别该循环,因而会导致 StackOverflowError。
+        // java.nio.file.Path 的实现类(如 sun.nio.fs.UnixPath)实现了 Iterable 接口;
+        // 遍历其子路径会不断创建新对象,IdentityHashMap 无法识别该循环,因而会导致 StackOverflowError。
         if (value instanceof java.nio.file.Path || isJdkType(value.getClass())) return;
         if (value instanceof Map) {
             for (Object entryObject : ((Map<?, ?>) value).entrySet()) {
diff --git a/cloud-server-account/src/main/java/com/dsh/privacy/UnmaskedSensitiveData.java b/cloud-server-account/src/main/java/com/dsh/privacy/UnmaskedSensitiveData.java
index 95b6240..a09e59b 100644
--- a/cloud-server-account/src/main/java/com/dsh/privacy/UnmaskedSensitiveData.java
+++ b/cloud-server-account/src/main/java/com/dsh/privacy/UnmaskedSensitiveData.java
@@ -6,8 +6,8 @@
 import java.lang.annotation.Target;
 
 /**
- * Allows a single response field to bypass sensitive-data masking.
- * Use only for endpoints that are authorised to return the original value.
+ * 允许单个响应字段跳过敏感数据脱敏。
+ * 仅限已获授权返回原始数据的接口使用。
  */
 @Target(ElementType.FIELD)
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/cloud-server-management/src/main/java/cn/mb/cloud/common/sentinel/fallback/DefaultFeignFallback.java b/cloud-server-management/src/main/java/cn/mb/cloud/common/sentinel/fallback/DefaultFeignFallback.java
index 4b6230f..d792aa8 100644
--- a/cloud-server-management/src/main/java/cn/mb/cloud/common/sentinel/fallback/DefaultFeignFallback.java
+++ b/cloud-server-management/src/main/java/cn/mb/cloud/common/sentinel/fallback/DefaultFeignFallback.java
@@ -18,12 +18,11 @@
 import java.util.Set;
 
 /**
- * Safe replacement for the common Sentinel Feign fallback.
+ * 公共 Sentinel Feign 降级处理的安全替代实现。
  *
- * <p>The dependency version assumes every generic return type is a Class. That
- * is false for declarations such as {@code Map<String, Object>}, whose runtime
- * type is {@link ParameterizedType}; the failed cast used to hide the original
- * downstream exception behind an AssertionError.</p>
+ * <p>依赖版本假定所有泛型返回类型均为 {@link Class}。对于
+ * {@code Map<String, Object>} 等声明并不成立,其运行时类型为
+ * {@link ParameterizedType};此前转换失败会以 AssertionError 掩盖原始下游异常。</p>
  */
 public class DefaultFeignFallback<T> implements MethodInterceptor {
     private static final Logger log = LoggerFactory.getLogger(DefaultFeignFallback.class);
@@ -47,9 +46,8 @@
         Class<?> returnType = rawType(declaredReturnType);
         Object data = defaultValue(returnType);
 
-        // Only methods that explicitly declare ResponseData may receive a
-        // ResponseData fallback. Returning it from Map/List methods causes a
-        // second ClassCastException in the Feign proxy.
+        // 仅显式声明返回 ResponseData 的方法可以返回 ResponseData 降级结果。
+        // 在 Map/List 方法中返回该对象会导致 Feign 代理再次抛出 ClassCastException。
         if (ResponseData.class.equals(returnType)) {
             Type dataType = firstTypeArgument(declaredReturnType);
             return ResponseData.builder()
diff --git a/cloud-server-management/src/main/java/com/dsh/course/feignClient/account/AppUserClient.java b/cloud-server-management/src/main/java/com/dsh/course/feignClient/account/AppUserClient.java
index eeaac72..3a70a7b 100644
--- a/cloud-server-management/src/main/java/com/dsh/course/feignClient/account/AppUserClient.java
+++ b/cloud-server-management/src/main/java/com/dsh/course/feignClient/account/AppUserClient.java
@@ -28,11 +28,11 @@
 @FeignClient("mb-cloud-account")
 public interface AppUserClient {
 
-    /** Only invoked by the super-administrator sensitive data query. */
+    /** 仅供超级管理员敏感信息查询接口调用。 */
     @PostMapping("/internal/sensitive/app-user/{id}")
     Map<String, Object> sensitiveAppUser(@PathVariable("id") Integer id);
 
-    /** Only invoked by the super-administrator sensitive student-data query. */
+    /** 仅供超级管理员学员敏感信息查询接口调用。 */
     @PostMapping("/internal/sensitive/student/{id}")
     Map<String, Object> sensitiveStudent(@PathVariable("id") Integer id);
 
diff --git a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/AppGuideManagementController.java b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/AppGuideManagementController.java
index d874b00..2a1046e 100644
--- a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/AppGuideManagementController.java
+++ b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/AppGuideManagementController.java
@@ -39,17 +39,32 @@
     @Autowired
     private ITSiteService siteService;
 
+    /**
+     * 打开 APP 下载引导管理页面。
+     *
+     * @return APP 下载引导管理页面路径
+     */
     @GetMapping("")
     public String index() {
         return "/system/appGuide/appGuide.html";
     }
 
+    /**
+     * 查询可用于生成订场二维码的场地列表。
+     *
+     * @return 按 ID 倒序排列的场地列表
+     */
     @ResponseBody
     @GetMapping("/sites")
     public List<TSite> queryAvailableSites() {
         return siteService.list(new QueryWrapper<TSite>().orderByDesc("id"));
     }
 
+    /**
+     * 查询 APP 下载引导页面所需的配置、宣传图和订场二维码数据。
+     *
+     * @return 下载引导页面的聚合数据
+     */
     @ResponseBody
     @GetMapping("/data")
     public Map<String, Object> data() {
@@ -69,6 +84,12 @@
         return r;
     }
 
+    /**
+     * 保存 APP 下载引导配置。
+     *
+     * @param config 下载引导配置
+     * @return 保存结果
+     */
     @ResponseBody
     @PostMapping("/config")
     public Map<String, Object> saveConfig(AppGuideConfig config) {
@@ -80,6 +101,12 @@
         return ok();
     }
 
+    /**
+     * 保存 APP 下载引导宣传图。
+     *
+     * @param banner 宣传图配置
+     * @return 保存结果
+     */
     @ResponseBody
     @PostMapping("/banner")
     public Map<String, Object> saveBanner(AppGuideBanner banner) {
@@ -89,6 +116,12 @@
         return ok();
     }
 
+    /**
+     * 删除 APP 下载引导宣传图。
+     *
+     * @param id 宣传图 ID
+     * @return 删除结果
+     */
     @ResponseBody
     @PostMapping("/banner/delete")
     public Map<String, Object> deleteBanner(Long id) {
@@ -96,6 +129,16 @@
         return ok();
     }
 
+    /**
+     * 为指定场地创建订场二维码。
+     *
+     * @param storeId 门店 ID
+     * @param siteId 场地 ID
+     * @param name 二维码名称
+     * @param channel 投放渠道
+     * @param pageName 引导页面名称
+     * @return 创建结果及二维码引导链接
+     */
     @ResponseBody
     @PostMapping("/siteQr")
     public Map<String, Object> createSiteQr(Integer storeId, Integer siteId, String name, String channel, String pageName) {
@@ -118,6 +161,13 @@
         return r;
     }
 
+    /**
+     * 修改场地订场二维码的启用状态。
+     *
+     * @param id 二维码 ID
+     * @param enabled 启用状态(0:停用;1:启用)
+     * @return 修改结果
+     */
     @ResponseBody
     @PostMapping("/siteQr/status")
     public Map<String, Object> changeStatus(Long id, Integer enabled) {
@@ -128,7 +178,12 @@
         return ok();
     }
 
-    /** 逻辑删除场地订场二维码。 */
+    /**
+     * 逻辑删除场地订场二维码。
+     *
+     * @param id 二维码 ID
+     * @return 删除结果
+     */
     @ResponseBody
     @PostMapping("/siteQr/delete")
     public Map<String, Object> deleteSiteQr(Long id) {
@@ -136,6 +191,13 @@
         return ok();
     }
 
+    /**
+     * 生成并输出场地订场二维码图片。
+     *
+     * @param id 二维码 ID
+     * @param response HTTP 响应
+     * @throws IOException 图片输出失败时抛出
+     */
     @GetMapping("/siteQr/{id}.png")
     public void qrImage(@PathVariable Long id, HttpServletResponse response) throws IOException {
         QrLink link = qrLinkMapper.selectById(id);
diff --git a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/util/ExcelUtil.java b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/util/ExcelUtil.java
index 22e26b5..b757ddc 100644
--- a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/util/ExcelUtil.java
+++ b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/util/ExcelUtil.java
@@ -40,7 +40,13 @@
 		return wb;
 	}
 
-	/** Export files are an external disclosure channel and always remain masked. */
+	/**
+	 * 导出文件属于对外数据出口,敏感字段必须始终保持脱敏。
+	 *
+	 * @param columnName 列名,用于识别手机号和身份证号等敏感字段
+	 * @param value 原始单元格值
+	 * @return 脱敏后的单元格值
+	 */
 	private static String maskSensitiveValue(String columnName, String value) {
 		if (value == null) return null;
 		String column = columnName == null ? "" : columnName.toLowerCase();
diff --git a/cloud-server-management/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java b/cloud-server-management/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java
index 5948ebb..3724891 100644
--- a/cloud-server-management/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java
+++ b/cloud-server-management/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java
@@ -15,14 +15,14 @@
 import java.util.Iterator;
 import java.util.Map;
 
-/** Ensures every normal management JSON response uses the same privacy rules. */
+/** 确保所有常规管理端 JSON 响应均遵循统一的隐私保护规则。 */
 @ControllerAdvice
 public class SensitiveDataMaskingAdvice implements ResponseBodyAdvice<Object> {
     private final HttpServletRequest request;
     public SensitiveDataMaskingAdvice(HttpServletRequest request) { this.request = request; }
 
     @Override public boolean supports(MethodParameter type, Class<? extends HttpMessageConverter<?>> converter) {
-        // Only the explicit, admin-only and audited endpoint returns the source value.
+        // 仅明确限定、仅管理员可访问且已审计的接口返回原始数据。
         return !request.getRequestURI().startsWith("/system/sensitive/");
     }
     @Override public Object beforeBodyWrite(Object body, MethodParameter type, MediaType mediaType,
@@ -32,13 +32,12 @@
     }
     private void mask(Object value, IdentityHashMap<Object, Boolean> seen) {
         if (value == null || value instanceof String || value.getClass().isEnum() || seen.put(value, Boolean.TRUE) != null) return;
-        // Reactive streams and their internal queues are runtime infrastructure, not
-        // response DTOs. In particular, Reactor's MpscLinkedQueue implements
-        // Iterable but deliberately throws UnsupportedOperationException from
-        // iterator(). Do not introspect it (or any other reactive infrastructure).
+        // 响应式流及其内部队列属于运行时基础设施,并非响应 DTO。特别是 Reactor 的
+        // MpscLinkedQueue 虽实现了 Iterable,却会在 iterator() 中主动抛出
+        // UnsupportedOperationException;不得反射遍历它或其他响应式基础设施。
         if (isReactiveInfrastructure(value.getClass())) return;
-        // UnixPath implements Iterable.  Its iterator creates a new Path for every
-        // segment, so identity-based cycle detection cannot stop the recursion.
+        // UnixPath 实现了 Iterable,其迭代器会为每个路径段创建新的 Path 对象,
+        // 因此基于对象标识的循环检测无法终止递归。
         if (value instanceof Path) return;
         if (value instanceof Map) {
             for (Object item : ((Map<?, ?>) value).entrySet()) {
@@ -62,16 +61,15 @@
     }
 
     /**
-     * Some third-party containers expose Iterable only for API compatibility and
-     * intentionally do not support iteration. A response privacy filter must never
-     * turn such an implementation detail into a 500 response.
+     * 部分第三方容器仅为 API 兼容而实现 Iterable,并不支持实际迭代。
+     * 响应隐私过滤器不得因这类实现细节导致接口返回 500 错误。
      */
     private void maskIterable(Iterable<?> values, IdentityHashMap<Object, Boolean> seen) {
         try {
             Iterator<?> iterator = values.iterator();
             while (iterator.hasNext()) mask(iterator.next(), seen);
         } catch (UnsupportedOperationException ignored) {
-            // There is no safely accessible element to mask.
+            // 没有可安全访问并进行脱敏的元素。
         }
     }
 
diff --git a/cloud-server-management/src/main/webapp/static/modular/system/appGuide/appGuide.js b/cloud-server-management/src/main/webapp/static/modular/system/appGuide/appGuide.js
index 270e688..56d88f1 100644
--- a/cloud-server-management/src/main/webapp/static/modular/system/appGuide/appGuide.js
+++ b/cloud-server-management/src/main/webapp/static/modular/system/appGuide/appGuide.js
@@ -1,11 +1,110 @@
-(function(){
-  function esc(v){return $('<div>').text(v==null?'':v).html()} function val(n,v){$('#configForm [name='+n+']').val(v==null?'':v)}
-  window.reloadAppGuide=function(){ $.get(Feng.ctxPath+'/appGuide/data',function(d){var c=d.config||{};['id','apkUrl','iosStoreUrl'].forEach(function(k){val(k,c[k])});$('#bannerRows').html((d.banners||[]).map(function(x){return '<tr><td><img class="qr" src="'+esc(x.imageUrl)+'"></td><td>'+esc(x.title)+'</td><td>'+esc(x.sort)+'</td><td>'+((x.enabled===1)?'启用':'停用')+'</td><td><button class="btn btn-danger btn-xs" onclick="deleteBanner(\''+x.id+'\')">删除</button></td></tr>'}).join(''));$('#linkRows').html((d.links||[]).map(function(x){var id=String(x.id),q=Feng.ctxPath+'/appGuide/siteQr/'+encodeURIComponent(id)+'.png';return '<tr><td>'+esc(x.name)+'</td><td>'+esc(x.pageName)+'</td><td>'+x.storeId+' / '+x.siteId+'</td><td><a href="'+q+'" target="_blank"><img class="qr" src="'+q+'"></a></td><td><code>'+esc(x.guideUrl)+'</code></td><td>'+((x.enabled===1)?'启用':'停用')+'</td><td><button class="btn btn-warning btn-xs" onclick="changeQr(\''+id+'\','+(x.enabled===1?0:1)+')">'+(x.enabled===1?'停用':'启用')+'</button> <button class="btn btn-danger btn-xs" onclick="deleteQr(\''+id+'\')">删除</button></td></tr>'}).join(''))})};
-  window.saveConfig=function(){$.post(Feng.ctxPath+'/appGuide/config',$('#configForm').serialize(),function(){Feng.success('保存成功');reloadAppGuide()})};
-  window.uploadBanner=function(){var f=$('#bannerFile')[0].files[0];if(!f){Feng.info('请选择图片');return}var d=new FormData();d.append('file',f);$.ajax({url:Feng.ctxPath+'/mgr/uploadFile',data:d,type:'POST',contentType:false,processData:false,success:function(url){$('#bannerUrl').val(url);$('#uploadTip').text('上传成功')}})};
-  window.addBanner=function(){if(!$('#bannerUrl').val()){Feng.info('请先上传图片');return}$.post(Feng.ctxPath+'/appGuide/banner',{imageUrl:$('#bannerUrl').val(),title:$('#bannerTitle').val(),sort:$('#bannerSort').val()||0,enabled:1},function(){reloadAppGuide();$('#bannerUrl,#bannerTitle,#bannerSort,#bannerFile').val('')})};
-  window.deleteBanner=function(id){$.post(Feng.ctxPath+'/appGuide/banner/delete',{id:id},reloadAppGuide)};
-  window.createQr=function(){var o=$('#siteSelect option:selected'),pageName='com.sinata.wepark.ui.home.PlaceDetailActivity';if(!o.val()){Feng.info('请选择场地');return}$.post(Feng.ctxPath+'/appGuide/siteQr',{storeId:o.data('store'),siteId:o.val(),name:o.text(),pageName:pageName},function(r){if(!r.success){Feng.error(r.message);return}Feng.success('已生成');reloadAppGuide()})};
-  window.changeQr=function(id,enabled){$.post(Feng.ctxPath+'/appGuide/siteQr/status',{id:id,enabled:enabled},reloadAppGuide)};$.get(Feng.ctxPath+'/appGuide/sites',function(s){$('#siteSelect').append((s||[]).map(function(x){return '<option value="'+x.id+'" data-store="'+x.storeId+'">['+x.storeId+'] '+esc(x.name)+'</option>'}).join(''))});$(reloadAppGuide);
-  window.deleteQr=function(id){if(!confirm('确认删除该场地订场二维码?'))return;$.post(Feng.ctxPath+'/appGuide/siteQr/delete',{id:id},reloadAppGuide)};
-})();
+(function() {
+  function esc(v) {
+    return $('<div>').text(v == null ? '' : v).html()
+  }
+
+  function val(n, v) {
+    $('#configForm [name=' + n + ']').val(v == null ? '' : v)
+  }
+  window.reloadAppGuide = function() {
+    $.get(Feng.ctxPath + '/appGuide/data', function(d) {
+      var c = d.config || {};
+      ['id', 'apkUrl', 'iosStoreUrl'].forEach(function(k) {
+        val(k, c[k])
+      });
+      $('#bannerRows').html((d.banners || []).map(function(x) {
+        return '<tr><td><img class="qr" src="' + esc(x.imageUrl) + '"></td><td>' + esc(x.title) + '</td><td>' + esc(x.sort) + '</td><td>' + ((x.enabled === 1) ? '启用' : '停用') + '</td><td><button class="btn btn-danger btn-xs" onclick="deleteBanner(\'' + x.id + '\')">删除</button></td></tr>'
+      }).join(''));
+      $('#linkRows').html((d.links || []).map(function(x) {
+        var id = String(x.id),
+          q = Feng.ctxPath + '/appGuide/siteQr/' + encodeURIComponent(id) + '.png';
+        return '<tr><td>' + esc(x.name) + '</td><td>' + esc(x.pageName) + '</td><td>' + x.storeId + ' / ' + x.siteId + '</td><td><a href="' + q + '" target="_blank"><img class="qr" src="' + q + '"></a></td><td><code>' + esc(x.guideUrl) + '</code></td><td>' + ((x.enabled === 1) ? '启用' : '停用') + '</td><td><button class="btn btn-warning btn-xs" onclick="changeQr(\'' + id + '\',' + (x.enabled === 1 ? 0 : 1) + ')">' + (x.enabled === 1 ? '停用' : '启用') + '</button> <button class="btn btn-danger btn-xs" onclick="deleteQr(\'' + id + '\')">删除</button></td></tr>'
+      }).join(''))
+    })
+  };
+  window.saveConfig = function() {
+    $.post(Feng.ctxPath + '/appGuide/config', $('#configForm').serialize(), function() {
+      Feng.success('保存成功');
+      reloadAppGuide()
+    })
+  };
+  window.uploadBanner = function() {
+    var f = $('#bannerFile')[0].files[0];
+    if (!f) {
+      Feng.info('请选择图片');
+      return
+    }
+    var d = new FormData();
+    d.append('file', f);
+    $.ajax({
+      url: Feng.ctxPath + '/mgr/uploadFile',
+      data: d,
+      type: 'POST',
+      contentType: false,
+      processData: false,
+      success: function(url) {
+        $('#bannerUrl').val(url);
+        $('#uploadTip').text('上传成功')
+      }
+    })
+  };
+  window.addBanner = function() {
+    if (!$('#bannerUrl').val()) {
+      Feng.info('请先上传图片');
+      return
+    }
+    $.post(Feng.ctxPath + '/appGuide/banner', {
+      imageUrl: $('#bannerUrl').val(),
+      title: $('#bannerTitle').val(),
+      sort: $('#bannerSort').val() || 0,
+      enabled: 1
+    }, function() {
+      reloadAppGuide();
+      $('#bannerUrl,#bannerTitle,#bannerSort,#bannerFile').val('')
+    })
+  };
+  window.deleteBanner = function(id) {
+    $.post(Feng.ctxPath + '/appGuide/banner/delete', {
+      id: id
+    }, reloadAppGuide)
+  };
+  window.createQr = function() {
+    var o = $('#siteSelect option:selected'),
+      pageName = 'com.sinata.wepark.ui.home.PlaceDetailActivity';
+    if (!o.val()) {
+      Feng.info('请选择场地');
+      return
+    }
+    $.post(Feng.ctxPath + '/appGuide/siteQr', {
+      storeId: o.data('store'),
+      siteId: o.val(),
+      name: o.text(),
+      pageName: pageName
+    }, function(r) {
+      if (!r.success) {
+        Feng.error(r.message);
+        return
+      }
+      Feng.success('已生成');
+      reloadAppGuide()
+    })
+  };
+  window.changeQr = function(id, enabled) {
+    $.post(Feng.ctxPath + '/appGuide/siteQr/status', {
+      id: id,
+      enabled: enabled
+    }, reloadAppGuide)
+  };
+  $.get(Feng.ctxPath + '/appGuide/sites', function(s) {
+    $('#siteSelect').append((s || []).map(function(x) {
+      return '<option value="' + x.id + '" data-store="' + x.storeId + '">[' + x.storeId + '] ' + esc(x.name) + '</option>'
+    }).join(''))
+  });
+  $(reloadAppGuide);
+  window.deleteQr = function(id) {
+    if (!confirm('确认删除该场地订场二维码?')) return;
+    $.post(Feng.ctxPath + '/appGuide/siteQr/delete', {
+      id: id
+    }, reloadAppGuide)
+  };
+})();
\ No newline at end of file
diff --git a/cloud-server-other/src/main/java/com/dsh/other/controller/AppGuideController.java b/cloud-server-other/src/main/java/com/dsh/other/controller/AppGuideController.java
index 8ff8bcf..83af6e9 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/controller/AppGuideController.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/controller/AppGuideController.java
@@ -15,26 +15,36 @@
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-
-import javax.annotation.Resource;
-import java.util.*;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 /** 对外下载引导页与 App 扫码解析接口。 */
 @RestController
 @Api(tags = "APP下载引导与场地二维码")
 public class AppGuideController {
-    @Autowired private AppGuideConfigMapper appGuideConfigMapper;
-    @Autowired private AppGuideBannerMapper appGuideBannerMapper;
-    @Autowired private QrLinkMapper qrLinkMapper;
-    @Autowired private TokenUtil tokenUtil;
+    @Autowired
+    private AppGuideConfigMapper appGuideConfigMapper;
+
+    @Autowired
+    private AppGuideBannerMapper appGuideBannerMapper;
+
+    @Autowired
+    private QrLinkMapper qrLinkMapper;
+
+    @Autowired
+    private TokenUtil tokenUtil;
 
 //    @GetMapping("/q/{shortCode}")
 //    public void guidePage(@PathVariable String shortCode, HttpServletRequest request,
@@ -48,10 +58,16 @@
     @ApiOperation("获取下载引导页配置(无需登录)")
     public ResultUtil<Map<String, Object>> guideConfig(String code) {
         AppGuideConfig config = appGuideConfigMapper.selectOne(new QueryWrapper<AppGuideConfig>()
-                .eq("enabled", EnableStatusEnum.ENABLED.getCode()).orderByDesc("updateTime").last("limit 1"));
-        if (config == null) return ResultUtil.error("下载引导页尚未配置");
+                .eq("enabled", EnableStatusEnum.ENABLED.getCode())
+                .orderByDesc("updateTime")
+                .last("limit 1"));
+        if (config == null) {
+            return ResultUtil.error("下载引导页尚未配置");
+        }
         QrLink link = validLink(code);
-        if (code != null && !code.isEmpty() && link == null) return ResultUtil.error("二维码无效或已失效");
+        if (code != null && !code.isEmpty() && link == null) {
+            return ResultUtil.error("二维码无效或已失效");
+        }
         Map<String, Object> data = new HashMap<>();
         data.put("appName", StringUtils.isNotBlank(config.getAppName()) ? config.getAppName() : "玩湃生活");
         data.put("androidPackage", StringUtils.isNotBlank(config.getAndroidPackage()) ? config.getAndroidPackage() : "com.sinata.wepark");
@@ -61,7 +77,9 @@
         data.put("androidDeepLink", config.getAndroidDeepLink() + (StringUtils.isNotBlank(code) ? "?route=" + code : ""));
         data.put("iosDeepLink", "weparklife://app" + (StringUtils.isNotBlank(code) ? "?code=" + code : ""));
         data.put("banners", appGuideBannerMapper.selectList(new QueryWrapper<AppGuideBanner>()
-                .eq("enabled", EnableStatusEnum.ENABLED.getCode()).orderByAsc("sort").orderByDesc("id")));
+                .eq("enabled", EnableStatusEnum.ENABLED.getCode())
+                .orderByAsc("sort")
+                .orderByDesc("id")));
 //        if (link != null) data.put("target", target(link));
         return ResultUtil.success(data);
     }
@@ -70,15 +88,23 @@
     @ApiOperation("App扫码解析二维码")
     public ResultUtil<Map<String, Object>> resolve(String code) {
         QrLink link = validLink(code);
-        if (link == null) return ResultUtil.error("二维码无效或已失效");
+        if (link == null) {
+            return ResultUtil.error("二维码无效或已失效");
+        }
         return ResultUtil.success(target(link));
     }
 
     private QrLink validLink(String code) {
-        if (code == null || !code.matches("[A-Za-z0-9]{6,32}")) return null;
-        QrLink link = qrLinkMapper.selectOne(new QueryWrapper<QrLink>().eq("shortCode", code).last("limit 1"));
+        if (code == null || !code.matches("[A-Za-z0-9]{6,32}")) {
+            return null;
+        }
+        QrLink link = qrLinkMapper.selectOne(new QueryWrapper<QrLink>()
+                .eq("shortCode", code)
+                .last("limit 1"));
         if (link == null || !Integer.valueOf(1).equals(link.getEnabled())
-                || (link.getExpiresAt() != null && link.getExpiresAt().before(new Date()))) return null;
+                || (link.getExpiresAt() != null && link.getExpiresAt().before(new Date()))) {
+            return null;
+        }
         return link;
     }
 
@@ -92,7 +118,13 @@
     }
 
     private Object parseJson(String text) {
-        if (text == null || text.trim().isEmpty()) return Collections.emptyMap();
-        try { return JSON.parseObject(text); } catch (Exception ignored) { return Collections.emptyMap(); }
+        if (text == null || text.trim().isEmpty()) {
+            return Collections.emptyMap();
+        }
+        try {
+            return JSON.parseObject(text);
+        } catch (Exception ignored) {
+            return Collections.emptyMap();
+        }
     }
 }
diff --git a/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideBanner.java b/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideBanner.java
index 788490e..c0d9f15 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideBanner.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideBanner.java
@@ -1,28 +1,48 @@
 package com.dsh.other.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Getter;
 import lombok.Setter;
+
 import java.util.Date;
 
 /** APP 下载引导宣传图实体,对应表 t_app_guide_banner。 */
 @Getter
 @Setter
 @TableName("t_app_guide_banner")
+@ApiModel(description = "APP 下载引导宣传图")
 public class AppGuideBanner {
     @TableId(type = IdType.ID_WORKER)
+    @ApiModelProperty("主键 ID")
     private Long id;
-    @TableField("imageUrl") private String imageUrl;
+
+    @TableField("imageUrl")
+    @ApiModelProperty("宣传图地址")
+    private String imageUrl;
+
+    @ApiModelProperty("宣传图标题")
     private String title;
+
+    @ApiModelProperty("排序值")
     private Integer sort;
+
+    @ApiModelProperty("启用状态:0-停用,1-启用")
     private Integer enabled;
+
     /** 逻辑删除标识:0-正常,1-删除。 */
     @TableLogic
     @TableField("isDeleted")
+    @ApiModelProperty("逻辑删除标识:0-正常,1-删除")
     private Integer isDeleted;
-    /** 创建时间。 */ @TableField("createTime") private Date createTime;
+
+    /** 创建时间。 */
+    @TableField("createTime")
+    @ApiModelProperty("创建时间")
+    private Date createTime;
 }
diff --git a/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideConfig.java b/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideConfig.java
index 7a1c734..963a02b 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideConfig.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/entity/AppGuideConfig.java
@@ -1,10 +1,12 @@
 package com.dsh.other.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -14,24 +16,67 @@
 @Getter
 @Setter
 @TableName("t_app_guide_config")
+@ApiModel(description = "APP 下载引导配置")
 public class AppGuideConfig {
-    /** 主键ID(雪花算法生成)。 */ @TableId(type = IdType.ID_WORKER)
+    /** 主键ID(雪花算法生成)。 */
+    @TableId(type = IdType.ID_WORKER)
+    @ApiModelProperty("主键 ID")
     private Long id;
-    @TableField("appName") private String appName;
-    @TableField("appScheme") private String appScheme;
-    @TableField("androidPackage") private String androidPackage;
-    @TableField("iosPackage") private String iosPackage;
-    @TableField("iosStoreUrl") private String iosStoreUrl;
-    @TableField("androidDefaultUrl") private String androidDefaultUrl;
-    @TableField("androidMarketUrls") private String androidMarketUrls;
-    @TableField("apkUrl") private String apkUrl;
-    @TableField("androidDeepLink") private String androidDeepLink;
-    @TableField("iosDeepLink") private String iosDeepLink;
-    @TableField("guideDomain") private String guideDomain;
+
+    @TableField("appName")
+    @ApiModelProperty("APP 名称")
+    private String appName;
+
+    @TableField("appScheme")
+    @ApiModelProperty("APP 自定义 Scheme")
+    private String appScheme;
+
+    @TableField("androidPackage")
+    @ApiModelProperty("Android 应用包名")
+    private String androidPackage;
+
+    @TableField("iosPackage")
+    @ApiModelProperty("iOS 应用包名")
+    private String iosPackage;
+
+    @TableField("iosStoreUrl")
+    @ApiModelProperty("iOS App Store 地址")
+    private String iosStoreUrl;
+
+    @TableField("androidDefaultUrl")
+    @ApiModelProperty("Android 默认应用市场地址")
+    private String androidDefaultUrl;
+
+    @TableField("androidMarketUrls")
+    @ApiModelProperty("Android 品牌应用市场地址 JSON")
+    private String androidMarketUrls;
+
+    @TableField("apkUrl")
+    @ApiModelProperty("APK 下载地址")
+    private String apkUrl;
+
+    @TableField("androidDeepLink")
+    @ApiModelProperty("Android 深度链接")
+    private String androidDeepLink;
+
+    @TableField("iosDeepLink")
+    @ApiModelProperty("iOS 深度链接")
+    private String iosDeepLink;
+
+    @TableField("guideDomain")
+    @ApiModelProperty("二维码引导域名")
+    private String guideDomain;
+
+    @ApiModelProperty("启用状态:0-停用,1-启用")
     private Integer enabled;
+
     /** 逻辑删除标识:0-正常,1-删除。 */
     @TableLogic
     @TableField("isDeleted")
+    @ApiModelProperty("逻辑删除标识:0-正常,1-删除")
     private Integer isDeleted;
-    @TableField("updateTime") private Date updateTime;
+
+    @TableField("updateTime")
+    @ApiModelProperty("更新时间")
+    private Date updateTime;
 }
diff --git a/cloud-server-other/src/main/java/com/dsh/other/entity/QrLink.java b/cloud-server-other/src/main/java/com/dsh/other/entity/QrLink.java
index be3bba8..f0da645 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/entity/QrLink.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/entity/QrLink.java
@@ -1,35 +1,75 @@
 package com.dsh.other.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Getter;
 import lombok.Setter;
+
 import java.util.Date;
 
 /** 二维码短链接实体,对应表 t_qr_link。 */
 @Getter
 @Setter
 @TableName("t_qr_link")
+@ApiModel(description = "二维码短链接")
 public class QrLink {
     @TableId(type = IdType.ID_WORKER)
+    @ApiModelProperty("主键 ID")
     private Long id;
-    @TableField("shortCode") private String shortCode;
+
+    @TableField("shortCode")
+    @ApiModelProperty("二维码短码")
+    private String shortCode;
+
+    @ApiModelProperty("二维码类型")
     private String type;
-    @TableField("storeId") private Integer storeId;
-    @TableField("siteId") private Integer siteId;
-    @TableField("bookingId") private Integer bookingId;
+
+    @TableField("storeId")
+    @ApiModelProperty("关联门店 ID")
+    private Integer storeId;
+
+    @TableField("siteId")
+    @ApiModelProperty("关联场地 ID")
+    private Integer siteId;
+
+    @TableField("bookingId")
+    @ApiModelProperty("关联预约订单 ID")
+    private Integer bookingId;
+
+    @ApiModelProperty("二维码名称")
     private String name;
+
+    @ApiModelProperty("投放渠道")
     private String channel;
-    @TableField("pageName") private String pageName;
-    @TableField("expiresAt") private Date expiresAt;
+
+    @TableField("pageName")
+    @ApiModelProperty("跳转页面名称")
+    private String pageName;
+
+    @TableField("expiresAt")
+    @ApiModelProperty("失效时间")
+    private Date expiresAt;
+
+    @ApiModelProperty("启用状态:0-停用,1-启用")
     private Integer enabled;
+
     /** 逻辑删除标识:0-正常,1-删除。 */
     @TableLogic
     @TableField("isDeleted")
+    @ApiModelProperty("逻辑删除标识:0-正常,1-删除")
     private Integer isDeleted;
-    /** 创建时间。 */ @TableField("createTime") private Date createTime;
-    @TableField("updateTime") private Date updateTime;
+
+    /** 创建时间。 */
+    @TableField("createTime")
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+
+    @TableField("updateTime")
+    @ApiModelProperty("更新时间")
+    private Date updateTime;
 }
diff --git a/cloud-server-other/src/main/java/com/dsh/other/feignclient/account/AppUserClient.java b/cloud-server-other/src/main/java/com/dsh/other/feignclient/account/AppUserClient.java
index 1e2b234..5c5b1cb 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/feignclient/account/AppUserClient.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/feignclient/account/AppUserClient.java
@@ -33,7 +33,7 @@
     @PostMapping("/base/appUser/updateAppUser")
     void updateAppUser(AppUser appUser);
 
-    /** Gets only the original phone for the authenticated user's site booking. */
+    /** 获取已认证用户订场所需的原始手机号。 */
     @PostMapping("/internal/sensitive/site-booking/app-user/{id}/phone")
     Map<String, Object> siteBookingPhone(@PathVariable("id") Integer appUserId,
                                          @RequestHeader("X-Internal-Sensitive-Access") String sensitiveAccess);
diff --git a/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideBannerMapper.java b/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideBannerMapper.java
index b351b27..fb896d4 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideBannerMapper.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideBannerMapper.java
@@ -1,4 +1,14 @@
 package com.dsh.other.mapper;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.dsh.other.entity.AppGuideBanner;
-public interface AppGuideBannerMapper extends BaseMapper<AppGuideBanner> {}
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * APP 下载引导宣传图数据访问层。
+ *
+ * <p>继承 {@link BaseMapper},提供 {@link AppGuideBanner} 的基础增删改查能力。</p>
+ */
+@Mapper
+public interface AppGuideBannerMapper extends BaseMapper<AppGuideBanner> {
+}
diff --git a/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideConfigMapper.java b/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideConfigMapper.java
index 7410414..fde70b2 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideConfigMapper.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/mapper/AppGuideConfigMapper.java
@@ -1,4 +1,14 @@
 package com.dsh.other.mapper;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.dsh.other.entity.AppGuideConfig;
-public interface AppGuideConfigMapper extends BaseMapper<AppGuideConfig> {}
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * APP 下载引导配置数据访问层。
+ *
+ * <p>继承 {@link BaseMapper},提供 {@link AppGuideConfig} 的基础增删改查能力。</p>
+ */
+@Mapper
+public interface AppGuideConfigMapper extends BaseMapper<AppGuideConfig> {
+}
diff --git a/cloud-server-other/src/main/java/com/dsh/other/mapper/QrLinkMapper.java b/cloud-server-other/src/main/java/com/dsh/other/mapper/QrLinkMapper.java
index cf988f8..c8a0f6c 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/mapper/QrLinkMapper.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/mapper/QrLinkMapper.java
@@ -1,4 +1,14 @@
 package com.dsh.other.mapper;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.dsh.other.entity.QrLink;
-public interface QrLinkMapper extends BaseMapper<QrLink> {}
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 二维码短链接数据访问层。
+ *
+ * <p>继承 {@link BaseMapper},提供 {@link QrLink} 的基础增删改查能力。</p>
+ */
+@Mapper
+public interface QrLinkMapper extends BaseMapper<QrLink> {
+}
diff --git a/cloud-server-other/src/main/java/com/dsh/other/mapper/SysAccountAuditLogMapper.java b/cloud-server-other/src/main/java/com/dsh/other/mapper/SysAccountAuditLogMapper.java
index d614800..cf6ed0d 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/mapper/SysAccountAuditLogMapper.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/mapper/SysAccountAuditLogMapper.java
@@ -4,6 +4,11 @@
 import com.dsh.other.entity.SysAccountAuditLog;
 import org.apache.ibatis.annotations.Mapper;
 
+/**
+ * 账户敏感信息访问审计日志数据访问层。
+ *
+ * <p>继承 {@link BaseMapper},提供 {@link SysAccountAuditLog} 的基础增删改查能力。</p>
+ */
 @Mapper
 public interface SysAccountAuditLogMapper extends BaseMapper<SysAccountAuditLog> {
 }
diff --git a/cloud-server-other/src/main/java/com/dsh/other/service/SysAccountAuditLogService.java b/cloud-server-other/src/main/java/com/dsh/other/service/SysAccountAuditLogService.java
index 4619176..f0df6a2 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/service/SysAccountAuditLogService.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/service/SysAccountAuditLogService.java
@@ -3,6 +3,17 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.dsh.other.entity.SysAccountAuditLog;
 
+/**
+ * 账户敏感信息访问审计日志服务。
+ *
+ * <p>继承 {@link IService},提供审计日志的基础服务能力。</p>
+ */
 public interface SysAccountAuditLogService extends IService<SysAccountAuditLog> {
+
+    /**
+     * 追加一条审计日志。
+     *
+     * @param auditLog 待写入的审计日志
+     */
     void append(SysAccountAuditLog auditLog);
 }

--
Gitblit v1.7.1