X723595506 2 weeks ago
parent
commit
542b7c4069
61 changed files with 2745 additions and 14 deletions
  1. 30 6
      pom.xml
  2. 2 1
      src/main/java/com/example/demo/TravelApplication.java
  3. 11 0
      src/main/java/com/example/demo/annotation/NonLoginRequired.java
  4. 18 0
      src/main/java/com/example/demo/common/config/CorsConfig.java
  5. 73 0
      src/main/java/com/example/demo/product/controller/ProductController.java
  6. 20 0
      src/main/java/com/example/demo/product/dao/ProductFlightMapper.java
  7. 20 0
      src/main/java/com/example/demo/product/dao/ProductHotelMapper.java
  8. 20 0
      src/main/java/com/example/demo/product/dao/ProductMapper.java
  9. 20 0
      src/main/java/com/example/demo/product/dao/ProductTicketMapper.java
  10. 20 0
      src/main/java/com/example/demo/product/dao/ProductTrainMapper.java
  11. 121 0
      src/main/java/com/example/demo/product/domain/Product.java
  12. 110 0
      src/main/java/com/example/demo/product/domain/ProductFlight.java
  13. 104 0
      src/main/java/com/example/demo/product/domain/ProductHotel.java
  14. 104 0
      src/main/java/com/example/demo/product/domain/ProductTicket.java
  15. 112 0
      src/main/java/com/example/demo/product/domain/ProductTrain.java
  16. 76 0
      src/main/java/com/example/demo/product/entity/ProductEntity.java
  17. 70 0
      src/main/java/com/example/demo/product/entity/ProductFlightEntity.java
  18. 67 0
      src/main/java/com/example/demo/product/entity/ProductHotelEntity.java
  19. 63 0
      src/main/java/com/example/demo/product/entity/ProductTicketEntity.java
  20. 64 0
      src/main/java/com/example/demo/product/entity/ProductTrainEntity.java
  21. 8 0
      src/main/java/com/example/demo/product/esmapper/ProductEsMapper.java
  22. 7 0
      src/main/java/com/example/demo/product/esmapper/ProductFlightEsMapper.java
  23. 7 0
      src/main/java/com/example/demo/product/esmapper/ProductHotelEsMapper.java
  24. 7 0
      src/main/java/com/example/demo/product/esmapper/ProductTicketEsMapper.java
  25. 7 0
      src/main/java/com/example/demo/product/esmapper/ProductTrainEsMapper.java
  26. 16 0
      src/main/java/com/example/demo/product/service/ProductFlightService.java
  27. 17 0
      src/main/java/com/example/demo/product/service/ProductHotelService.java
  28. 18 0
      src/main/java/com/example/demo/product/service/ProductService.java
  29. 16 0
      src/main/java/com/example/demo/product/service/ProductTicketService.java
  30. 16 0
      src/main/java/com/example/demo/product/service/ProductTrainService.java
  31. 66 0
      src/main/java/com/example/demo/product/service/impl/ProductFlightServiceImpl.java
  32. 64 0
      src/main/java/com/example/demo/product/service/impl/ProductHotelServiceImpl.java
  33. 67 0
      src/main/java/com/example/demo/product/service/impl/ProductServiceImpl.java
  34. 61 0
      src/main/java/com/example/demo/product/service/impl/ProductTicketServiceImpl.java
  35. 65 0
      src/main/java/com/example/demo/product/service/impl/ProductTrainServiceImpl.java
  36. 24 0
      src/main/java/com/example/demo/scenic_spot/controller/ScenicSpotController.java
  37. 20 0
      src/main/java/com/example/demo/scenic_spot/dao/ScenicSpotMapper.java
  38. 289 0
      src/main/java/com/example/demo/scenic_spot/domain/ScenicSpot.java
  39. 200 0
      src/main/java/com/example/demo/scenic_spot/entity/ScenicSpotEntity.java
  40. 7 0
      src/main/java/com/example/demo/scenic_spot/esmapper/ScenicSpotEsMapper.java
  41. 17 0
      src/main/java/com/example/demo/scenic_spot/service/ScenicSpotService.java
  42. 90 0
      src/main/java/com/example/demo/scenic_spot/service/impl/ScenicSpotServiceImpl.java
  43. 0 5
      src/main/java/com/example/demo/user/dto/UserDto.java
  44. 1 1
      src/main/java/com/example/demo/user/service/impl/UserServiceImpl.java
  45. 10 1
      src/main/resources/application.yml
  46. 22 0
      src/main/resources/com/example/demo/product/mapper/ProductFlightMapper.xml
  47. 21 0
      src/main/resources/com/example/demo/product/mapper/ProductHotelMapper.xml
  48. 23 0
      src/main/resources/com/example/demo/product/mapper/ProductMapper.xml
  49. 21 0
      src/main/resources/com/example/demo/product/mapper/ProductTicketMapper.xml
  50. 22 0
      src/main/resources/com/example/demo/product/mapper/ProductTrainMapper.xml
  51. 49 0
      src/main/resources/com/example/demo/scenic_spot/mapper/ScenicSpotMapper.xml
  52. 33 0
      src/test/java/com/example/demo/Driving.java
  53. 46 0
      src/test/java/com/example/demo/TencentMapUtils.java
  54. 33 0
      src/test/java/com/example/demo/Walking.java
  55. 39 0
      src/test/java/com/example/demo/addressResolution.java
  56. 25 0
      src/test/java/com/example/demo/addressStandardization.java
  57. 33 0
      src/test/java/com/example/demo/bicycling.java
  58. 67 0
      src/test/java/com/example/demo/inverseAddressResolution.java
  59. 24 0
      src/test/java/com/example/demo/ipPositioning.java
  60. 30 0
      src/test/java/com/example/demo/keywordInputPrompt.java
  61. 32 0
      src/test/java/com/example/demo/locationSearch.java

+ 30 - 6
pom.xml

@@ -83,12 +83,6 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
-        <!--   生成二维码   -->
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>core</artifactId>
-            <version>3.3.3</version>
-        </dependency>
         <!--   io常用工具类   -->
         <dependency>
             <groupId>commons-io</groupId>
@@ -152,6 +146,36 @@
             <version>3.14.1</version>
         </dependency>
         <dependency>
+            <groupId>cn.easy-es</groupId>
+            <artifactId>easy-es-boot-starter</artifactId>
+            <version>1.1.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.elasticsearch.client</groupId>
+                    <artifactId>elasticsearch-rest-high-level-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.elasticsearch</groupId>
+                    <artifactId>elasticsearch</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-high-level-client</artifactId>
+            <version>7.14.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.elasticsearch</groupId>
+            <artifactId>elasticsearch</artifactId>
+            <version>7.14.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.locationtech.jts</groupId>
+            <artifactId>jts-core</artifactId>
+            <version>1.19.0</version> <!-- 版本可根据实际情况调整,建议使用较新稳定版 -->
+        </dependency>
+        <dependency>
             <groupId>org.apache.poi</groupId>
             <artifactId>poi-ooxml</artifactId>
             <version>4.1.2</version>

+ 2 - 1
src/main/java/com/example/demo/TravelApplication.java

@@ -1,10 +1,11 @@
 package com.example.demo;
 
-import cn.hutool.crypto.digest.BCrypt;
+import cn.easyes.starter.register.EsMapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
+@EsMapperScan("com.example.demo")
 public class TravelApplication {
 
     public static void main(String[] args) {

+ 11 - 0
src/main/java/com/example/demo/annotation/NonLoginRequired.java

@@ -0,0 +1,11 @@
+package com.example.demo.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface NonLoginRequired {
+}

+ 18 - 0
src/main/java/com/example/demo/common/config/CorsConfig.java

@@ -0,0 +1,18 @@
+package com.example.demo.common.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class CorsConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+            .allowedOrigins("*")
+            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+            .maxAge(3600);
+    }
+
+}

+ 73 - 0
src/main/java/com/example/demo/product/controller/ProductController.java

@@ -0,0 +1,73 @@
+package com.example.demo.product.controller;
+
+import com.example.demo.product.service.impl.*;
+import com.example.demo.user.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/product")
+public class ProductController {
+    @Autowired
+    private ProductServiceImpl productService;
+    @Autowired
+    private ProductFlightServiceImpl productFlightService;
+    @Autowired
+    private ProductHotelServiceImpl productHotelService;
+    @Autowired
+    private ProductTicketServiceImpl productTicketService;
+    @Autowired
+    private ProductTrainServiceImpl productTrainService;
+
+    @RequestMapping("/syncDataToEs")
+    public ResultVo syncDataToEs() {
+        return productService.syncDataToEs();
+    }
+
+    @RequestMapping("/getProductList")
+    public ResultVo getProductList(@RequestHeader("token") String token) {
+        return productService.getProductList(token);
+    }
+
+    @RequestMapping("/flightSyncDataToEs")
+    public ResultVo FlightSyncDataToEs(){
+        return productFlightService.flightSyncDataToEs();
+    }
+
+    @RequestMapping("/getFlightList")
+    public ResultVo getFlightList(@RequestHeader("token") String token) {
+        return productFlightService.getFlightList(token);
+    }
+
+    @RequestMapping("/hotelSyncDataToEs")
+    public ResultVo hotelSyncDataToEs(){
+        return productHotelService.hotelSyncDataToEs();
+    }
+
+    @RequestMapping("/getHotelList")
+    public ResultVo getHotelList(@RequestHeader("token") String token) {
+        return productHotelService.getHotelList(token);
+    }
+
+    @RequestMapping("/ticketSyncDataToEs")
+    public ResultVo ticketSyncDataToEs(){
+        return productTicketService.ticketSyncDataToEs();
+    }
+
+    @RequestMapping("/getTicketList")
+    public ResultVo getTicketList(@RequestHeader("token") String token) {
+        return productTicketService.getTicketList(token);
+    }
+
+    @RequestMapping("/trainSyncDataToEs")
+    public ResultVo trainSyncDataToEs(){
+        return productTrainService.trainSyncDataToEs();
+    }
+
+    @RequestMapping("/getTrainList")
+    public ResultVo getTrainList(@RequestHeader("token") String token) {
+        return productTrainService.getTrainList(token);
+    }
+}

+ 20 - 0
src/main/java/com/example/demo/product/dao/ProductFlightMapper.java

@@ -0,0 +1,20 @@
+package com.example.demo.product.dao;
+
+import com.example.demo.product.domain.ProductFlight;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 徐乐
+* @description 针对表【product_flight(机票产品扩展信息表)】的数据库操作Mapper
+* @createDate 2025-06-10 20:12:01
+* @Entity com.example.demo.product.domain.ProductFlight
+*/
+@Mapper
+public interface ProductFlightMapper extends BaseMapper<ProductFlight> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/example/demo/product/dao/ProductHotelMapper.java

@@ -0,0 +1,20 @@
+package com.example.demo.product.dao;
+
+import com.example.demo.product.domain.ProductHotel;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 徐乐
+* @description 针对表【product_hotel(酒店产品扩展信息表)】的数据库操作Mapper
+* @createDate 2025-06-17 08:56:49
+* @Entity com.example.demo.product.domain.ProductHotel
+*/
+@Mapper
+public interface ProductHotelMapper extends BaseMapper<ProductHotel> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/example/demo/product/dao/ProductMapper.java

@@ -0,0 +1,20 @@
+package com.example.demo.product.dao;
+
+import com.example.demo.product.domain.Product;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 徐乐
+* @description 针对表【product(全品类产品主表)】的数据库操作Mapper
+* @createDate 2025-06-10 20:12:01
+* @Entity com.example.demo.product.domain.Product
+*/
+@Mapper
+public interface ProductMapper extends BaseMapper<Product> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/example/demo/product/dao/ProductTicketMapper.java

@@ -0,0 +1,20 @@
+package com.example.demo.product.dao;
+
+import com.example.demo.product.domain.ProductTicket;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 徐乐
+* @description 针对表【product_ticket(门票产品扩展信息表)】的数据库操作Mapper
+* @createDate 2025-06-16 20:08:46
+* @Entity com.example.demo.product.domain.ProductTicket
+*/
+@Mapper
+public interface ProductTicketMapper extends BaseMapper<ProductTicket> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/example/demo/product/dao/ProductTrainMapper.java

@@ -0,0 +1,20 @@
+package com.example.demo.product.dao;
+
+import com.example.demo.product.domain.ProductTrain;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 徐乐
+* @description 针对表【product_train(车票产品扩展信息表)】的数据库操作Mapper
+* @createDate 2025-06-10 20:12:01
+* @Entity com.example.demo.product.domain.ProductTrain
+*/
+@Mapper
+public interface ProductTrainMapper extends BaseMapper<ProductTrain> {
+
+}
+
+
+
+

+ 121 - 0
src/main/java/com/example/demo/product/domain/Product.java

@@ -0,0 +1,121 @@
+package com.example.demo.product.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.math.BigDecimal;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 全品类产品主表
+ * @TableName product
+ */
+@TableName(value ="product")
+@Data
+public class Product {
+    /**
+     * 产品唯一ID
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 类型:1-机票 2-酒店 3-门票 4-车票
+     */
+    private Integer productType;
+
+    /**
+     * 产品标题
+     */
+    private String title;
+
+    /**
+     * 售价
+     */
+    private BigDecimal price;
+
+    /**
+     * 库存(适用于门票、车票等)
+     */
+    private Integer stock;
+
+    /**
+     * 产品详情描述
+     */
+    private String description;
+
+    /**
+     * 封面图地址
+     */
+    private String coverImg;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        Product other = (Product) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getProductType() == null ? other.getProductType() == null : this.getProductType().equals(other.getProductType()))
+            && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()))
+            && (this.getPrice() == null ? other.getPrice() == null : this.getPrice().equals(other.getPrice()))
+            && (this.getStock() == null ? other.getStock() == null : this.getStock().equals(other.getStock()))
+            && (this.getDescription() == null ? other.getDescription() == null : this.getDescription().equals(other.getDescription()))
+            && (this.getCoverImg() == null ? other.getCoverImg() == null : this.getCoverImg().equals(other.getCoverImg()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getProductType() == null) ? 0 : getProductType().hashCode());
+        result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
+        result = prime * result + ((getPrice() == null) ? 0 : getPrice().hashCode());
+        result = prime * result + ((getStock() == null) ? 0 : getStock().hashCode());
+        result = prime * result + ((getDescription() == null) ? 0 : getDescription().hashCode());
+        result = prime * result + ((getCoverImg() == null) ? 0 : getCoverImg().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().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(", productType=").append(productType);
+        sb.append(", title=").append(title);
+        sb.append(", price=").append(price);
+        sb.append(", stock=").append(stock);
+        sb.append(", description=").append(description);
+        sb.append(", coverImg=").append(coverImg);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 110 - 0
src/main/java/com/example/demo/product/domain/ProductFlight.java

@@ -0,0 +1,110 @@
+package com.example.demo.product.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 机票产品扩展信息表
+ * @TableName product_flight
+ */
+@TableName(value ="product_flight")
+@Data
+public class ProductFlight {
+    /**
+     * 机票产品ID
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    private Long productId;
+
+    /**
+     * 航班号
+     */
+    private String flightNo;
+
+    /**
+     * 出发机场
+     */
+    private String departureAirport;
+
+    /**
+     * 到达机场
+     */
+    private String arrivalAirport;
+
+    /**
+     * 出发时间
+     */
+    private Date departureTime;
+
+    /**
+     * 到达时间
+     */
+    private Date arrivalTime;
+
+    /**
+     * 座位类型(如“经济舱”“商务舱”)
+     */
+    private String seatType;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        ProductFlight other = (ProductFlight) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getProductId() == null ? other.getProductId() == null : this.getProductId().equals(other.getProductId()))
+            && (this.getFlightNo() == null ? other.getFlightNo() == null : this.getFlightNo().equals(other.getFlightNo()))
+            && (this.getDepartureAirport() == null ? other.getDepartureAirport() == null : this.getDepartureAirport().equals(other.getDepartureAirport()))
+            && (this.getArrivalAirport() == null ? other.getArrivalAirport() == null : this.getArrivalAirport().equals(other.getArrivalAirport()))
+            && (this.getDepartureTime() == null ? other.getDepartureTime() == null : this.getDepartureTime().equals(other.getDepartureTime()))
+            && (this.getArrivalTime() == null ? other.getArrivalTime() == null : this.getArrivalTime().equals(other.getArrivalTime()))
+            && (this.getSeatType() == null ? other.getSeatType() == null : this.getSeatType().equals(other.getSeatType()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getProductId() == null) ? 0 : getProductId().hashCode());
+        result = prime * result + ((getFlightNo() == null) ? 0 : getFlightNo().hashCode());
+        result = prime * result + ((getDepartureAirport() == null) ? 0 : getDepartureAirport().hashCode());
+        result = prime * result + ((getArrivalAirport() == null) ? 0 : getArrivalAirport().hashCode());
+        result = prime * result + ((getDepartureTime() == null) ? 0 : getDepartureTime().hashCode());
+        result = prime * result + ((getArrivalTime() == null) ? 0 : getArrivalTime().hashCode());
+        result = prime * result + ((getSeatType() == null) ? 0 : getSeatType().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(", productId=").append(productId);
+        sb.append(", flightNo=").append(flightNo);
+        sb.append(", departureAirport=").append(departureAirport);
+        sb.append(", arrivalAirport=").append(arrivalAirport);
+        sb.append(", departureTime=").append(departureTime);
+        sb.append(", arrivalTime=").append(arrivalTime);
+        sb.append(", seatType=").append(seatType);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 104 - 0
src/main/java/com/example/demo/product/domain/ProductHotel.java

@@ -0,0 +1,104 @@
+package com.example.demo.product.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.util.Date;
+import lombok.Data;
+
+/**
+ * 酒店产品扩展信息表
+ * @TableName product_hotel
+ */
+@TableName(value ="product_hotel")
+@Data
+public class ProductHotel {
+    /**
+     * 酒店产品ID
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    private Long productId;
+
+    /**
+     * 酒店名称
+     */
+    private String hotelName;
+
+    /**
+     * 房型(如“标间”“大床房”)
+     */
+    private String roomType;
+
+    /**
+     * 酒店地址
+     */
+    private String address;
+
+    /**
+     * 入住时间
+     */
+    private Date checkinTime;
+
+    /**
+     * 退房时间
+     */
+    private Date checkoutTime;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        ProductHotel other = (ProductHotel) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getProductId() == null ? other.getProductId() == null : this.getProductId().equals(other.getProductId()))
+            && (this.getHotelName() == null ? other.getHotelName() == null : this.getHotelName().equals(other.getHotelName()))
+            && (this.getRoomType() == null ? other.getRoomType() == null : this.getRoomType().equals(other.getRoomType()))
+            && (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress()))
+            && (this.getCheckinTime() == null ? other.getCheckinTime() == null : this.getCheckinTime().equals(other.getCheckinTime()))
+            && (this.getCheckoutTime() == null ? other.getCheckoutTime() == null : this.getCheckoutTime().equals(other.getCheckoutTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getProductId() == null) ? 0 : getProductId().hashCode());
+        result = prime * result + ((getHotelName() == null) ? 0 : getHotelName().hashCode());
+        result = prime * result + ((getRoomType() == null) ? 0 : getRoomType().hashCode());
+        result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode());
+        result = prime * result + ((getCheckinTime() == null) ? 0 : getCheckinTime().hashCode());
+        result = prime * result + ((getCheckoutTime() == null) ? 0 : getCheckoutTime().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(", productId=").append(productId);
+        sb.append(", hotelName=").append(hotelName);
+        sb.append(", roomType=").append(roomType);
+        sb.append(", address=").append(address);
+        sb.append(", checkinTime=").append(checkinTime);
+        sb.append(", checkoutTime=").append(checkoutTime);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 104 - 0
src/main/java/com/example/demo/product/domain/ProductTicket.java

@@ -0,0 +1,104 @@
+package com.example.demo.product.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.util.Date;
+import lombok.Data;
+
+/**
+ * 门票产品扩展信息表
+ * @TableName product_ticket
+ */
+@TableName(value ="product_ticket")
+@Data
+public class ProductTicket {
+    /**
+     * 门票产品ID
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    private Long productId;
+
+    /**
+     * 景区名称
+     */
+    private String scenicName;
+
+    /**
+     * 门票类型(如“成人票”“儿童票”)
+     */
+    private String ticketType;
+
+    /**
+     * 景区地址
+     */
+    private String address;
+
+    /**
+     * 有效期开始日期
+     */
+    private Date validStartDate;
+
+    /**
+     * 有效期结束日期
+     */
+    private Date validEndDate;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        ProductTicket other = (ProductTicket) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getProductId() == null ? other.getProductId() == null : this.getProductId().equals(other.getProductId()))
+            && (this.getScenicName() == null ? other.getScenicName() == null : this.getScenicName().equals(other.getScenicName()))
+            && (this.getTicketType() == null ? other.getTicketType() == null : this.getTicketType().equals(other.getTicketType()))
+            && (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress()))
+            && (this.getValidStartDate() == null ? other.getValidStartDate() == null : this.getValidStartDate().equals(other.getValidStartDate()))
+            && (this.getValidEndDate() == null ? other.getValidEndDate() == null : this.getValidEndDate().equals(other.getValidEndDate()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getProductId() == null) ? 0 : getProductId().hashCode());
+        result = prime * result + ((getScenicName() == null) ? 0 : getScenicName().hashCode());
+        result = prime * result + ((getTicketType() == null) ? 0 : getTicketType().hashCode());
+        result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode());
+        result = prime * result + ((getValidStartDate() == null) ? 0 : getValidStartDate().hashCode());
+        result = prime * result + ((getValidEndDate() == null) ? 0 : getValidEndDate().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(", productId=").append(productId);
+        sb.append(", scenicName=").append(scenicName);
+        sb.append(", ticketType=").append(ticketType);
+        sb.append(", address=").append(address);
+        sb.append(", validStartDate=").append(validStartDate);
+        sb.append(", validEndDate=").append(validEndDate);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 112 - 0
src/main/java/com/example/demo/product/domain/ProductTrain.java

@@ -0,0 +1,112 @@
+package com.example.demo.product.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.util.Date;
+import lombok.Data;
+
+/**
+ * 车票产品扩展信息表
+ * @TableName product_train
+ */
+@TableName(value ="product_train")
+@Data
+public class ProductTrain {
+    /**
+     * 车票产品ID
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    private Long productId;
+
+    /**
+     * 车次
+     */
+    private String trainNo;
+
+    /**
+     * 出发站
+     */
+    private String departureStation;
+
+    /**
+     * 到达站
+     */
+    private String arrivalStation;
+
+    /**
+     * 出发时间
+     */
+    private Date departureTime;
+
+    /**
+     * 到达时间
+     */
+    private Date arrivalTime;
+
+    /**
+     * 座位类型(如“硬座”“软卧”)
+     */
+    private String seatType;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        ProductTrain other = (ProductTrain) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getProductId() == null ? other.getProductId() == null : this.getProductId().equals(other.getProductId()))
+            && (this.getTrainNo() == null ? other.getTrainNo() == null : this.getTrainNo().equals(other.getTrainNo()))
+            && (this.getDepartureStation() == null ? other.getDepartureStation() == null : this.getDepartureStation().equals(other.getDepartureStation()))
+            && (this.getArrivalStation() == null ? other.getArrivalStation() == null : this.getArrivalStation().equals(other.getArrivalStation()))
+            && (this.getDepartureTime() == null ? other.getDepartureTime() == null : this.getDepartureTime().equals(other.getDepartureTime()))
+            && (this.getArrivalTime() == null ? other.getArrivalTime() == null : this.getArrivalTime().equals(other.getArrivalTime()))
+            && (this.getSeatType() == null ? other.getSeatType() == null : this.getSeatType().equals(other.getSeatType()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getProductId() == null) ? 0 : getProductId().hashCode());
+        result = prime * result + ((getTrainNo() == null) ? 0 : getTrainNo().hashCode());
+        result = prime * result + ((getDepartureStation() == null) ? 0 : getDepartureStation().hashCode());
+        result = prime * result + ((getArrivalStation() == null) ? 0 : getArrivalStation().hashCode());
+        result = prime * result + ((getDepartureTime() == null) ? 0 : getDepartureTime().hashCode());
+        result = prime * result + ((getArrivalTime() == null) ? 0 : getArrivalTime().hashCode());
+        result = prime * result + ((getSeatType() == null) ? 0 : getSeatType().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(", productId=").append(productId);
+        sb.append(", trainNo=").append(trainNo);
+        sb.append(", departureStation=").append(departureStation);
+        sb.append(", arrivalStation=").append(arrivalStation);
+        sb.append(", departureTime=").append(departureTime);
+        sb.append(", arrivalTime=").append(arrivalTime);
+        sb.append(", seatType=").append(seatType);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 76 - 0
src/main/java/com/example/demo/product/entity/ProductEntity.java

@@ -0,0 +1,76 @@
+package com.example.demo.product.entity;
+
+import cn.easyes.annotation.HighLight;
+import cn.easyes.annotation.IndexField;
+import cn.easyes.annotation.IndexId;
+import cn.easyes.annotation.IndexName;
+import cn.easyes.annotation.rely.Analyzer;
+import cn.easyes.annotation.rely.FieldType;
+import cn.easyes.annotation.rely.IdType;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 全品类产品主表
+ *  product
+ */
+@IndexName(value ="product",shardsNum = 3,replicasNum = 2)
+@Data
+public class ProductEntity {
+    /**
+     * 产品唯一ID
+     */
+    @IndexId(type = IdType.CUSTOMIZE)
+    private Long id;
+
+    /**
+     * 类型:1-机票 2-酒店 3-门票 4-车票
+     */
+    @IndexField(fieldType = FieldType.INTEGER)
+    private Integer productType;
+
+    /**
+     * 产品标题
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String title;
+
+    /**
+     * 售价
+     */
+    @IndexField(fieldType = FieldType.DOUBLE)
+    private BigDecimal price;
+
+    /**
+     * 库存(适用于门票、车票等)
+     */
+    @IndexField(fieldType = FieldType.INTEGER)
+    private Integer stock;
+
+    /**
+     * 产品详情描述
+     */
+    @IndexField(fieldType = FieldType.TEXT)
+    private String description;
+
+    /**
+     * 封面图地址
+     */
+    @IndexField(fieldType = FieldType.TEXT)
+    private String coverImg;
+
+    /**
+     * 创建时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date updateTime;
+}

+ 70 - 0
src/main/java/com/example/demo/product/entity/ProductFlightEntity.java

@@ -0,0 +1,70 @@
+package com.example.demo.product.entity;
+
+import cn.easyes.annotation.HighLight;
+import cn.easyes.annotation.IndexField;
+import cn.easyes.annotation.IndexId;
+import cn.easyes.annotation.IndexName;
+import cn.easyes.annotation.rely.Analyzer;
+import cn.easyes.annotation.rely.FieldType;
+import cn.easyes.annotation.rely.IdType;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 机票产品扩展信息表
+ *  product_flight
+ */
+@IndexName(value ="flight",shardsNum = 3, replicasNum = 2)
+@Data
+public class ProductFlightEntity {
+    /**
+     * 机票产品ID
+     */
+    @IndexId(type = IdType.CUSTOMIZE)
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    @IndexField(fieldType = FieldType.LONG)
+    private Long productId;
+
+    /**
+     * 航班号
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String flightNo;
+
+    /**
+     * 出发机场
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String departureAirport;
+
+    /**
+     * 到达机场
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String arrivalAirport;
+
+    /**
+     * 出发时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date departureTime;
+
+    /**
+     * 到达时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date arrivalTime;
+
+    /**
+     * 座位类型(如“经济舱”“商务舱”)
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String seatType;
+}

+ 67 - 0
src/main/java/com/example/demo/product/entity/ProductHotelEntity.java

@@ -0,0 +1,67 @@
+package com.example.demo.product.entity;
+
+import cn.easyes.annotation.HighLight;
+import cn.easyes.annotation.IndexField;
+import cn.easyes.annotation.IndexId;
+import cn.easyes.annotation.IndexName;
+import cn.easyes.annotation.rely.Analyzer;
+import cn.easyes.annotation.rely.FieldType;
+import cn.easyes.annotation.rely.IdType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 酒店产品扩展信息表
+ *  product_hotel
+ */
+@IndexName(value ="hotel",shardsNum = 3, replicasNum = 2)
+@Data
+public class ProductHotelEntity {
+    /**
+     * 酒店产品ID
+     */
+    @IndexId(type = IdType.CUSTOMIZE)
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    @IndexField(fieldType = FieldType.LONG)
+    private Long productId;
+
+    /**
+     * 酒店名称
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String hotelName;
+
+    /**
+     * 房型(如“标间”“大床房”)
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String roomType;
+
+    /**
+     * 酒店地址
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String address;
+
+    /**
+     * 入住时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") // 指定格式和时区
+    private Date checkinTime;
+
+    /**
+     * 退房时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") // 指定格式和时区
+    private Date checkoutTime;
+}

+ 63 - 0
src/main/java/com/example/demo/product/entity/ProductTicketEntity.java

@@ -0,0 +1,63 @@
+package com.example.demo.product.entity;
+
+import cn.easyes.annotation.HighLight;
+import cn.easyes.annotation.IndexField;
+import cn.easyes.annotation.IndexId;
+import cn.easyes.annotation.IndexName;
+import cn.easyes.annotation.rely.Analyzer;
+import cn.easyes.annotation.rely.FieldType;
+import cn.easyes.annotation.rely.IdType;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 门票产品扩展信息表
+ *  product_ticket
+ */
+@IndexName(value ="ticket",shardsNum = 3,replicasNum = 2)
+@Data
+public class ProductTicketEntity {
+    /**
+     * 门票产品ID
+     */
+    @IndexId(type = IdType.CUSTOMIZE)
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    @IndexField(fieldType = FieldType.LONG)
+    private Long productId;
+
+    /**
+     * 景区名称
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String scenicName;
+
+    /**
+     * 门票类型(如“成人票”“儿童票”)
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String ticketType;
+
+    /**
+     * 景区地址
+     */
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String address;
+
+    /**
+     * 有效期开始日期
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date validStartDate;
+
+    /**
+     * 有效期结束日期
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date validEndDate;
+}

+ 64 - 0
src/main/java/com/example/demo/product/entity/ProductTrainEntity.java

@@ -0,0 +1,64 @@
+package com.example.demo.product.entity;
+
+import cn.easyes.annotation.HighLight;
+import cn.easyes.annotation.IndexField;
+import cn.easyes.annotation.IndexId;
+import cn.easyes.annotation.IndexName;
+import cn.easyes.annotation.rely.Analyzer;
+import cn.easyes.annotation.rely.FieldType;
+import cn.easyes.annotation.rely.IdType;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 车票产品扩展信息表
+ *  product_train
+ */
+@IndexName(value ="train",shardsNum = 3,replicasNum = 2)
+@Data
+public class ProductTrainEntity {
+    /**
+     * 车票产品ID
+     */
+    @IndexId(type = IdType.CUSTOMIZE)
+    private Long id;
+
+    /**
+     * 关联产品主表ID
+     */
+    @IndexField(fieldType = FieldType.LONG)
+    private Long productId;
+
+    /**
+     * 车次
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String trainNo;
+
+    /**
+     * 出发站
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String departureStation;
+
+    /**
+     * 到达站
+     */
+    @HighLight(mappingField = "highlightContent")
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String arrivalStation;
+
+    /**
+     * 出发时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date departureTime;
+
+    /**
+     * 到达时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date arrivalTime;
+}

+ 8 - 0
src/main/java/com/example/demo/product/esmapper/ProductEsMapper.java

@@ -0,0 +1,8 @@
+package com.example.demo.product.esmapper;
+
+import cn.easyes.core.conditions.interfaces.BaseEsMapper;
+import com.example.demo.product.entity.ProductEntity;
+
+public interface ProductEsMapper extends BaseEsMapper<ProductEntity> {
+
+}

+ 7 - 0
src/main/java/com/example/demo/product/esmapper/ProductFlightEsMapper.java

@@ -0,0 +1,7 @@
+package com.example.demo.product.esmapper;
+
+import cn.easyes.core.conditions.interfaces.BaseEsMapper;
+import com.example.demo.product.entity.ProductFlightEntity;
+
+public interface ProductFlightEsMapper extends BaseEsMapper<ProductFlightEntity> {
+}

+ 7 - 0
src/main/java/com/example/demo/product/esmapper/ProductHotelEsMapper.java

@@ -0,0 +1,7 @@
+package com.example.demo.product.esmapper;
+
+import cn.easyes.core.conditions.interfaces.BaseEsMapper;
+import com.example.demo.product.entity.ProductHotelEntity;
+
+public interface ProductHotelEsMapper extends BaseEsMapper<ProductHotelEntity> {
+}

+ 7 - 0
src/main/java/com/example/demo/product/esmapper/ProductTicketEsMapper.java

@@ -0,0 +1,7 @@
+package com.example.demo.product.esmapper;
+
+import cn.easyes.core.conditions.interfaces.BaseEsMapper;
+import com.example.demo.product.entity.ProductTicketEntity;
+
+public interface ProductTicketEsMapper extends BaseEsMapper<ProductTicketEntity> {
+}

+ 7 - 0
src/main/java/com/example/demo/product/esmapper/ProductTrainEsMapper.java

@@ -0,0 +1,7 @@
+package com.example.demo.product.esmapper;
+
+import cn.easyes.core.conditions.interfaces.BaseEsMapper;
+import com.example.demo.product.entity.ProductTrainEntity;
+
+public interface ProductTrainEsMapper extends BaseEsMapper<ProductTrainEntity> {
+}

+ 16 - 0
src/main/java/com/example/demo/product/service/ProductFlightService.java

@@ -0,0 +1,16 @@
+package com.example.demo.product.service;
+
+import com.example.demo.product.domain.ProductFlight;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.user.vo.ResultVo;
+
+/**
+* @author 徐乐
+* @description 针对表【product_flight(机票产品扩展信息表)】的数据库操作Service
+* @createDate 2025-06-10 20:12:01
+*/
+public interface ProductFlightService extends IService<ProductFlight> {
+    ResultVo flightSyncDataToEs();
+
+    ResultVo getFlightList(String token);
+}

+ 17 - 0
src/main/java/com/example/demo/product/service/ProductHotelService.java

@@ -0,0 +1,17 @@
+package com.example.demo.product.service;
+
+import com.example.demo.product.domain.ProductHotel;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.user.vo.ResultVo;
+
+/**
+* @author 徐乐
+* @description 针对表【product_hotel(酒店产品扩展信息表)】的数据库操作Service
+* @createDate 2025-06-17 08:56:49
+*/
+public interface ProductHotelService extends IService<ProductHotel> {
+
+    ResultVo hotelSyncDataToEs();
+
+    ResultVo getHotelList(String token);
+}

+ 18 - 0
src/main/java/com/example/demo/product/service/ProductService.java

@@ -0,0 +1,18 @@
+package com.example.demo.product.service;
+
+import com.example.demo.product.domain.Product;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.user.vo.ResultVo;
+
+/**
+* @author 徐乐
+* @description 针对表【product(全品类产品主表)】的数据库操作Service
+* @createDate 2025-06-10 20:12:01
+*/
+public interface ProductService extends IService<Product> {
+
+    ResultVo syncDataToEs();
+
+    ResultVo getProductList(String token);
+
+}

+ 16 - 0
src/main/java/com/example/demo/product/service/ProductTicketService.java

@@ -0,0 +1,16 @@
+package com.example.demo.product.service;
+
+import com.example.demo.product.domain.ProductTicket;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.user.vo.ResultVo;
+
+/**
+* @author 徐乐
+* @description 针对表【product_ticket(门票产品扩展信息表)】的数据库操作Service
+* @createDate 2025-06-16 20:08:46
+*/
+public interface ProductTicketService extends IService<ProductTicket> {
+    ResultVo ticketSyncDataToEs();
+
+    ResultVo getTicketList(String token);
+}

+ 16 - 0
src/main/java/com/example/demo/product/service/ProductTrainService.java

@@ -0,0 +1,16 @@
+package com.example.demo.product.service;
+
+import com.example.demo.product.domain.ProductTrain;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.user.vo.ResultVo;
+
+/**
+* @author 徐乐
+* @description 针对表【product_train(车票产品扩展信息表)】的数据库操作Service
+* @createDate 2025-06-10 20:12:01
+*/
+public interface ProductTrainService extends IService<ProductTrain> {
+    ResultVo trainSyncDataToEs();
+
+    ResultVo getTrainList(String token);
+}

+ 66 - 0
src/main/java/com/example/demo/product/service/impl/ProductFlightServiceImpl.java

@@ -0,0 +1,66 @@
+package com.example.demo.product.service.impl;
+
+import cn.easyes.core.biz.EsPageInfo;
+import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.TokenUtils;
+import com.example.demo.product.domain.ProductFlight;
+import com.example.demo.product.entity.ProductFlightEntity;
+import com.example.demo.product.esmapper.ProductFlightEsMapper;
+import com.example.demo.product.service.ProductFlightService;
+import com.example.demo.product.dao.ProductFlightMapper;
+import com.example.demo.user.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author 徐乐
+* @description 针对表【product_flight(机票产品扩展信息表)】的数据库操作Service实现
+* @createDate 2025-06-10 20:12:01
+*/
+@Service
+public class ProductFlightServiceImpl extends ServiceImpl<ProductFlightMapper, ProductFlight>
+    implements ProductFlightService{
+    @Autowired
+    private ProductFlightEsMapper productFlightEsMapper;
+
+    @Override
+    public ResultVo flightSyncDataToEs() {
+        //创建索引
+        productFlightEsMapper.createIndex();
+        List<ProductFlight> flightList = this.list();
+        List<ProductFlightEntity> productFlightEntityList = new ArrayList<>();
+        for (ProductFlight productFlight : flightList) {
+            ProductFlightEntity productFlightEntity = new ProductFlightEntity();
+            productFlightEntity.setId(productFlight.getId());
+            productFlightEntity.setProductId(productFlight.getProductId());
+            productFlightEntity.setFlightNo(productFlight.getFlightNo());
+            productFlightEntity.setDepartureAirport(productFlight.getDepartureAirport());
+            productFlightEntity.setArrivalAirport(productFlight.getArrivalAirport());
+            productFlightEntity.setDepartureTime(productFlight.getDepartureTime());
+            productFlightEntity.setArrivalTime(productFlight.getArrivalTime());
+            productFlightEntity.setSeatType(productFlight.getSeatType());
+            productFlightEntityList.add(productFlightEntity);
+        }
+        productFlightEsMapper.insertBatch(productFlightEntityList);
+        return ResultVo.success("同步数据成功");
+    }
+
+    @Override
+    public ResultVo getFlightList(String token) {
+        Long userId = TokenUtils.getUserId(token);
+        if (userId==null){
+            return ResultVo.error(101,"请先登录");
+        }
+        LambdaEsQueryWrapper<ProductFlightEntity> wrapper = new LambdaEsQueryWrapper();
+        EsPageInfo<ProductFlightEntity> pageInfo = productFlightEsMapper.pageQuery(wrapper,1,20);
+        return ResultVo.success(pageInfo);
+    }
+}
+
+
+
+

+ 64 - 0
src/main/java/com/example/demo/product/service/impl/ProductHotelServiceImpl.java

@@ -0,0 +1,64 @@
+package com.example.demo.product.service.impl;
+
+import cn.easyes.core.biz.EsPageInfo;
+import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.TokenUtils;
+import com.example.demo.product.domain.ProductHotel;
+import com.example.demo.product.entity.ProductHotelEntity;
+import com.example.demo.product.esmapper.ProductHotelEsMapper;
+import com.example.demo.product.service.ProductHotelService;
+import com.example.demo.product.dao.ProductHotelMapper;
+import com.example.demo.user.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author 徐乐
+* @description 针对表【product_hotel(酒店产品扩展信息表)】的数据库操作Service实现
+* @createDate 2025-06-17 08:56:49
+*/
+@Service
+public class ProductHotelServiceImpl extends ServiceImpl<ProductHotelMapper, ProductHotel>
+    implements ProductHotelService{
+
+    @Autowired
+    private ProductHotelEsMapper productHotelEsMapper;
+    @Override
+    public ResultVo hotelSyncDataToEs() {
+        productHotelEsMapper.createIndex();
+        List<ProductHotel> hotelList = this.list();
+        List<ProductHotelEntity> productHotelEntityList = new ArrayList<>();
+        for (ProductHotel productHotel : hotelList) {
+            ProductHotelEntity productHotelEntity = new ProductHotelEntity();
+            productHotelEntity.setId(productHotel.getId());
+            productHotelEntity.setProductId(productHotel.getProductId());
+            productHotelEntity.setHotelName(productHotel.getHotelName());
+            productHotelEntity.setRoomType(productHotel.getRoomType());
+            productHotelEntity.setAddress(productHotel.getAddress());
+            productHotelEntity.setCheckinTime(productHotel.getCheckinTime());
+            productHotelEntity.setCheckoutTime(productHotel.getCheckoutTime());
+            productHotelEntityList.add(productHotelEntity);
+        }
+        productHotelEsMapper.insertBatch(productHotelEntityList);
+        return ResultVo.success("数据同步成功");
+    }
+
+    @Override
+    public ResultVo getHotelList(String token) {
+        Long userId = TokenUtils.getUserId(token);
+        if (userId==null){
+            return ResultVo.error(101,"请先登录");
+        }
+        LambdaEsQueryWrapper<ProductHotelEntity> wrapper = new LambdaEsQueryWrapper<>();
+        EsPageInfo<ProductHotelEntity> pageInfo = productHotelEsMapper.pageQuery(wrapper, 1, 20);
+        return ResultVo.success(pageInfo);
+    }
+}
+
+
+
+

+ 67 - 0
src/main/java/com/example/demo/product/service/impl/ProductServiceImpl.java

@@ -0,0 +1,67 @@
+package com.example.demo.product.service.impl;
+
+import cn.easyes.core.biz.EsPageInfo;
+import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.TokenUtils;
+import com.example.demo.product.domain.Product;
+import com.example.demo.product.entity.ProductEntity;
+import com.example.demo.product.esmapper.ProductEsMapper;
+import com.example.demo.product.service.ProductService;
+import com.example.demo.product.dao.ProductMapper;
+import com.example.demo.user.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author
+* @description 针对表【product(全品类产品主表)】的数据库操作Service实现
+* @createDate 2025-06-10 20:12:01
+*/
+@Service
+public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product>
+    implements ProductService{
+    @Autowired
+    private ProductEsMapper productEsMapper;
+
+    @Override
+    public ResultVo syncDataToEs() {
+        //创建索引
+        productEsMapper.createIndex();
+        List<Product> productList = this.list();
+        List<ProductEntity> productEntityList = new ArrayList<>();
+        for (Product product : productList) {
+            ProductEntity productEntity = new ProductEntity();
+            productEntity.setId(product.getId());
+            productEntity.setProductType(product.getProductType());
+            productEntity.setTitle(product.getTitle());
+            productEntity.setPrice(product.getPrice());
+            productEntity.setStock(product.getStock());
+            productEntity.setDescription(product.getDescription());
+            productEntity.setCoverImg(product.getCoverImg());
+            productEntity.setCreateTime(product.getCreateTime());
+            productEntity.setUpdateTime(product.getUpdateTime());
+            productEntityList.add(productEntity);
+        }
+        productEsMapper.insertBatch(productEntityList);
+        return ResultVo.success("数据同步成功");
+    }
+
+    @Override
+    public ResultVo getProductList(String token) {
+        Long userId = TokenUtils.getUserId(token);
+        if (userId==null){
+            return ResultVo.error(101,"请先登录");
+        }
+        LambdaEsQueryWrapper<ProductEntity> wrapper = new LambdaEsQueryWrapper<>();
+        EsPageInfo<ProductEntity> pageInfo = productEsMapper.pageQuery(wrapper,1,10);
+        return ResultVo.success(pageInfo);
+    }
+}
+
+
+
+

+ 61 - 0
src/main/java/com/example/demo/product/service/impl/ProductTicketServiceImpl.java

@@ -0,0 +1,61 @@
+package com.example.demo.product.service.impl;
+
+import cn.easyes.core.biz.EsPageInfo;
+import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.TokenUtils;
+import com.example.demo.product.domain.ProductTicket;
+import com.example.demo.product.entity.ProductTicketEntity;
+import com.example.demo.product.esmapper.ProductTicketEsMapper;
+import com.example.demo.product.service.ProductTicketService;
+import com.example.demo.product.dao.ProductTicketMapper;
+import com.example.demo.user.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author 徐乐
+* @description 针对表【product_ticket(门票产品扩展信息表)】的数据库操作Service实现
+* @createDate 2025-06-16 20:08:46
+*/
+@Service
+public class ProductTicketServiceImpl extends ServiceImpl<ProductTicketMapper, ProductTicket>
+    implements ProductTicketService{
+    @Autowired
+    private ProductTicketEsMapper productTicketEsMapper;
+
+    @Override
+    public ResultVo ticketSyncDataToEs() {
+        //创建索引
+        productTicketEsMapper.createIndex();
+        List<ProductTicket> ticketList = this.list();
+        List<ProductTicketEntity> productTicketEntityList = new ArrayList<>();
+        for (ProductTicket productTicket : ticketList) {
+            ProductTicketEntity productTicketEntity = new ProductTicketEntity();
+            productTicketEntity.setId(productTicket.getId());
+            productTicketEntity.setProductId(productTicket.getProductId());
+            productTicketEntity.setScenicName(productTicket.getScenicName());
+            productTicketEntity.setTicketType(productTicket.getTicketType());
+            productTicketEntity.setAddress(productTicket.getAddress());
+            productTicketEntity.setValidStartDate(productTicket.getValidStartDate());
+            productTicketEntity.setValidEndDate(productTicket.getValidEndDate());
+            productTicketEntityList.add(productTicketEntity);
+        }
+        productTicketEsMapper.insertBatch(productTicketEntityList);
+        return ResultVo.success("数据同步成功");
+    }
+
+    @Override
+    public ResultVo getTicketList(String token) {
+        Long userId = TokenUtils.getUserId(token);
+        if (userId==null){
+            return ResultVo.error(101,"请先登录");
+        }
+        LambdaEsQueryWrapper<ProductTicketEntity> wrapper = new LambdaEsQueryWrapper<>();
+        EsPageInfo<ProductTicketEntity> pageInfo = productTicketEsMapper.pageQuery(wrapper, 1, 20);
+        return ResultVo.success(pageInfo);
+    }
+}

+ 65 - 0
src/main/java/com/example/demo/product/service/impl/ProductTrainServiceImpl.java

@@ -0,0 +1,65 @@
+package com.example.demo.product.service.impl;
+
+import cn.easyes.core.biz.EsPageInfo;
+import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.TokenUtils;
+import com.example.demo.product.domain.ProductTrain;
+import com.example.demo.product.entity.ProductTrainEntity;
+import com.example.demo.product.esmapper.ProductTrainEsMapper;
+import com.example.demo.product.service.ProductTrainService;
+import com.example.demo.product.dao.ProductTrainMapper;
+import com.example.demo.user.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author 徐乐
+* @description 针对表【product_train(车票产品扩展信息表)】的数据库操作Service实现
+* @createDate 2025-06-10 20:12:01
+*/
+@Service
+public class ProductTrainServiceImpl extends ServiceImpl<ProductTrainMapper, ProductTrain>
+    implements ProductTrainService{
+    @Autowired
+    private ProductTrainEsMapper productTrainEsMapper;
+
+    @Override
+    public ResultVo trainSyncDataToEs() {
+        //创建索引
+        productTrainEsMapper.createIndex();
+        List<ProductTrain> trainList = this.list();
+        List<ProductTrainEntity> productTrainEntityList = new ArrayList<>();
+        for (ProductTrain productTrain : trainList) {
+            ProductTrainEntity productTrainEntity = new ProductTrainEntity();
+            productTrainEntity.setId(productTrain.getId());
+            productTrainEntity.setProductId(productTrain.getProductId());
+            productTrainEntity.setTrainNo(productTrain.getTrainNo());
+            productTrainEntity.setDepartureStation(productTrain.getDepartureStation());
+            productTrainEntity.setArrivalStation(productTrain.getArrivalStation());
+            productTrainEntity.setDepartureTime(productTrain.getDepartureTime());
+            productTrainEntity.setArrivalTime(productTrain.getArrivalTime());
+            productTrainEntityList.add(productTrainEntity);
+        }
+        productTrainEsMapper.insertBatch(productTrainEntityList);
+        return ResultVo.success("同步数据成功");
+    }
+
+    @Override
+    public ResultVo getTrainList(String token) {
+        Long userId = TokenUtils.getUserId(token);
+        if (userId==null){
+            return ResultVo.error(101,"请先登录");
+        }
+        LambdaEsQueryWrapper<ProductTrainEntity> wrapper = new LambdaEsQueryWrapper<>();
+        EsPageInfo<ProductTrainEntity> pageInfo = productTrainEsMapper.pageQuery(wrapper, 1, 20);
+        return ResultVo.success(pageInfo);
+    }
+}
+
+
+
+

+ 24 - 0
src/main/java/com/example/demo/scenic_spot/controller/ScenicSpotController.java

@@ -0,0 +1,24 @@
+package com.example.demo.scenic_spot.controller;
+
+import com.example.demo.scenic_spot.service.impl.ScenicSpotServiceImpl;
+import com.example.demo.user.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/scenicSpot")
+public class ScenicSpotController {
+    @Autowired
+    private ScenicSpotServiceImpl scenicSpotService;
+
+    @RequestMapping("/syncDataToEs")
+    public ResultVo syncDataToEs() {
+        return scenicSpotService.syncDataToEs();
+    }
+    @RequestMapping("/getScenicSpotList")
+    public ResultVo getScenicSpotList(@RequestHeader("token") String token) {
+        return scenicSpotService.getScenicSpotList(token);
+    }
+}

+ 20 - 0
src/main/java/com/example/demo/scenic_spot/dao/ScenicSpotMapper.java

@@ -0,0 +1,20 @@
+package com.example.demo.scenic_spot.dao;
+
+import com.example.demo.scenic_spot.domain.ScenicSpot;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 徐乐
+* @description 针对表【scenic_spot(景点信息表)】的数据库操作Mapper
+* @createDate 2025-06-17 14:17:18
+* @Entity com.example.demo.scenic_spot.domain.ScenicSpot
+*/
+@Mapper
+public interface ScenicSpotMapper extends BaseMapper<ScenicSpot> {
+
+}
+
+
+
+

+ 289 - 0
src/main/java/com/example/demo/scenic_spot/domain/ScenicSpot.java

@@ -0,0 +1,289 @@
+package com.example.demo.scenic_spot.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.math.BigDecimal;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 景点信息表
+ * @TableName scenic_spot
+ */
+@TableName(value ="scenic_spot")
+@Data
+public class ScenicSpot {
+    /**
+     * 景点ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 景点名称
+     */
+    private String name;
+
+    /**
+     * 景点拼音,用于拼音搜索
+     */
+    private String pinyin;
+
+    /**
+     * 景点描述
+     */
+    private String description;
+
+    /**
+     * 详细地址
+     */
+    private String address;
+
+    /**
+     * 所在城市
+     */
+    private String city;
+
+    /**
+     * 所在区县
+     */
+    private String district;
+
+    /**
+     * 经度(字符串格式)
+     */
+    private String longitudeStr;
+
+    /**
+     * 纬度(字符串格式)
+     */
+    private String latitudeStr;
+
+    /**
+     * 景点类型
+     */
+    private String category;
+
+    /**
+     * 景区等级
+     */
+    private String level;
+
+    /**
+     * 封面图片
+     */
+    private String coverImage;
+
+    /**
+     * 门票价格
+     */
+    private BigDecimal ticketPrice;
+
+    /**
+     * 优惠价格
+     */
+    private BigDecimal discountPrice;
+
+    /**
+     * 开放时间描述
+     */
+    private String openTime;
+
+    /**
+     * 营业时间(开始)
+     */
+    private Date openTimeStart;
+
+    /**
+     * 营业时间(结束)
+     */
+    private Date openTimeEnd;
+
+    /**
+     * 建议游玩时长(分钟)
+     */
+    private Integer recommendedTime;
+
+    /**
+     * 联系电话
+     */
+    private String contactPhone;
+
+    /**
+     * 官方网站
+     */
+    private String website;
+
+    /**
+     * 平均评分
+     */
+    private BigDecimal avgRating;
+
+    /**
+     * 是否热门景点
+     */
+    private Integer isHot;
+
+    /**
+     * 是否推荐景点
+     */
+    private Integer isRecommended;
+
+    /**
+     * 状态
+     */
+    private String status;
+
+    /**
+     * 景点标签,多个用逗号分隔
+     */
+    private String tags;
+
+    /**
+     * 创建人ID
+     */
+    private Long createdBy;
+
+    /**
+     * 创建时间
+     */
+    private Date createdTime;
+
+    /**
+     * 更新人ID
+     */
+    private Long updatedBy;
+
+    /**
+     * 更新时间
+     */
+    private Date updatedTime;
+
+    /**
+     * 是否删除 0:否 1:是
+     */
+    private Integer isDeleted;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        ScenicSpot other = (ScenicSpot) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
+            && (this.getPinyin() == null ? other.getPinyin() == null : this.getPinyin().equals(other.getPinyin()))
+            && (this.getDescription() == null ? other.getDescription() == null : this.getDescription().equals(other.getDescription()))
+            && (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress()))
+            && (this.getCity() == null ? other.getCity() == null : this.getCity().equals(other.getCity()))
+            && (this.getDistrict() == null ? other.getDistrict() == null : this.getDistrict().equals(other.getDistrict()))
+            && (this.getLongitudeStr() == null ? other.getLongitudeStr() == null : this.getLongitudeStr().equals(other.getLongitudeStr()))
+            && (this.getLatitudeStr() == null ? other.getLatitudeStr() == null : this.getLatitudeStr().equals(other.getLatitudeStr()))
+            && (this.getCategory() == null ? other.getCategory() == null : this.getCategory().equals(other.getCategory()))
+            && (this.getLevel() == null ? other.getLevel() == null : this.getLevel().equals(other.getLevel()))
+            && (this.getCoverImage() == null ? other.getCoverImage() == null : this.getCoverImage().equals(other.getCoverImage()))
+            && (this.getTicketPrice() == null ? other.getTicketPrice() == null : this.getTicketPrice().equals(other.getTicketPrice()))
+            && (this.getDiscountPrice() == null ? other.getDiscountPrice() == null : this.getDiscountPrice().equals(other.getDiscountPrice()))
+            && (this.getOpenTime() == null ? other.getOpenTime() == null : this.getOpenTime().equals(other.getOpenTime()))
+            && (this.getOpenTimeStart() == null ? other.getOpenTimeStart() == null : this.getOpenTimeStart().equals(other.getOpenTimeStart()))
+            && (this.getOpenTimeEnd() == null ? other.getOpenTimeEnd() == null : this.getOpenTimeEnd().equals(other.getOpenTimeEnd()))
+            && (this.getRecommendedTime() == null ? other.getRecommendedTime() == null : this.getRecommendedTime().equals(other.getRecommendedTime()))
+            && (this.getContactPhone() == null ? other.getContactPhone() == null : this.getContactPhone().equals(other.getContactPhone()))
+            && (this.getWebsite() == null ? other.getWebsite() == null : this.getWebsite().equals(other.getWebsite()))
+            && (this.getAvgRating() == null ? other.getAvgRating() == null : this.getAvgRating().equals(other.getAvgRating()))
+            && (this.getIsHot() == null ? other.getIsHot() == null : this.getIsHot().equals(other.getIsHot()))
+            && (this.getIsRecommended() == null ? other.getIsRecommended() == null : this.getIsRecommended().equals(other.getIsRecommended()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getTags() == null ? other.getTags() == null : this.getTags().equals(other.getTags()))
+            && (this.getCreatedBy() == null ? other.getCreatedBy() == null : this.getCreatedBy().equals(other.getCreatedBy()))
+            && (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.getIsDeleted() == null ? other.getIsDeleted() == null : this.getIsDeleted().equals(other.getIsDeleted()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result + ((getPinyin() == null) ? 0 : getPinyin().hashCode());
+        result = prime * result + ((getDescription() == null) ? 0 : getDescription().hashCode());
+        result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode());
+        result = prime * result + ((getCity() == null) ? 0 : getCity().hashCode());
+        result = prime * result + ((getDistrict() == null) ? 0 : getDistrict().hashCode());
+        result = prime * result + ((getLongitudeStr() == null) ? 0 : getLongitudeStr().hashCode());
+        result = prime * result + ((getLatitudeStr() == null) ? 0 : getLatitudeStr().hashCode());
+        result = prime * result + ((getCategory() == null) ? 0 : getCategory().hashCode());
+        result = prime * result + ((getLevel() == null) ? 0 : getLevel().hashCode());
+        result = prime * result + ((getCoverImage() == null) ? 0 : getCoverImage().hashCode());
+        result = prime * result + ((getTicketPrice() == null) ? 0 : getTicketPrice().hashCode());
+        result = prime * result + ((getDiscountPrice() == null) ? 0 : getDiscountPrice().hashCode());
+        result = prime * result + ((getOpenTime() == null) ? 0 : getOpenTime().hashCode());
+        result = prime * result + ((getOpenTimeStart() == null) ? 0 : getOpenTimeStart().hashCode());
+        result = prime * result + ((getOpenTimeEnd() == null) ? 0 : getOpenTimeEnd().hashCode());
+        result = prime * result + ((getRecommendedTime() == null) ? 0 : getRecommendedTime().hashCode());
+        result = prime * result + ((getContactPhone() == null) ? 0 : getContactPhone().hashCode());
+        result = prime * result + ((getWebsite() == null) ? 0 : getWebsite().hashCode());
+        result = prime * result + ((getAvgRating() == null) ? 0 : getAvgRating().hashCode());
+        result = prime * result + ((getIsHot() == null) ? 0 : getIsHot().hashCode());
+        result = prime * result + ((getIsRecommended() == null) ? 0 : getIsRecommended().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getTags() == null) ? 0 : getTags().hashCode());
+        result = prime * result + ((getCreatedBy() == null) ? 0 : getCreatedBy().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 + ((getIsDeleted() == null) ? 0 : getIsDeleted().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(", name=").append(name);
+        sb.append(", pinyin=").append(pinyin);
+        sb.append(", description=").append(description);
+        sb.append(", address=").append(address);
+        sb.append(", city=").append(city);
+        sb.append(", district=").append(district);
+        sb.append(", longitudeStr=").append(longitudeStr);
+        sb.append(", latitudeStr=").append(latitudeStr);
+        sb.append(", category=").append(category);
+        sb.append(", level=").append(level);
+        sb.append(", coverImage=").append(coverImage);
+        sb.append(", ticketPrice=").append(ticketPrice);
+        sb.append(", discountPrice=").append(discountPrice);
+        sb.append(", openTime=").append(openTime);
+        sb.append(", openTimeStart=").append(openTimeStart);
+        sb.append(", openTimeEnd=").append(openTimeEnd);
+        sb.append(", recommendedTime=").append(recommendedTime);
+        sb.append(", contactPhone=").append(contactPhone);
+        sb.append(", website=").append(website);
+        sb.append(", avgRating=").append(avgRating);
+        sb.append(", isHot=").append(isHot);
+        sb.append(", isRecommended=").append(isRecommended);
+        sb.append(", status=").append(status);
+        sb.append(", tags=").append(tags);
+        sb.append(", createdBy=").append(createdBy);
+        sb.append(", createdTime=").append(createdTime);
+        sb.append(", updatedBy=").append(updatedBy);
+        sb.append(", updatedTime=").append(updatedTime);
+        sb.append(", isDeleted=").append(isDeleted);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 200 - 0
src/main/java/com/example/demo/scenic_spot/entity/ScenicSpotEntity.java

@@ -0,0 +1,200 @@
+package com.example.demo.scenic_spot.entity;
+
+import cn.easyes.annotation.IndexField;
+import cn.easyes.annotation.IndexId;
+import cn.easyes.annotation.IndexName;
+import cn.easyes.annotation.rely.Analyzer;
+import cn.easyes.annotation.rely.FieldType;
+import cn.easyes.annotation.rely.IdType;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 景点信息表
+ *  scenic_spot
+ */
+@IndexName(value ="scenic_spot",shardsNum = 3,replicasNum = 2)
+@Data
+public class ScenicSpotEntity {
+    /**
+     * 景点ID
+     */
+    @IndexId(type = IdType.CUSTOMIZE)
+    private Long id;
+
+    /**
+     * 景点名称
+     */
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String name;
+
+    /**
+     * 景点拼音,用于拼音搜索
+     */
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String pinyin;
+
+    /**
+     * 景点描述
+     */
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String description;
+
+    /**
+     * 详细地址
+     */
+    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
+    private String address;
+
+    /**
+     * 所在城市
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String city;
+
+    /**
+     * 所在区县
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String district;
+
+    /**
+     * 经度(字符串格式)
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String longitudeStr;
+
+    /**
+     * 纬度(字符串格式)
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String latitudeStr;
+
+    /**
+     * 景点类型
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String category;
+
+    /**
+     * 景区等级
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String level;
+
+    /**
+     * 封面图片
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String coverImage;
+
+    /**
+     * 门票价格
+     */
+    @IndexField(fieldType = FieldType.DOUBLE)
+    private BigDecimal ticketPrice;
+
+    /**
+     * 优惠价格
+     */
+    @IndexField(fieldType = FieldType.DOUBLE)
+    private BigDecimal discountPrice;
+
+    /**
+     * 开放时间描述
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String openTime;
+
+    /**
+     * 营业时间(开始)
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date openTimeStart;
+
+    /**
+     * 营业时间(结束)
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date openTimeEnd;
+
+    /**
+     * 建议游玩时长(分钟)
+     */
+    @IndexField(fieldType = FieldType.INTEGER)
+    private Integer recommendedTime;
+
+    /**
+     * 联系电话
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String contactPhone;
+
+    /**
+     * 官方网站
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String website;
+
+    /**
+     * 平均评分
+     */
+    @IndexField(fieldType = FieldType.DOUBLE)
+    private BigDecimal avgRating;
+
+    /**
+     * 是否热门景点
+     */
+    @IndexField(fieldType = FieldType.INTEGER)
+    private Integer isHot;
+
+    /**
+     * 是否推荐景点
+     */
+    @IndexField(fieldType = FieldType.INTEGER)
+    private Integer isRecommended;
+
+    /**
+     * 状态
+     */
+    @IndexField(fieldType = FieldType.KEYWORD)
+    private String status;
+
+    /**
+     * 景点标签,多个用逗号分隔
+     */
+    @IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_MAX_WORD, searchAnalyzer = Analyzer.IK_MAX_WORD)
+    private String tags;
+
+    /**
+     * 创建人ID
+     */
+    @IndexField(fieldType = FieldType.LONG)
+    private Long createdBy;
+
+    /**
+     * 创建时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date createdTime;
+
+    /**
+     * 更新人ID
+     */
+    @IndexField(fieldType = FieldType.LONG)
+    private Long updatedBy;
+
+    /**
+     * 更新时间
+     */
+    @IndexField(fieldType = FieldType.DATE)
+    private Date updatedTime;
+
+    /**
+     * 是否删除 0:否 1:是
+     */
+    @IndexField(fieldType = FieldType.INTEGER)
+    private Integer isDeleted;
+}

+ 7 - 0
src/main/java/com/example/demo/scenic_spot/esmapper/ScenicSpotEsMapper.java

@@ -0,0 +1,7 @@
+package com.example.demo.scenic_spot.esmapper;
+
+import cn.easyes.core.conditions.interfaces.BaseEsMapper;
+import com.example.demo.scenic_spot.entity.ScenicSpotEntity;
+
+public interface ScenicSpotEsMapper extends BaseEsMapper<ScenicSpotEntity> {
+}

+ 17 - 0
src/main/java/com/example/demo/scenic_spot/service/ScenicSpotService.java

@@ -0,0 +1,17 @@
+package com.example.demo.scenic_spot.service;
+
+import com.example.demo.scenic_spot.domain.ScenicSpot;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.user.vo.ResultVo;
+
+/**
+* @author 徐乐
+* @description 针对表【scenic_spot(景点信息表)】的数据库操作Service
+* @createDate 2025-06-17 14:17:18
+*/
+public interface ScenicSpotService extends IService<ScenicSpot> {
+
+    ResultVo syncDataToEs();
+
+    ResultVo getScenicSpotList(String token);
+}

+ 90 - 0
src/main/java/com/example/demo/scenic_spot/service/impl/ScenicSpotServiceImpl.java

@@ -0,0 +1,90 @@
+package com.example.demo.scenic_spot.service.impl;
+
+import cn.easyes.core.biz.EsPageInfo;
+import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+import cn.hutool.core.util.IdUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.TokenUtils;
+import com.example.demo.scenic_spot.domain.ScenicSpot;
+import com.example.demo.scenic_spot.entity.ScenicSpotEntity;
+import com.example.demo.scenic_spot.esmapper.ScenicSpotEsMapper;
+import com.example.demo.scenic_spot.service.ScenicSpotService;
+import com.example.demo.scenic_spot.dao.ScenicSpotMapper;
+import com.example.demo.user.vo.ResultVo;
+import org.elasticsearch.client.indices.GetIndexResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author 徐乐
+* @description 针对表【scenic_spot(景点信息表)】的数据库操作Service实现
+* @createDate 2025-06-17 14:17:18
+*/
+@Service
+public class ScenicSpotServiceImpl extends ServiceImpl<ScenicSpotMapper, ScenicSpot>
+    implements ScenicSpotService{
+
+    @Autowired
+    private ScenicSpotEsMapper scenicSpotEsMapper;
+    @Override
+    public ResultVo syncDataToEs() {
+        //创建索引
+        scenicSpotEsMapper.createIndex();
+        List<ScenicSpot> scenicSpotList = this.list();
+        List<ScenicSpotEntity> scenicSpotEntityList = new ArrayList<>();
+        for (ScenicSpot scenicSpot : scenicSpotList) {
+            ScenicSpotEntity scenicSpotEntity = new ScenicSpotEntity();
+            scenicSpotEntity.setId(scenicSpot.getId());
+            scenicSpotEntity.setName(scenicSpot.getName());
+            scenicSpotEntity.setPinyin(scenicSpot.getPinyin());
+            scenicSpotEntity.setDescription(scenicSpot.getDescription());
+            scenicSpotEntity.setAddress(scenicSpot.getAddress());
+            scenicSpotEntity.setCity(scenicSpot.getCity());
+            scenicSpotEntity.setDistrict(scenicSpot.getDistrict());
+            scenicSpotEntity.setLongitudeStr(scenicSpot.getLongitudeStr());
+            scenicSpotEntity.setLatitudeStr(scenicSpot.getLatitudeStr());
+            scenicSpotEntity.setCategory(scenicSpot.getCategory());
+            scenicSpotEntity.setLevel(scenicSpot.getLevel());
+            scenicSpotEntity.setCoverImage(scenicSpot.getCoverImage());
+            scenicSpotEntity.setTicketPrice(scenicSpot.getTicketPrice());
+            scenicSpotEntity.setDiscountPrice(scenicSpot.getDiscountPrice());
+            scenicSpotEntity.setOpenTime(scenicSpot.getOpenTime());
+            scenicSpotEntity.setOpenTimeStart(scenicSpot.getOpenTimeStart());
+            scenicSpotEntity.setOpenTimeEnd(scenicSpot.getOpenTimeEnd());
+            scenicSpotEntity.setRecommendedTime(scenicSpot.getRecommendedTime());
+            scenicSpotEntity.setContactPhone(scenicSpot.getContactPhone());
+            scenicSpotEntity.setWebsite(scenicSpot.getWebsite());
+            scenicSpotEntity.setIsHot(scenicSpot.getIsHot());
+            scenicSpotEntity.setIsRecommended(scenicSpot.getIsRecommended());
+            scenicSpotEntity.setStatus(scenicSpot.getStatus());
+            scenicSpotEntity.setTags(scenicSpot.getTags());
+            scenicSpotEntity.setCreatedBy(scenicSpot.getCreatedBy());
+            scenicSpotEntity.setCreatedTime(scenicSpot.getCreatedTime());
+            scenicSpotEntity.setUpdatedBy(scenicSpot.getUpdatedBy());
+            scenicSpotEntity.setUpdatedTime(scenicSpot.getUpdatedTime());
+            scenicSpotEntity.setIsDeleted(scenicSpot.getIsDeleted());
+            scenicSpotEntityList.add(scenicSpotEntity);
+        }
+        scenicSpotEsMapper.insertBatch(scenicSpotEntityList, "scenic_spot");
+        return ResultVo.success("数据同步成功");
+    }
+
+    @Override
+    public ResultVo getScenicSpotList(String token) {
+        Long userId = TokenUtils.getUserId(token);
+        if (userId==null){
+            return ResultVo.error(101,"请先登录");
+        }
+        LambdaEsQueryWrapper<ScenicSpotEntity> wrapper = new LambdaEsQueryWrapper<>();
+        EsPageInfo<ScenicSpotEntity> pageInfo = scenicSpotEsMapper.pageQuery(wrapper, 1, 20);
+        return ResultVo.success(pageInfo);
+    }
+}
+
+
+
+

+ 0 - 5
src/main/java/com/example/demo/user/dto/UserDto.java

@@ -20,11 +20,6 @@ public class UserDto {
     private String phone;
 
     /**
-     * 用户邮箱
-     */
-    private String email;
-
-    /**
      * 头像地址
      */
     private String avatar;

+ 1 - 1
src/main/java/com/example/demo/user/service/impl/UserServiceImpl.java

@@ -65,7 +65,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
             //加密
             String md5Password = Md5Util.MD5(uuid + password);
             u.setPassword(md5Password);
-            u.setEmail(dto.getEmail());
+            u.setEmail(dto.getUsername()+"@example.com");
             u.setPhone(dto.getPhone());
             u.setAvatar(dto.getAvatar());
             userMapper.insert(u);

+ 10 - 1
src/main/resources/application.yml

@@ -17,4 +17,13 @@ mybatis-plus:
   configuration:
     map-underscore-to-camel-case: true
     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
-  mapper-locations: classpath:mapper/*.xml
+  mapper-locations: classpath:mapper/*.xml
+easy-es:
+  enable: true # 默认为true,若为false时,则认为不启用本框架
+  address: localhost:9200  #填你的es连接地址
+  global-config:
+    process-index-mode: manual
+
+logging:
+  level:
+    tracer: trace # 设置日志级别为trace,开发时可开启以打印ES全部请求信息及DSL语句

+ 22 - 0
src/main/resources/com/example/demo/product/mapper/ProductFlightMapper.xml

@@ -0,0 +1,22 @@
+<?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.example.demo.product.dao.ProductFlightMapper">
+
+    <resultMap id="BaseResultMap" type="com.example.demo.product.domain.ProductFlight">
+            <id property="id" column="id" />
+            <result property="productId" column="product_id" />
+            <result property="flightNo" column="flight_no" />
+            <result property="departureAirport" column="departure_airport" />
+            <result property="arrivalAirport" column="arrival_airport" />
+            <result property="departureTime" column="departure_time" />
+            <result property="arrivalTime" column="arrival_time" />
+            <result property="seatType" column="seat_type" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,product_id,flight_no,departure_airport,arrival_airport,departure_time,
+        arrival_time,seat_type
+    </sql>
+</mapper>

+ 21 - 0
src/main/resources/com/example/demo/product/mapper/ProductHotelMapper.xml

@@ -0,0 +1,21 @@
+<?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.example.demo.product.dao.ProductHotelMapper">
+
+    <resultMap id="BaseResultMap" type="com.example.demo.product.domain.ProductHotel">
+            <id property="id" column="id" />
+            <result property="productId" column="product_id" />
+            <result property="hotelName" column="hotel_name" />
+            <result property="roomType" column="room_type" />
+            <result property="address" column="address" />
+            <result property="checkinTime" column="checkin_time" />
+            <result property="checkoutTime" column="checkout_time" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,product_id,hotel_name,room_type,address,checkin_time,
+        checkout_time
+    </sql>
+</mapper>

+ 23 - 0
src/main/resources/com/example/demo/product/mapper/ProductMapper.xml

@@ -0,0 +1,23 @@
+<?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.example.demo.product.dao.ProductMapper">
+
+    <resultMap id="BaseResultMap" type="com.example.demo.product.domain.Product">
+            <id property="id" column="id" />
+            <result property="productType" column="product_type" />
+            <result property="title" column="title" />
+            <result property="price" column="price" />
+            <result property="stock" column="stock" />
+            <result property="description" column="description" />
+            <result property="coverImg" column="cover_img" />
+            <result property="createTime" column="create_time" />
+            <result property="updateTime" column="update_time" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,product_type,title,price,stock,description,
+        cover_img,create_time,update_time
+    </sql>
+</mapper>

+ 21 - 0
src/main/resources/com/example/demo/product/mapper/ProductTicketMapper.xml

@@ -0,0 +1,21 @@
+<?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.example.demo.product.dao.ProductTicketMapper">
+
+    <resultMap id="BaseResultMap" type="com.example.demo.product.domain.ProductTicket">
+            <id property="id" column="id" />
+            <result property="productId" column="product_id" />
+            <result property="scenicName" column="scenic_name" />
+            <result property="ticketType" column="ticket_type" />
+            <result property="address" column="address" />
+            <result property="validStartDate" column="valid_start_date" />
+            <result property="validEndDate" column="valid_end_date" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,product_id,scenic_name,ticket_type,address,valid_start_date,
+        valid_end_date
+    </sql>
+</mapper>

+ 22 - 0
src/main/resources/com/example/demo/product/mapper/ProductTrainMapper.xml

@@ -0,0 +1,22 @@
+<?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.example.demo.product.dao.ProductTrainMapper">
+
+    <resultMap id="BaseResultMap" type="com.example.demo.product.domain.ProductTrain">
+            <id property="id" column="id" />
+            <result property="productId" column="product_id" />
+            <result property="trainNo" column="train_no" />
+            <result property="departureStation" column="departure_station" />
+            <result property="arrivalStation" column="arrival_station" />
+            <result property="departureTime" column="departure_time" />
+            <result property="arrivalTime" column="arrival_time" />
+            <result property="seatType" column="seat_type" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,product_id,train_no,departure_station,arrival_station,departure_time,
+        arrival_time,seat_type
+    </sql>
+</mapper>

+ 49 - 0
src/main/resources/com/example/demo/scenic_spot/mapper/ScenicSpotMapper.xml

@@ -0,0 +1,49 @@
+<?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.example.demo.scenic_spot.dao.ScenicSpotMapper">
+
+    <resultMap id="BaseResultMap" type="com.example.demo.scenic_spot.domain.ScenicSpot">
+            <id property="id" column="id" />
+            <result property="name" column="name" />
+            <result property="pinyin" column="pinyin" />
+            <result property="description" column="description" />
+            <result property="address" column="address" />
+            <result property="city" column="city" />
+            <result property="district" column="district" />
+            <result property="longitudeStr" column="longitude_str" />
+            <result property="latitudeStr" column="latitude_str" />
+            <result property="category" column="category" />
+            <result property="level" column="level" />
+            <result property="coverImage" column="cover_image" />
+            <result property="ticketPrice" column="ticket_price" />
+            <result property="discountPrice" column="discount_price" />
+            <result property="openTime" column="open_time" />
+            <result property="openTimeStart" column="open_time_start" />
+            <result property="openTimeEnd" column="open_time_end" />
+            <result property="recommendedTime" column="recommended_time" />
+            <result property="contactPhone" column="contact_phone" />
+            <result property="website" column="website" />
+            <result property="avgRating" column="avg_rating" />
+            <result property="isHot" column="is_hot" />
+            <result property="isRecommended" column="is_recommended" />
+            <result property="status" column="status" />
+            <result property="tags" column="tags" />
+            <result property="createdBy" column="created_by" />
+            <result property="createdTime" column="created_time" />
+            <result property="updatedBy" column="updated_by" />
+            <result property="updatedTime" column="updated_time" />
+            <result property="isDeleted" column="is_deleted" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,name,pinyin,description,address,city,
+        district,longitude_str,latitude_str,category,level,
+        cover_image,ticket_price,discount_price,open_time,open_time_start,
+        open_time_end,recommended_time,contact_phone,website,avg_rating,
+        is_hot,is_recommended,status,tags,
+        created_by,created_time,updated_by,updated_time,
+        is_deleted
+    </sql>
+</mapper>

+ 33 - 0
src/test/java/com/example/demo/Driving.java

@@ -0,0 +1,33 @@
+package com.example.demo;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 20:00
+ * @PackageName:com.jsxs.TentcentMap.routePlanning
+ * @ClassName: Driving
+ * @Description: TODO  驾车
+ * @Version 1.0
+ */
+public class Driving {
+    public static JSONArray getDriving(String startLan,String startLon,String endLan,String endLon,String key){
+        String keyURL="https://apis.map.qq.com/ws/direction/v1/driving/?from="+startLan+","+startLon+"&to="+endLan+","+endLon+"&key="+key;
+        System.out.println(keyURL);
+        String s = TencentMapUtils.getTencentMap(keyURL).toString();
+        // 2. JSON字符串转换为JSON对象
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        JSONObject result = (JSONObject)jsonObject.get("result");
+        JSONArray routes = (JSONArray)result.get("routes");
+        return routes;
+    }
+    public static void main(String[] args) {
+        JSONArray array = getDriving("39.915285", "116.403857", "39.915285", "116.803857", "HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ");
+        System.out.println("总距离是:"+array.getJSONObject(0).get("distance")+"米");
+        System.out.println("预计消耗时间是:"+array.getJSONObject(0).get("duration")+"分钟");
+        // 详细方案的数组
+        JSONArray steps = (JSONArray)array.getJSONObject(0).get("steps");
+        for (int i = 0; i < steps.size(); i++) {
+            System.out.println(steps.getJSONObject(i).get("instruction")+" -》 注意是:"+steps.getJSONObject(i).get("act_desc"));
+        }
+    }
+}

+ 46 - 0
src/test/java/com/example/demo/TencentMapUtils.java

@@ -0,0 +1,46 @@
+package com.example.demo;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 13:37
+ * @PackageName:com.jsxs.TencentMapUtils
+ * @ClassName: TencentMapUtils
+ * @Description: TODO
+ * @Version 1.0
+ */
+public class TencentMapUtils {
+    // 1. 工具类
+    public static StringBuffer getTencentMap(String keyUrl){
+        //请求的url
+        URL url = null;
+        //请求的输入流
+        BufferedReader in = null;
+        //输入流的缓冲
+        StringBuffer sb = new StringBuffer();
+        try {
+            url = new URL(keyUrl);
+            in = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
+            String str = null;
+            //一行一行进行读入
+            while ((str = in.readLine()) != null) {
+                sb.append(str);
+            }
+        } catch (Exception ex) {
+            System.out.println("读取出现异常...");
+        } finally {
+            try {
+                if (in != null) {
+                    in.close(); //关闭流
+                }
+            } catch (IOException ex) {
+                System.out.println("关闭资源出现异常");
+            }finally {
+                return sb;
+            }
+        }
+    }
+}

+ 33 - 0
src/test/java/com/example/demo/Walking.java

@@ -0,0 +1,33 @@
+package com.example.demo;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 20:44
+ * @PackageName:com.jsxs.TentcentMap.routePlanning
+ * @ClassName: Walking
+ * @Description: TODO  步行
+ * @Version 1.0
+ */
+public class Walking {
+    public static JSONArray getWalking(String startLan,String startLon,String endLan,String endLon,String key){
+        String keyURL="https://apis.map.qq.com/ws/direction/v1/walking/?from="+startLan+","+startLon+"&to="+endLan+","+endLon+"&key="+key;
+        System.out.println(keyURL);
+        String s = TencentMapUtils.getTencentMap(keyURL).toString();
+        // 2. JSON字符串转换为JSON对象
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        JSONObject result = (JSONObject)jsonObject.get("result");
+        JSONArray routes = (JSONArray)result.get("routes");
+        return routes;
+    }
+    public static void main(String[] args) {
+        JSONArray array = getWalking("39.915285", "116.403857", "39.915285", "116.803857", "HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ");
+        System.out.println("总距离是:"+array.getJSONObject(0).get("distance")+"米");
+        System.out.println("预计消耗时间是:"+array.getJSONObject(0).get("duration")+"分钟");
+        // 详细方案的数组
+        JSONArray steps = (JSONArray)array.getJSONObject(0).get("steps");
+        for (int i = 0; i < steps.size(); i++) {
+            System.out.println(steps.getJSONObject(i).get("instruction")+" -》 注意是:"+steps.getJSONObject(i).get("act_desc"));
+        }
+    }
+}

+ 39 - 0
src/test/java/com/example/demo/addressResolution.java

@@ -0,0 +1,39 @@
+package com.example.demo;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/4 20:28
+ * @PackageName:com.jsxs
+ * @ClassName: getLineByAdress
+ * @Description: TODO  地址转经纬度
+ * @Version 1.0
+ */
+public class addressResolution {
+    public static Map<String, Object> getURLContent(String address) {
+        //这里需要使用你的key值⭐
+        String urlStr = "https://apis.map.qq.com/ws/geocoder/v1/?address=" + address + "&key=HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ";
+        // 1.这里是JSON字符串-通过哇能工具类获取
+        String result = TencentMapUtils.getTencentMap(urlStr).toString();
+        // 2.JSON字符串转JSON对象
+        JSONObject jsonObject = JSONObject.parseObject(result);
+        // 3. 强制转换 Object转换为 JSONObject-获取键值是: result的值
+        JSONObject result1 = (JSONObject)jsonObject.get("result");
+        // 4.在result的基础上继续获取键值是: location的值
+        JSONObject location = (JSONObject)result1.get("location");
+        // 5.在location的基础上获取: 经纬度的值
+        String lng = location.get("lng")+"";
+        String lat = location.get("lat")+"";
+        Map<String, Object> map = new HashMap<>();
+        map.put("lat", lat);
+        map.put("lng", lng);
+        return map;
+    }
+    public static void main(String[] args) {
+        Map<String, Object> map = getURLContent("吉林省长春市净月国家高新技术产业开发区福祉大路1016号长春工业大学人文信息学院");
+        System.out.println("lat=" + map.get("lat") + ",lng=" + map.get("lng"));
+    }
+}

+ 25 - 0
src/test/java/com/example/demo/addressStandardization.java

@@ -0,0 +1,25 @@
+package com.example.demo;
+import com.alibaba.fastjson.JSONObject;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 15:20
+ * @PackageName:com.jsxs.TentcentMap.addressStandardization
+ * @ClassName: addressStandardization
+ * @Description: TODO 地址标准化
+ * @Version 1.0
+ */
+public class addressStandardization {
+    public static String getAddressStandardization(String address,String key){
+        String keyURL="https://apis.map.qq.com/ws/smart_address/address_complete?address="+address+"&key="+key;
+        // 1.JSON字符串
+        String s = TencentMapUtils.getTencentMap(keyURL).toString();
+        // 2.JSON字符串转换为JSON对象
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        JSONObject result = (JSONObject)jsonObject.get("result");
+        String completed_address = result.get("completed_address")+"";
+        return completed_address;
+    }
+    public static void main(String[] args) {
+        System.out.println(getAddressStandardization("河南周口商水","HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ"));
+    }
+}

+ 33 - 0
src/test/java/com/example/demo/bicycling.java

@@ -0,0 +1,33 @@
+package com.example.demo;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 20:57
+ * @PackageName:com.jsxs.TentcentMap.routePlanning
+ * @ClassName: bicycling
+ * @Description: TODO
+ * @Version 1.0
+ */
+public class bicycling {
+    public static JSONArray getBicycling(String startLan,String startLon,String endLan,String endLon,String key){
+        String keyURL="https://apis.map.qq.com/ws/direction/v1/bicycling/?from="+startLan+","+startLon+"&to="+endLan+","+endLon+"&key="+key;
+        System.out.println(keyURL);
+        String s = TencentMapUtils.getTencentMap(keyURL).toString();
+        // 2. JSON字符串转换为JSON对象
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        JSONObject result = (JSONObject)jsonObject.get("result");
+        JSONArray routes = (JSONArray)result.get("routes");
+        return routes;
+    }
+    public static void main(String[] args) {
+        JSONArray array = getBicycling("39.915285", "116.403857", "39.915285", "116.803857", "HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ");
+        System.out.println("总距离是:"+array.getJSONObject(0).get("distance")+"米");
+        System.out.println("预计消耗时间是:"+array.getJSONObject(0).get("duration")+"分钟");
+        // 详细方案的数组
+        JSONArray steps = (JSONArray)array.getJSONObject(0).get("steps");
+        for (int i = 0; i < steps.size(); i++) {
+            System.out.println(steps.getJSONObject(i).get("instruction")+" -》 注意是:"+steps.getJSONObject(i).get("act_desc"));
+        }
+    }
+}

+ 67 - 0
src/test/java/com/example/demo/inverseAddressResolution.java

@@ -0,0 +1,67 @@
+package com.example.demo;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/4 19:39
+ * @PackageName:com.jsxs
+ * @ClassName: Test
+ * @Description: TODO  经纬度转地址
+ * @Version 1.0
+ */
+import com.alibaba.fastjson.JSONObject;
+import java.io.*;
+import java.net.URL;
+public class inverseAddressResolution {
+    /**
+     * 通过腾讯地图将经纬度转成详细地址
+     *
+     * @param lat 纬度
+     * @param lng 经度
+     * @param key 开发密钥(Key) 需自行申请
+     * @return
+     */
+    public static JSONObject getLatAndLng(String lat, String lng, String key) throws Exception {
+        // 1. 腾讯地图密钥
+        String hsUrl = "https://apis.map.qq.com/ws/geocoder/v1/?location=" + lat + "," + lng + "&key=" + key + "&get_poi=1";
+        // 2. 设置URL
+        URL url = null;
+        // 3. 设置缓存输入流()
+        BufferedReader in = null;
+        // 4. 设置缓冲区
+        StringBuffer sb = new StringBuffer();
+        try {
+            // 5. 初始化URL对象
+            url = new URL(hsUrl);
+            // 6. 初始化初始化
+            in = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
+            // 7.
+            String str = null;
+            // 8. 进行读取数据并写入数据(一行行读取)
+            while ((str = in.readLine()) != null) {
+            // 9. 添加到我们的字符串缓冲区
+                sb.append(str);
+            }
+        } catch (Exception ex) {
+            System.out.println("出现错误");
+        } finally {
+            try {
+                // 10. 关闭流
+                if (in != null) {
+                    in.close();
+                }
+            } catch (IOException ex) {
+            }
+        }
+        // 1.这里是JSON字符串
+        String result = sb.toString();
+        // 2.JSON字符串转换为JSON对象
+        JSONObject object = JSONObject.parseObject(result);
+        // 3.通过JSON对象获取result这个对象属性
+        JSONObject result1 = (JSONObject) object.get("result");
+        // 4.然后再次获取address_component这个对象。
+        JSONObject address_component = (JSONObject) result1.get("address_component");
+        return address_component;
+    }
+    public static void main(String[] args) throws Exception {
+        System.out.println(getLatAndLng("43.828281", "125.29985", "HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ"));
+    }
+}

+ 24 - 0
src/test/java/com/example/demo/ipPositioning.java

@@ -0,0 +1,24 @@
+package com.example.demo;
+import com.alibaba.fastjson.JSONObject;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 15:49
+ * @PackageName:com.jsxs.TentcentMap.ipPositioning
+ * @ClassName: ipPositioning
+ * @Description: TODO   IP定位
+ * @Version 1.0
+ */
+public class ipPositioning {
+    public static JSONObject getIpPositioning(String ip,String key){
+        String keyURL="https://apis.map.qq.com/ws/location/v1/ip?ip="+ip+"&key="+key;
+        String s = TencentMapUtils.getTencentMap(keyURL).toString();
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        JSONObject result = (JSONObject)jsonObject.get("result");
+        JSONObject ad_info = (JSONObject)result.get("ad_info");
+        return ad_info;
+    }
+    public static void main(String[] args) {
+        // 外网: 我们的服务器的IP就是外网。这里的IP是外网、不是局域网。
+        System.out.println(getIpPositioning("43.143.204.137","HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ"));
+    }
+}

+ 30 - 0
src/test/java/com/example/demo/keywordInputPrompt.java

@@ -0,0 +1,30 @@
+package com.example.demo;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 14:45
+ * @PackageName:com.jsxs.TentcentMap.keywordInputPrompt
+ * @ClassName: keywordInputPrompt
+ * @Description: TODO 关键词输入提示
+ * @Version 1.0
+ */
+public class keywordInputPrompt {
+    public static JSONArray getKeywordInputPrompt(String region,String keyword,String key){
+        String keyURL="https://apis.map.qq.com/ws/place/v1/suggestion/?region="+region+"&keyword="+keyword+"&key="+key;
+        // 1.JSON字符串
+        String s = TencentMapUtils.getTencentMap(keyURL).toString();
+        // 2.JSON字符串转JSON对象
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        // 3.获取JSON数组
+        JSONArray data = (JSONArray)jsonObject.get("data");
+        return data;
+    }
+    public static void main(String[] args) {
+        // 范围、关键字、密钥
+        JSONArray array = getKeywordInputPrompt("莲池", "公园", "HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ");
+        for (int i = 0; i < array.size(); i++) {
+            System.out.println(array.getJSONObject(i).get("title")+" "+array.getJSONObject(i).get("address"));
+        }
+    }
+}

+ 32 - 0
src/test/java/com/example/demo/locationSearch.java

@@ -0,0 +1,32 @@
+package com.example.demo;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+/**
+ * @Author Jsxs
+ * @Date 2023/4/5 13:55
+ * @PackageName:com.jsxs.TentcentMap.locationSearch
+ * @ClassName: locationSearch
+ * @Description: TODO  地点搜索
+ * @Version 1.0
+ */
+public class locationSearch {
+    public static JSONArray getLocationSearch(String latitude, String longitude, String radius, String keyword, String page_size, String page_index, String key) {
+        // latitude->维度  经度->longitude
+        String keyURL="https://apis.map.qq.com/ws/place/v1/search?boundary=nearby("+latitude+","+longitude+","+radius+")&keyword="+keyword+"&page_size="+page_size+"&page_index="+page_index+"&key="+key;
+        // 1.JSON字符串
+        String s = TencentMapUtils.getTencentMap(keyURL).toString();
+        // 2.JSON字符串转换为JSON对象
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        // 3.获取JSON数组
+        JSONArray data = (JSONArray)jsonObject.get("data");
+        return data;
+    }
+    public static void main(String[] args) {
+    // 经度 维度 半径/米 关键字 显示条数 显示页数 密钥
+        JSONArray array = getLocationSearch("40.040589", "116.273543", "1000", "公园", "10", "1", "HWTBZ-6YFLT-42BXH-VJFWR-YMUZS-T5FBJ");
+        // 遍历Json数组
+        for (int i = 0; i < array.size(); i++) {
+            System.out.println(array.getJSONObject(i).get("address"));
+        }
+    }
+}