Browse Source

0529 车票查询通过mysql

Qing 1 year ago
parent
commit
b08862fa7a
19 changed files with 1073 additions and 9 deletions
  1. 1 1
      12306-demo/my-ticket-service/src/main/java/com/sf/controller/TicketController.java
  2. 42 0
      12306-demo/my-ticket-service/src/main/java/com/sf/dto/domain/RouteDTO.java
  3. 42 0
      12306-demo/my-ticket-service/src/main/java/com/sf/dto/domain/SeatTypeCountDTO.java
  4. 82 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/SeatDO.java
  5. 61 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/StationDO.java
  6. 98 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainDO.java
  7. 91 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainStationDO.java
  8. 83 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainStationRelationDO.java
  9. 44 0
      12306-demo/my-ticket-service/src/main/java/com/sf/mapper/SeatMapper.java
  10. 29 0
      12306-demo/my-ticket-service/src/main/java/com/sf/mapper/StationMapper.java
  11. 29 0
      12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainMapper.java
  12. 28 0
      12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainStationMapper.java
  13. 29 0
      12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainStationPriceMapper.java
  14. 29 0
      12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainStationRelationMapper.java
  15. 3 1
      12306-demo/my-ticket-service/src/main/java/com/sf/service/TicketService.java
  16. 159 7
      12306-demo/my-ticket-service/src/main/java/com/sf/service/impl/TicketServiceImpl.java
  17. 76 0
      12306-demo/my-ticket-service/src/main/java/com/sf/util/DateUtil.java
  18. 95 0
      12306-demo/my-ticket-service/src/main/java/com/sf/util/StationCalculateUtil.java
  19. 52 0
      12306-demo/my-ticket-service/src/main/resources/mapper/SeatMapper.xml

+ 1 - 1
12306-demo/my-ticket-service/src/main/java/com/sf/controller/TicketController.java

@@ -19,7 +19,7 @@ public class TicketController {
     @GetMapping("/api/ticket-service/ticket/query")
     public Result<TicketPageQueryRespDTO> pageListTicketQuery(TicketPageQueryReqDTO requestParam) {
         System.out.println("TicketController pageListTicketQuery");
-        return Results.success(ticketService.pageListTicketQueryV1(requestParam));
+        return Results.success(ticketService.pageListTicketQueryByMysql(requestParam));
     }
 
 }

+ 42 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/dto/domain/RouteDTO.java

@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.dto.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 站点路线实体
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class RouteDTO {
+
+    /**
+     * 出发站点
+     */
+    private String startStation;
+
+    /**
+     * 目的站点
+     */
+    private String endStation;
+}

+ 42 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/dto/domain/SeatTypeCountDTO.java

@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.dto.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 座位类型和座位数量实体
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SeatTypeCountDTO {
+
+    /**
+     * 座位类型
+     */
+    private Integer seatType;
+
+    /**
+     * 座位类型 - 对应数量
+     */
+    private Integer seatCount;
+}

+ 82 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/entity/SeatDO.java

@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.opengoofy.index12306.framework.starter.database.base.BaseDO;
+
+/**
+ * 座位实体
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Data
+@TableName("t_seat")
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class SeatDO extends BaseDO {
+
+    /**
+     * id
+     */
+    private Long id;
+
+    /**
+     * 列车id
+     */
+    private Long trainId;
+
+    /**
+     * 车厢号
+     */
+    private String carriageNumber;
+
+    /**
+     * 座位号
+     */
+    private String seatNumber;
+
+    /**
+     * 座位类型
+     */
+    private Integer seatType;
+
+    /**
+     * 起始站
+     */
+    private String startStation;
+
+    /**
+     * 终点站
+     */
+    private String endStation;
+
+    /**
+     * 座位状态
+     */
+    private Integer seatStatus;
+
+    /**
+     * 车票价格
+     */
+    private Integer price;
+}

+ 61 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/entity/StationDO.java

@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import org.opengoofy.index12306.framework.starter.database.base.BaseDO;
+
+/**
+ * 车站实体
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Data
+@TableName("t_station")
+public class StationDO extends BaseDO {
+
+    /**
+     * id
+     */
+    private Long id;
+
+    /**
+     * 车站编码
+     */
+    private String code;
+
+    /**
+     * 车站名称
+     */
+    private String name;
+
+    /**
+     * 拼音
+     */
+    private String spell;
+
+    /**
+     * 地区编号
+     */
+    private String region;
+
+    /**
+     * 地区名称
+     */
+    private String regionName;
+}

