Commit 32c634a1 authored by Administrator's avatar Administrator

班车模块接口

parent 5849a12a
package com.dlbridge.jadp.plugins.cmpt.dao.mapper;
import com.dlbridge.jadp.plugins.cmpt.dto.BusSchedule;
import com.dlbridge.jadp.plugins.cmpt.dto.BusStation;
import com.dlbridge.jadp.plugins.cmpt.dto.BusTicketVerification;
import com.dlbridge.jadp.plugins.cmpt.dto.BusVerificationRecord;
import feign.Param;
import java.util.List;
public interface BusMapper {
/**
* 通过证件号查询购票列表
* @param idNumber
* @return
*/
List<BusTicketVerification> selectTicketByIdNumber(@Param("cmptId") Integer cmptId, @Param("idNumber") String idNumber);
/**
* 通过票号查询车票信息
* @param ticketNo 票号
* @return
*/
BusTicketVerification selectTicketByTicketNo(@Param("cmptId") Integer cmptId, @Param("ticketNo") String ticketNo);
/**
* 核销信息查询
* @param idNumber 证件号
* @param scheduleId 班次ID
* @return
*/
BusTicketVerification selectTicketForVerification(@Param("cmptId") Integer cmptId, @Param("idNumber") String idNumber,
@Param("scheduleId") Integer scheduleId);
/**
* 核销车票
* @param ticketVerification
* @return
*/
int updateVerificationInfo(BusTicketVerification ticketVerification);
/**
* 保存核销记录
* @param record
* @return
*/
int insertVerificationRecord(BusVerificationRecord record);
/**
* 查询赛事班车班次列表
* @param cmptId 赛事ID
* @return
*/
List<BusSchedule> selectSchedulesByCmptId(@Param("cmptId") Integer cmptId);
BusSchedule selectScheduleById(@Param("id") Long id);
/**
* 查询班车站点列表
* @param scheduleId 班次ID
* @return
*/
List<BusStation> selectStationsByScheduleId(@Param("scheduleId") Integer scheduleId);
List<BusStation> selectStationsByCmptId(@Param("cmptId") Integer cmptId);
}
<?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.dlbridge.jadp.plugins.cmpt.dao.mapper.BusMapper">
<resultMap id="BaseResultMap" type="com.dlbridge.jadp.plugins.cmpt.dto.BusTicketVerification">
<id column="id" property="id" />
<result column="cmpt_id" property="cmptId" />
<result column="ticket_no" property="ticketNo" />
<result column="schedule_id" property="scheduleId" />
<result column="passenger_name" property="passengerName" />
<result column="passenger_phone" property="passengerPhone" />
<result column="id_number" property="idNumber" />
<result column="boarding_station_id" property="boardingStationId" />
<result column="alighting_station_id" property="alightingStationId" />
<result column="purchase_time" property="purchaseTime" />
<result column="verification_count" property="verificationCount" />
<result column="last_verification_time" property="lastVerificationTime" />
<result column="ticket_status" property="ticketStatus" />
<result column="seat_number" property="seatNumber" />
<result column="ticket_price" property="ticketPrice" />
<!-- 关联字段 -->
<result column="schedule_name" property="scheduleName" />
<result column="license_plate" property="licensePlate" />
<result column="departure_time_from" property="departureTimeFrom" />
<result column="departure_time_to" property="departureTimeTo" />
<result column="allow_multiple_verification" property="allowMultipleVerification" />
</resultMap>
<select id="selectTicketByIdNumber" resultMap="BaseResultMap">
SELECT tv.*,
bs.schedule_name,
bs.license_plate,
bs.departure_time_from,
bs.departure_time_to
FROM gksite.bus_ticket_verification tv
LEFT JOIN gksite.bus_schedule bs ON tv.schedule_id = bs.id
WHERE tv.cmpt_id = #{cmptId}
AND tv.id_number = #{idNumber}
AND tv.ticket_status IN (1, 2) -- 已购买或已使用
AND tv.del_flag = 0
ORDER BY bs.departure_time_from DESC
</select>
<select id="selectTicketByTicketNo" resultMap="BaseResultMap">
SELECT tv.*,
bs.schedule_name,
bs.license_plate,
bs.departure_time_from,
bs.departure_time_to
FROM gksite.bus_ticket_verification tv
LEFT JOIN gksite.bus_schedule bs ON tv.schedule_id = bs.id
WHERE tv.cmpt_id = #{cmptId}
AND tv.ticket_no = #{ticketNo}
AND tv.del_flag = 0
</select>
<select id="selectTicketForVerification" resultMap="BaseResultMap">
SELECT tv.*,
bs.schedule_name,
bs.license_plate,
bs.departure_time_from,
bs.departure_time_to,
bs.allow_multiple_verification
FROM gksite.bus_ticket_verification tv
LEFT JOIN gksite.bus_schedule bs ON tv.schedule_id = bs.id
WHERE tv.cmpt_id = #{cmptId}
AND tv.id_number = #{idNumber}
AND tv.schedule_id = #{scheduleId}
AND tv.del_flag = 0
</select>
<update id="updateVerificationInfo">
UPDATE gksite.bus_ticket_verification
SET verification_count = #{verificationCount},
last_verification_time = NOW(),
ticket_status = #{ticketStatus},
update_time = NOW()
WHERE cmpt_id = #{cmptId}
AND ticket_no = #{ticketNo}
</update>
<insert id="insertVerificationRecord" parameterType="com.dlbridge.jadp.plugins.cmpt.dto.BusVerificationRecord"
useGeneratedKeys="true" keyProperty="id">
INSERT INTO gksite.bus_verification_record
(cmpt_id,
ticket_id,
ticket_no,
schedule_id,
verification_time,
verification_station_id,
verifier_id,
device_id,
create_time)
VALUES (#{cmptId},
#{ticketId},
#{ticketNo},
#{scheduleId},
now(),
#{verificationStationId},
#{verifierId},
#{deviceId},
now())
</insert>
<resultMap id="SchedulesResultMap" type="com.dlbridge.jadp.plugins.cmpt.dto.BusSchedule">
<id column="id" property="id" />
<result column="cmpt_id" property="cmptId" />
<result column="schedule_name" property="scheduleName" />
<result column="license_plate" property="licensePlate" />
<result column="start_station_id" property="startStationId" />
<result column="end_station_id" property="endStationId" />
<result column="departure_time_from" property="departureTimeFrom" />
<result column="departure_time_to" property="departureTimeTo" />
<result column="driver_name" property="driverName" />
<result column="driver_phone" property="driverPhone" />
<result column="volunteer_name" property="volunteerName" />
<result column="volunteer_phone" property="volunteerPhone" />
<result column="allow_multiple_verification" property="allowMultipleVerification" />
<result column="total_seats" property="totalSeats" />
<result column="available_seats" property="availableSeats" />
<result column="ticket_price" property="ticketPrice" />
<result column="remark1" property="remark1" />
<result column="remark2" property="remark2" />
<result column="status" property="status" />
<result column="create_time" property="createTime" />
<result column="update_time" property="updateTime" />
</resultMap>
<select id="selectSchedulesByCmptId" resultMap="SchedulesResultMap">
SELECT
id, cmpt_id, schedule_name, license_plate, departure_time_from, departure_time_to, remark1, remark2
FROM gksite.bus_schedule
WHERE cmpt_id = #{cmptId}
AND status = 1 -- 正常状态
AND del_flag = 0
ORDER BY departure_time_from ASC
</select>
<select id="selectScheduleById" resultMap="SchedulesResultMap">
SELECT * FROM gksite.bus_schedule WHERE id = #{id}
</select>
<resultMap id="StationsResultMap" type="com.dlbridge.jadp.plugins.cmpt.dto.BusStation">
<id column="id" property="id" />
<result column="cmpt_id" property="cmptId" />
<result column="station_name" property="stationName" />
<result column="station_description" property="stationDescription" />
<result column="station_coordinates" property="stationCoordinates" />
<result column="station_address" property="stationAddress" />
<result column="station_order" property="stationOrder" />
<result column="status" property="status" />
</resultMap>
<select id="selectStationsByScheduleId" resultMap="StationsResultMap">
SELECT bs.*,
ssr.station_order
FROM gksite.bus_station bs
INNER JOIN gksite.bus_schedule_station ssr ON bs.id = ssr.station_id
WHERE bs.del_flag = 0
AND ssr.schedule_id = #{scheduleId}
ORDER BY ssr.station_order ASC
</select>
<select id="selectStationsByCmptId" resultMap="StationsResultMap">
SELECT bs.*
FROM gksite.bus_station bs
WHERE bs.del_flag = 0
AND bs.cmpt_id = #{cmptId}
</select>
</mapper>
\ No newline at end of file
package com.dlbridge.jadp.plugins.cmpt.dao.model.param;
import lombok.Data;
@Data
public class BusParam {
private Integer cmptId;
private String ticketNo;
private Integer scheduleId;
private String idNumber;
private Long qrTimestamp;
private String verifierId;
private String deviceId;
}
package com.dlbridge.jadp.plugins.cmpt.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 班车模块:班次表
*/
@Data
public class BusSchedule {
private Integer id;
private Integer cmptId;
private String scheduleName;
private String licensePlate;
private Integer startStationId;
private Integer endStationId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime departureTimeFrom;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime departureTimeTo;
private String driverName;
private String driverPhone;
private String volunteerName;
private String volunteerPhone;
private Integer allowMultipleVerification;
private Integer totalSeats;
private Integer availableSeats;
private BigDecimal ticketPrice;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime scheduleDate;
private Integer status;
private String remark1;
private String remark2;
// 关联字段
private String startStationName;
private String endStationName;
}
\ No newline at end of file
package com.dlbridge.jadp.plugins.cmpt.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 班车模块:班次站点关系表
*/
@Data
public class BusScheduleStation {
private Integer id;
private Integer scheduleId;
private Integer stationId;
private Integer stationOrder;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime estimatedArrivalTime;
private Integer stopDuration;
private BigDecimal distanceFromStart;
private BigDecimal segmentPrice;
// 关联字段
private String stationName;
private String stationAddress;
}
\ No newline at end of file
package com.dlbridge.jadp.plugins.cmpt.dto;
import lombok.Data;
/**
* 班车模块:站点表
*/
@Data
public class BusStation {
private Integer id;
private Integer cmptId;
private String stationName;
private String stationAddress;
private String stationDescription;
private Double longitude;
private Double latitude;
private Integer stationOrder;
private Integer status;
}
package com.dlbridge.jadp.plugins.cmpt.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 班车模块:购票核销表
*/
@Data
public class BusTicketVerification {
private Integer id;
private Integer cmptId;
private String ticketNo;
private Integer scheduleId;
private String passengerName;
private String passengerPhone;
private String idNumber;
private Integer boardingStationId;
private String boardingStationName;
private Integer alightingStationId;
private String alightingStationName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime purchaseTime;
private Integer verificationCount;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime lastVerificationTime;
private Integer ticketStatus;
private String seatNumber;
private BigDecimal ticketPrice;
// 关联字段
private String scheduleName;
private String licensePlate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime departureTimeFrom;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime departureTimeTo;
private Integer allowMultipleVerification;
}
package com.dlbridge.jadp.plugins.cmpt.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 班车模块:核销记录表
*/
@Data
public class BusVerificationRecord {
private Integer id;
private Integer cmptId;
private Integer ticketId;
private String ticketNo;
private Integer scheduleId;
private Integer verificationStationId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime verificationTime;
private String verifierId;
private String deviceId;
}
package com.dlbridge.jadp.plugins.cmpt.service;
import com.dlbridge.jadp.plugins.cmpt.dao.mapper.BusMapper;
import com.dlbridge.jadp.plugins.cmpt.dao.model.param.BusParam;
import com.dlbridge.jadp.plugins.cmpt.dto.BusSchedule;
import com.dlbridge.jadp.plugins.cmpt.dto.BusStation;
import com.dlbridge.jadp.plugins.cmpt.dto.BusTicketVerification;
import com.dlbridge.jadp.plugins.cmpt.dto.BusVerificationRecord;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.neusoft.www.utils.web.Result;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional
@Log4j2
public class BusService {
@Resource
private BusMapper busMapper;
public List<BusTicketVerification> selectTicketByIdNumber(Integer cmptId, String idNumber) {
// 获取我购买的车票列表
List<BusTicketVerification> tickets = busMapper.selectTicketByIdNumber(cmptId, idNumber);
// 获取赛事站点信息
List<BusStation> stations = busMapper.selectStationsByCmptId(cmptId);
Map<Integer, BusStation> stationMap = stations.stream().collect(Collectors.toMap(BusStation::getId, p -> p));
for(BusTicketVerification ticket : tickets){
ticket.setBoardingStationName(stationMap.get(ticket.getBoardingStationId()).getStationName());
ticket.setAlightingStationName(stationMap.get(ticket.getAlightingStationId()).getStationName());
}
return tickets;
}
public BusTicketVerification getTicketDetail(Integer cmptId, String ticketNo) {
// 获取车票信息
BusTicketVerification ticket = busMapper.selectTicketByTicketNo(cmptId, ticketNo);
// 获取赛事站点信息
List<BusStation> stations = busMapper.selectStationsByCmptId(cmptId);
Map<Integer, BusStation> stationMap = stations.stream().collect(Collectors.toMap(BusStation::getId, p -> p));
ticket.setBoardingStationName(stationMap.get(ticket.getBoardingStationId()).getStationName());
ticket.setAlightingStationName(stationMap.get(ticket.getAlightingStationId()).getStationName());
return ticket;
}
/**
* 生成乘车二维码
* @param cmptId 赛事ID
* @param ticketNo 票号
* @return
*/
public byte[] generateQRCode(Integer cmptId, String ticketNo) {
try {
BusTicketVerification ticket = busMapper.selectTicketByTicketNo(cmptId, ticketNo);
if (ticket == null) {
throw new RuntimeException("票号不存在");
}
// 生成二维码内容:票号+时间戳
long timestamp = System.currentTimeMillis();
String qrContent = String.format("idNumber=%s&timestamp=%d", ticket.getIdNumber(), timestamp);
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(qrContent, BarcodeFormat.QR_CODE, 200, 200);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);
return outputStream.toByteArray();
} catch (Exception e) {
log.error("生成二维码失败", e);
throw new RuntimeException("生成二维码失败");
}
}
/**
* 车票核销方法
* @param param 核销参数
* @return
*/
@Transactional
public Result verifyTicket(BusParam param) {
if (param.getCmptId() == null || param.getScheduleId() == null || StringUtils.isBlank(param.getIdNumber()) || param.getQrTimestamp() == null) {
return Result.fail().setMsg("主要参数不能为空");
}
// 验证二维码时效性(1分钟)
long currentTime = System.currentTimeMillis();
if (currentTime - param.getQrTimestamp() > 60000) {
return Result.fail().setMsg("二维码已过期,请重新生成");
}
// 查询票务信息
BusTicketVerification ticket = busMapper.selectTicketForVerification(param.getCmptId(), param.getIdNumber(), param.getScheduleId());
if (ticket == null) {
return Result.fail().setMsg("未找到有效的车票信息");
}
// 检查是否允许多次核销
if (ticket.getAllowMultipleVerification() == 0) {
if (ticket.getVerificationCount() > 0) {
return Result.fail().setMsg("该车票已核销,不支持多次核销");
}
}
// 更新核销信息
int newVerificationCount = ticket.getVerificationCount() + 1;
ticket.setTicketStatus(newVerificationCount > 0 ? 2 : 1);
ticket.setVerificationCount(newVerificationCount);
busMapper.updateVerificationInfo(ticket);
// 记录核销记录
BusVerificationRecord record = new BusVerificationRecord();
record.setCmptId(param.getCmptId());
record.setTicketId(ticket.getId());
record.setTicketNo(ticket.getTicketNo());
record.setScheduleId(param.getScheduleId());
record.setVerifierId(param.getVerifierId());
record.setVerificationStationId(ticket.getBoardingStationId());
busMapper.insertVerificationRecord(record);
return Result.success();
}
/**
* 查询赛事班车列表
* @param cmptId 赛事ID
* @return
*/
public List<BusSchedule> selectSchedulesByCmptId(Integer cmptId) {
List<BusSchedule> schedules = busMapper.selectSchedulesByCmptId(cmptId);
List<BusStation> stations = busMapper.selectStationsByCmptId(cmptId);
Map<Integer, BusStation> stationMap = stations.stream().collect(Collectors.toMap(BusStation::getId, p -> p));
for(BusSchedule schedule : schedules){
schedule.setStartStationName(stationMap.get(schedule.getStartStationId()).getStationName());
schedule.setEndStationName(stationMap.get(schedule.getEndStationId()).getStationName());
}
return schedules;
}
/**
* 查询班次站点列表
* @param scheduleId 班次ID
* @return
*/
public List<BusStation> selectStationsByScheduleId(Integer scheduleId) {
return busMapper.selectStationsByScheduleId(scheduleId);
}
}
package com.dlbridge.jadp.plugins.cmpt.web;
import com.dlbridge.jadp.plugins.cmpt.dao.model.param.BusParam;
import com.dlbridge.jadp.plugins.cmpt.dto.BusSchedule;
import com.dlbridge.jadp.plugins.cmpt.dto.BusStation;
import com.dlbridge.jadp.plugins.cmpt.dto.BusTicketVerification;
import com.dlbridge.jadp.plugins.cmpt.service.BusService;
import com.neusoft.www.utils.web.Result;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Controller
@RequestMapping("gk/bus/")
public class BusController {
@Resource
private BusService busService;
/**
* 查询个人购票列表
* @return
*/
@ResponseBody
@RequestMapping(value = "/mine/tickets", method = RequestMethod.POST)
public Result getPersonalTickets(@RequestBody BusParam param) {
List<BusTicketVerification> tickets = busService.selectTicketByIdNumber(param.getCmptId(), param.getIdNumber());
return Result.success().setContent(tickets);
}
/**
* 查询车票详情
* @param param
* @return
*/
@ResponseBody
@RequestMapping(value = "/ticket/detail", method = RequestMethod.POST)
public Result getTicketDetail(@RequestBody BusParam param) {
BusTicketVerification ticket = busService.getTicketDetail(param.getCmptId(), param.getTicketNo());
return Result.success().setContent(ticket);
}
/**
* 生成车票二维码
* @param cmptId
* @param ticketNo
* @return
*/
@RequestMapping("/ticket/qrcode/{cmptId}/{ticketNo}")
public ResponseEntity<byte[]> generateBusQRCode(@PathVariable("cmptId") Integer cmptId, @PathVariable("ticketNo") String ticketNo) {
byte[] qrCode = busService.generateQRCode(cmptId, ticketNo);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(qrCode.length);
headers.set("Content-Disposition", "inline; filename=qrcode.png");
return new ResponseEntity<>(qrCode, headers, HttpStatus.OK);
}
/**
* 车票核销接口
* @return
*/
@ResponseBody
@RequestMapping(value = "/ticket/verify", method = RequestMethod.POST)
public Result verifyTicket(@RequestBody BusParam param) {
return busService.verifyTicket(param);
}
/**
* 查询赛事班车列表接口
* @return
*/
@ResponseBody
@RequestMapping(value = "/schedules", method = RequestMethod.POST)
public Result selectSchedulesByCmptId(@RequestBody BusParam param) {
List<BusSchedule> schedules = busService.selectSchedulesByCmptId(param.getCmptId());
List<BusStation> stations = busService.selectStationsByScheduleId(param.getScheduleId());
return Result.success().setContent(schedules);
}
/**
* 查询班车站点列表
* @return
*/
@ResponseBody
@RequestMapping(value = "/stations", method = RequestMethod.POST)
public Result selectStationsByScheduleId(@RequestBody BusParam param) {
List<BusStation> stations = busService.selectStationsByScheduleId(param.getScheduleId());
return Result.success().setContent(stations);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment