Lenovo 1 month ago
commit
80ee0935ef
97 changed files with 4198 additions and 0 deletions
  1. 33 0
      .gitignore
  2. 1 0
      ArcFace64.dat
  3. BIN
      libs/WIN64/libarcsoft_face.dll
  4. BIN
      libs/WIN64/libarcsoft_face_engine.dll
  5. BIN
      libs/WIN64/libarcsoft_face_engine_jni.dll
  6. BIN
      libs/arcsoft-sdk-face-3.0.0.0.jar
  7. 240 0
      pom.xml
  8. 27 0
      src/main/java/com/zhentao/TourismHdApplication.java
  9. 26 0
      src/main/java/com/zhentao/config/ESConfig.java
  10. 43 0
      src/main/java/com/zhentao/config/RedissonConfig.java
  11. 45 0
      src/main/java/com/zhentao/controller/AI/Deekseep.java
  12. 19 0
      src/main/java/com/zhentao/controller/advertisement/AdvertisementController.java
  13. 20 0
      src/main/java/com/zhentao/controller/dto/DeeseekRequest.java
  14. 139 0
      src/main/java/com/zhentao/controller/renlian/FaceDetectionController.java
  15. 53 0
      src/main/java/com/zhentao/controller/user/UserController.java
  16. 30 0
      src/main/java/com/zhentao/controller/user/WeChatController.java
  17. 30 0
      src/main/java/com/zhentao/domain/Advertisement.java
  18. 86 0
      src/main/java/com/zhentao/domain/FaceFeature.java
  19. 297 0
      src/main/java/com/zhentao/domain/UserLogin.java
  20. 16 0
      src/main/java/com/zhentao/dto/user/ForgetPassDto.java
  21. 19 0
      src/main/java/com/zhentao/dto/user/NoteDto.java
  22. 18 0
      src/main/java/com/zhentao/dto/user/UserLoginDto.java
  23. 14 0
      src/main/java/com/zhentao/dto/user/UserPassDto.java
  24. 26 0
      src/main/java/com/zhentao/dto/user/UserRegister.java
  25. 13 0
      src/main/java/com/zhentao/dto/user/WeChatLoginDto.java
  26. 14 0
      src/main/java/com/zhentao/dto/user/WeChatMode.java
  27. 16 0
      src/main/java/com/zhentao/dto/user/WeChatSessionModel.java
  28. 28 0
      src/main/java/com/zhentao/enums/ApiServerException.java
  29. 6 0
      src/main/java/com/zhentao/enums/BaseExceptionEnum.java
  30. 15 0
      src/main/java/com/zhentao/exception/AsynException.java
  31. 56 0
      src/main/java/com/zhentao/exception/GlobalExceptionHandler.java
  32. 26 0
      src/main/java/com/zhentao/filter/TokenFilter.java
  33. 23 0
      src/main/java/com/zhentao/hotel/controller/Hotel_Controller.java
  34. 20 0
      src/main/java/com/zhentao/hotel/controller/Hotel_Sort_Controller.java
  35. 20 0
      src/main/java/com/zhentao/hotel/controller/Hoteldetails_controller.java
  36. 41 0
      src/main/java/com/zhentao/hotel/domain/HotelSort.java
  37. 92 0
      src/main/java/com/zhentao/hotel/domain/Hoteldetails.java
  38. 141 0
      src/main/java/com/zhentao/hotel/domain/Hotels.java
  39. 9 0
      src/main/java/com/zhentao/hotel/dto/HotelDetailDto.java
  40. 9 0
      src/main/java/com/zhentao/hotel/dto/HotelDto.java
  41. 18 0
      src/main/java/com/zhentao/hotel/mapper/HotelSortMapper.java
  42. 18 0
      src/main/java/com/zhentao/hotel/mapper/HoteldetailsMapper.java
  43. 18 0
      src/main/java/com/zhentao/hotel/mapper/HotelsMapper.java
  44. 13 0
      src/main/java/com/zhentao/hotel/service/HotelSortService.java
  45. 16 0
      src/main/java/com/zhentao/hotel/service/HoteldetailsService.java
  46. 15 0
      src/main/java/com/zhentao/hotel/service/HotelsService.java
  47. 22 0
      src/main/java/com/zhentao/hotel/service/impl/HotelSortServiceImpl.java
  48. 43 0
      src/main/java/com/zhentao/hotel/service/impl/HoteldetailsServiceImpl.java
  49. 97 0
      src/main/java/com/zhentao/hotel/service/impl/HotelsServiceImpl.java
  50. 18 0
      src/main/java/com/zhentao/mapper/AdvertisementMapper.java
  51. 20 0
      src/main/java/com/zhentao/mapper/FaceFeatureMapper.java
  52. 18 0
      src/main/java/com/zhentao/mapper/UserLoginMapper.java
  53. 75 0
      src/main/java/com/zhentao/order/controller/QrCodeController.java
  54. 13 0
      src/main/java/com/zhentao/service/AdvertisementService.java
  55. 83 0
      src/main/java/com/zhentao/service/FaceEngineService.java
  56. 13 0
      src/main/java/com/zhentao/service/FaceFeatureService.java
  57. 4 0
      src/main/java/com/zhentao/service/PropsService.java
  58. 30 0
      src/main/java/com/zhentao/service/UserLoginService.java
  59. 9 0
      src/main/java/com/zhentao/service/WeChatLogin.java
  60. 22 0
      src/main/java/com/zhentao/service/impl/AdvertisementServiceImpl.java
  61. 239 0
      src/main/java/com/zhentao/service/impl/FaceEngineServiceImpl.java
  62. 22 0
      src/main/java/com/zhentao/service/impl/FaceFeatureServiceImpl.java
  63. 267 0
      src/main/java/com/zhentao/service/impl/UserLoginServiceImpl.java
  64. 88 0
      src/main/java/com/zhentao/service/impl/WeChatLoginimpl.java
  65. 92 0
      src/main/java/com/zhentao/tool/TokenUtils.java
  66. 83 0
      src/main/java/com/zhentao/tool/WechatLoginUtil.java
  67. 22 0
      src/main/java/com/zhentao/touristAttractions/controller/TickentinfoDtoController.java
  68. 22 0
      src/main/java/com/zhentao/touristAttractions/controller/TouristAttractionsController.java
  69. 66 0
      src/main/java/com/zhentao/touristAttractions/domain/Ticketinfo.java
  70. 75 0
      src/main/java/com/zhentao/touristAttractions/domain/Touristattractions.java
  71. 10 0
      src/main/java/com/zhentao/touristAttractions/dto/TickentinfoDto.java
  72. 9 0
      src/main/java/com/zhentao/touristAttractions/dto/TouristattrcationDto.java
  73. 18 0
      src/main/java/com/zhentao/touristAttractions/mapper/TicketinfoMapper.java
  74. 18 0
      src/main/java/com/zhentao/touristAttractions/mapper/TouristattractionsMapper.java
  75. 15 0
      src/main/java/com/zhentao/touristAttractions/service/TicketinfoService.java
  76. 15 0
      src/main/java/com/zhentao/touristAttractions/service/TouristattractionsService.java
  77. 34 0
      src/main/java/com/zhentao/touristAttractions/service/impl/TicketinfoServiceImpl.java
  78. 36 0
      src/main/java/com/zhentao/touristAttractions/service/impl/TouristattractionsServiceImpl.java
  79. 111 0
      src/main/java/com/zhentao/utils/FaceEngineService.java
  80. 173 0
      src/main/java/com/zhentao/utils/FaceEngineTest.java
  81. 53 0
      src/main/java/com/zhentao/utils/FcFileKit.java
  82. 76 0
      src/main/java/com/zhentao/utils/WebServerConfig.java
  83. 17 0
      src/main/java/com/zhentao/vo/PicUploadResult.java
  84. 38 0
      src/main/java/com/zhentao/vo/Result.java
  85. 57 0
      src/main/resources/application.yml
  86. 15 0
      src/main/resources/mapper/AdvertisementMapper.xml
  87. 19 0
      src/main/resources/mapper/FaceFeatureMapper.xml
  88. 18 0
      src/main/resources/mapper/HotelSortMapper.xml
  89. 31 0
      src/main/resources/mapper/HoteldetailsMapper.xml
  90. 43 0
      src/main/resources/mapper/HotelsMapper.xml
  91. 24 0
      src/main/resources/mapper/TicketinfoMapper.xml
  92. 26 0
      src/main/resources/mapper/TouristattractionsMapper.xml
  93. 52 0
      src/main/resources/mapper/UserLoginMapper.xml
  94. 25 0
      src/test/java/com/zhentao/tourismhd/TestFaceEngineService.java
  95. 13 0
      src/test/java/com/zhentao/tourismhd/TourismHdApplicationTests.java
  96. BIN
      upload/imagesOIP-C.jpg
  97. BIN
      upload/imagesOIP-C1 (2).jpg

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 1 - 0
ArcFace64.dat

@@ -0,0 +1 @@
+EWEPEPEOGMGTELIZJUGECKIUJDBCJTCNISGPBNHLJTJUBHEWGNAKGEGAIOHJDQAJGNCFDRFZJEDMJTGQFXJFESBQIGGHFEERBNAYBFABBTIEIQCQHNISEEJHILFSGKFYBHFEHDIQEZEHJFALJPCOGBAGHEBIBUDLGPEQBZEEDUJIESGJJBIZGWJBJCASCWGGBKFHIHFKDZGWAUDKHNDNECCEHKDGDGCFJDFRDKDLJCAYCVJVCMBZDMFVCRFSGSHOFLAIGMIUEXJFAIGMBBDDCDAMATHMCOHTJGFFCQHIJBBLBIHTEMDKCMDCAHJUFVCQHTDFFPIFJHEJALBAFDIUDGBBGHHRESFRJQEZFMBKCYJMFAFCIMGTITHSAQHEILHMJRHQJRITAXEWGVIFBNCBGXCBCYFOEKFTBZDOAHEWGFGPIDEMFFGLBWGPJPFAEWDBGGGRAOGDJEGJDBJFBWDFHSCMFHDIGHIEGOJAJVFOCHDLEUIKJUITICGZBJGIJECBGZJHCCCNAOBYJACCIJEPDTAVDGEMCXCCGGBDJECOAUDSDIGJBRDLIZDPHKBBJBHGHJBRJKDAJKJBCQJVBNAICBDAHOJEILBKFAFZIJHTIYCIIIFCETEIEPJEIRFFFWHSAGDTEHHGGRHBAVGIBDGCJFFLEFJNFNDHEUEJHKHSIHBNDPCRDDFOJOILGPGIJTDJACDXGNDNJRDSFZGLJIJPATIREKCTGSCVCFFMBSJBBVBDCAEDCKGCHYFSGOERGRGYBVFJCYBFGOJEGLFXELJBDZIVJGAYHPIJDFHWEFABAOHBGFGYIJGMAJGUEBCTEJABHMBVCDGCFNAQFOGVIQGGIPENCJHVIACKBLDAAKHPJLHLEVCICAFXEFIOBDHNHBEWDVGOFEILCFJDEAGIFHDGBWFOJUHPJKCAEWIJIDHMGUHHEYCWGQBUFEFFGIIGDZFBERFIESHIAXEEELCGCPALGRAMIEJICBICIZFOJPECFFHRAPGECKDOCCJHGJBHEZAGGKCNBBBVGSDZIVBWFODCHGEPDSHVAOESHRIZGPGCCDACJLDIIUAFHVJTGXCIJSHFIFAEFVAQEQFCDUAHDSAQDCEAIMHCHIHHFOFNGQAWBIFWDFDFFTCOGLFFIKADFSABHJETAJGMAXINCAEABNAMGWBVHWIXITFHCUIDCMFCECJJAW

BIN
libs/WIN64/libarcsoft_face.dll


BIN
libs/WIN64/libarcsoft_face_engine.dll


BIN
libs/WIN64/libarcsoft_face_engine_jni.dll


BIN
libs/arcsoft-sdk-face-3.0.0.0.jar


+ 240 - 0
pom.xml

@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.zhentao</groupId>
+    <artifactId>TourismHD</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>TourismHD</name>
+    <description>TourismHD</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <spring-boot.version>2.6.13</spring-boot.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.12.0</version>
+        </dependency>
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+            <version>2.9.9</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.4</version>
+        </dependency>
+
+        <!-- Mockito 依赖 -->
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>2.8.3</version>
+        </dependency>
+
+
+
+        <dependency>
+            <groupId>com.arcsoft.face</groupId>
+            <artifactId>arcsoft-sdk-face</artifactId>
+            <version>3.0.0.0</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.5.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.5.1</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-high-level-client</artifactId>
+            <version>7.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-client</artifactId>
+            <version>7.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.elasticsearch</groupId>
+            <artifactId>elasticsearch</artifactId>
+            <version>7.4.0</version>
+        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-data-mongodb</artifactId>-->
+<!--        </dependency>-->
+<!--        deekseep-->
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>4.9.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.mashape.unirest</groupId>
+            <artifactId>unirest-java</artifactId>
+            <version>1.4.9</version>
+        </dependency>
+        <!-- Spring Boot Starters -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- MyBatis Plus -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.4</version>
+        </dependency>
+
+        <!-- MySQL -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!-- Lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+<!--        关于微信登录的配置-->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.13</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.11</version> <!-- 确保版本号是正确的 -->
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.14</version>
+        </dependency>
+        <!-- jwt支持 -->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.19.2</version>
+        </dependency>
+
+        <!-- json格式化 -->
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.9</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate.validator</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <version>6.2.0.Final</version>
+        </dependency>
+        <!-- Redisson -->
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson</artifactId>
+            <version>3.18.0</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+        </dependency>
+
+
+    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>11</source>
+                    <target>11</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <mainClass>com.zhentao.TourismHdApplication</mainClass>
+                    <skip>true</skip>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>repackage</id>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 27 - 0
src/main/java/com/zhentao/TourismHdApplication.java

@@ -0,0 +1,27 @@
+package com.zhentao;
+
+import com.arcsoft.face.ActiveFileInfo;
+import com.arcsoft.face.EngineConfiguration;
+import com.arcsoft.face.FaceEngine;
+import com.arcsoft.face.FunctionConfiguration;
+import com.arcsoft.face.enums.DetectMode;
+import com.arcsoft.face.enums.DetectOrient;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+
+import java.io.File;
+import java.util.Date;
+
+
+@SpringBootApplication
+@MapperScan("com.zhentao.**.mapper")
+public class TourismHdApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(TourismHdApplication.class, args);
+
+    }
+
+}

+ 26 - 0
src/main/java/com/zhentao/config/ESConfig.java

@@ -0,0 +1,26 @@
+package com.zhentao.config;
+
+import org.apache.http.HttpHost;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ESConfig {
+
+    public static final RequestOptions COMMON_OPTIONS;
+    static {
+        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
+        COMMON_OPTIONS = builder.build();
+    }
+
+    @Bean
+    public RestHighLevelClient restESClient(){
+        RestHighLevelClient client = new RestHighLevelClient(
+                RestClient.builder(
+                        new HttpHost("192.168.108.131", 9200, "http")));
+        return client;
+    }
+}

+ 43 - 0
src/main/java/com/zhentao/config/RedissonConfig.java

@@ -0,0 +1,43 @@
+package com.zhentao.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+// 定义这是一个Spring配置类,用于配置Redisson相关的Bean
+@Configuration
+public class RedissonConfig {
+//     从配置文件(如application.properties或application.yml)中获取Redis服务器的主机地址
+    @Value("${spring.redis.host}")
+    private String host;
+    // 从配置文件中获取Redis服务器的端口号
+    @Value("${spring.redis.port}")
+    private int port;
+    // 从配置文件中获取要使用的Redis数据库索引
+    @Value("${spring.redis.database}")
+    private int database;
+    // 定义一个Bean,名称为getRedisson,返回一个RedissonClient实例,Spring会在需要RedissonClient的地方注入这个实例
+    @Bean
+    public RedissonClient getRedisson(){
+
+        // 创建一个Redisson的配置对象z
+        Config config = new Config();
+
+        // 配置Redisson使用单机模式,并设置Redis服务器的地址
+        config.useSingleServer().setAddress("redis://"+host+":"+port)
+
+                // 设置要使用的Redis数据库索引
+                .setDatabase(database)
+                ;
+
+
+        // 设置锁的看门狗超时时间为2000毫秒。看门狗用于自动延长锁的持有时间,防止业务执行时间过长导致锁提前释放
+        config.setLockWatchdogTimeout(2000);
+
+        // 根据配置创建并返回RedissonClient实例
+        return Redisson.create(config);
+    }
+}