+ 98 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainDO.java

@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import org.opengoofy.index12306.framework.starter.database.base.BaseDO;
+
+import java.util.Date;
+
+/**
+ * 列车实体
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Data
+@TableName("t_train")
+public class TrainDO extends BaseDO {
+
+    /**
+     * id
+     */
+    private Long id;
+
+    /**
+     * 列车车次
+     */
+    private String trainNumber;
+
+    /**
+     * 列车类型 0:高铁 1:动车 2:普通车
+     */
+    private Integer trainType;
+
+    /**
+     * 列车标签 0:复兴号 1:智能动车组 2:静音车厢 3:支持选铺
+     */
+    private String trainTag;
+
+    /**
+     * 列车品牌类型 0:GC-高铁/城际 1:D-动车 2:Z-直达 3:T-特快 4:K-快速 5:其他 6:复兴号 7:智能动车组
+     */
+    private String trainBrand;
+
+    /**
+     * 起始站
+     */
+    private String startStation;
+
+    /**
+     * 终点站
+     */
+    private String endStation;
+
+    /**
+     * 起始城市
+     */
+    private String startRegion;
+
+    /**
+     * 终点城市
+     */
+    private String endRegion;
+
+    /**
+     * 销售时间
+     */
+    private Date saleTime;
+
+    /**
+     * 销售状态 0:可售 1:不可售 2:未知
+     */
+    private Integer saleStatus;
+
+    /**
+     * 出发时间
+     */
+    private Date departureTime;
+
+    /**
+     * 到达时间
+     */
+    private Date arrivalTime;
+}

+ 91 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainStationDO.java

@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import org.opengoofy.index12306.framework.starter.database.base.BaseDO;
+
+import java.util.Date;
+
+/**
+ * 列车站点实体
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Data
+@TableName("t_train_station")
+public class TrainStationDO extends BaseDO {
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 车次id
+     */
+    private Long trainId;
+
+    /**
+     * 车站id
+     */
+    private Long stationId;
+
+    /**
+     * 站点顺序
+     */
+    private String sequence;
+
+    /**
+     * 出发站点
+     */
+    private String departure;
+
+    /**
+     * 到达站点
+     */
+    private String arrival;
+
+    /**
+     * 起始城市
+     */
+    private String startRegion;
+
+    /**
+     * 终点城市
+     */
+    private String endRegion;
+
+    /**
+     * 到站时间
+     */
+    private Date arrivalTime;
+
+    /**
+     * 出站时间
+     */
+    private Date departureTime;
+
+    /**
+     * 停留时间,单位分
+     */
+    private Integer stopoverTime;
+}

+ 83 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainStationRelationDO.java

@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import org.opengoofy.index12306.framework.starter.database.base.BaseDO;
+
+import java.util.Date;
+
+/**
+ * 列车站点关系实体
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Data
+@TableName("t_train_station_relation")
+public class TrainStationRelationDO extends BaseDO {
+
+    /**
+     * id
+     */
+    private Long id;
+
+    /**
+     * 车次id
+     */
+    private Long trainId;
+
+    /**
+     * 出发站点
+     */
+    private String departure;
+
+    /**
+     * 到达站点
+     */
+    private String arrival;
+
+    /**
+     * 起始城市
+     */
+    private String startRegion;
+
+    /**
+     * 终点城市
+     */
+    private String endRegion;
+
+    /**
+     * 始发站标识
+     */
+    private Boolean departureFlag;
+
+    /**
+     * 终点站标识
+     */
+    private Boolean arrivalFlag;
+
+    /**
+     * 出发时间
+     */
+    private Date departureTime;
+
+    /**
+     * 到达时间
+     */
+    private Date arrivalTime;
+}

+ 44 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/mapper/SeatMapper.java

