diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..28dccd4
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..63e9001
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/house_lease.iml b/.idea/house_lease.iml
new file mode 100644
index 0000000..78b2cc5
--- /dev/null
+++ b/.idea/house_lease.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..2d9362f
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..1cd6847
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/161914 b/161914
new file mode 100644
index 0000000..7f8c609
--- /dev/null
+++ b/161914
@@ -0,0 +1,50 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+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
+BK0Df2ueXfubC+lTf2R4VjCIM=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/161914.pub b/161914.pub
new file mode 100644
index 0000000..76eb8dd
--- /dev/null
+++ b/161914.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDtk5Pp1MJJjawtWDrOXwykKmD7AiEpZMjJ/h9aW0oOH+y/xWX095+5m90vLcKQTMApT0Ev4tgcFh/HJBfL6btZRys3K64RtBm0zuAtKXzguupFiNZcthATiPGyQAmEbzyLHBB4dMfjWrkl6CMiW+yEaC30GOOVHcOEQHZZ6oeP93O+kNJnhjxZqLWV7qyMHWez1jT+I5XRBOP4oS1lEfRDUjI4v4gDsDp/dlwO1vbOQsKysbxqT/fDJ0jvz3PEK8xWG7BpnJD6FH41l3NOK9+sFoF5DF4rY+I4+oimVZuP27f9EtDi30/Rk0av+VGJ4TlBtLWyIVK548K20e0svADqiMn0IjTHC6iBW6Stf6ze6VZf4Xk4oBhl2qXKNPaSo19Iru7FYeMJ03EVX5d+vFXHlBOpVqGkeiudHzewQPdb5bdtcVR4A21nvALDBvh1867QxOyhI+Du95bFfzUZpZbhui3c2Go9ZtI9MejTEPL0Yf68UpNM/b6q1jKGRsTbj/sHu5osd0fMawgTtQMVBbMPoz/96XjOaf+KwiCLQDmb8Jv5ZjuiE1tHMbTTXhvXL2ke1jMzgY1fVGVPPyie+x7h1LVTikMTM2vnVNF7tFz7lC/7GH5Q1S5LEDMpNL3FCLRDjmpA0J1tTGdp8FBNEIcZuqa0nlo7joSLTK88e87Eqw== 1634482602@qq.com
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..59499bc
--- /dev/null
+++ b/META-INF/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+
diff --git a/houselease.iml b/houselease.iml
new file mode 100644
index 0000000..78b2cc5
--- /dev/null
+++ b/houselease.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..bc349f3
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,125 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ com.jlwl
+
+ t020
+ 0.0.1-SNAPSHOT
+ springboot-schema
+ 房屋租赁系统
+
+
+ 1.8
+ 1.2.8
+ 3.1.1
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.1.1
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.32
+
+
+ org.apache.shiro
+ shiro-spring
+ 1.3.2
+
+
+ com.baomidou
+ mybatis-plus
+ 2.3
+
+
+ com.baomidou
+ mybatisplus-spring-boot-starter
+ 1.0.5
+
+
+ com.google.protobuf
+ protobuf-java
+ 3.10.0
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.0
+
+
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
+
+
+
+ commons-io
+ commons-io
+ 2.5
+
+
+
+
+ cn.hutool
+ hutool-all
+ 4.0.12
+
+
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
+ com.baidu.aip
+ java-sdk
+ 4.4.1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/src/main/java/com/SpringbootSchemaApplication.java b/src/main/java/com/SpringbootSchemaApplication.java
new file mode 100644
index 0000000..e020617
--- /dev/null
+++ b/src/main/java/com/SpringbootSchemaApplication.java
@@ -0,0 +1,33 @@
+package com;
+
+// 导入 MyBatis 的 MapperScan 注解,用于扫描 DAO 层接口
+import org.mybatis.spring.annotation.MapperScan;
+// 导入 Spring Boot 的核心注解,用于启动应用程序
+import org.springframework.boot.SpringApplication;
+// 导入 Spring Boot 的自动配置注解,启用自动配置功能
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+// 导入 SpringApplicationBuilder,用于构建 Spring Boot 应用程序
+import org.springframework.boot.builder.SpringApplicationBuilder;
+// 导入 SpringBootServletInitializer,用于支持将应用部署到外部 Servlet 容器
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+// 标记该类为 Spring Boot 的主应用程序类
+// 启用组件扫描和自动配置功能
+@SpringBootApplication
+// 使用 @MapperScan 指定 MyBatis 的 DAO 接口所在的包路径
+@MapperScan(basePackages = {"com.dao"})
+public class SpringbootSchemaApplication extends SpringBootServletInitializer {
+
+ // 主方法,应用程序的入口点
+ public static void main(String[] args) {
+ // 启动 Spring Boot 应用程序
+ SpringApplication.run(SpringbootSchemaApplication.class, args);
+ }
+
+ // 重写 configure 方法,支持将应用部署到外部 Servlet 容器
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
+ // 指定 Spring Boot 应用程序的主类
+ return applicationBuilder.sources(SpringbootSchemaApplication.class);
+ }
+}
diff --git a/src/main/java/com/annotation/APPLoginUser.java b/src/main/java/com/annotation/APPLoginUser.java
new file mode 100644
index 0000000..f660eba
--- /dev/null
+++ b/src/main/java/com/annotation/APPLoginUser.java
@@ -0,0 +1,17 @@
+package com.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 登录用户信息
+ */
+// 该注解用于标识方法参数,表示该参数应注入当前登录的用户对象
+@Target(ElementType.PARAMETER) // 限定该注解只能标注在方法参数上
+@Retention(RetentionPolicy.RUNTIME) // 指定注解在运行时保留,可通过反射读取
+public @interface APPLoginUser {
+ // 这是一个标记注解,不需要定义额外属性
+ // 框架处理器会根据该注解自动注入当前认证用户
+}
diff --git a/src/main/java/com/annotation/IgnoreAuth.java b/src/main/java/com/annotation/IgnoreAuth.java
new file mode 100644
index 0000000..1015dd7
--- /dev/null
+++ b/src/main/java/com/annotation/IgnoreAuth.java
@@ -0,0 +1,15 @@
+package com.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 忽略Token验证
+ */
+// 忽略认证的标记注解,标注该注解的方法将跳过权限/登录校验
+@Target(ElementType.METHOD) // 限定该注解只能标注在方法上
+@Retention(RetentionPolicy.RUNTIME) // 注解在运行时保留,可通过反射读取
+@Documented // 表明该注解应当被包含在Javadoc中
+public @interface IgnoreAuth {
+ // 标记注解不包含任何属性
+ // 仅需标注在方法上即可使该方法跳过认证流程
+}
diff --git a/src/main/java/com/annotation/LoginUser.java b/src/main/java/com/annotation/LoginUser.java
new file mode 100644
index 0000000..c8f482e
--- /dev/null
+++ b/src/main/java/com/annotation/LoginUser.java
@@ -0,0 +1,17 @@
+package com.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 登录用户信息
+ */
+// 用户认证参数注解,用于自动注入当前登录用户信息
+@Target(ElementType.PARAMETER) // 限定该注解只能标注在方法参数上
+@Retention(RetentionPolicy.RUNTIME) // 注解在运行时保留,可通过反射机制获取
+public @interface LoginUser {
+ // 标记型注解,不包含任何配置属性
+ // 框架会自动将当前登录用户对象注入到被注解的参数
+}
diff --git a/src/main/java/com/config/InterceptorConfig.java b/src/main/java/com/config/InterceptorConfig.java
new file mode 100644
index 0000000..acf85fa
--- /dev/null
+++ b/src/main/java/com/config/InterceptorConfig.java
@@ -0,0 +1,54 @@
+package com.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+import com.interceptor.AuthorizationInterceptor;
+
+// 拦截器配置类,用于配置Spring MVC的拦截器和静态资源处理
+@Configuration // 标识这是一个Spring配置类
+public class InterceptorConfig extends WebMvcConfigurationSupport {
+
+ /**
+ * 创建并返回授权拦截器Bean
+ * @return 授权拦截器实例
+ */
+ @Bean
+ public AuthorizationInterceptor getAuthorizationInterceptor() {
+ return new AuthorizationInterceptor(); // 实例化自定义的授权拦截器
+ }
+
+ /**
+ * 添加拦截器配置
+ * @param registry 拦截器注册器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 注册授权拦截器并配置拦截路径
+ registry.addInterceptor(getAuthorizationInterceptor())
+ .addPathPatterns("/**") // 拦截所有请求路径
+ .excludePathPatterns("/static/**"); // 排除静态资源路径
+ super.addInterceptors(registry); // 调用父类方法保持默认拦截器配置
+ }
+
+ /**
+ * 重写静态资源处理配置
+ * 注意:继承WebMvcConfigurationSupport会覆盖默认静态资源配置,需要手动添加
+ * @param registry 资源处理器注册器
+ */
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 配置静态资源映射
+ registry.addResourceHandler("/**") // 匹配所有URL路径
+ // 添加静态资源位置(按优先级排序)
+ .addResourceLocations("classpath:/resources/") // 类路径下的resources目录
+ .addResourceLocations("classpath:/static/") // 类路径下的static目录
+ .addResourceLocations("classpath:/admin/") // 类路径下的admin目录
+ .addResourceLocations("classpath:/front/") // 类路径下的front目录
+ .addResourceLocations("classpath:/public/"); // 类路径下的public目录
+ super.addResourceHandlers(registry); // 调用父类方法保持默认资源处理配置
+ }
+}
diff --git a/src/main/java/com/config/MybatisPlusConfig.java b/src/main/java/com/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..ec2e84b
--- /dev/null
+++ b/src/main/java/com/config/MybatisPlusConfig.java
@@ -0,0 +1,24 @@
+
+package com.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.baomidou.mybatisplus.mapper.MetaObjectHandler;
+import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
+
+/**
+ * mybatis-plus配置
+ */
+@Configuration
+public class MybatisPlusConfig {
+
+ /**
+ * 分页插件
+ */
+ @Bean
+ public PaginationInterceptor paginationInterceptor() {
+ return new PaginationInterceptor();
+ }
+
+}
diff --git a/src/main/java/com/controller/CommonController.java b/src/main/java/com/controller/CommonController.java
new file mode 100644
index 0000000..961e848
--- /dev/null
+++ b/src/main/java/com/controller/CommonController.java
@@ -0,0 +1,359 @@
+package com.controller;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.annotation.IgnoreAuth;
+import com.baidu.aip.face.AipFace;
+import com.baidu.aip.face.MatchRequest;
+import com.baidu.aip.util.Base64Util;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.entity.ConfigEntity;
+import com.service.CommonService;
+import com.service.ConfigService;
+import com.utils.BaiduUtil;
+import com.utils.FileUtil;
+import com.utils.R;
+
+/**
+ * 通用接口
+ */
+@RestController // 声明为RESTful控制器,自动将返回对象转为JSON
+public class CommonController{
+
+ // 注入通用服务组件,用于处理通用业务逻辑
+ @Autowired
+ private CommonService commonService;
+
+ // 注入配置服务组件,用于获取系统配置信息
+ @Autowired
+ private ConfigService configService;
+
+ // 百度AI人脸识别客户端(静态变量保证全局唯一)
+ private static AipFace client = null;
+
+ // 百度地图API访问密钥(静态变量保证全局唯一)
+ private static String BAIDU_DITU_AK = null;
+
+ /**
+ * 经纬度定位接口
+ * @param lng 经度坐标
+ * @param lat 纬度坐标
+ * @return 标准化响应结果
+ */
+ @RequestMapping("/location")
+ public R location(String lng,String lat) {
+ // 首次使用时初始化百度地图AK
+ if(BAIDU_DITU_AK==null) {
+ // 从数据库配置表查询AK值
+ BAIDU_DITU_AK = configService.selectOne(
+ new EntityWrapper().eq("name", "baidu_ditu_ak")
+ ).getValue();
+ // AK未配置时返回错误提示
+ if(BAIDU_DITU_AK==null) {
+ return R.error("请在配置管理中正确配置baidu_ditu_ak");
+ }
+ }
+ // 调用百度工具类获取地理位置信息
+ Map map = BaiduUtil.getCityByLonLat(BAIDU_DITU_AK, lng, lat);
+ // 返回标准化成功响应
+ return R.ok().put("data", map);
+ }
+
+ /**
+ * 人脸比对接口
+ * @param face1 第一张人脸图片文件名
+ * @param face2 第二张人脸图片文件名
+ * @return 包含比对结果的响应
+ */
+ @RequestMapping("/matchFace")
+ public R matchFace(String face1, String face2) {
+ // 初始化百度AI客户端
+ if(client==null) {
+ // 从数据库获取API认证信息
+ String APIKey = configService.selectOne(
+ new EntityWrapper().eq("name", "APIKey")
+ ).getValue();
+ String SecretKey = configService.selectOne(
+ new EntityWrapper().eq("name", "SecretKey")
+ ).getValue();
+
+ // 获取访问令牌
+ String token = BaiduUtil.getAuth(APIKey, SecretKey);
+ // 认证失败处理
+ if(token==null) {
+ return R.error("请在配置管理中正确配置APIKey和SecretKey");
+ }
+ // 创建客户端实例并设置超时参数
+ client = new AipFace(null, APIKey, SecretKey);
+ client.setConnectionTimeoutInMillis(2000); // 2秒连接超时
+ client.setSocketTimeoutInMillis(60000); // 60秒读写超时
+ }
+
+ JSONObject res = null;
+ try {
+ // 构建图片文件完整路径
+ File file1 = new File(
+ ResourceUtils.getFile("classpath:static/upload").getAbsolutePath()+"/"+face1
+ );
+ File file2 = new File(
+ ResourceUtils.getFile("classpath:static/upload").getAbsolutePath()+"/"+face2
+ );
+
+ // 将图片文件转为Base64编码
+ String img1 = Base64Util.encode(FileUtil.FileToByte(file1));
+ String img2 = Base64Util.encode(FileUtil.FileToByte(file2));
+
+ // 创建比对请求对象
+ MatchRequest req1 = new MatchRequest(img1, "BASE64");
+ MatchRequest req2 = new MatchRequest(img2, "BASE64");
+ // 添加请求到列表
+ ArrayList requests = new ArrayList();
+ requests.add(req1);
+ requests.add(req2);
+
+ // 执行人脸比对并获取结果
+ res = client.match(requests);
+ System.out.println(res.get("result")); // 调试输出结果
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return R.error("文件不存在"); // 文件不存在异常处理
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // 返回标准化结果
+ return R.ok().put("data", com.alibaba.fastjson.JSONObject.parse(res.get("result").toString()));
+ }
+
+ /**
+ * 获取数据表字段选项列表(联动接口)
+ * @param tableName 表名称
+ * @param columnName 字段名称
+ * @param level 层级参数(可选)
+ * @param parent 父级参数(可选)
+ * @return 包含选项列表的响应
+ */
+ @IgnoreAuth // 跳过权限验证
+ @RequestMapping("/option/{tableName}/{columnName}")
+ public R getOption(
+ @PathVariable("tableName") String tableName,
+ @PathVariable("columnName") String columnName,
+ String level,
+ String parent
+ ) {
+ // 构建查询参数Map
+ Map params = new HashMap();
+ params.put("table", tableName); // 设置表名参数
+ params.put("column", columnName); // 设置字段名参数
+
+ // 处理可选参数
+ if(StringUtils.isNotBlank(level)) {
+ params.put("level", level); // 设置层级参数
+ }
+ if(StringUtils.isNotBlank(parent)) {
+ params.put("parent", parent); // 设置父级参数
+ }
+
+ // 调用服务获取数据
+ List data = commonService.getOption(params);
+ // 返回标准化响应
+ return R.ok().put("data", data);
+ }
+
+ /**
+ * 根据字段值查询单条记录
+ * @param tableName 表名称
+ * @param columnName 字段名称
+ * @param columnValue 字段值
+ * @return 包含查询结果的响应
+ */
+ @IgnoreAuth // 跳过权限验证
+ @RequestMapping("/follow/{tableName}/{columnName}")
+ public R getFollowByOption(
+ @PathVariable("tableName") String tableName,
+ @PathVariable("columnName") String columnName,
+ @RequestParam String columnValue
+ ) {
+ // 构建查询参数Map
+ Map params = new HashMap();
+ params.put("table", tableName); // 设置表名参数
+ params.put("column", columnName); // 设置字段名参数
+ params.put("columnValue", columnValue); // 设置字段值参数
+
+ // 调用服务获取单条记录
+ Map result = commonService.getFollowByOption(params);
+ // 返回标准化响应
+ return R.ok().put("data", result);
+ }
+
+ /**
+ * 审核状态修改接口
+ * @param tableName 表名称
+ * @param map 包含审核参数的Map
+ * @return 操作结果响应
+ */
+ @RequestMapping("/sh/{tableName}")
+ public R sh(
+ @PathVariable("tableName") String tableName,
+ @RequestBody Map map
+ ) {
+ map.put("table", tableName); // 将表名添加到参数Map
+ commonService.sh(map); // 调用审核服务
+ return R.ok(); // 返回成功响应
+ }
+
+ /**
+ * 获取提醒记录数接口
+ * @param tableName 表名称
+ * @param columnName 字段名称
+ * @param type 提醒类型(1:数字 2:日期)
+ * @param map 包含提醒参数的Map
+ * @return 包含记录数的响应
+ */
+ @IgnoreAuth // 跳过权限验证
+ @RequestMapping("/remind/{tableName}/{columnName}/{type}")
+ public R remindCount(
+ @PathVariable("tableName") String tableName,
+ @PathVariable("columnName") String columnName,
+ @PathVariable("type") String type,
+ @RequestParam Map map
+ ) {
+ // 设置基础参数
+ map.put("table", tableName); // 表名参数
+ map.put("column", columnName); // 字段名参数
+ map.put("type", type); // 类型参数
+
+ // 日期类型特殊处理
+ if(type.equals("2")) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式化
+ Calendar c = Calendar.getInstance(); // 日历实例
+ Date remindStartDate = null; // 提醒开始日期
+ Date remindEndDate = null; // 提醒结束日期
+
+ // 处理提醒开始日期
+ if(map.get("remindstart")!=null) {
+ Integer remindStart = Integer.parseInt(map.get("remindstart").toString());
+ c.setTime(new Date());
+ c.add(Calendar.DAY_OF_MONTH,remindStart); // 计算开始日期
+ remindStartDate = c.getTime();
+ map.put("remindstart", sdf.format(remindStartDate)); // 格式化日期
+ }
+
+ // 处理提醒结束日期
+ if(map.get("remindend")!=null) {
+ Integer remindEnd = Integer.parseInt(map.get("remindend").toString());
+ c.setTime(new Date());
+ c.add(Calendar.DAY_OF_MONTH,remindEnd); // 计算结束日期
+ remindEndDate = c.getTime();
+ map.put("remindend", sdf.format(remindEndDate)); // 格式化日期
+ }
+ }
+
+ // 调用服务获取提醒记录数
+ int count = commonService.remindCount(map);
+ // 返回标准化响应
+ return R.ok().put("count", count);
+ }
+
+ /**
+ * 单列求和统计接口
+ * @param tableName 表名称
+ * @param columnName 字段名称
+ * @return 包含统计结果的响应
+ */
+ @IgnoreAuth // 跳过权限验证
+ @RequestMapping("/cal/{tableName}/{columnName}")
+ public R cal(
+ @PathVariable("tableName") String tableName,
+ @PathVariable("columnName") String columnName
+ ) {
+ // 构建查询参数
+ Map params = new HashMap();
+ params.put("table", tableName); // 表名参数
+ params.put("column", columnName); // 字段名参数
+
+ // 调用服务获取计算结果
+ Map result = commonService.selectCal(params);
+ // 返回标准化响应
+ return R.ok().put("data", result);
+ }
+
+ /**
+ * 分组统计接口
+ * @param tableName 表名称
+ * @param columnName 分组字段名称
+ * @return 包含分组结果的响应
+ */
+ @IgnoreAuth // 跳过权限验证
+ @RequestMapping("/group/{tableName}/{columnName}")
+ public R group(
+ @PathVariable("tableName") String tableName,
+ @PathVariable("columnName") String columnName
+ ) {
+ // 构建查询参数
+ Map params = new HashMap();
+ params.put("table", tableName); // 表名参数
+ params.put("column", columnName); // 分组字段参数
+
+ // 调用服务获取分组结果
+ List