+ 45 - 0
src/main/java/com/zhentao/controller/AI/Deekseep.java

@@ -0,0 +1,45 @@
+package com.zhentao.controller.AI;
+
+import com.mashape.unirest.http.exceptions.UnirestException;
+import com.zhentao.controller.dto.DeeseekRequest;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.mashape.unirest.http.HttpResponse;
+import com.mashape.unirest.http.Unirest;
+import com.google.gson.Gson;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+public class Deekseep {
+    private final Gson gson = new Gson();
+    //智能Ai智能推荐功能
+    @RequestMapping("tall")
+    public String tallQuestion(String question) throws IOException, UnirestException {
+
+        Unirest.setTimeouts(0, 0);
+//DeeseekRequest: 自己的实体类名称
+
+        List<DeeseekRequest.Message> messages = new ArrayList<>();
+//给deepSeek一个角色
+        messages.add(DeeseekRequest.Message.builder().role("system").content("你是一个美食家").build());
+
+// question:说你自己想说的话
+        messages.add(DeeseekRequest.Message.builder().role("user").content(question).build());
+
+        DeeseekRequest requestBody = DeeseekRequest.builder()
+                .model("deepseek-chat")
+                .messages(messages)
+                .build();
+        HttpResponse<String> response = Unirest.post("https://api.deepseek.com/chat/completions")
+                .header("Content-Type", "application/json")
+                .header("Accept", "application/json")
+                .header("Authorization", "Bearer "+"sk-df51dab7323441998d41f18494098ddc")
+                .body(gson.toJson(requestBody))
+                .asString();
+        return  response.getBody();
+
+    }
+}

+ 19 - 0
src/main/java/com/zhentao/controller/advertisement/AdvertisementController.java

@@ -0,0 +1,19 @@
+package com.zhentao.controller.advertisement;
+
+import com.zhentao.service.AdvertisementService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("advertisement")
+public class AdvertisementController {
+    @Autowired
+    private AdvertisementService service;
+//    广告的查询接口
+    @RequestMapping("list")
+    public Result list() {
+        return Result.OK(service.list(),"查询成功");
+    }
+}

+ 20 - 0
src/main/java/com/zhentao/controller/dto/DeeseekRequest.java

@@ -0,0 +1,20 @@
+package com.zhentao.controller.dto;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@Builder
+public class DeeseekRequest {
+    private String model;
+    private List<Message> messages;
+
+    @Data
+    @Builder
+    public static class Message {
+        private String role;
+        private String content;
+    }
+}

+ 139 - 0
src/main/java/com/zhentao/controller/renlian/FaceDetectionController.java