@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sf.dto.domain.SeatTypeCountDTO;
+import com.sf.entity.SeatDO;
+import org.apache.ibatis.annotations.Param;
+
+
+
+import java.util.List;
+
+/**
+ * 座位持久层
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+public interface SeatMapper extends BaseMapper<SeatDO> {
+
+    /**
+     * 获取列车车厢余票集合
+     */
+    List<Integer> listSeatRemainingTicket(@Param("seatDO") SeatDO seatDO, @Param("trainCarriageList") List<String> trainCarriageList);
+
+    /**
+     * 获取列车 startStation 到 endStation 区间可用座位数量
+     */
+    List<SeatTypeCountDTO> listSeatTypeCount(@Param("trainId") Long trainId, @Param("startStation") String startStation, @Param("endStation") String endStation, @Param("seatTypes") List<Integer> seatTypes);
+}

+ 29 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/mapper/StationMapper.java

@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sf.entity.StationDO;
+
+
+/**
+ * 车站持久层
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+public interface StationMapper extends BaseMapper<StationDO> {
+}

+ 29 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainMapper.java

@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sf.entity.TrainDO;
+
+
+/**
+ * 列车持久层
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+public interface TrainMapper extends BaseMapper<TrainDO> {
+}

+ 28 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainStationMapper.java

@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sf.entity.TrainStationDO;
+
+/**
+ * 列车站点持久层
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+public interface TrainStationMapper extends BaseMapper<TrainStationDO> {
+}

+ 29 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainStationPriceMapper.java

@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sf.entity.TrainStationPriceDO;
+
+
+/**
+ * 列车站点价格持久层
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+public interface TrainStationPriceMapper extends BaseMapper<TrainStationPriceDO> {
+}

+ 29 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TrainStationRelationMapper.java

@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sf.entity.TrainStationRelationDO;
+
+
+/**
+ * 列车站点关系持久层
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+public interface TrainStationRelationMapper extends BaseMapper<TrainStationRelationDO> {
+}

+ 3 - 1
12306-demo/my-ticket-service/src/main/java/com/sf/service/TicketService.java

@@ -7,11 +7,13 @@ import com.sf.entity.TicketDO;
 
 public interface TicketService extends IService<TicketDO> {
 
+    TicketPageQueryRespDTO pageListTicketQueryByMysql(TicketPageQueryReqDTO requestParam);
+
     /**
      * 根据条件分页查询车票
      *
      * @param requestParam 分页查询车票请求参数
      * @return 查询车票返回结果
      */
-    TicketPageQueryRespDTO pageListTicketQueryV1(TicketPageQueryReqDTO requestParam);
+    TicketPageQueryRespDTO pageListTicketQueryByRedis(TicketPageQueryReqDTO requestParam);
 }

+ 159 - 7
12306-demo/my-ticket-service/src/main/java/com/sf/service/impl/TicketServiceImpl.java

@@ -1,6 +1,5 @@
 package com.sf.service.impl;
 
-import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -9,15 +8,18 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.Lists;
 import com.sf.dto.SeatClassDTO;
 import com.sf.dto.TicketListDTO;
+import com.sf.dto.domain.RouteDTO;
 import com.sf.dto.req.TicketPageQueryReqDTO;
 import com.sf.dto.resp.TicketPageQueryRespDTO;
-import com.sf.entity.TicketDO;
-import com.sf.entity.TrainStationPriceDO;
-import com.sf.mapper.TicketMapper;
+import com.sf.entity.*;
+import com.sf.mapper.*;
 import com.sf.service.TicketService;
+import com.sf.util.DateUtil;
+import com.sf.util.StationCalculateUtil;
 import com.sf.util.TimeStringComparator;
 import lombok.RequiredArgsConstructor;
 import org.opengoofy.index12306.framework.starter.cache.DistributedCache;
+import org.opengoofy.index12306.framework.starter.cache.toolkit.CacheUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
@@ -30,16 +32,167 @@ import java.util.stream.Collectors;
 
 import static com.sf.constant.Index12306Constant.ADVANCE_TICKET_DAY;
 import static com.sf.constant.RedisKeyConstant.*;
+import static com.sf.util.DateUtil.convertDateToLocalTime;
 
 @RequiredArgsConstructor
 @Service
 public class TicketServiceImpl extends ServiceImpl<TicketMapper, TicketDO> implements TicketService {
 
     private final DistributedCache distributedCache;
+    private final StationMapper stationMapper;
+    private final TrainStationRelationMapper trainStationRelationMapper;
+    private final TrainMapper trainMapper;
+    private final TrainStationPriceMapper trainStationPriceMapper;
+    private final TrainStationMapper trainStationMapper;
+    private final SeatMapper seatMapper;
+
+    @Override
+    public TicketPageQueryRespDTO pageListTicketQueryByMysql(TicketPageQueryReqDTO requestParam) {
+        System.out.println("TicketPageQueryRespDTO pageListTicketQueryByMysql");
+        // 准备stationDetails 找到出发站和到达站的名字
+        List<StationDO> stationDOList = stationMapper.selectList(Wrappers.emptyWrapper());
+        Map<String, String> regionTrainStationMap = new HashMap<>();
+        stationDOList.forEach(each -> regionTrainStationMap.put(each.getCode(), each.getRegionName()));
+
+        List<Object> stationDetails = new ArrayList<>();
+        stationDetails.add(regionTrainStationMap.get(requestParam.getFromStation()));
+        stationDetails.add(regionTrainStationMap.get(requestParam.getToStation()));
+
+        // 然后将两个名字作为参数 去 train_station_relation表中查询
+        LambdaQueryWrapper<TrainStationRelationDO> queryWrapper = Wrappers.lambdaQuery(TrainStationRelationDO.class)
+                .eq(TrainStationRelationDO::getStartRegion, stationDetails.get(0))
+                .eq(TrainStationRelationDO::getEndRegion, stationDetails.get(1));
+        List<TrainStationRelationDO> trainStationRelationList = trainStationRelationMapper.selectList(queryWrapper);
+
+        // 将TrainDO和TrainStationRelationDO中的数据整合在一起
+        List<TicketListDTO> seatResults = new ArrayList<>();
+        Map<Object, Object> regionTrainStationAllMap = new HashMap<>();
+        for (TrainStationRelationDO each : trainStationRelationList) {
+            TrainDO trainDO = trainMapper.selectById(each.getTrainId());
+
+            TicketListDTO result = new TicketListDTO();
+            result.setTrainId(String.valueOf(trainDO.getId()));
+            result.setTrainNumber(trainDO.getTrainNumber());
+            result.setDepartureTime(convertDateToLocalTime(each.getDepartureTime(), "HH:mm"));
+            result.setArrivalTime(convertDateToLocalTime(each.getArrivalTime(), "HH:mm"));
+            result.setDuration(DateUtil.calculateHourDifference(each.getDepartureTime(), each.getArrivalTime()));
+            result.setDeparture(each.getDeparture());
+            result.setArrival(each.getArrival());
+            result.setDepartureFlag(each.getDepartureFlag());
+            result.setArrivalFlag(each.getArrivalFlag());
+            result.setTrainType(trainDO.getTrainType());
+            result.setTrainBrand(trainDO.getTrainBrand());
+            if (StrUtil.isNotBlank(trainDO.getTrainTag())) {
+                result.setTrainTags(StrUtil.split(trainDO.getTrainTag(), ","));
+            }
+            long betweenDay = cn.hutool.core.date.DateUtil.betweenDay(each.getDepartureTime(), each.getArrivalTime(), false);
+            result.setDaysArrived((int) betweenDay);
+            result.setSaleStatus(new Date().after(trainDO.getSaleTime()) ? 0 : 1);
+            result.setSaleTime(convertDateToLocalTime(trainDO.getSaleTime(), "MM-dd HH:mm"));
+            seatResults.add(result);
+            regionTrainStationAllMap.put(
+                    // TrainId_Departure_Arrival
+                    CacheUtil.buildKey(String.valueOf(each.getTrainId()), each.getDeparture(), each.getArrival()),
+                    JSON.toJSONString(result));
+        }
+        // 按照出发时间排序
+        seatResults = seatResults.stream().sorted(new TimeStringComparator()).toList();
+
+        for (TicketListDTO each : seatResults) {
+            LambdaQueryWrapper<TrainStationPriceDO> trainStationPriceQueryWrapper = Wrappers.lambdaQuery(TrainStationPriceDO.class)
+                    .eq(TrainStationPriceDO::getDeparture, each.getDeparture())
+                    .eq(TrainStationPriceDO::getArrival, each.getArrival())
+                    .eq(TrainStationPriceDO::getTrainId, each.getTrainId());
+            List<TrainStationPriceDO> trainStationPriceDOList = trainStationPriceMapper.selectList(trainStationPriceQueryWrapper);
+
+            List<SeatClassDTO> seatClassList = new ArrayList<>();
+            trainStationPriceDOList.forEach(item -> {
+                String trainId = each.getTrainId();
+                String departure = item.getDeparture();
+                String arrival = item.getArrival();
+
+                //  Map<String, String> seatMarginMap = seatMarginCacheLoader.load(
+                //       String.valueOf(each.getTrainId()), seatType, item.getDeparture(), item.getArrival());
+                Map<String, Map<String, String>> trainStationRemainingTicketMaps = new LinkedHashMap<>();
+                String keySuffix = CacheUtil.buildKey(trainId, departure, arrival);
+                TrainDO trainDO = trainMapper.selectById(each.getTrainId());
+                LambdaQueryWrapper<TrainStationDO> queryWrapperNew = Wrappers.lambdaQuery(TrainStationDO.class)
+                        .eq(TrainStationDO::getTrainId, trainId)
+                        .select(TrainStationDO::getDeparture);
+                List<TrainStationDO> trainStationDOList = trainStationMapper.selectList(queryWrapperNew);
+                List<String> trainStationAllList = trainStationDOList.stream().map(TrainStationDO::getDeparture).collect(Collectors.toList());
+                // 计算出发站和终点站中间的站点
+                List<RouteDTO> routeDTOList = StationCalculateUtil.throughStation(trainStationAllList, departure, arrival);
+
+                // 假设不为空
+                switch (trainDO.getTrainType()) {
+                    // TODO 通过已有列车类型座位枚举重构
+                    case 0 -> {
+                        for (RouteDTO routeDTO : routeDTOList) {
+                            Map<String, String> trainStationRemainingTicket = new LinkedHashMap<>();
+                            trainStationRemainingTicket.put("0", selectSeatMargin(trainId, 0, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("1", selectSeatMargin(trainId, 1, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("2", selectSeatMargin(trainId, 2, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            String actualKeySuffix = CacheUtil.buildKey(trainId, routeDTO.getStartStation(), routeDTO.getEndStation());
+                            trainStationRemainingTicketMaps.put(TRAIN_STATION_REMAINING_TICKET + actualKeySuffix, trainStationRemainingTicket);
+                        }
+                    }
+                    case 1 -> {
+                        for (RouteDTO routeDTO : routeDTOList) {
+                            Map<String, String> trainStationRemainingTicket = new LinkedHashMap<>();
+                            trainStationRemainingTicket.put("3", selectSeatMargin(trainId, 3, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("4", selectSeatMargin(trainId, 4, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("5", selectSeatMargin(trainId, 5, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("13", selectSeatMargin(trainId, 13, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            String actualKeySuffix = CacheUtil.buildKey(trainId, routeDTO.getStartStation(), routeDTO.getEndStation());
+                            trainStationRemainingTicketMaps.put(TRAIN_STATION_REMAINING_TICKET + actualKeySuffix, trainStationRemainingTicket);
+                        }
+                    }
+                    case 2 -> {
+                        for (RouteDTO routeDTO : routeDTOList) {
+                            Map<String, String> trainStationRemainingTicket = new LinkedHashMap<>();
+                            trainStationRemainingTicket.put("6", selectSeatMargin(trainId, 6, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("7", selectSeatMargin(trainId, 7, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("8", selectSeatMargin(trainId, 8, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            trainStationRemainingTicket.put("13", selectSeatMargin(trainId, 13, routeDTO.getStartStation(), routeDTO.getEndStation()));
+                            String actualKeySuffix = CacheUtil.buildKey(trainId, routeDTO.getStartStation(), routeDTO.getEndStation());
+                            trainStationRemainingTicketMaps.put(TRAIN_STATION_REMAINING_TICKET + actualKeySuffix, trainStationRemainingTicket);
+                        }
+                    }
+                }
+
+                Map<String, String> seatMarginMap = trainStationRemainingTicketMaps.get(TRAIN_STATION_REMAINING_TICKET + keySuffix);
+                int quantity = Integer.parseInt(seatMarginMap.get(String.valueOf(item.getSeatType())));
+
+                seatClassList.add(new SeatClassDTO(
+                        item.getSeatType(), quantity,
+                        new BigDecimal(item.getPrice()).divide(new BigDecimal("100"), 1, RoundingMode.HALF_UP), false));
+            });
+            each.setSeatClassList(seatClassList);
+        }
+
+        return TicketPageQueryRespDTO.builder()
+                .trainList(seatResults)
+                .departureStationList(buildDepartureStationList(seatResults))
+                .arrivalStationList(buildArrivalStationList(seatResults))
+                .trainBrandList(buildTrainBrandList(seatResults))
+                .seatClassTypeList(buildSeatClassList(seatResults))
+                .build();
+    }
+
+    private String selectSeatMargin(String trainId, Integer type, String departure, String arrival) {
+        LambdaQueryWrapper<SeatDO> queryWrapper = Wrappers.lambdaQuery(SeatDO.class)
+                .eq(SeatDO::getTrainId, trainId)
+                .eq(SeatDO::getSeatType, type)
+                .eq(SeatDO::getSeatStatus, 0)
+                .eq(SeatDO::getStartStation, departure)
+                .eq(SeatDO::getEndStation, arrival);
+        return String.valueOf(seatMapper.selectCount(queryWrapper));
+    }
 
     // http://localhost:9000/api/ticket-service/ticket/query?fromStation=BJP&toStation=HZH&departureDate=2024-05-15
     @Override
-    public TicketPageQueryRespDTO pageListTicketQueryV1(TicketPageQueryReqDTO requestParam) {
+    public TicketPageQueryRespDTO pageListTicketQueryByRedis(TicketPageQueryReqDTO requestParam) {
 
         StringRedisTemplate stringRedisTemplate = (StringRedisTemplate) distributedCache.getInstance();
 
@@ -88,8 +241,7 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, TicketDO> imple
                 // 获取每个席别对应的票数
                 Object quantityObj = stringRedisTemplate.opsForHash().get(TRAIN_STATION_REMAINING_TICKET + keySuffix, seatType);
                 int quantity = Optional.ofNullable(quantityObj).map(Object::toString).map(Integer::parseInt).get();
-                seatClassList.add(new SeatClassDTO(
-                        item.getSeatType(), quantity,
+                seatClassList.add(new SeatClassDTO(item.getSeatType(), quantity,
                         new BigDecimal(item.getPrice()).divide(new BigDecimal("100"), 1, RoundingMode.HALF_UP),
                         false));
             });

+ 76 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/util/DateUtil.java

@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.util;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+
+import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+
+/**
+ * 日期工具类
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+@Slf4j
+public final class DateUtil {
+
+    /**
+     * 计算小时差
+     *
+     * @param startTime 开始时间 2022-10-01 00:00:00
+     * @param endTime   结束时间 2022-10-01 12:23:00
+     * @return 12:23
+     */
+    public static String calculateHourDifference(Date startTime, Date endTime) {
+        LocalDateTime startDateTime = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+        LocalDateTime endDateTime = endTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+        Duration duration = Duration.between(startDateTime, endDateTime);
+        long hours = duration.toHours();
+        long minutes = duration.toMinutes() % 60;
+        return String.format("%02d:%02d", hours, minutes);
+    }
+
+    /**
+     * 日期转换为列车行驶开始时间和结束时间
+     *
+     * @param date    时间
+     * @param pattern 日期格式
+     * @return 日期格式对应的时间
+     */
+    public static String convertDateToLocalTime(Date date, String pattern) {
+        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(pattern);
+        return localDateTime.format(outputFormatter);
+    }
+
+    @SneakyThrows
+    public static void main(String[] args) {
+        String startTimeStr = "2022-10-01 01:00:00";
+        String endTimeStr = "2022-10-01 12:23:00";
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date startTime = formatter.parse(startTimeStr);
+        Date endTime = formatter.parse(endTimeStr);
+        String calculateHourDifference = calculateHourDifference(startTime, endTime);
+        log.info("开始时间:{},结束时间:{},两个时间相差时分:{}", startTimeStr, endTimeStr, calculateHourDifference);
+    }
+}

+ 95 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/util/StationCalculateUtil.java

@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sf.util;
+
+
+import com.sf.dto.domain.RouteDTO;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 站点计算工具
+ * 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
+ */
+public final class StationCalculateUtil {
+
+    /**
+     * 计算出发站和终点站中间的站点(包含出发站和终点站)
+     *
+     * @param stations     所有站点数据
+     * @param startStation 出发站
+     * @param endStation   终点站
+     * @return 出发站和终点站中间的站点(包含出发站和终点站)
+     */
+    public static List<RouteDTO> throughStation(List<String> stations, String startStation, String endStation) {
+        List<RouteDTO> routesToDeduct = new ArrayList<>();
+        int startIndex = stations.indexOf(startStation);
+        int endIndex = stations.indexOf(endStation);
+        if (startIndex < 0 || endIndex < 0 || startIndex >= endIndex) {
+            return routesToDeduct;
+        }
+        for (int i = startIndex; i < endIndex; i++) {
+            for (int j = i + 1; j <= endIndex; j++) {
+                String currentStation = stations.get(i);
+                String nextStation = stations.get(j);
+                RouteDTO routeDTO = new RouteDTO(currentStation, nextStation);
+                routesToDeduct.add(routeDTO);
+            }
+        }
+        return routesToDeduct;
+    }
+
+    /**
+     * 计算出发站和终点站需要扣减余票的站点(包含出发站和终点站)
+     *
+     * @param stations     所有站点数据
+     * @param startStation 出发站
+     * @param endStation   终点站
+     * @return 出发站和终点站需要扣减余票的站点(包含出发站和终点站)
+     */
+    public static List<RouteDTO> takeoutStation(List<String> stations, String startStation, String endStation) {
+        List<RouteDTO> takeoutStationList = new ArrayList<>();
+        int startIndex = stations.indexOf(startStation);
+        int endIndex = stations.indexOf(endStation);
+        if (startIndex == -1 || endIndex == -1 || startIndex >= endIndex) {
+            return takeoutStationList;
+        }
+        if (startIndex != 0) {
+            for (int i = 0; i < startIndex; i++) {
+                for (int j = 1; j < stations.size() - startIndex; j++) {
+                    takeoutStationList.add(new RouteDTO(stations.get(i), stations.get(startIndex + j)));
+                }
+            }
+        }
+        for (int i = startIndex; i <= endIndex; i++) {
+            for (int j = i + 1; j < stations.size() && i < endIndex; j++) {
+                takeoutStationList.add(new RouteDTO(stations.get(i), stations.get(j)));
+            }
+        }
+        return takeoutStationList;
+    }
+
+    public static void main(String[] args) {
+        List<String> stations = Arrays.asList("北京南", "济南西", "南京南", "杭州东", "宁波");
+        String startStation = "北京南";
+        String endStation = "南京南";
+        StationCalculateUtil.takeoutStation(stations, startStation, endStation).forEach(System.out::println);
+    }
+}

+ 52 - 0
12306-demo/my-ticket-service/src/main/resources/mapper/SeatMapper.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.sf.mapper.SeatMapper">
+
+    <!-- 获取列车车厢余票集合 -->
+    <select id="listSeatRemainingTicket" parameterType="com.sf.entity.SeatDO"
+            resultType="Integer">
+        select count(*) as count
+        from t_seat
+        where train_id = #{seatDO.trainId}
+        and start_station = #{seatDO.startStation}
+        and end_station = #{seatDO.endStation}
+        and seat_status = '0'
+        and carriage_number in
+        <foreach collection="trainCarriageList" item="carriage" open="(" separator="," close=")">
+            #{carriage}
+        </foreach>
+        group by carriage_number
+    </select>
+
+    <select id="listSeatTypeCount" resultType="com.sf.dto.domain.SeatTypeCountDTO">
+        select seat_type as seatType, count(*) as seatCount
+        from t_seat
+        where train_id = #{trainId}
+        and start_station = #{startStation}
+        and end_station = #{endStation}
+        and seat_status = '0'
+        and seat_type in
+        <foreach collection="seatTypes" item="seatType" open="(" separator="," close=")">
+            #{seatType}
+        </foreach>
+        group by seat_type
+        having seatCount > 0
+    </select>
+</mapper>