@@ -0,0 +1,139 @@
+package com.zhentao.controller.renlian;
+
+
+import com.zhentao.utils.FaceEngineService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/api/face")
+public class FaceDetectionController {
+
+    @Autowired
+    private FaceEngineService faceEngineService;
+
+    // 临时文件存储路径
+    private static final String TEMP_DIR = "E:\\专高五\\旅游\\tourismapp\\upload\\images";
+    // 图片库路径
+    private static final String GALLERY_PATH = "E:\\专高五\\旅游\\tourismapp\\upload";
+    // 相似度阈值
+    private static final float THRESHOLD = 0.8f;
+
+    /**
+     * 测试接口:检测上传的图片是否为人像
+     */
+    @PostMapping("/detect")
+    @ResponseBody
+    public ResultResponse checkPortrait(@RequestParam("image") MultipartFile image) {
+        try {
+            // 1. 方式一:直接通过MultipartFile检测
+            boolean isPortrait = faceEngineService.checkIsPortrait(image);
+
+            // 2. 方式二:先保存为文件再检测(可选)
+            /*
+            File tempFile = saveToTempFile(image);
+            boolean isPortrait = faceEngineService.checkIsPortrait(tempFile);
+            deleteTempFile(tempFile);
+            */
+
+            return ResultResponse.success(isPortrait ? "检测到人像" : "未检测到人像", isPortrait);
+        } catch (Exception e) {
+            return ResultResponse.error("检测失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 人脸识别接口:检查上传的图片中的人脸是否存在于图片库中
+     */
+    @PostMapping("/recognize")
+    @ResponseBody
+    public ResultResponse recognizeFace(@RequestParam("image") MultipartFile image) {
+        try {
+            boolean faceExists = faceEngineService.checkIsPortrait(image);
+            return ResultResponse.success(faceExists ? "人脸存在于图片库中" : "人脸不存在于图片库中", faceExists);
+        } catch (Exception e) {
+            return ResultResponse.error("人脸识别失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 辅助方法:保存文件到临时目录
+     */
+    @PostMapping("/insert")
+    private File saveToTempFile(MultipartFile file) throws IOException {
+        new File(TEMP_DIR).mkdirs();
+        Path path = Paths.get(TEMP_DIR + file.getOriginalFilename());
+        Files.write(path, file.getBytes());
+        return path.toFile();
+    }
+
+    /**
+     * 辅助方法:删除临时文件
+     */
+    private void deleteTempFile(File file) {
+        if (file.exists()) {
+            file.delete();
+        }
+    }
+}
+
+/**
+ * 统一响应结果类
+ */
+class ResultResponse {
+    private int code;
+    private String message;
+    private Object data;
+
+    public static ResultResponse success(String message, Object data) {
+        ResultResponse response = new ResultResponse();
+        response.code = 200;
+        response.message = message;
+        response.data = data;
+        return response;
+    }
+
+    public static ResultResponse error(String message) {
+        ResultResponse response = new ResultResponse();
+        response.code = 500;
+        response.message = message;
+        return response;
+    }
+
+    // getter和setter省略
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+}
+

+ 53 - 0
src/main/java/com/zhentao/controller/user/UserController.java

@@ -0,0 +1,53 @@
+package com.zhentao.controller.user;
+
+import com.zhentao.dto.user.*;
+import com.zhentao.service.UserLoginService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+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.validation.Valid;
+
+
+@RestController
+@RequestMapping("user")
+public class UserController {
+
+    @Autowired
+    public UserLoginService userLoginService;
+
+    //注册
+    @PostMapping("/register")
+    public Result Register(@RequestBody @Valid UserRegister userRegister){
+        return userLoginService.register(userRegister);
+    }
+
+    //验证码
+    @PostMapping("/code")
+    public Result code(@RequestBody @Valid NoteDto noteDto) {
+//        System.err.println(noteDto);
+        return userLoginService.note(noteDto);
+    }
+
+    //手机号登录
+    @PostMapping("/login")
+    public Result login(@RequestBody @Valid UserLoginDto userLoginDto) {
+        return userLoginService.login(userLoginDto);
+    }
+
+    //账号和密码进行登录
+    @PostMapping("/UserPassLogin")
+    public Result UserPassLogin(@RequestBody @Valid UserPassDto userPassDto) {
+        return userLoginService.UserPassLogin(userPassDto);
+    }
+
+//    忘记密码
+    @PostMapping("/ForgetPass")
+    public Result ForgetPass(@RequestBody @Valid ForgetPassDto forgetPassDto) {
+        return userLoginService.ForgetPass(forgetPassDto);
+    }
+}

+ 30 - 0
src/main/java/com/zhentao/controller/user/WeChatController.java

@@ -0,0 +1,30 @@
+package com.zhentao.controller.user;
+
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.service.WeChatLogin;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+public class WeChatController {
+    @Autowired
+    private WeChatLogin weChatLogin;
+
+
+    /**
+     * 处理微信登录请求的接口方法
+     * 该方法通过接收微信服务器发送的授权码(Code)来实现用户的登录功能
+     *
+     * @param weChatMode 包含微信授权码等信息的实体对象
+     * @return 返回登录结果,通常包括用户信息或错误信息
+     */
+    @PostMapping("/WeChart/login")
+    public Result WeChartLogin(@RequestBody WeChatMode weChatMode) {
+        // 打印接收到的微信授权码,用于调试和验证
+        System.err.println(weChatMode.getCode());
+        // 调用服务层方法处理微信登录逻辑
+        return weChatLogin.WeChatLogin(weChatMode);
+    }
+
+}

+ 30 - 0
src/main/java/com/zhentao/domain/Advertisement.java

@@ -0,0 +1,30 @@
+package com.zhentao.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ * 广告表
+ * @TableName Advertisement
+ */
+@TableName(value ="Advertisement")
+@Data
+public class Advertisement implements Serializable {
+    /**
+     * 广告
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 图片
+     */
+    private String image;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 86 - 0
src/main/java/com/zhentao/domain/FaceFeature.java

@@ -0,0 +1,86 @@
+package com.zhentao.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 人脸特征表
+ * @TableName face_feature
+ */
+@TableName(value ="face_feature")
+@Data
+public class FaceFeature implements Serializable {
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 关联用户ID
+     */
+    private Long userId;
+
+    /**
+     * 人脸唯一标识
+     */
+    private String faceId;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 人脸特征二进制数据
+     */
+    private byte[] featureData;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getFaceId() {
+        return faceId;
+    }
+
+    public void setFaceId(String faceId) {
+        this.faceId = faceId;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public byte[] getFeatureData() {
+        return featureData;
+    }
+
+    public void setFeatureData(byte[] featureData) {
+        this.featureData = featureData;
+    }
+}

+ 297 - 0
src/main/java/com/zhentao/domain/UserLogin.java

@@ -0,0 +1,297 @@
+package com.zhentao.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 用户
+ * @TableName user_login
+ */
+@TableName(value ="user_login")
+@Data
+public class UserLogin implements Serializable {
+    /**
+     * 用户ID
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 账号
+     */
+    private String userUsername;
+
+    /**
+     * 密码
+     */
+    private String userPassword;
+
+    /**
+     * 盐
+     */
+    private String salt;
+
+    /**
+     * 用户昵称
+     */
+    private String nickName;
+
+    /**
+     * 头像图片
+     */
+    private String avatar;
+
+    /**
+     * 用户名称
+     */
+    private String userName;
+
+    /**
+     * 性别1男2女3未知
+     */
+    private Integer gender;
+
+    /**
+     * 个性签名
+     */
+    private String userIntro;
+
+    /**
+     * 手机号
+     */
+    private String userMobile;
+
+    /**
+     * 身份证号
+     */
+    private String idenNo;
+
+    /**
+     * 用户等级
+     */
+    private Long gradeId;
+
+    /**
+     * 等级描述
+     */
+    private String gradeDesc;
+
+    /**
+     * 是否付费会员0否1是
+     */
+    private Integer isMember;
+
+    /**
+     * 过期时间
+     */
+    private Date loseDate;
+
+    /**
+     * 1临时会员2副卡3正式会员
+     */
+    private Integer memberType;
+
+    /**
+     * 生日
+     */
+    private Date birthDay;
+
+    /**
+     * 月
+     */
+    private Integer birthMonth;
+
+    /**
+     * 日
+     */
+    private Integer days;
+
+    /**
+     * 总订单数
+     */
+    private Integer totalOrder;
+
+    /**
+     * 总消费金额
+     */
+    private BigDecimal totalConsume;
+
+    /**
+     * 标签列表
+     */
+    private String labelList;
+
+    /**
+     * 状态1正常0锁定
+     */
+    private Integer status;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建时间
+     */
+    private Date createdTime;
+
+    /**
+     * 更新人
+     */
+    private String updatedBy;
+
+    /**
+     * 更新时间
+     */
+    private Date updatedTime;
+
+    /**
+     *
+     */
+    private String openId;
+
+    /**
+     *
+     */
+    private String sessionKey;
+
+    /**
+     *
+     */
+    private String uniId;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        UserLogin other = (UserLogin) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getUserUsername() == null ? other.getUserUsername() == null : this.getUserUsername().equals(other.getUserUsername()))
+            && (this.getUserPassword() == null ? other.getUserPassword() == null : this.getUserPassword().equals(other.getUserPassword()))
+            && (this.getSalt() == null ? other.getSalt() == null : this.getSalt().equals(other.getSalt()))
+            && (this.getNickName() == null ? other.getNickName() == null : this.getNickName().equals(other.getNickName()))
+            && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
+            && (this.getUserName() == null ? other.getUserName() == null : this.getUserName().equals(other.getUserName()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getUserIntro() == null ? other.getUserIntro() == null : this.getUserIntro().equals(other.getUserIntro()))
+            && (this.getUserMobile() == null ? other.getUserMobile() == null : this.getUserMobile().equals(other.getUserMobile()))
+            && (this.getIdenNo() == null ? other.getIdenNo() == null : this.getIdenNo().equals(other.getIdenNo()))
+            && (this.getGradeId() == null ? other.getGradeId() == null : this.getGradeId().equals(other.getGradeId()))
+            && (this.getGradeDesc() == null ? other.getGradeDesc() == null : this.getGradeDesc().equals(other.getGradeDesc()))
+            && (this.getIsMember() == null ? other.getIsMember() == null : this.getIsMember().equals(other.getIsMember()))
+            && (this.getLoseDate() == null ? other.getLoseDate() == null : this.getLoseDate().equals(other.getLoseDate()))
+            && (this.getMemberType() == null ? other.getMemberType() == null : this.getMemberType().equals(other.getMemberType()))
+            && (this.getBirthDay() == null ? other.getBirthDay() == null : this.getBirthDay().equals(other.getBirthDay()))
+            && (this.getBirthMonth() == null ? other.getBirthMonth() == null : this.getBirthMonth().equals(other.getBirthMonth()))
+            && (this.getDays() == null ? other.getDays() == null : this.getDays().equals(other.getDays()))
+            && (this.getTotalOrder() == null ? other.getTotalOrder() == null : this.getTotalOrder().equals(other.getTotalOrder()))
+            && (this.getTotalConsume() == null ? other.getTotalConsume() == null : this.getTotalConsume().equals(other.getTotalConsume()))
+            && (this.getLabelList() == null ? other.getLabelList() == null : this.getLabelList().equals(other.getLabelList()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getRemark() == null ? other.getRemark() == null : this.getRemark().equals(other.getRemark()))
+            && (this.getCreatedTime() == null ? other.getCreatedTime() == null : this.getCreatedTime().equals(other.getCreatedTime()))
+            && (this.getUpdatedBy() == null ? other.getUpdatedBy() == null : this.getUpdatedBy().equals(other.getUpdatedBy()))
+            && (this.getUpdatedTime() == null ? other.getUpdatedTime() == null : this.getUpdatedTime().equals(other.getUpdatedTime()))
+            && (this.getOpenId() == null ? other.getOpenId() == null : this.getOpenId().equals(other.getOpenId()))
+            && (this.getSessionKey() == null ? other.getSessionKey() == null : this.getSessionKey().equals(other.getSessionKey()))
+            && (this.getUniId() == null ? other.getUniId() == null : this.getUniId().equals(other.getUniId()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getUserUsername() == null) ? 0 : getUserUsername().hashCode());
+        result = prime * result + ((getUserPassword() == null) ? 0 : getUserPassword().hashCode());
+        result = prime * result + ((getSalt() == null) ? 0 : getSalt().hashCode());
+        result = prime * result + ((getNickName() == null) ? 0 : getNickName().hashCode());
+        result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
+        result = prime * result + ((getUserName() == null) ? 0 : getUserName().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getUserIntro() == null) ? 0 : getUserIntro().hashCode());
+        result = prime * result + ((getUserMobile() == null) ? 0 : getUserMobile().hashCode());
+        result = prime * result + ((getIdenNo() == null) ? 0 : getIdenNo().hashCode());
+        result = prime * result + ((getGradeId() == null) ? 0 : getGradeId().hashCode());
+        result = prime * result + ((getGradeDesc() == null) ? 0 : getGradeDesc().hashCode());
+        result = prime * result + ((getIsMember() == null) ? 0 : getIsMember().hashCode());
+        result = prime * result + ((getLoseDate() == null) ? 0 : getLoseDate().hashCode());
+        result = prime * result + ((getMemberType() == null) ? 0 : getMemberType().hashCode());
+        result = prime * result + ((getBirthDay() == null) ? 0 : getBirthDay().hashCode());
+        result = prime * result + ((getBirthMonth() == null) ? 0 : getBirthMonth().hashCode());
+        result = prime * result + ((getDays() == null) ? 0 : getDays().hashCode());
+        result = prime * result + ((getTotalOrder() == null) ? 0 : getTotalOrder().hashCode());
+        result = prime * result + ((getTotalConsume() == null) ? 0 : getTotalConsume().hashCode());
+        result = prime * result + ((getLabelList() == null) ? 0 : getLabelList().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getRemark() == null) ? 0 : getRemark().hashCode());
+        result = prime * result + ((getCreatedTime() == null) ? 0 : getCreatedTime().hashCode());
+        result = prime * result + ((getUpdatedBy() == null) ? 0 : getUpdatedBy().hashCode());
+        result = prime * result + ((getUpdatedTime() == null) ? 0 : getUpdatedTime().hashCode());
+        result = prime * result + ((getOpenId() == null) ? 0 : getOpenId().hashCode());
+        result = prime * result + ((getSessionKey() == null) ? 0 : getSessionKey().hashCode());
+        result = prime * result + ((getUniId() == null) ? 0 : getUniId().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", userUsername=").append(userUsername);
+        sb.append(", userPassword=").append(userPassword);
+        sb.append(", salt=").append(salt);
+        sb.append(", nickName=").append(nickName);
+        sb.append(", avatar=").append(avatar);
+        sb.append(", userName=").append(userName);
+        sb.append(", gender=").append(gender);
+        sb.append(", userIntro=").append(userIntro);
+        sb.append(", userMobile=").append(userMobile);
+        sb.append(", idenNo=").append(idenNo);
+        sb.append(", gradeId=").append(gradeId);
+        sb.append(", gradeDesc=").append(gradeDesc);
+        sb.append(", isMember=").append(isMember);
+        sb.append(", loseDate=").append(loseDate);
+        sb.append(", memberType=").append(memberType);
+        sb.append(", birthDay=").append(birthDay);
+        sb.append(", birthMonth=").append(birthMonth);
+        sb.append(", days=").append(days);
+        sb.append(", totalOrder=").append(totalOrder);
+        sb.append(", totalConsume=").append(totalConsume);
+        sb.append(", labelList=").append(labelList);
+        sb.append(", status=").append(status);
+        sb.append(", remark=").append(remark);
+        sb.append(", createdTime=").append(createdTime);
+        sb.append(", updatedBy=").append(updatedBy);
+        sb.append(", updatedTime=").append(updatedTime);
+        sb.append(", openId=").append(openId);
+        sb.append(", sessionKey=").append(sessionKey);
+        sb.append(", uniId=").append(uniId);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+
+
+
+}

+ 16 - 0
src/main/java/com/zhentao/dto/user/ForgetPassDto.java

@@ -0,0 +1,16 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class ForgetPassDto {
+//    手机号
+    @NotBlank(message = "手机号不能为空")
+    private String phone;
+    @NotBlank(message = "验证码不能为空")
+    private String code;
+    @NotBlank(message = "密码不能为空")
+    private String password;
+}

+ 19 - 0
src/main/java/com/zhentao/dto/user/NoteDto.java

@@ -0,0 +1,19 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+@Data
+public class NoteDto {
+
+    @NotBlank(message = "手机号不能为空")
+    @Pattern(regexp = "^1[3-9]\\d{9}$",message = "手机号格式不正确" )
+    private String phone;
+
+
+
+
+
+}

+ 18 - 0
src/main/java/com/zhentao/dto/user/UserLoginDto.java

@@ -0,0 +1,18 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+@Data
+public class UserLoginDto {
+
+    @NotBlank(message = "手机号不能为空")
+    @Pattern(regexp = "^1[3-9]\\d{9}$",message = "手机号格式不正确" )
+    private String phone;
+
+    //验证码
+    @NotBlank(message = "验证码不能为空")
+    private String code;
+}

+ 14 - 0
src/main/java/com/zhentao/dto/user/UserPassDto.java

@@ -0,0 +1,14 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class UserPassDto {
+
+    @NotBlank(message = "账号不能为空")
+    private String username;
+    @NotBlank(message = "密码不能为空")
+    private String password;
+}

+ 26 - 0
src/main/java/com/zhentao/dto/user/UserRegister.java

@@ -0,0 +1,26 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+@Data
+public class UserRegister {
+    //手机号
+    @NotBlank(message = "手机号不能为空")
+    @Pattern(regexp = "^1[3-9]\\d{9}$",message = "手机号格式不正确" )
+    private String phone;
+
+    //验证码
+    @NotBlank(message = "验证码不能为空")
+    private String code;
+
+    //用户名
+    @NotBlank(message = "用户名不能为空")
+    private String username;
+
+    //密码
+    @NotBlank(message = "密码不能为空")
+    private String password;
+}

+ 13 - 0
src/main/java/com/zhentao/dto/user/WeChatLoginDto.java

@@ -0,0 +1,13 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+@Data
+public class WeChatLoginDto {
+    //头像图片
+    private String avatarUrl;
+    //性别1男2女3未知
+    private Integer gender;
+//    用户昵称
+    private String nickName;
+}

+ 14 - 0
src/main/java/com/zhentao/dto/user/WeChatMode.java

@@ -0,0 +1,14 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+//用来接受前端传来的参数
+@Data
+public class WeChatMode {
+//    临时登录凭证
+    private String code;
+    private WeChatLoginDto weChatLoginDto;
+
+    //微信服务器上的唯一id
+    private String openId;
+}

+ 16 - 0
src/main/java/com/zhentao/dto/user/WeChatSessionModel.java

@@ -0,0 +1,16 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+//用来就接受调用微信验证code后返回的数据
+@Data
+public class WeChatSessionModel {
+
+    //微信服务器上辨识用户的唯一id
+    private String openid;
+    //身份凭证
+    private String session_key;
+    //错误代码
+    private String errcode;
+    //错误信息
+    private String errmsg;
+}

+ 28 - 0
src/main/java/com/zhentao/enums/ApiServerException.java

@@ -0,0 +1,28 @@
+package com.zhentao.enums;
+
+public enum ApiServerException implements BaseExceptionEnum{
+    SUCCESS(1, "成功"),
+    NULL_USERNAME(1,"用户名错误"),
+    SUCCESS_login(1,"登录成功"),
+    TOKEN_ERR(101,"token错误,请重新登录"),
+    INTERRUPT(1,"操作中断"),
+    REGISTERED(1,"已注册"),
+    NOTE_ERROR(1,"验证码错误"),
+    NULL_PASSWORD(1,"密码错误");
+
+    ApiServerException(Integer code,String msg){
+        this.code=code;
+        this.msg=msg;
+    }
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+
+    @Override
+    public String getMsg() {
+        return msg;
+    }
+    private Integer code;
+    private String msg;
+}

+ 6 - 0
src/main/java/com/zhentao/enums/BaseExceptionEnum.java

@@ -0,0 +1,6 @@
+package com.zhentao.enums;
+
+public interface BaseExceptionEnum {
+    Integer getCode();
+    String getMsg();
+}

+ 15 - 0
src/main/java/com/zhentao/exception/AsynException.java

@@ -0,0 +1,15 @@
+package com.zhentao.exception;
+
+import com.zhentao.enums.BaseExceptionEnum;
+import lombok.Data;
+
+@Data
+public class AsynException extends RuntimeException{
+    private Integer code;
+    private String msg;
+    public AsynException(BaseExceptionEnum baseExceptionEnum){
+        super(baseExceptionEnum.getMsg());
+        this.code = baseExceptionEnum.getCode();
+        this.msg = baseExceptionEnum.getMsg();
+    }
+}

+ 56 - 0
src/main/java/com/zhentao/exception/GlobalExceptionHandler.java

@@ -0,0 +1,56 @@
+package com.zhentao.exception;
+
+
+import com.zhentao.vo.Result;
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MultipartException;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Slf4j
+@RestControllerAdvice
+@ControllerAdvice
+public class GlobalExceptionHandler {
+    // 捕获所有异常的处理器,指定捕获的异常类型为Exception
+    @ExceptionHandler(value = Exception.class)
+// 将处理结果以JSON格式返回
+    @ResponseBody
+    public Result defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
+        // 记录异常信息到日志,这里只记录异常信息,不记录堆栈信息
+        log.error(e.getMessage());
+
+        // 判断异常类型并进行处理
+        if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
+            // 如果是404异常,即没有找到处理器
+            return Result.error(404,"不存在页面请求");
+        }
+
+        if (e instanceof AsynException) {
+            // 如果是自定义的AsynException
+            AsynException customException = (AsynException) e;
+
+            // 返回自定义异常的错误码和错误信息
+            return Result.error(customException.getCode(), customException.getMessage());
+        } else if (e instanceof MultipartException) {
+            // 如果是文件上传异常
+            log.error("系统异常{}", e); // 记录异常堆栈信息
+            return Result.error(1000, "上传文件异常");
+        } else if (e instanceof MethodArgumentNotValidException) {
+            // 如果是校验异常,例如使用@Valid注解校验参数失败
+            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) e;
+
+            // 获取校验失败的第一个字段的错误信息
+            return Result.error(1002, methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage());
+        } else {
+            // 其他未处理的异常
+            log.error("系统异常{}", e); // 记录异常堆栈信息
+            return Result.error(1001, "系统参数异常");
+        }
+    }
+}

+ 26 - 0
src/main/java/com/zhentao/filter/TokenFilter.java

@@ -0,0 +1,26 @@
+package com.zhentao.filter;
+
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * TokenFilter类实现了Filter接口,用于在Servlet请求处理前后进行拦截和处理
+ * 主要功能是进行跨域资源共享(CORS)配置,以允许来自不同域的请求
+ */
+public class TokenFilter implements Filter {
+
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        // 将ServletResponse转换为HttpServletResponse,以便后续操作
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        // 将ServletRequest转换为HttpServletRequest,以便后续操作
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        // 将请求和响应对象传递给链中的下一个过滤器或目标资源
+        filterChain.doFilter(request,response);
+    }
+}
+

+ 23 - 0
src/main/java/com/zhentao/hotel/controller/Hotel_Controller.java

@@ -0,0 +1,23 @@
+package com.zhentao.hotel.controller;
+
+import com.zhentao.hotel.dto.HotelDto;
+import com.zhentao.hotel.service.HotelsService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@RestController
+@RequestMapping("hotel")
+public class Hotel_Controller {
+    @Autowired
+    private HotelsService service;
+//    查询酒店的基本信息
+    @PostMapping("list")
+    public Result list(@RequestBody HotelDto hotelDto){
+        return service.findAll(hotelDto);
+    }
+
+}

+ 20 - 0
src/main/java/com/zhentao/hotel/controller/Hotel_Sort_Controller.java

@@ -0,0 +1,20 @@
+package com.zhentao.hotel.controller;
+
+import com.zhentao.hotel.service.HotelSortService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("sort")
+public class Hotel_Sort_Controller {
+    @Autowired
+    private HotelSortService service;
+//    查询酒店的分类
+    @PostMapping("list")
+    public Result list(){
+        return Result.OK(service.list(),"查询成功");
+    }
+}

+ 20 - 0
src/main/java/com/zhentao/hotel/controller/Hoteldetails_controller.java

@@ -0,0 +1,20 @@
+package com.zhentao.hotel.controller;
+
+import com.zhentao.hotel.service.HoteldetailsService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("hoteldetails")
+public class Hoteldetails_controller {
+    @Autowired
+    private HoteldetailsService service;
+//    查询酒店的详细信息
+    @PostMapping("findAll")
+    public Result findAll(){
+        return Result.OK(service.list(),"查询成功");
+    }
+}

+ 41 - 0
src/main/java/com/zhentao/hotel/domain/HotelSort.java

@@ -0,0 +1,41 @@
+package com.zhentao.hotel.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 酒店分类
+ * @TableName hotel_sort
+ */
+@TableName(value ="hotel_sort")
+@Data
+public class HotelSort implements Serializable {
+    /**
+     * 分类的主键
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 分类的名称
+     */
+    private String sortName;
+
+    /**
+     * 名称的类型
+     */
+    private String sortLei;
+
+    /**
+     * 创建的时间
+     */
+    private Date createTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 92 - 0
src/main/java/com/zhentao/hotel/domain/Hoteldetails.java

@@ -0,0 +1,92 @@
+package com.zhentao.hotel.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 酒店详情表,存储每个酒店的房间详细信息,包括房间类型、描述、价格等
+ * @TableName HotelDetails
+ */
+@TableName(value ="HotelDetails")
+@Data
+public class Hoteldetails implements Serializable {
+    /**
+     * 酒店详情的唯一标识符,自动递增
+     */
+    @TableId(type = IdType.AUTO)
+    private Long detailid;
+
+    /**
+     * 关联的酒店ID,外键关联到Hotels表
+     */
+    private Long hotelid;
+
+    /**
+     * 房间类型,如单人间、双人间、套房等
+     */
+    private String roomtype;
+
+    /**
+     * 房间的详细描述,包括设施和服务
+     */
+    private String roomdescription;
+
+    /**
+     * 房间提供的设施,如免费Wi-Fi、空调、迷你吧等
+     */
+    private String roomamenities;
+
+    /**
+     * 房间的价格
+     */
+    private BigDecimal roomprice;
+
+    /**
+     * 房间的大小(平方米)
+     */
+    private Integer roomsize;
+
+    /**
+     * 房间的景观,如城市景观、海景等
+     */
+    private String roomview;
+
+    /**
+     * 房间的最大入住人数
+     */
+    private Integer roomcapacity;
+
+    /**
+     * 是否包含早餐
+     */
+    private Integer breakfastincluded;
+
+    /**
+     * 允许入住的时间
+     */
+    private Date checkintime;
+
+    /**
+     * 必须退房的时间
+     */
+    private Date checkouttime;
+
+    /**
+     * 记录创建时间,默认为当前时间
+     */
+    private Date createtime;
+
+    /**
+     * 记录最后更新时间,默认为当前时间,更新时自动更新
+     */
+    private Date updatetime;
+    private String image;
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 141 - 0
src/main/java/com/zhentao/hotel/domain/Hotels.java

@@ -0,0 +1,141 @@
+package com.zhentao.hotel.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import lombok.Data;
+
+/**
+ * 酒店数据表,存储酒店的基本信息、联系方式、分类信息、设施与服务、价格信息、评价与评分等
+ * @TableName Hotels
+ */
+@TableName(value ="Hotels")
+@Data
+public class Hotels implements Serializable {
+    /**
+     * ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long hotelid;
+
+    /**
+     * 酒店分类
+     */
+    private Long sortId;
+
+    /**
+     * 酒店名称
+     */
+    private String hotelname;
+
+    /**
+     * 酒店的具体地址
+     */
+    private String address;
+
+    /**
+     * 酒店所在的城市
+     */
+    private String city;
+
+    /**
+     * 酒店所在的州或省
+     */
+    private String stateprovince;
+
+    /**
+     * 酒店所在的国家
+     */
+    private String country;
+
+    /**
+     * 酒店的邮政编码
+     */
+    private String postalcode;
+
+    /**
+     * 酒店的联系电话
+     */
+    private String phonenumber;
+
+    /**
+     * 酒店的电子邮件地址
+     */
+    private String email;
+
+    /**
+     * 酒店的官方网站
+     */
+    private String website;
+
+    /**
+     * 酒店的星级评定
+     */
+    private Integer starrating;
+
+    /**
+     * 酒店的类型(如商务酒店、度假酒店等)
+     */
+    private String type;
+
+    /**
+     * 酒店所属的品牌或连锁
+     */
+    private String brand;
+
+    /**
+     * 酒店提供的设施(如免费Wi-Fi、健身房等)
+     */
+    private String amenities;
+
+    /**
+     * 酒店提供的服务(如客房服务、机场接送等)
+     */
+    private String services;
+
+    /**
+     * 酒店价格
+     */
+    private BigDecimal price;
+
+    /**
+     * 酒店的用户评分
+     */
+    private BigDecimal rating;
+
+    /**
+     * 酒店的评价数量
+     */
+    private Integer reviewcount;
+
+    /**
+     * 酒店的详细描述
+     */
+    private String description;
+
+    /**
+     * 酒店的图片链接
+     */
+    private String imageurl;
+
+    /**
+     * 记录创建时间,默认为当前时间
+     */
+    private Date createtime;
+
+    /**
+     * 记录最后更新时间,默认为当前时间,更新时自动更新
+     */
+    private Date updatetime;
+    @TableField(exist = false)
+    private List<Hoteldetails> list;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 9 - 0
src/main/java/com/zhentao/hotel/dto/HotelDetailDto.java

@@ -0,0 +1,9 @@
+package com.zhentao.hotel.dto;
+
+import lombok.Data;
+
+@Data
+public class HotelDetailDto {
+//    酒店的ID
+    private Integer id;
+}

+ 9 - 0
src/main/java/com/zhentao/hotel/dto/HotelDto.java

@@ -0,0 +1,9 @@
+package com.zhentao.hotel.dto;
+
+import lombok.Data;
+
+@Data
+public class HotelDto {
+    private Long id;
+    private String hotelName;
+}

+ 18 - 0
src/main/java/com/zhentao/hotel/mapper/HotelSortMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.hotel.mapper;
+
+import com.zhentao.hotel.domain.HotelSort;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 86183
+* @description 针对表【hotel_sort(酒店分类)】的数据库操作Mapper
+* @createDate 2025-05-21 11:39:54
+* @Entity com.zhentao.hotel.domain.HotelSort
+*/
+public interface HotelSortMapper extends BaseMapper<HotelSort> {
+
+}
+
+
+
+

+ 18 - 0
src/main/java/com/zhentao/hotel/mapper/HoteldetailsMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.hotel.mapper;
+
+import com.zhentao.hotel.domain.Hoteldetails;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 86183
+* @description 针对表【HotelDetails(酒店详情表,存储每个酒店的房间详细信息,包括房间类型、描述、价格等)】的数据库操作Mapper
+* @createDate 2025-05-22 14:58:06
+* @Entity com.zhentao.hotel.domain.Hoteldetails
+*/
+public interface HoteldetailsMapper extends BaseMapper<Hoteldetails> {
+
+}
+
+
+
+

+ 18 - 0
src/main/java/com/zhentao/hotel/mapper/HotelsMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.hotel.mapper;
+
+import com.zhentao.hotel.domain.Hotels;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 86183
+* @description 针对表【Hotels(酒店数据表,存储酒店的基本信息、联系方式、分类信息、设施与服务、价格信息、评价与评分等)】的数据库操作Mapper
+* @createDate 2025-05-21 11:42:24
+* @Entity com.zhentao.hotel.domain.Hotels
+*/
+public interface HotelsMapper extends BaseMapper<Hotels> {
+
+}
+
+
+
+

+ 13 - 0
src/main/java/com/zhentao/hotel/service/HotelSortService.java

@@ -0,0 +1,13 @@
+package com.zhentao.hotel.service;
+
+import com.zhentao.hotel.domain.HotelSort;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 86183
+* @description 针对表【hotel_sort(酒店分类)】的数据库操作Service
+* @createDate 2025-05-21 11:39:54
+*/
+public interface HotelSortService extends IService<HotelSort> {
+
+}

+ 16 - 0
src/main/java/com/zhentao/hotel/service/HoteldetailsService.java

@@ -0,0 +1,16 @@
+package com.zhentao.hotel.service;
+
+import com.zhentao.hotel.domain.Hoteldetails;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.hotel.dto.HotelDetailDto;
+import com.zhentao.vo.Result;
+
+/**
+* @author 86183
+* @description 针对表【HotelDetails(酒店详情表,存储每个酒店的房间详细信息,包括房间类型、描述、价格等)】的数据库操作Service
+* @createDate 2025-05-22 14:58:06
+*/
+public interface HoteldetailsService extends IService<Hoteldetails> {
+//    查询详细
+    Result hotelDetails(HotelDetailDto dto);
+}

+ 15 - 0
src/main/java/com/zhentao/hotel/service/HotelsService.java

@@ -0,0 +1,15 @@
+package com.zhentao.hotel.service;
+
+import com.zhentao.hotel.domain.Hotels;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.hotel.dto.HotelDto;
+import com.zhentao.vo.Result;
+
+/**
+* @author 86183
+* @description 针对表【Hotels(酒店数据表,存储酒店的基本信息、联系方式、分类信息、设施与服务、价格信息、评价与评分等)】的数据库操作Service
+* @createDate 2025-05-21 11:42:24
+*/
+public interface HotelsService extends IService<Hotels> {
+    Result findAll(HotelDto hotelDto);
+}

+ 22 - 0
src/main/java/com/zhentao/hotel/service/impl/HotelSortServiceImpl.java

@@ -0,0 +1,22 @@
+package com.zhentao.hotel.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.hotel.domain.HotelSort;
+import com.zhentao.hotel.service.HotelSortService;
+import com.zhentao.hotel.mapper.HotelSortMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 86183
+* @description 针对表【hotel_sort(酒店分类)】的数据库操作Service实现
+* @createDate 2025-05-21 11:39:54
+*/
+@Service
+public class HotelSortServiceImpl extends ServiceImpl<HotelSortMapper, HotelSort>
+    implements HotelSortService{
+
+}
+
+
+
+

+ 43 - 0
src/main/java/com/zhentao/hotel/service/impl/HoteldetailsServiceImpl.java

@@ -0,0 +1,43 @@
+package com.zhentao.hotel.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.hotel.domain.Hoteldetails;
+import com.zhentao.hotel.domain.Hotels;
+import com.zhentao.hotel.dto.HotelDetailDto;
+import com.zhentao.hotel.service.HoteldetailsService;
+import com.zhentao.hotel.mapper.HoteldetailsMapper;
+import com.zhentao.hotel.service.HotelsService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+* @author 86183
+* @description 针对表【HotelDetails(酒店详情表,存储每个酒店的房间详细信息,包括房间类型、描述、价格等)】的数据库操作Service实现
+* @createDate 2025-05-22 14:58:06
+*/
+@Service
+public class HoteldetailsServiceImpl extends ServiceImpl<HoteldetailsMapper, Hoteldetails>
+    implements HoteldetailsService{
+    @Autowired
+    private HotelsService service;
+//查询详细
+    @Override
+    public Result hotelDetails(HotelDetailDto dto) {
+//        查询酒店的信息
+        Hotels byId = service.getById(dto.getId());
+//        查询酒店的基本信息
+        QueryWrapper<Hoteldetails> queryWrapper=new QueryWrapper<>();
+        queryWrapper.eq("hotelId",dto.getId());
+        List<Hoteldetails> list = this.list(queryWrapper);
+        byId.setList(list);
+        return Result.OK(list,"查询成功");
+    }
+}
+
+
+
+

+ 97 - 0
src/main/java/com/zhentao/hotel/service/impl/HotelsServiceImpl.java

@@ -0,0 +1,97 @@
+package com.zhentao.hotel.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.hotel.domain.Hotels;
+import com.zhentao.hotel.dto.HotelDto;
+import com.zhentao.hotel.service.HotelsService;
+import com.zhentao.hotel.mapper.HotelsMapper;
+import com.zhentao.vo.Result;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author 86183
+* @description 针对表【Hotels(酒店数据表,存储酒店的基本信息、联系方式、分类信息、设施与服务、价格信息、评价与评分等)】的数据库操作Service实现
+* @createDate 2025-05-21 11:42:24
+*/
+@Service
+public class HotelsServiceImpl extends ServiceImpl<HotelsMapper, Hotels>
+    implements HotelsService{
+    @Autowired
+    private RestHighLevelClient restHighLevelClient;
+    @Override
+    public Result findAll(HotelDto hotelDto) {
+//        查询所有酒店的信息
+        QueryWrapper<Hotels> queryWrapper=new QueryWrapper<>();
+//        根据分类ID
+        queryWrapper.eq("sort_id",hotelDto.getId());
+//        根据详细地址
+        queryWrapper.like("hotelName",hotelDto.getHotelName());
+        List<Hotels> list = this.list(queryWrapper);
+        return Result.OK(list,"查询成功");
+    }
+
+
+//    @Override
+//    public Result findAll(HotelDto hotelDto) {
+//        // 创建ES查询请求
+//        SearchRequest searchRequest = new SearchRequest("hotel_index"); // 假设索引名为hotel_index
+//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
+//
+//        // 构建查询条件
+//        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
+//        if (hotelDto.getId() != null) {
+//            boolQuery.must(QueryBuilders.termQuery("sort_id", hotelDto.getId()));
+//        }
+//        if (hotelDto.getHotelName() != null) {
+//            boolQuery.must(QueryBuilders.matchQuery("hotelName", hotelDto.getHotelName()));
+//        }
+//        sourceBuilder.query(boolQuery);
+//
+//        // 设置查询请求的源
+//        searchRequest.source(sourceBuilder);
+//
+//        // 执行查询
+//        try {
+//            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+//            SearchHits hits = searchResponse.getHits();
+//
+//            // 处理查询结果
+//            List<Hotels> list = new ArrayList<>();
+//            for (SearchHit hit : hits) {
+//                // 将ES查询结果转换为Hotels对象
+//                Hotels hotel = new Hotels();
+//                hotel.setHotelid(Long.valueOf(hit.getId()));
+//                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
+//                hotel.setHotelname((String) sourceAsMap.get("hotelName"));
+//                // 其他字段的映射...
+//                list.add(hotel);
+//            }
+//
+//            // 返回结果
+//            return Result.OK(list, "查询成功");
+//        } catch (IOException e) {
+//            e.printStackTrace();
+//            return Result.error(400,"查询失败");
+//        }
+//    }
+}
+
+
+
+

+ 18 - 0
src/main/java/com/zhentao/mapper/AdvertisementMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.mapper;
+
+import com.zhentao.domain.Advertisement;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 86183
+* @description 针对表【Advertisement(广告表)】的数据库操作Mapper
+* @createDate 2025-05-20 22:07:18
+* @Entity com.zhentao.domain.Advertisement
+*/
+public interface AdvertisementMapper extends BaseMapper<Advertisement> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/zhentao/mapper/FaceFeatureMapper.java

@@ -0,0 +1,20 @@
+package com.zhentao.mapper;
+
+import com.zhentao.domain.FaceFeature;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.Optional;
+
+/**
+* @author Lenovo
+* @description 针对表【face_feature(人脸特征表)】的数据库操作Mapper
+* @createDate 2025-05-26 11:53:34
+* @Entity com.zhentao.domain.FaceFeature
+*/
+public interface FaceFeatureMapper extends BaseMapper<FaceFeature> {
+    Optional<FaceFeature> findByFaceId(String faceId);
+}
+
+
+
+

+ 18 - 0
src/main/java/com/zhentao/mapper/UserLoginMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.mapper;
+
+import com.zhentao.domain.UserLogin;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author lenovo
+* @description 针对表【user_login(用户)】的数据库操作Mapper
+* @createDate 2025-05-16 18:48:43
+* @Entity com.zhentao.domain.UserLogin
+*/
+public interface UserLoginMapper extends BaseMapper<UserLogin> {
+
+}
+
+
+
+

+ 75 - 0
src/main/java/com/zhentao/order/controller/QrCodeController.java

@@ -0,0 +1,75 @@
+package com.zhentao.order.controller;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import org.springframework.web.bind.annotation.*;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/api/qrcode")
+public class QrCodeController {
+
+    // 生成带用户数据的二维码接口
+    @PostMapping("/generate")
+    public Map<String, Object> generateQrCode(@RequestBody UserData userData) {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            // 1. 处理用户数据
+            String dataToEncode = userData.toJsonString();
+
+            // 2. 生成二维码图片
+            int width = 300;
+            int height = 300;
+//            使用ZXIng ("Zebra Crossing")库来生成一个二维码图像
+            BitMatrix bitMatrix = new MultiFormatWriter().encode(dataToEncode, BarcodeFormat.QR_CODE, width, height);
+//            用于将bitMatrix变成图片
+            BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
+
+            // 3. 转换为Base64字符串
+//            这是一个输出流
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//            把对象写入到创建的输出流中
+            ImageIO.write(image, "png", baos);
+//            将字节数组转换成byte数组
+            byte[] imageBytes = baos.toByteArray();
+//            这个字符串可以方便地在文本环境中传输和存储图像数据
+            String base64Image = Base64.getEncoder().encodeToString(imageBytes);
+
+            // 4. 返回结果
+            result.put("success", true);
+            result.put("qrCodeUrl", "data:image/png;base64," + base64Image);
+            result.put("expireTime", System.currentTimeMillis() + 3600000); // 1小时有效期
+        } catch (Exception e) {
+            result.put("success", false);
+            result.put("message", "生成二维码失败: " + e.getMessage());
+        }
+        return result;
+    }
+}
+class UserData {
+    private String userId;
+    private String name;
+    private long timestamp;
+
+    // getters and setters
+    public String getUserId() { return userId; }
+    public void setUserId(String userId) { this.userId = userId; }
+    public String getName() { return name; }
+    public void setName(String name) { this.name = name; }
+    public long getTimestamp() { return timestamp; }
+    public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
+
+    // 转换为JSON字符串(简化实现,实际建议用JSON库)
+    public String toJsonString() {
+        return String.format("{\"userId\":\"%s\",\"name\":\"%s\",\"timestamp\":%d}",
+                userId, name, timestamp);
+    }
+}

+ 13 - 0
src/main/java/com/zhentao/service/AdvertisementService.java

@@ -0,0 +1,13 @@
+package com.zhentao.service;
+
+import com.zhentao.domain.Advertisement;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 86183
+* @description 针对表【Advertisement(广告表)】的数据库操作Service
+* @createDate 2025-05-20 22:07:18
+*/
+public interface AdvertisementService extends IService<Advertisement> {
+
+}

+ 83 - 0
src/main/java/com/zhentao/service/FaceEngineService.java

@@ -0,0 +1,83 @@
+package com.zhentao.service;
+
+import com.arcsoft.face.toolkit.ImageInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+public interface FaceEngineService {
+
+    /**
+     * 检测图片是否为人像
+     *
+     * @param imageInfo 图像对象
+     * @return true:人像,false:非人像
+     */
+//    boolean checkIsPortrait(ImageInfo imageInfo);
+
+    /**
+     * 检测图片是否为人像
+     *
+     * @param imageData 图像二进制数据
+     * @return true:人像,false:非人像
+     */
+//    boolean checkIsPortrait(byte[] imageData);
+
+    /**
+     * 检测上传的MultipartFile是否为人像
+     *
+     * @param multipartFile 上传的文件
+     * @return true:人像,false:非人像
+     */
+//    boolean checkIsPortrait(MultipartFile multipartFile);
+
+    /**
+     * 检测文件是否为人像
+     *
+     * @param file 文件对象
+     * @return true:人像,false:非人像
+     */
+//    boolean checkIsPortrait(File file);
+
+    /**
+     * 销毁引擎,释放资源
+     */
+    void destroyEngine();
+
+
+    boolean checkIsPortrait(ImageInfo imageInfo);
+    boolean checkIsPortrait(byte[] imageData);
+    boolean checkIsPortrait(MultipartFile multipartFile);
+    boolean checkIsPortrait(File file);
+
+
+
+        /**
+         * 提取人脸特征
+         * @param imageInfo 图像对象
+         * @return 人脸特征字节数组,如果未检测到人脸则返回 null
+         */
+        byte[] extractFaceFeature(ImageInfo imageInfo);
+
+        /**
+         * 比较两个人脸特征的相似度
+         * @param feature1 第一个人脸特征字节数组
+         * @param feature2 第二个人脸特征字节数组
+         * @return 相似度得分
+         */
+        float compareFaceFeature(byte[] feature1, byte[] feature2);
+
+        /**
+         * 检查上传的图片中的人脸是否存在于图片库中
+         * @param multipartFile 上传的文件
+         * @param galleryPath 图片库的路径
+         * @param threshold 相似度阈值
+         * @return true: 存在,false: 不存在
+         */
+
+    // 添加新方法定义
+    boolean checkFaceExistsInGallery(MultipartFile multipartFile, String galleryPath, float threshold);
+
+}

+ 13 - 0
src/main/java/com/zhentao/service/FaceFeatureService.java

@@ -0,0 +1,13 @@
+package com.zhentao.service;
+
+import com.zhentao.domain.FaceFeature;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author Lenovo
+* @description 针对表【face_feature(人脸特征表)】的数据库操作Service
+* @createDate 2025-05-26 11:53:34
+*/
+public interface FaceFeatureService extends IService<FaceFeature> {
+
+}

+ 4 - 0
src/main/java/com/zhentao/service/PropsService.java

@@ -0,0 +1,4 @@
+package com.zhentao.service;
+
+public interface PropsService {
+}

+ 30 - 0
src/main/java/com/zhentao/service/UserLoginService.java

@@ -0,0 +1,30 @@
+package com.zhentao.service;
+
+import com.zhentao.domain.UserLogin;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.dto.user.*;
+import com.zhentao.vo.Result;
+import org.apache.tomcat.jni.User;
+
+import java.io.InputStream;
+
+/**
+* @author lenovo
+* @description 针对表【user_login(用户)】的数据库操作Service
+* @createDate 2025-05-16 18:48:43
+*/
+public interface UserLoginService extends IService<UserLogin> {
+
+    //注册
+    Result  register(UserRegister userRegister);
+    //验证码
+    Result note(NoteDto noteDto);
+
+    //手机号登录
+    Result login(UserLoginDto userLoginDto);
+
+    //账号密码登录
+    Result UserPassLogin(UserPassDto userPassDto);
+//    忘记密码
+    Result ForgetPass(ForgetPassDto forgetPassDto);
+}

+ 9 - 0
src/main/java/com/zhentao/service/WeChatLogin.java

@@ -0,0 +1,9 @@
+package com.zhentao.service;
+
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.vo.Result;
+
+public interface WeChatLogin {
+    //微信登录
+    Result WeChatLogin(WeChatMode weChatMode);
+}

+ 22 - 0
src/main/java/com/zhentao/service/impl/AdvertisementServiceImpl.java

@@ -0,0 +1,22 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.domain.Advertisement;
+import com.zhentao.service.AdvertisementService;
+import com.zhentao.mapper.AdvertisementMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 86183
+* @description 针对表【Advertisement(广告表)】的数据库操作Service实现
+* @createDate 2025-05-20 22:07:18
+*/
+@Service
+public class AdvertisementServiceImpl extends ServiceImpl<AdvertisementMapper, Advertisement>
+    implements AdvertisementService{
+
+}
+
+
+
+

+ 239 - 0
src/main/java/com/zhentao/service/impl/FaceEngineServiceImpl.java

@@ -0,0 +1,239 @@
+package com.zhentao.service.impl;
+
+import com.arcsoft.face.*;
+import com.arcsoft.face.enums.DetectMode;
+import com.arcsoft.face.enums.DetectOrient;
+import com.arcsoft.face.enums.ErrorInfo;
+import com.arcsoft.face.enums.ImageFormat;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
+import com.zhentao.service.FaceEngineService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class FaceEngineServiceImpl implements FaceEngineService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(FaceEngineServiceImpl.class);
+
+    @Value("${arcsoft.appid}")
+    private String appid;
+
+    @Value("${arcsoft.sdkKey}")
+    private String sdkKey;
+
+    @Value("${arcsoft.libPath}")
+    private String libPath;
+
+    private FaceEngine faceEngine;
+
+    @PostConstruct
+    public void init() {
+        // 激活并且初始化引擎
+        faceEngine = new FaceEngine(libPath);
+        int activeCode = faceEngine.activeOnline(appid, sdkKey);
+        if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            LOGGER.error("引擎激活失败");
+            throw new RuntimeException("引擎激活失败");
+        }
+
+        // 引擎配置
+        EngineConfiguration engineConfiguration = new EngineConfiguration();
+        // IMAGE检测模式,用于处理单张的图像数据
+        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+        // 人脸检测角度,全角度
+        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
+
+        // 功能配置
+        FunctionConfiguration functionConfiguration = new FunctionConfiguration();
+        functionConfiguration.setSupportAge(true);
+        functionConfiguration.setSupportFace3dAngle(true);
+        functionConfiguration.setSupportFaceDetect(true);
+        functionConfiguration.setSupportFaceRecognition(true);
+        functionConfiguration.setSupportGender(true);
+        functionConfiguration.setSupportLiveness(true);
+        functionConfiguration.setSupportIRLiveness(true);
+        engineConfiguration.setFunctionConfiguration(functionConfiguration);
+
+        // 初始化引擎
+        int initCode = faceEngine.init(engineConfiguration);
+
+        if (initCode != ErrorInfo.MOK.getValue()) {
+            LOGGER.error("初始化引擎出错!");
+            throw new RuntimeException("初始化引擎出错!");
+        }
+    }
+
+    @Override
+    public boolean checkIsPortrait(ImageInfo imageInfo) {
+        // 定义人脸列表
+        List<FaceInfo> faceInfoList = new ArrayList<>();
+        int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList);
+        if (errorCode != ErrorInfo.MOK.getValue()) {
+            LOGGER.error("人脸检测失败,错误码: {}", errorCode);
+            return false;
+        }
+        return !faceInfoList.isEmpty();
+    }
+
+    @Override
+    public boolean checkIsPortrait(byte[] imageData) {
+        return this.checkIsPortrait(ImageFactory.getRGBData(imageData));
+    }
+
+    @Override
+    public boolean checkIsPortrait(MultipartFile multipartFile) {
+        try {
+            return this.checkIsPortrait(ImageFactory.getRGBData(multipartFile.getBytes()));
+        } catch (Exception e) {
+            LOGGER.error("处理MultipartFile时出错", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean checkIsPortrait(File file) {
+        try {
+            return this.checkIsPortrait(ImageFactory.getRGBData(file));
+        } catch (Exception e) {
+            LOGGER.error("处理文件时出错", e);
+            return false;
+        }
+    }
+
+    @Override
+    @PreDestroy
+    public void destroyEngine() {
+        if (faceEngine != null) {
+            faceEngine.unInit();
+            faceEngine = null;
+            LOGGER.info("人脸引擎已成功释放");
+        }
+    }
+
+    @Override
+    public byte[] extractFaceFeature(ImageInfo imageInfo) {
+        List<FaceInfo> faceInfoList = new ArrayList<>();
+        int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList);
+        if (errorCode != ErrorInfo.MOK.getValue() || faceInfoList.isEmpty()) {
+            LOGGER.error("人脸检测失败,错误码: {}", errorCode);
+            return null;
+        }
+        com.arcsoft.face.FaceFeature faceFeature =new com.arcsoft.face.FaceFeature();
+        errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList.get(0), faceFeature);
+        if (errorCode != ErrorInfo.MOK.getValue()) {
+            LOGGER.error("人脸特征提取失败,错误码: {}", errorCode);
+            return null;
+        }
+        return faceFeature.getFeatureData();
+    }
+
+    @Override
+    public float compareFaceFeature(byte[] feature1, byte[] feature2) {
+        com.arcsoft.face.FaceFeature faceFeature1 = new com.arcsoft.face.FaceFeature(feature1);
+        com.arcsoft.face.FaceFeature faceFeature2 = new FaceFeature(feature2);
+        FaceSimilar faceSimilar = new FaceSimilar();
+        int errorCode = faceEngine.compareFaceFeature(faceFeature1, faceFeature2, faceSimilar);
+        if (errorCode != ErrorInfo.MOK.getValue()) {
+            LOGGER.error("人脸特征比较失败,错误码: {}", errorCode);
+            return 0.0f;
+        }
+        return faceSimilar.getScore();
+    }
+
+    @Override
+    public boolean checkFaceExistsInGallery(MultipartFile multipartFile, String galleryPath, float threshold) {
+        try {
+            // 处理上传的图片
+            ImageInfo uploadImageInfo = ImageFactory.getRGBData(multipartFile.getBytes());
+            List<FaceInfo> uploadFaceInfoList = new ArrayList<>();
+            int errorCode = faceEngine.detectFaces(uploadImageInfo.getImageData(),
+                    uploadImageInfo.getWidth(),
+                    uploadImageInfo.getHeight(),
+                    ImageFormat.CP_PAF_BGR24,
+                    uploadFaceInfoList);
+            if (errorCode != ErrorInfo.MOK.getValue() || uploadFaceInfoList.isEmpty()) {
+                LOGGER.error("上传图片人脸检测失败,错误码: {}", errorCode);
+                return false;
+            }
+
+            // 提取上传图片的人脸特征
+            FaceFeature uploadFaceFeature = new FaceFeature();
+            errorCode = faceEngine.extractFaceFeature(uploadImageInfo.getImageData(),
+                    uploadImageInfo.getWidth(),
+                    uploadImageInfo.getHeight(),
+                    ImageFormat.CP_PAF_BGR24,
+                    uploadFaceInfoList.get(0),
+                    uploadFaceFeature);
+            if (errorCode != ErrorInfo.MOK.getValue()) {
+                LOGGER.error("上传图片人脸特征提取失败,错误码: {}", errorCode);
+                return false;
+            }
+
+            // 处理图片库中的图片
+            File galleryDir = new File(galleryPath);
+            if (!galleryDir.exists() || !galleryDir.isDirectory()) {
+                LOGGER.error("图片库路径不存在或不是一个目录");
+                return false;
+            }
+
+            File[] galleryFiles = galleryDir.listFiles();
+            if (galleryFiles != null) {
+                for (File galleryFile : galleryFiles) {
+                    // 从文件中获取图像数据
+                    ImageInfo galleryImageInfo = ImageFactory.getRGBData(galleryFile);
+                    List<FaceInfo> galleryFaceInfoList = new ArrayList<>();
+                    errorCode = faceEngine.detectFaces(galleryImageInfo.getImageData(),
+                            galleryImageInfo.getWidth(),
+                            galleryImageInfo.getHeight(),
+                            ImageFormat.CP_PAF_BGR24,
+                            galleryFaceInfoList);
+                    if (errorCode != ErrorInfo.MOK.getValue() || galleryFaceInfoList.isEmpty()) {
+                        LOGGER.error("图片库图片人脸检测失败,错误码: {}", errorCode);
+                        continue;
+                    }
+
+                    // 提取图片库中图片的人脸特征
+                    FaceFeature galleryFaceFeature = new FaceFeature();
+                    errorCode = faceEngine.extractFaceFeature(galleryImageInfo.getImageData(),
+                            galleryImageInfo.getWidth(),
+                            galleryImageInfo.getHeight(),
+                            ImageFormat.CP_PAF_BGR24,
+                            galleryFaceInfoList.get(0),
+                            galleryFaceFeature);
+                    if (errorCode != ErrorInfo.MOK.getValue()) {
+                        LOGGER.error("图片库图片人脸特征提取失败,错误码: {}", errorCode);
+                        continue;
+                    }
+
+                    // 比较人脸特征
+                    FaceSimilar faceSimilar = new FaceSimilar();
+                    errorCode = faceEngine.compareFaceFeature(uploadFaceFeature, galleryFaceFeature, faceSimilar);
+                    if (errorCode != ErrorInfo.MOK.getValue()) {
+                        LOGGER.error("人脸特征比较失败,错误码: {}", errorCode);
+                        continue;
+                    }
+
+                    // 如果相似度超过阈值,返回true
+                    if (faceSimilar.getScore() >= threshold) {
+                        return true;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.error("人脸识别过程中出现异常", e);
+        }
+        return false;
+    }
+}

+ 22 - 0
src/main/java/com/zhentao/service/impl/FaceFeatureServiceImpl.java

@@ -0,0 +1,22 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.domain.FaceFeature;
+import com.zhentao.service.FaceFeatureService;
+import com.zhentao.mapper.FaceFeatureMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author Lenovo
+* @description 针对表【face_feature(人脸特征表)】的数据库操作Service实现
+* @createDate 2025-05-26 11:53:34
+*/
+@Service
+public class FaceFeatureServiceImpl extends ServiceImpl<FaceFeatureMapper, FaceFeature>
+    implements FaceFeatureService{
+
+}
+
+
+
+

+ 267 - 0
src/main/java/com/zhentao/service/impl/UserLoginServiceImpl.java

@@ -0,0 +1,267 @@
+package com.zhentao.service.impl;
+
+import cn.hutool.core.util.IdUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.domain.UserLogin;
+import com.zhentao.dto.user.*;
+import com.zhentao.enums.ApiServerException;
+import com.zhentao.exception.AsynException;
+import com.zhentao.service.UserLoginService;
+import com.zhentao.mapper.UserLoginMapper;
+import com.zhentao.tool.TokenUtils;
+import com.zhentao.vo.Result;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.util.DigestUtils;
+
+
+import java.io.InputStream;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+* @author lenovo
+* @description 针对表【user_login(用户)】的数据库操作Service实现
+* @createDate 2025-05-16 18:48:43
+*/
+@Service
+public class UserLoginServiceImpl extends ServiceImpl<UserLoginMapper, UserLogin>
+    implements UserLoginService{
+
+    @Autowired
+    private UserLoginMapper userLoginMapper;
+    @Autowired
+    private RedissonClient redissonClient;
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    //注册
+    @Override
+    public Result register(UserRegister userRegister) {
+        //打印用户注册的信息
+        System.err.println(userRegister);
+        //使用redisson客户端获取分布式锁,确保并发情况下用户注册的安全性
+        RLock lock = redissonClient.getLock(userRegister.getPhone() + userRegister.getPassword());
+        try {
+            boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS);
+
+            if(b){
+                //用来判断验证码是否正确
+                String s = stringRedisTemplate.opsForValue().get(userRegister.getPhone());
+                System.err.println("redis取出来的验证码"+s);
+
+                //验证码不匹配就抛出异常
+                if(!s.equals(userRegister.getCode())){
+                    throw new AsynException(ApiServerException.NOTE_ERROR);
+                }
+                //根据手机号查询信息
+                QueryWrapper<UserLogin> queryWrapper=new QueryWrapper<>();
+                queryWrapper.eq("user_mobile",userRegister.getPhone());
+                UserLogin one = this.getOne(queryWrapper);
+
+                if(one==null){
+                    //新用户注册的流程
+                    UserLogin userLogin=new UserLogin();
+                    userLogin.setUserMobile(userRegister.getPhone());
+                    userLogin.setUserUsername(userRegister.getUsername());
+                    //随机字符串
+                    String uuid = String.valueOf(UUID.randomUUID());
+                    userLogin.setSalt(uuid);
+
+                    //md5加密
+                    String s1 = DigestUtils.md5DigestAsHex((uuid + userRegister.getPassword()).getBytes());
+                    userLogin.setUserPassword(s1);
+
+                    //生成唯一Id
+                    long l = IdUtil.getSnowflake(1, 1).nextId();
+                    //进行注册
+                    boolean save = this.save(userLogin);
+                    if(save){
+                        return Result.OK(save,"注册成功");
+                    }else{
+                        return Result.ERR(save,"注册失败");
+                    }
+                }else{
+                    //老用户更新信息流程
+                    one.setUserUsername(userRegister.getUsername());
+                    //随机字符串
+                    String uuid = String.valueOf(UUID.randomUUID());
+                    one.setSalt(uuid);
+                    //md5加密
+                    String s1 = DigestUtils.md5DigestAsHex((uuid + userRegister.getPassword()).getBytes());
+                    one.setUserPassword(s1);
+
+                    //进行更新
+                    boolean b1 = this.updateById(one);
+                    if(b1){
+                        return Result.OK(b1,"注册成功");
+                    }else{
+                        return Result.ERR(b1,"注册失败");
+                    }
+                }
+            }
+
+        }catch (InterruptedException e){
+            Thread.currentThread().interrupt();
+        }finally {
+            //释放锁
+            lock.unlock();
+        }
+        return null;
+    }
+
+
+    //验证码
+    @Override
+    public Result note(NoteDto noteDto) {
+        //随机生成六位数
+        int randomSixDigit=100000 + (int)(Math.random() * 900000);
+        System.err.println("手机号:"+noteDto.getPhone());
+        System.err.println("验证码:"+randomSixDigit);
+        stringRedisTemplate.opsForValue().set(noteDto.getPhone(),randomSixDigit+"");
+
+        return Result.OK(randomSixDigit,"发送成功");
+    }
+    //登录
+    /**
+     * 用户登录方法
+     * 使用Redis分布式锁来防止并发登录
+     * @param userLoginDto 用户登录信息,包含手机号和验证码
+     * @return 登录结果,包括token和提示信息
+     */
+    @Override
+    public Result login(UserLoginDto userLoginDto) {
+        // 获取Redis锁,锁的键为用户手机号,防止并发登录
+        RLock lock = redissonClient.getLock(userLoginDto.getPhone() + "phone");
+        try {
+            // 尝试获取锁,等待时间10秒,锁的过期时间为20秒
+            boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS);
+            if (b) {
+                // 打印用户登录信息,用于调试
+                System.err.println(userLoginDto);
+                // 从Redis中获取验证码
+                String s = stringRedisTemplate.opsForValue().get(userLoginDto.getPhone());
+                // 打印从Redis中获取的验证码,用于调试
+                System.err.println("redis取出来的验证码" + s);
+                // 验证码不匹配则抛出异常
+                if (!s.equals(userLoginDto.getCode())) {
+                    throw new AsynException(ApiServerException.NOTE_ERROR);
+                }
+                try {
+                    // 查询数据库中是否存在该用户
+                    QueryWrapper<UserLogin> queryWrapper = new QueryWrapper<>();
+                    queryWrapper.eq("user_mobile", userLoginDto.getPhone());
+                    UserLogin one = this.getOne(queryWrapper);
+                    // 生成JWT token
+                    String token = TokenUtils.createJwtToken(one.getId() + "");
+                    // 返回登录成功结果,包含token
+                    return Result.OK(token, "登录成功");
+                } catch (NullPointerException e) {
+                    // 用户不存在时返回错误结果
+                    return Result.ERR("登录失败", "用户不存在");
+                }
+            }
+        } catch (InterruptedException e) {
+            // 中断当前线程,重新抛出自定义异常
+            Thread.currentThread().interrupt();
+            throw new AsynException(ApiServerException.NOTE_ERROR);
+        } finally {
+            // 释放锁
+            lock.unlock();
+        }
+        return null;
+    }
+    //账号密码登录
+    /**
+     * 使用用户名和密码进行用户登录的方法
+     * 该方法实现了用户认证和JWT令牌的生成
+     *
+     * @param userPassDto 包含用户名和密码的DTO对象
+     * @return 登录结果,包括登录状态和JWT令牌
+     */
+    @Override
+    public Result UserPassLogin(UserPassDto userPassDto) {
+        // 获取Redisson客户端的锁对象,用于处理并发登录请求
+        RLock lock = redissonClient.getLock(userPassDto.getUsername());
+        try {
+            // 尝试获取锁,设置等待和持有时间
+            boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS);
+            if (b){
+                // 查询用户信息,根据用户名
+                QueryWrapper<UserLogin> queryWrapper = new QueryWrapper<>();
+                queryWrapper.eq("user_username",userPassDto.getUsername());
+                UserLogin one = this.getOne(queryWrapper);
+                // 如果用户不存在,抛出异常
+                if (one==null){
+                    throw new AsynException(ApiServerException.NULL_USERNAME);
+                }
+                // 获取用户盐值,用于密码加密
+                String salt = one.getSalt();
+                // 加密用户输入的密码,并与数据库中的密码进行比较
+                String s = DigestUtils.md5DigestAsHex((salt + userPassDto.getPassword()).getBytes());
+                if (!s.equals(one.getUserPassword())){
+                    throw new AsynException(ApiServerException.NULL_PASSWORD);
+                }
+                // 生成JWT令牌
+                String jwtToken = TokenUtils.createJwtToken(one.getId()+"");
+                // 返回登录成功结果和JWT令牌
+                return Result.OK("登录成功",jwtToken);
+            }else {
+                // 如果获取锁超时,返回错误信息
+                return Result.ERR("获取锁超时",null);
+            }
+        }catch (InterruptedException e){
+            // 如果线程被中断,恢复中断状态,并返回错误信息
+            Thread.currentThread().interrupt();
+            return Result.ERR("线程被中断",null);
+        }finally {
+            // 释放锁
+            lock.unlock();
+        }
+    }
+//忘记密码
+    @Override
+    public Result ForgetPass(ForgetPassDto forgetPassDto) {
+        RLock lock = redissonClient.getLock(forgetPassDto.getPhone() + "Phone");
+        try {
+            boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS);
+            if (b) {
+                QueryWrapper<UserLogin> queryWrapper = new QueryWrapper<>();
+                queryWrapper.eq("user_mobile", forgetPassDto.getPhone());
+                UserLogin one = this.getOne(queryWrapper);
+                if (one == null) {
+                    return Result.ERR("用户不存在", null);
+                }
+                // 获取Redis中的验证码
+                String s = stringRedisTemplate.opsForValue().get(forgetPassDto.getPhone());
+                // 验证码不匹配则抛出异常
+                if (!s.equals(forgetPassDto.getCode())) {
+                    throw new AsynException(ApiServerException.NOTE_ERROR);
+                }
+                // 获取用户信息,根据手机号
+                String salt = one.getSalt();
+                String s1 = DigestUtils.md5DigestAsHex((salt + forgetPassDto.getPassword()).getBytes());
+                one.setUserPassword(s1);
+                boolean b1 = this.updateById(one);
+                if (b1){
+                    return Result.OK("修改成功", null);
+                }else {
+                    return Result.ERR("修改失败", null);
+                }
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+        return null;
+    }
+
+
+}
+
+
+
+

+ 88 - 0
src/main/java/com/zhentao/service/impl/WeChatLoginimpl.java

@@ -0,0 +1,88 @@
+package com.zhentao.service.impl;
+
+import cn.hutool.core.util.IdUtil;
+import com.zhentao.domain.UserLogin;
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.dto.user.WeChatSessionModel;
+import com.zhentao.service.UserLoginService;
+import com.zhentao.service.WeChatLogin;
+import com.zhentao.tool.TokenUtils;
+import com.zhentao.tool.WechatLoginUtil;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+@Service
+public class WeChatLoginimpl implements WeChatLogin {
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Autowired
+    private UserLoginService userLoginService;
+    //微信登录
+    @Override
+    public Result WeChatLogin(WeChatMode weChatMode) {
+        try {
+            // 获取微信会话信息
+            WeChatSessionModel authInfo = WechatLoginUtil.getAuthInfo(weChatMode.getCode());
+            if(authInfo.getErrcode() == null) {
+                // 生成用户令牌
+                String token = generateToken(authInfo.getOpenid());
+
+                // 将用户信息存储到Redis
+                stringRedisTemplate.opsForValue().set(authInfo.getOpenid(),authInfo.toString());
+
+                // 创建包含token和用户信息的Map
+                HashMap<String,Object> map=new HashMap<>();
+                map.put("token",token);
+                map.put("openid",authInfo);
+
+                // 创建用户登录对象并设置属性
+                UserLogin userLogin=new UserLogin();
+                long l = IdUtil.getSnowflake(1, 1).nextId();
+                userLogin.setId(l);
+                userLogin.setOpenId(authInfo.getOpenid());
+                userLogin.setSessionKey(authInfo.getSession_key());
+                userLogin.setNickName(weChatMode.getWeChatLoginDto().getNickName());
+                userLogin.setAvatar(weChatMode.getWeChatLoginDto().getAvatarUrl());
+                userLogin.setGender(weChatMode.getWeChatLoginDto().getGender());
+
+                // 保存用户登录信息到数据库
+                userLoginService.save(userLogin);
+
+                // 返回登录成功结果
+                return Result.OK(map,"登录成功");
+            } else {
+                // 返回登录失败结果
+                return Result.ERR("登录失败",authInfo.getErrmsg());
+            }
+        } catch (IOException e) {
+            // 打印异常信息并返回登录失败结果
+            e.printStackTrace();
+            return Result.ERR("登录失败",null);
+        }
+
+    }
+
+
+
+
+
+    /**
+     * 生成用户认证令牌
+     *
+     * 本方法通过调用TokenUtils工具类的createJwtToken方法,为给定的用户openid生成一个JWT令牌
+     * 这个令牌可以用于后续的用户身份验证和授权操作
+     *
+     * @param openid 用户的唯一标识符,用于标识请求的用户
+     * @return 生成的JWT令牌字符串
+     */
+    private String generateToken(String openid){
+        String token = TokenUtils.createJwtToken(openid);
+        return token;
+    }
+}

+ 92 - 0
src/main/java/com/zhentao/tool/TokenUtils.java

@@ -0,0 +1,92 @@
+package com.zhentao.tool;
+
+import com.zhentao.enums.ApiServerException;
+import com.zhentao.exception.AsynException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
+import java.security.Key;
+import java.util.Date;
+
+public class TokenUtils {
+
+    public static final String SECRET = "cjyfutu1688";
+
+    public static String createJwtToken(String id) {
+        String issuer = "www.futureading.com";
+        String subject = "65532781@qq.com";
+        long ttlMillis = 3600000; // 例如,设置token有效期为1小时
+        return createJwtToken(id, issuer, subject, ttlMillis);
+    }
+
+    public static String createJwtToken(String id, String issuer, String subject, long ttlMillis) {
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
+        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
+
+        JwtBuilder builder = Jwts.builder().setId(id)
+                .setIssuedAt(now)
+                .setSubject(subject)
+                .setIssuer(issuer)
+                .signWith(signatureAlgorithm, signingKey);
+
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            builder.setExpiration(exp);
+        }
+
+        return builder.compact();
+    }
+
+    public static Claims parseJWT(String jwt) {
+        Claims claims = Jwts.parser()
+                .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET))
+                .parseClaimsJws(jwt).getBody();
+        return claims;
+    }
+
+    public static Long getUserId(String token) {
+        Claims claims = null;
+        try {
+            claims = parseJWT(token);
+        } catch (Exception e) {
+            throw new AsynException(ApiServerException.TOKEN_ERR);
+        }
+
+        if (null == claims) {
+            throw new AsynException(ApiServerException.TOKEN_ERR);
+        }
+        String id = claims.getId();
+        Long userId = Long.valueOf(id);
+
+        return userId;
+    }
+
+    /**
+     * 检查token是否过期
+     * @param jwt 要检查的token
+     * @return 如果token过期返回true,否则返回false
+     */
+    public static boolean isTokenExpired(String jwt) {
+        Claims claims = parseJWT(jwt);
+        Date exp = claims.getExpiration();
+        if (exp == null) {
+            // 如果没有设置过期时间,可以认为token不过期
+            return false;
+        }
+        return exp.before(new Date()); // 比较当前时间和过期时间
+    }
+
+    public static void main(String[] args) {
+        String token = TokenUtils.createJwtToken("admin");
+        System.out.println("Token: " + token);
+        System.out.println("Is expired: " + TokenUtils.isTokenExpired(token));
+    }
+}

+ 83 - 0
src/main/java/com/zhentao/tool/WechatLoginUtil.java

@@ -0,0 +1,83 @@
+package com.zhentao.tool;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.dto.user.WeChatSessionModel;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+public class WechatLoginUtil {
+
+    private static final String APP_ID = "wx97b71d70f5b2d51f"; // 替换为你的AppID
+    private static final String APP_SECRET = "b78d9bf60e17518475bc8e1d44fd9ad6"; // 替换为你的AppSecret
+    private static final String WECHAT_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
+
+    public static WeChatSessionModel getAuthInfo(String code) throws IOException {
+        // 构造微信登录接口的URL,包含必要的参数
+        String url = WECHAT_LOGIN_URL + "?appid=" + APP_ID + "&secret=" + APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
+
+        // 创建一个默认的HTTP客户端,用于发送HTTP请求
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+
+        // 创建一个HTTP GET请求对象,指定请求的URL
+        HttpGet httpGet = new HttpGet(url);
+
+        // 执行HTTP GET请求,获取微信服务器的响应
+        CloseableHttpResponse response = httpClient.execute(httpGet);
+
+        // 从响应中获取响应体内容,并将其转换为字符串
+        String jsonResponse = EntityUtils.toString(response.getEntity());
+        // 创建一个Jackson的ObjectMapper对象,用于处理JSON数据
+        ObjectMapper objectMapper = new ObjectMapper();
+
+        // 将微信返回的JSON字符串解析为WechatAuthResponse对象
+        // WechatAuthResponse是一个自定义的Java类,用于封装微信返回的用户认证信息
+        return objectMapper.readValue(jsonResponse, WeChatSessionModel.class);
+    }
+
+    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
+
+    public static String decryptPhoneNumber(String encryptedData, String sessionKey, String iv) throws Exception {
+        // Base64解码
+        byte[] encryptedDataBytes = Base64.getDecoder().decode(encryptedData);
+        byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey);
+        byte[] ivBytes = Base64.getDecoder().decode(iv);
+
+        // 设置AES密钥和初始化向量
+        SecretKeySpec secretKeySpec = new SecretKeySpec(sessionKeyBytes, "AES");
+        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
+
+        // 创建Cipher实例并初始化
+        Cipher cipher = Cipher.getInstance(ALGORITHM);
+        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
+
+        // 解密
+        byte[] decryptedBytes = cipher.doFinal(encryptedDataBytes);
+        // 将解密后的字节转换为字符串
+        return new String(decryptedBytes, StandardCharsets.UTF_8);
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+}

+ 22 - 0
src/main/java/com/zhentao/touristAttractions/controller/TickentinfoDtoController.java

@@ -0,0 +1,22 @@
+package com.zhentao.touristAttractions.controller;
+
+import com.zhentao.touristAttractions.dto.TickentinfoDto;
+import com.zhentao.touristAttractions.service.TicketinfoService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@RestController
+@RequestMapping("TickentinfoDto")
+public class TickentinfoDtoController {
+    @Autowired
+    private TicketinfoService service;
+//    查询出当前景区的一个门票信息
+    @PostMapping("findAll")
+    public Result findAll(@RequestBody TickentinfoDto dto){
+        return service.findAll(dto);
+    }
+}

+ 22 - 0
src/main/java/com/zhentao/touristAttractions/controller/TouristAttractionsController.java

@@ -0,0 +1,22 @@
+package com.zhentao.touristAttractions.controller;
+
+import com.zhentao.touristAttractions.dto.TouristattrcationDto;
+import com.zhentao.touristAttractions.service.TouristattractionsService;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("touristAttractions")
+public class TouristAttractionsController {
+    @Autowired
+    private TouristattractionsService service;
+//    查询所有的旅游景点
+    @RequestMapping("findAll")
+    public Result findAll(@RequestBody TouristattrcationDto dto) {
+        return service.findAll(dto);
+    }
+
+}

+ 66 - 0
src/main/java/com/zhentao/touristAttractions/domain/Ticketinfo.java

@@ -0,0 +1,66 @@
+package com.zhentao.touristAttractions.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import lombok.Data;
+
+/**
+ * 门票信息表
+ * @TableName TicketInfo
+ */
+@TableName(value ="TicketInfo")
+@Data
+public class Ticketinfo implements Serializable {
+    /**
+     * 主键ID,自增
+     */
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 景区ID
+     */
+    private Long tid;
+
+    /**
+     * 票种,如成人票、儿童票等
+     */
+    private String type;
+
+    /**
+     * 原价(单位:元)
+     */
+    private BigDecimal price;
+
+    /**
+     * 优惠价(单位:元)
+     */
+    private BigDecimal discountPrice;
+
+    /**
+     * 描述信息
+     */
+    private String description;
+
+    /**
+     * 已售数量
+     */
+    private Integer sales;
+
+    /**
+     * 身高限制(仅对儿童票)
+     */
+    private String heightLimit;
+
+    /**
+     * 年龄限制(仅对老人票)
+     */
+    private String ageLimit;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 75 - 0
src/main/java/com/zhentao/touristAttractions/domain/Touristattractions.java

@@ -0,0 +1,75 @@
+package com.zhentao.touristAttractions.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 旅游信息表
+ * @TableName TouristAttractions
+ */
+@TableName(value ="TouristAttractions")
+@Data
+public class Touristattractions implements Serializable {
+    /**
+     * 景区ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 景区名称
+     */
+    private String name;
+
+    /**
+     * 景区级别
+     */
+    private String level;
+
+    /**
+     * 用户评分
+     */
+    private BigDecimal rating;
+
+    /**
+     * 评论数量
+     */
+    private Integer reviewCount;
+
+    /**
+     * 距离(单位:公里)
+     */
+    private BigDecimal distanceKm;
+
+    /**
+     * 门票价格(单位:元)
+     */
+    private BigDecimal ticketPrice;
+
+    /**
+     * 销量
+     */
+    private Integer sales;
+
+    /**
+     * 景区图片URL
+     */
+    private String imageUrl;
+
+    /**
+     * 创建的时间
+     */
+    private Date createTime;
+//    开园时间
+    private Date startTime;
+//    地址
+    private String address;
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 10 - 0
src/main/java/com/zhentao/touristAttractions/dto/TickentinfoDto.java

@@ -0,0 +1,10 @@
+package com.zhentao.touristAttractions.dto;
+
+import lombok.Data;
+
+@Data
+public class TickentinfoDto {
+//    景区的id
+    private Long tourId;
+
+}

+ 9 - 0
src/main/java/com/zhentao/touristAttractions/dto/TouristattrcationDto.java

@@ -0,0 +1,9 @@
+package com.zhentao.touristAttractions.dto;
+
+import lombok.Data;
+
+@Data
+public class TouristattrcationDto {
+    private String address;
+    private String name;
+}

+ 18 - 0
src/main/java/com/zhentao/touristAttractions/mapper/TicketinfoMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.touristAttractions.mapper;
+
+import com.zhentao.touristAttractions.domain.Ticketinfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 86183
+* @description 针对表【TicketInfo(门票信息表)】的数据库操作Mapper
+* @createDate 2025-05-22 17:29:49
+* @Entity com.zhentao.touristAttractions.domain.Ticketinfo
+*/
+public interface TicketinfoMapper extends BaseMapper<Ticketinfo> {
+
+}
+
+
+
+

+ 18 - 0
src/main/java/com/zhentao/touristAttractions/mapper/TouristattractionsMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.touristAttractions.mapper;
+
+import com.zhentao.touristAttractions.domain.Touristattractions;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 86183
+* @description 针对表【TouristAttractions(旅游信息表)】的数据库操作Mapper
+* @createDate 2025-05-22 15:42:58
+* @Entity com.zhentao.touristAttractions.domain.Touristattractions
+*/
+public interface TouristattractionsMapper extends BaseMapper<Touristattractions> {
+
+}
+
+
+
+

+ 15 - 0
src/main/java/com/zhentao/touristAttractions/service/TicketinfoService.java

@@ -0,0 +1,15 @@
+package com.zhentao.touristAttractions.service;
+
+import com.zhentao.touristAttractions.domain.Ticketinfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.touristAttractions.dto.TickentinfoDto;
+import com.zhentao.vo.Result;
+
+/**
+* @author 86183
+* @description 针对表【TicketInfo(门票信息表)】的数据库操作Service
+* @createDate 2025-05-22 17:29:49
+*/
+public interface TicketinfoService extends IService<Ticketinfo> {
+    Result findAll(TickentinfoDto dto);
+}

+ 15 - 0
src/main/java/com/zhentao/touristAttractions/service/TouristattractionsService.java

@@ -0,0 +1,15 @@
+package com.zhentao.touristAttractions.service;
+
+import com.zhentao.touristAttractions.domain.Touristattractions;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.touristAttractions.dto.TouristattrcationDto;
+import com.zhentao.vo.Result;
+
+/**
+* @author 86183
+* @description 针对表【TouristAttractions(旅游信息表)】的数据库操作Service
+* @createDate 2025-05-22 15:42:58
+*/
+public interface TouristattractionsService extends IService<Touristattractions> {
+    Result findAll(TouristattrcationDto dto);
+}

+ 34 - 0
src/main/java/com/zhentao/touristAttractions/service/impl/TicketinfoServiceImpl.java

@@ -0,0 +1,34 @@
+package com.zhentao.touristAttractions.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.touristAttractions.domain.Ticketinfo;
+import com.zhentao.touristAttractions.dto.TickentinfoDto;
+import com.zhentao.touristAttractions.service.TicketinfoService;
+import com.zhentao.touristAttractions.mapper.TicketinfoMapper;
+import com.zhentao.vo.Result;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+* @author 86183
+* @description 针对表【TicketInfo(门票信息表)】的数据库操作Service实现
+* @createDate 2025-05-22 17:29:49
+*/
+@Service
+public class TicketinfoServiceImpl extends ServiceImpl<TicketinfoMapper, Ticketinfo>
+    implements TicketinfoService{
+
+    @Override
+    public Result findAll(TickentinfoDto dto) {
+        QueryWrapper<Ticketinfo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("tid",dto.getTourId());
+        List<Ticketinfo> list = this.list(queryWrapper);
+        return Result.OK(list,"查询成功");
+    }
+}
+
+
+
+

+ 36 - 0
src/main/java/com/zhentao/touristAttractions/service/impl/TouristattractionsServiceImpl.java

@@ -0,0 +1,36 @@
+package com.zhentao.touristAttractions.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.touristAttractions.domain.Touristattractions;
+import com.zhentao.touristAttractions.dto.TouristattrcationDto;
+import com.zhentao.touristAttractions.service.TouristattractionsService;
+import com.zhentao.touristAttractions.mapper.TouristattractionsMapper;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+* @author 86183
+* @description 针对表【TouristAttractions(旅游信息表)】的数据库操作Service实现
+* @createDate 2025-05-22 15:42:58
+*/
+@Service
+public class TouristattractionsServiceImpl extends ServiceImpl<TouristattractionsMapper, Touristattractions>
+    implements TouristattractionsService{
+    @Override
+    public Result findAll(TouristattrcationDto dto) {
+        QueryWrapper<Touristattractions> queryWrapper = new QueryWrapper<>();
+        queryWrapper.like("address",dto.getAddress());
+        queryWrapper.like("name",dto.getName());
+        queryWrapper.orderByDesc("rating");
+        List<Touristattractions> list = this.list(queryWrapper);
+        return Result.OK(list,"查询成功");
+    }
+}
+
+
+
+

+ 111 - 0
src/main/java/com/zhentao/utils/FaceEngineService.java

@@ -0,0 +1,111 @@
+package com.zhentao.utils;
+
+import com.arcsoft.face.EngineConfiguration;
+import com.arcsoft.face.FaceEngine;
+import com.arcsoft.face.FaceInfo;
+import com.arcsoft.face.FunctionConfiguration;
+import com.arcsoft.face.enums.DetectMode;
+import com.arcsoft.face.enums.DetectOrient;
+import com.arcsoft.face.enums.ErrorInfo;
+import com.arcsoft.face.enums.ImageFormat;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.PostConstruct;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class FaceEngineService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(FaceEngineService.class);
+
+    @Value("${arcsoft.appid}")
+    private String appid;
+
+    @Value("${arcsoft.sdkKey}")
+    private String sdkKey;
+
+    @Value("${arcsoft.libPath}")
+    private String libPath;
+
+    private FaceEngine faceEngine;
+
+    @PostConstruct
+    public void init() {
+        // 激活并且初始化引擎
+        FaceEngine faceEngine = new FaceEngine(libPath);
+        int activeCode = faceEngine.activeOnline(appid, sdkKey);
+        if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            LOGGER.error("引擎激活失败");
+            throw new RuntimeException("引擎激活失败");
+        }
+
+        //引擎配置
+        EngineConfiguration engineConfiguration = new EngineConfiguration();
+        //IMAGE检测模式,用于处理单张的图像数据
+        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+        //人脸检测角度,全角度
+        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
+
+        //功能配置
+        FunctionConfiguration functionConfiguration = new FunctionConfiguration();
+        functionConfiguration.setSupportAge(true);
+        functionConfiguration.setSupportFace3dAngle(true);
+        functionConfiguration.setSupportFaceDetect(true);
+        functionConfiguration.setSupportFaceRecognition(true);
+        functionConfiguration.setSupportGender(true);
+        functionConfiguration.setSupportLiveness(true);
+        functionConfiguration.setSupportIRLiveness(true);
+        engineConfiguration.setFunctionConfiguration(functionConfiguration);
+
+        //初始化引擎
+        int initCode = faceEngine.init(engineConfiguration);
+
+        if (initCode != ErrorInfo.MOK.getValue()) {
+            LOGGER.error("初始化引擎出错!");
+            throw new RuntimeException("初始化引擎出错!");
+        }
+
+        this.faceEngine = faceEngine;
+    }
+
+    /**
+     * 检测图片是否为人像
+     *
+     * @param imageInfo 图像对象
+     * @return true:人像,false:非人像
+     */
+    public boolean checkIsPortrait(ImageInfo imageInfo) {
+        // 定义人脸列表
+        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
+        faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList);
+        return !faceInfoList.isEmpty();
+    }
+
+    public boolean checkIsPortrait(byte[] imageData) {
+        return this.checkIsPortrait(ImageFactory.getRGBData(imageData));
+    }
+    public boolean checkIsPortrait(MultipartFile multipartFile) {
+        try{
+            return this.checkIsPortrait(ImageFactory.getRGBData(multipartFile.getBytes()));
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return false;
+
+    }
+
+    public boolean checkIsPortrait(File file) {
+        return this.checkIsPortrait(ImageFactory.getRGBData(file));
+    }
+
+
+
+}

+ 173 - 0
src/main/java/com/zhentao/utils/FaceEngineTest.java

@@ -0,0 +1,173 @@
+//package com.zhentao.utils;
+//
+//import com.arcsoft.face.*;
+//import com.arcsoft.face.enums.*;
+//import com.arcsoft.face.toolkit.ImageInfo;
+//
+//import java.io.File;
+//import java.util.ArrayList;
+//import java.util.List;
+//
+//import com.arcsoft.face.toolkit.ImageInfoEx;
+//
+//import static com.arcsoft.face.toolkit.ImageFactory.getGrayData;
+//import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
+//
+//
+//public class FaceEngineTest {
+//
+//
+//    public static void main(String[] args) {
+//
+//        //从官网获取
+//        String appId = "8KN5ZPgaAkgmRbEJXQbep2euFZ5h888p5bP3wUGGJnTp";
+//        String sdkKey = "HzLDheVLZBFWQZaK1YZhcUfG5RECQfabYmBSdEiyQP5H";
+//
+//
+//        FaceEngine faceEngine = new FaceEngine("E:\\专高五\\旅游\\tourismapp\\libs\\WIN64");
+//        //激活引擎
+//        int errorCode = faceEngine.activeOnline(appId, sdkKey);
+//
+//        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+//            System.out.println("引擎激活失败");
+//        }
+//
+//
+//        ActiveFileInfo activeFileInfo=new ActiveFileInfo();
+//        errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
+//        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+//            System.out.println("获取激活文件信息失败");
+//        }
+//
+//        //引擎配置
+//        EngineConfiguration engineConfiguration = new EngineConfiguration();
+//        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+//        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
+//        engineConfiguration.setDetectFaceMaxNum(10);
+//        engineConfiguration.setDetectFaceScaleVal(16);
+//        //功能配置
+//        FunctionConfiguration functionConfiguration = new FunctionConfiguration();
+//        functionConfiguration.setSupportAge(true);
+//        functionConfiguration.setSupportFace3dAngle(true);
+//        functionConfiguration.setSupportFaceDetect(true);
+//        functionConfiguration.setSupportFaceRecognition(true);
+//        functionConfiguration.setSupportGender(true);
+//        functionConfiguration.setSupportLiveness(true);
+//        functionConfiguration.setSupportIRLiveness(true);
+//        engineConfiguration.setFunctionConfiguration(functionConfiguration);
+//
+//
+//        //初始化引擎
+//        errorCode = faceEngine.init(engineConfiguration);
+//
+//        if (errorCode != ErrorInfo.MOK.getValue()) {
+//            System.out.println("初始化引擎失败");
+//        }
+//
+//
+//        //人脸检测
+//        ImageInfo imageInfo = getRGBData(new File("C:\\Users\\Lenovo\\Pictures\\mm\\OIP-C.jpg"));
+//        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
+//        errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
+//        System.out.println(faceInfoList);
+//
+//        //特征提取
+//        FaceFeature faceFeature = new FaceFeature();
+//        errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
+//        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
+//
+//        //人脸检测2
+//        ImageInfo imageInfo2 = getRGBData(new File("C:\\Users\\Lenovo\\Pictures\\mm\\OIP-C.jpg"));
+//        List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
+//        errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo2.getImageFormat(), faceInfoList2);
+//        System.out.println(faceInfoList2);
+//
+//        //特征提取2
+//        FaceFeature faceFeature2 = new FaceFeature();
+//        errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
+//        System.out.println("特征值大小:" + faceFeature2.getFeatureData().length);
+//
+//        //特征比对
+//        FaceFeature targetFaceFeature = new FaceFeature();
+//        targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
+//        FaceFeature sourceFaceFeature = new FaceFeature();
+//        sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
+//        FaceSimilar faceSimilar = new FaceSimilar();
+//
+//        errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
+//
+//        System.out.println("相似度:" + faceSimilar.getScore());
+//
+//
+//
+//        //设置活体测试
+//        errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
+//        //人脸属性检测
+//        FunctionConfiguration configuration = new FunctionConfiguration();
+//        configuration.setSupportAge(true);
+//        configuration.setSupportFace3dAngle(true);
+//        configuration.setSupportGender(true);
+//        configuration.setSupportLiveness(true);
+//        errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
+//
+//
+//        //性别检测
+//        List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
+//        errorCode = faceEngine.getGender(genderInfoList);
+//        System.out.println("性别:" + genderInfoList.get(0).getGender());
+//
+//        //年龄检测
+//        List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
+//        errorCode = faceEngine.getAge(ageInfoList);
+//        System.out.println("年龄:" + ageInfoList.get(0).getAge());
+//
+//        //3D信息检测
+//        List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
+//        errorCode = faceEngine.getFace3DAngle(face3DAngleList);
+//        System.out.println("3D角度:" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());
+//
+//        //活体检测
+//        List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
+//        errorCode = faceEngine.getLiveness(livenessInfoList);
+//        System.out.println("活体:" + livenessInfoList.get(0).getLiveness());
+//
+//
+//        //IR属性处理
+////        ImageInfo imageInfoGray = getGrayData(new File("d:\\IR_480p.jpg"));
+//        ImageInfo imageInfoGray = getGrayData(new File("C:\\Users\\Lenovo\\Pictures\\mm\\OIP-C.jpg"));
+//        List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
+//        errorCode = faceEngine.detectFaces(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray);
+//
+//        FunctionConfiguration configuration2 = new FunctionConfiguration();
+//        configuration2.setSupportIRLiveness(true);
+//        errorCode = faceEngine.processIr(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray, configuration2);
+//        //IR活体检测
+//        List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
+//        errorCode = faceEngine.getLivenessIr(irLivenessInfo);
+//        System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness());
+//
+//        ImageInfoEx imageInfoEx = new ImageInfoEx();
+//        imageInfoEx.setHeight(imageInfo.getHeight());
+//        imageInfoEx.setWidth(imageInfo.getWidth());
+//        imageInfoEx.setImageFormat(imageInfo.getImageFormat());
+//        imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
+//        imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
+//        List<FaceInfo> faceInfoList1 = new ArrayList<>();
+//        errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);
+//
+//        FunctionConfiguration fun = new FunctionConfiguration();
+//        fun.setSupportAge(true);
+//        errorCode = faceEngine.process(imageInfoEx, faceInfoList1, functionConfiguration);
+//        List<AgeInfo> ageInfoList1 = new ArrayList<>();
+//        int age = faceEngine.getAge(ageInfoList1);
+//        System.out.println("年龄:" + ageInfoList1.get(0).getAge());
+//
+//        FaceFeature feature = new FaceFeature();
+//        errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), feature);
+//
+//
+//        //引擎卸载
+//        errorCode = faceEngine.unInit();
+//
+//    }
+//}

+ 53 - 0
src/main/java/com/zhentao/utils/FcFileKit.java

@@ -0,0 +1,53 @@
+package com.zhentao.utils;
+
+import cn.hutool.core.img.Img;
+import cn.hutool.core.io.FileUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+public class FcFileKit {
+
+    /**
+     * 本地文件path转化为二进制文件
+     *
+     * @param imagePath 本地文件path
+     * @return 二进制文件
+     */
+    public static byte[] imagePathToBytes(String imagePath) {
+        try {
+             return FileUtil.readBytes(imagePath);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 远程文件Url转化为二进制文件
+     *
+     * @param imageUrl 文件Url
+     * @return 二进制文件
+     */
+    public static byte[] imageUrlToBytes(String imageUrl) {
+        try {
+            URL url = new URL(imageUrl);
+            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+                Img.from(url).write(outputStream); // 写文件
+                return outputStream.toByteArray();
+            } catch (Exception e) {
+                e.printStackTrace();
+                return null;
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+}
+

+ 76 - 0
src/main/java/com/zhentao/utils/WebServerConfig.java

@@ -0,0 +1,76 @@
+package com.zhentao.utils;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class WebServerConfig {
+
+    @Value("${server.port}")
+    private int httpsPort;
+
+    @Value("${server.http.port:8080}")
+    private int httpPort;
+
+    @Value("${server.ssl.key-store}")
+    private String keyStore;
+
+    @Value("${server.ssl.key-store-password}")
+    private String keyStorePassword;
+
+    @Value("${server.ssl.key-alias}")
+    private String keyAlias;
+
+    @Bean
+    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> customizer() {
+        return factory -> {
+            // 配置HTTPS连接器
+            Connector httpsConnector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
+            httpsConnector.setPort(httpsPort);
+            httpsConnector.setSecure(true);
+            httpsConnector.setScheme("https");
+
+            // 配置SSL
+            org.apache.coyote.http11.Http11NioProtocol protocol =
+                    (org.apache.coyote.http11.Http11NioProtocol) httpsConnector.getProtocolHandler();
+            protocol.setSSLEnabled(true);
+            protocol.setKeystoreFile(keyStore);
+            protocol.setKeystorePass(keyStorePassword);
+            protocol.setKeyAlias(keyAlias);
+
+            // 仅启用TLS 1.2和1.3
+            protocol.setSslProtocol("TLSv1.2+TLSv1.3");
+            protocol.setCiphers("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256," +
+                    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384," +
+                    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256," +
+                    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
+
+            factory.addAdditionalTomcatConnectors(httpsConnector);
+
+            // 配置HTTP到HTTPS的重定向
+            factory.addContextCustomizers(context -> {
+                SecurityConstraint securityConstraint = new SecurityConstraint();
+                securityConstraint.setUserConstraint("CONFIDENTIAL");
+                SecurityCollection collection = new SecurityCollection();
+                collection.addPattern("/*");
+                securityConstraint.addCollection(collection);
+                context.addConstraint(securityConstraint);
+            });
+
+            // 配置HTTP连接器(用于重定向)
+            Connector httpConnector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
+            httpConnector.setPort(httpPort);
+            httpConnector.setSecure(false);
+            httpConnector.setScheme("http");
+            httpConnector.setRedirectPort(httpsPort);
+            factory.addAdditionalTomcatConnectors(httpConnector);
+        };
+    }
+}

+ 17 - 0
src/main/java/com/zhentao/vo/PicUploadResult.java

@@ -0,0 +1,17 @@
+package com.zhentao.vo;
+
+import lombok.Data;
+
+@Data
+public class PicUploadResult {
+
+    // 文件唯一标识
+    private String uid;
+    // 文件名
+    private String name;
+    // 状态有:uploading done error removed
+    private String status;
+    // 服务端响应内容,如:'{"status": "success"}'
+    private String response;
+
+}

+ 38 - 0
src/main/java/com/zhentao/vo/Result.java

@@ -0,0 +1,38 @@
+package com.zhentao.vo;
+
+import lombok.Data;
+
+@Data
+public class Result {
+    private Integer code;
+    private Object data;
+    private String msg;
+
+
+    public static Result OK(Object data,String msg) {
+        Result result = new Result();
+        result.setCode(200);
+        result.setData(data);
+        result.setMsg(msg);
+        return result;
+    }
+
+
+    public static Result ERR(Object data,String msg) {
+        Result result = new Result();
+        result.setCode(400);
+        result.setData(data);
+        result.setMsg(msg);
+        return result;
+    }
+
+    public static Result error(Integer code,Object data){
+        Result result=new Result();
+        result.setCode(code);
+        result.setData(data);
+        return result;
+    }
+
+
+
+}

+ 57 - 0
src/main/resources/application.yml

@@ -0,0 +1,57 @@
+server:
+  port: 3333
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://47.110.46.22/lvYou?useSSL=false&serverTimezone=UTC
+    username: root
+    password: Fengjaijia0610
+  redis:
+    host: 47.110.46.22
+    port: 6379
+    database: 0
+## 人脸认证引擎配置
+#face-engine:
+#  # 应用id
+#  app-id: 8KN5ZPgaAkgmRbEJXQbep2euFZ5h888p5bP3wUGGJnTp
+#  # sdk密匙
+#  sdk-key: HzLDheVLZBFWQZaK1YZhcUfG5RECQfabYmBSdEiyQP5H
+#  # 人脸对比阀值(建议0.8)
+#  face-similar-score: 0.8
+#  # RGB活体检测阀值(建议0.5)
+#  rgb-threshold: 0.5
+#  # IR活体检测阀值(建议0.7)
+#  ir-threshold: 0.7
+
+mybatis-plus:
+  mapper-locations: classpath:mapper/*.xml
+  type-aliases-package: com.example.facerecognition.entity
+  global-config:
+    db-config:
+      id-type: auto
+
+arcsoft:
+  appId: 8KN5ZPgaAkgmRbEJXQbep2euFZ5h888p5bP3wUGGJnTp
+  sdkKey: HzLDheVLZBFWQZaK1YZhcUfG5RECQfabYmBSdEiyQP5H
+  libPath: E:\专高五\旅游\tourismapp\libs\WIN64
+
+
+aliyun:
+  oss:
+    endpoint: oss-cn-beijing.aliyuncs.com
+    accessKeyId: LTAI5tHMgiojdBfP8gysS1N4
+    accessKeySecret: h44T1gW5Dh4049fwzZM754C84I4sEf
+    bucketName: hchneko
+# application.yml
+
+
+#  aliyun.endpoint = http://oss-cn-beijing.aliyuncs.com
+#  aliyun.accessKeyId = LTAI5tKy8djwYHDaQ3QjpcKJ
+#  aliyun.accessKeySecret = hYSDMNLsEIOqdjsnPtIlzmnfdWB0y11
+#  aliyun.bucketName= itcast-face
+#  aliyun.urlPrefix=http://itcast-face.oss-cn-beijing.aliyuncs.com
+#
+#face:
+#  imagePath: ./upload/images/
+
+

+ 15 - 0
src/main/resources/mapper/AdvertisementMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.AdvertisementMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.domain.Advertisement">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="image" column="image" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,image
+    </sql>
+</mapper>

+ 19 - 0
src/main/resources/mapper/FaceFeatureMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.FaceFeatureMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.domain.FaceFeature">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="userId" column="user_id" jdbcType="BIGINT"/>
+            <result property="faceId" column="face_id" jdbcType="VARCHAR"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,user_id,face_id,
+        create_time,feature_data
+    </sql>
+    <select id="findByFaceId" resultType="com.zhentao.domain.FaceFeature"></select>
+</mapper>

+ 18 - 0
src/main/resources/mapper/HotelSortMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.hotel.mapper.HotelSortMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.hotel.domain.HotelSort">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="sortName" column="sort_name" jdbcType="VARCHAR"/>
+            <result property="sortLei" column="sort_lei" jdbcType="VARCHAR"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,sort_name,sort_lei,
+        create_time
+    </sql>
+</mapper>

+ 31 - 0
src/main/resources/mapper/HoteldetailsMapper.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.hotel.mapper.HoteldetailsMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.hotel.domain.Hoteldetails">
+            <id property="detailid" column="DetailID" jdbcType="BIGINT"/>
+            <result property="hotelid" column="HotelID" jdbcType="BIGINT"/>
+            <result property="roomtype" column="RoomType" jdbcType="VARCHAR"/>
+            <result property="roomdescription" column="RoomDescription" jdbcType="VARCHAR"/>
+            <result property="roomamenities" column="RoomAmenities" jdbcType="VARCHAR"/>
+            <result property="roomprice" column="RoomPrice" jdbcType="DECIMAL"/>
+            <result property="roomsize" column="RoomSize" jdbcType="INTEGER"/>
+            <result property="roomview" column="RoomView" jdbcType="VARCHAR"/>
+            <result property="roomcapacity" column="RoomCapacity" jdbcType="INTEGER"/>
+            <result property="breakfastincluded" column="BreakfastIncluded" jdbcType="TINYINT"/>
+            <result property="checkintime" column="CheckInTime" jdbcType="TIME"/>
+            <result property="checkouttime" column="CheckOutTime" jdbcType="TIME"/>
+            <result property="createtime" column="CreateTime" jdbcType="TIMESTAMP"/>
+            <result property="updatetime" column="UpdateTime" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        DetailID,HotelID,RoomType,
+        RoomDescription,RoomAmenities,RoomPrice,
+        RoomSize,RoomView,RoomCapacity,
+        BreakfastIncluded,CheckInTime,CheckOutTime,
+        CreateTime,UpdateTime
+    </sql>
+</mapper>

+ 43 - 0
src/main/resources/mapper/HotelsMapper.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.hotel.mapper.HotelsMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.hotel.domain.Hotels">
+            <id property="hotelid" column="HotelID" jdbcType="BIGINT"/>
+            <result property="sortId" column="sort_id" jdbcType="BIGINT"/>
+            <result property="hotelname" column="HotelName" jdbcType="VARCHAR"/>
+            <result property="address" column="Address" jdbcType="VARCHAR"/>
+            <result property="city" column="City" jdbcType="VARCHAR"/>
+            <result property="stateprovince" column="StateProvince" jdbcType="VARCHAR"/>
+            <result property="country" column="Country" jdbcType="VARCHAR"/>
+            <result property="postalcode" column="PostalCode" jdbcType="VARCHAR"/>
+            <result property="phonenumber" column="PhoneNumber" jdbcType="VARCHAR"/>
+            <result property="email" column="Email" jdbcType="VARCHAR"/>
+            <result property="website" column="Website" jdbcType="VARCHAR"/>
+            <result property="starrating" column="StarRating" jdbcType="INTEGER"/>
+            <result property="type" column="Type" jdbcType="VARCHAR"/>
+            <result property="brand" column="Brand" jdbcType="VARCHAR"/>
+            <result property="amenities" column="Amenities" jdbcType="VARCHAR"/>
+            <result property="services" column="Services" jdbcType="VARCHAR"/>
+            <result property="price" column="price" jdbcType="DECIMAL"/>
+            <result property="rating" column="Rating" jdbcType="DECIMAL"/>
+            <result property="reviewcount" column="ReviewCount" jdbcType="INTEGER"/>
+            <result property="description" column="Description" jdbcType="VARCHAR"/>
+            <result property="imageurl" column="ImageURL" jdbcType="VARCHAR"/>
+            <result property="createtime" column="CreateTime" jdbcType="TIMESTAMP"/>
+            <result property="updatetime" column="UpdateTime" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        HotelID,sort_id,HotelName,
+        Address,City,StateProvince,
+        Country,PostalCode,PhoneNumber,
+        Email,Website,StarRating,
+        Type,Brand,Amenities,
+        Services,price,Rating,
+        ReviewCount,Description,ImageURL,
+        CreateTime,UpdateTime
+    </sql>
+</mapper>

+ 24 - 0
src/main/resources/mapper/TicketinfoMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.touristAttractions.mapper.TicketinfoMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.touristAttractions.domain.Ticketinfo">
+            <id property="id" column="id" jdbcType="INTEGER"/>
+            <result property="tid" column="tid" jdbcType="BIGINT"/>
+            <result property="type" column="type" jdbcType="VARCHAR"/>
+            <result property="price" column="price" jdbcType="DECIMAL"/>
+            <result property="discountPrice" column="discount_price" jdbcType="DECIMAL"/>
+            <result property="description" column="description" jdbcType="VARCHAR"/>
+            <result property="sales" column="sales" jdbcType="INTEGER"/>
+            <result property="heightLimit" column="height_limit" jdbcType="VARCHAR"/>
+            <result property="ageLimit" column="age_limit" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,tid,type,
+        price,discount_price,description,
+        sales,height_limit,age_limit
+    </sql>
+</mapper>

+ 26 - 0
src/main/resources/mapper/TouristattractionsMapper.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.touristAttractions.mapper.TouristattractionsMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.touristAttractions.domain.Touristattractions">
+            <id property="id" column="id" jdbcType="INTEGER"/>
+            <result property="name" column="name" jdbcType="VARCHAR"/>
+            <result property="level" column="level" jdbcType="VARCHAR"/>
+            <result property="rating" column="rating" jdbcType="DECIMAL"/>
+            <result property="reviewCount" column="review_count" jdbcType="INTEGER"/>
+            <result property="distanceKm" column="distance_km" jdbcType="DECIMAL"/>
+            <result property="ticketPrice" column="ticket_price" jdbcType="DECIMAL"/>
+            <result property="sales" column="sales" jdbcType="INTEGER"/>
+            <result property="imageUrl" column="image_url" jdbcType="VARCHAR"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,name,level,
+        rating,review_count,distance_km,
+        ticket_price,sales,image_url,
+        create_time
+    </sql>
+</mapper>

+ 52 - 0
src/main/resources/mapper/UserLoginMapper.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.UserLoginMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.domain.UserLogin">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="userUsername" column="user_username" jdbcType="VARCHAR"/>
+            <result property="userPassword" column="user_password" jdbcType="VARCHAR"/>
+            <result property="salt" column="salt" jdbcType="VARCHAR"/>
+            <result property="nickName" column="nick_name" jdbcType="VARCHAR"/>
+            <result property="avatar" column="avatar" jdbcType="VARCHAR"/>
+            <result property="userName" column="user_name" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="INTEGER"/>
+            <result property="userIntro" column="user_intro" jdbcType="VARCHAR"/>
+            <result property="userMobile" column="user_mobile" jdbcType="VARCHAR"/>
+            <result property="idenNo" column="iden_no" jdbcType="VARCHAR"/>
+            <result property="gradeId" column="grade_id" jdbcType="BIGINT"/>
+            <result property="gradeDesc" column="grade_desc" jdbcType="VARCHAR"/>
+            <result property="isMember" column="is_member" jdbcType="INTEGER"/>
+            <result property="loseDate" column="lose_date" jdbcType="TIMESTAMP"/>
+            <result property="memberType" column="member_type" jdbcType="INTEGER"/>
+            <result property="birthDay" column="birth_day" jdbcType="DATE"/>
+            <result property="birthMonth" column="birth_month" jdbcType="INTEGER"/>
+            <result property="days" column="days" jdbcType="INTEGER"/>
+            <result property="totalOrder" column="total_order" jdbcType="INTEGER"/>
+            <result property="totalConsume" column="total_consume" jdbcType="DECIMAL"/>
+            <result property="labelList" column="label_list" jdbcType="VARCHAR"/>
+            <result property="status" column="status" jdbcType="INTEGER"/>
+            <result property="remark" column="remark" jdbcType="VARCHAR"/>
+            <result property="createdTime" column="created_time" jdbcType="TIMESTAMP"/>
+            <result property="updatedBy" column="updated_by" jdbcType="VARCHAR"/>
+            <result property="updatedTime" column="updated_time" jdbcType="TIMESTAMP"/>
+            <result property="openId" column="open_id" jdbcType="VARCHAR"/>
+            <result property="sessionKey" column="session_key" jdbcType="VARCHAR"/>
+            <result property="uniId" column="uni_id" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,user_username,user_password,
+        salt,nick_name,avatar,
+        user_name,gender,user_intro,
+        user_mobile,iden_no,grade_id,
+        grade_desc,is_member,lose_date,
+        member_type,birth_day,birth_month,
+        days,total_order,total_consume,
+        label_list,status,remark,
+        created_time,updated_by,updated_time,
+        open_id,session_key,uni_id
+    </sql>
+</mapper>

+ 25 - 0
src/test/java/com/zhentao/tourismhd/TestFaceEngineService.java

@@ -0,0 +1,25 @@
+package com.zhentao.tourismhd;
+
+import com.zhentao.utils.FaceEngineService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.io.File;
+
+@SpringBootTest
+@RunWith(SpringJUnit4ClassRunner.class)
+public class TestFaceEngineService {
+
+    @Autowired
+    private FaceEngineService faceEngineService;
+
+    @Test
+    public void testCheckIsPortrait(){
+        File file = new File("C:\\Users\\Lenovo\\Pictures\\mm\\1.jpg");
+        boolean checkIsPortrait = this.faceEngineService.checkIsPortrait(file);
+        System.out.println(checkIsPortrait); // true|false
+    }
+}

+ 13 - 0
src/test/java/com/zhentao/tourismhd/TourismHdApplicationTests.java

@@ -0,0 +1,13 @@
+package com.zhentao.tourismhd;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TourismHdApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}

BIN
upload/imagesOIP-C.jpg


BIN
upload/imagesOIP-C1 (2).jpg