diff --git a/gather-app/src/main/java/com/ruoyi/database/controller/ParkingLotOrderInfoController.java b/gather-app/src/main/java/com/ruoyi/database/controller/ParkingBillInfoController.java similarity index 53% rename from gather-app/src/main/java/com/ruoyi/database/controller/ParkingLotOrderInfoController.java rename to gather-app/src/main/java/com/ruoyi/database/controller/ParkingBillInfoController.java index b9d0059..2672943 100644 --- a/gather-app/src/main/java/com/ruoyi/database/controller/ParkingLotOrderInfoController.java +++ b/gather-app/src/main/java/com/ruoyi/database/controller/ParkingBillInfoController.java @@ -6,8 +6,8 @@ import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.database.domain.ParkingLotOrderInfo; -import com.ruoyi.database.service.ParkingLotOrderInfoService; +import com.ruoyi.database.domain.ParkingBillInfo; +import com.ruoyi.database.service.ParkingBillInfoService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; @@ -15,42 +15,42 @@ import org.springframework.web.bind.annotation.*; import java.util.List; -@RequestMapping("/ParkingLotOrderInfo") +@RequestMapping("/ParkingBillInfo") @Api(tags = "订单管理") @RestController @RequiredArgsConstructor -public class ParkingLotOrderInfoController extends BaseController { +public class ParkingBillInfoController extends BaseController { - private final ParkingLotOrderInfoService parkingLotOrderInfoService; + private final ParkingBillInfoService parkingBillInfoService; @GetMapping @ApiOperation("查询订单管理") - public TableDataInfo list(ParkingLotOrderInfo parkingLotOrderInfo) { + public TableDataInfo list(ParkingBillInfo ParkingBillInfo) { startPage(); - QueryWrapper queryWrapper = new QueryWrapper<>(parkingLotOrderInfo); - List list = parkingLotOrderInfoService.list(queryWrapper); - long size = parkingLotOrderInfoService.count(queryWrapper); + QueryWrapper queryWrapper = new QueryWrapper<>(ParkingBillInfo); + List list = parkingBillInfoService.list(queryWrapper); + long size = parkingBillInfoService.count(queryWrapper); return getDataTableEnhance(list,size); } @PostMapping @ApiOperation("新增订单管理") @Log(title = "订单管理表", businessType = BusinessType.INSERT) - public AjaxResult insert(@RequestBody ParkingLotOrderInfo parkingLotOrderInfo) { - return toAjax(parkingLotOrderInfoService.save(parkingLotOrderInfo)); + public AjaxResult insert(@RequestBody ParkingBillInfo ParkingBillInfo) { + return toAjax(parkingBillInfoService.save(ParkingBillInfo)); } @PutMapping @ApiOperation("修改订单管理") @Log(title = "订单管理表", businessType = BusinessType.UPDATE) - public AjaxResult update(@RequestBody ParkingLotOrderInfo parkingLotOrderInfo) { - return toAjax(parkingLotOrderInfoService.updateById(parkingLotOrderInfo)); + public AjaxResult update(@RequestBody ParkingBillInfo ParkingBillInfo) { + return toAjax(parkingBillInfoService.updateById(ParkingBillInfo)); } @DeleteMapping @ApiOperation("删除订单管理") @Log(title = "订单管理表", businessType = BusinessType.DELETE) public AjaxResult delete(@RequestParam("idList") List idList) { - return toAjax(parkingLotOrderInfoService.removeByIds(idList)); + return toAjax(parkingBillInfoService.removeByIds(idList)); } } diff --git a/gather-app/src/main/java/com/ruoyi/database/controller/SmallProgramController.java b/gather-app/src/main/java/com/ruoyi/database/controller/SmallProgramController.java new file mode 100644 index 0000000..27466b6 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/controller/SmallProgramController.java @@ -0,0 +1,156 @@ +package com.ruoyi.database.controller; + +import cn.hutool.core.util.ReUtil; +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUserByPhone; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.utils.bean.BeanUtils; +import com.ruoyi.database.domain.*; +import com.ruoyi.database.mapper.ParkingBillInfoMapper; +import com.ruoyi.database.service.CustomerPlateNoInfoService; +import com.ruoyi.database.service.ParkingBillInfoService; +import com.ruoyi.database.service.ParkingBillPaymentInfoService; +import com.ruoyi.database.util.HaiKangApiUtils; +import com.ruoyi.database.util.LicensePlateValidator; +import com.ruoyi.framework.web.service.TokenService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Api(tags = "小程序接口") +@RestController +@RequiredArgsConstructor +@RequestMapping("/SmallProgram") +public class SmallProgramController extends BaseController { + + private final ParkingBillInfoService parkingBillInfoService; + private final ParkingBillPaymentInfoService parkingBillPaymentInfoService; + private final CustomerPlateNoInfoService customerPlateNoInfoService; + private final TokenService tokenService; + private final HaiKangApiUtils haiKangApiUtils; + private final ObjectMapper objectMapper = new ObjectMapper(); + + @GetMapping("/getOrder") + @ApiOperation("根据车牌号查询缴费订单") + public AjaxResult getOrder(String plateNo) { + String parkingPaymentInfo = haiKangApiUtils.getParkingPaymentInfo(plateNo); + if(parkingPaymentInfo==null){ + return AjaxResult.error("未查询到停车信息"); + } + JSONObject jsonObject = new JSONObject(parkingPaymentInfo); + String data = jsonObject.getJSONObject("data").toString(); + if(data==null){ + return AjaxResult.error("未查询到停车信息"); + } + try { + ParkingBill vehicleRecord = objectMapper.readValue(data, ParkingBill.class); + ParkingBillInfo parkingBillInfo = new ParkingBillInfo(); + BeanUtils.copyProperties(vehicleRecord,parkingBillInfo); + parkingBillInfo.setPayMoneyYuan(vehicleRecord.getPayMoneyYuan()); + parkingBillInfo.setDeductMoneyYuan(vehicleRecord.getDeductMoneyYuan()); + parkingBillInfo.setTotalCostYuan(vehicleRecord.getTotalCostYuan()); + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(ParkingBillInfo::getBillCode,parkingBillInfo.getBillCode()); + parkingBillInfoService.saveOrUpdate(parkingBillInfo,updateWrapper); + return AjaxResult.success(parkingBillInfo); + } catch (JsonProcessingException e) { + return AjaxResult.error("未查询到停车信息"); + } + } + + + + @GetMapping("/getHistoryPlateNo") + @ApiOperation("历史缴费车牌列表") + public AjaxResult getHistoryOrder(HttpServletRequest request){ + LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); + String phone = loginUserByPhone.getPhone(); + List list = parkingBillPaymentInfoService.lambdaQuery() + .eq(ParkingBillPaymentInfo::getPhone, phone) + .eq(ParkingBillPaymentInfo::getPayStatus, 1) + .list(); + Map> groupedByPlateNo = list.stream() + .collect(Collectors.groupingBy( + ParkingBillPaymentInfo::getPlateNo, // 按车牌分组 + Collectors.toList() // 收集为List + )); + ArrayList> maps = new ArrayList<>(); + for (String plateNo : groupedByPlateNo.keySet()) { + List list1 = groupedByPlateNo.get(plateNo); + ParkingBillPaymentInfo parkingBillPaymentInfo = list1.get(0); + Map map = new HashMap<>(); + map.put("plateNo", plateNo); + map.put("plateColor",parkingBillPaymentInfo.getPlateColorCn()); + maps.add(map); + } + return AjaxResult.success(maps); + } + + + + @GetMapping("/getHistoryNoPayOrder") + @ApiOperation("查询历史未缴费订单") + public AjaxResult getHistoryNoPayOrder(HttpServletRequest request){ + LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); + + return AjaxResult.success(); + } + + + + + @GetMapping("/getBindTheVehicle") + @ApiOperation("查询已绑定车辆") + public AjaxResult getBindTheVehicle(HttpServletRequest request){ + LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); + List list = customerPlateNoInfoService.lambdaQuery() + .eq(CustomerPlateNoInfo::getPhone, loginUserByPhone.getPhone()) + .list(); + return AjaxResult.success(list); + } + + + + @PostMapping("/bindTheVehicle") + @ApiOperation("绑定车辆") + public AjaxResult bindTheVehicle(@RequestBody BindTheVehicle bindTheVehicle,HttpServletRequest request){ + LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); + String plateNo = bindTheVehicle.getPlateNo(); + if (plateNo == null || "".equals(plateNo)) { + return AjaxResult.error("绑定的车牌不能为空"); + }else{ + boolean valid = LicensePlateValidator.isValid(plateNo); + if (!valid) { + return AjaxResult.error("绑定的车牌格式不正确"); + } + } + List list = customerPlateNoInfoService.lambdaQuery() + .eq(CustomerPlateNoInfo::getPlateNo, plateNo) + .list(); + if (list != null && list.size() > 0) { + return AjaxResult.error("车牌已被绑定"); + } + CustomerPlateNoInfo customerPlateNoInfo = new CustomerPlateNoInfo(); + customerPlateNoInfo.setPlateNo(plateNo); + customerPlateNoInfo.setPlateType(bindTheVehicle.getPlateType()); + customerPlateNoInfo.setPhone(loginUserByPhone.getPhone()); + customerPlateNoInfoService.saveOrUpdate(customerPlateNoInfo); + return AjaxResult.success(customerPlateNoInfo); + } + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/BindTheVehicle.java b/gather-app/src/main/java/com/ruoyi/database/domain/BindTheVehicle.java new file mode 100644 index 0000000..add57ca --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/BindTheVehicle.java @@ -0,0 +1,20 @@ +package com.ruoyi.database.domain; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +public class BindTheVehicle { + + + @NotBlank(message = "不能为空") + private String plateNo; + + + @ApiModelProperty("车牌类型 1,蓝牌车 2,黄牌车 3,新能源车") + @NotBlank(message = "车牌类型不能为空") + private Integer plateType; +} diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/ImageInfo.java b/gather-app/src/main/java/com/ruoyi/database/domain/ImageInfo.java new file mode 100644 index 0000000..5e90ddc --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/ImageInfo.java @@ -0,0 +1,20 @@ +package com.ruoyi.database.domain; + +import lombok.Data; + +/** + * 进出场图片信息 + */ +@Data +public class ImageInfo { + + /** + * 图片类型 + */ + private Integer type; + + /** + * 图片URL + */ + private String url; +} diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBill.java b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBill.java new file mode 100644 index 0000000..340565d --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBill.java @@ -0,0 +1,100 @@ +package com.ruoyi.database.domain; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 停车场账单信息 + */ +@Data +public class ParkingBill { + + /** + * 账单编号 + */ + @JsonProperty("billCode") + private String billCode; + + /** + * 停车场编码 + */ + @JsonProperty("parkCode") + private String parkCode; + + /** + * 停车场名称 + */ + @JsonProperty("parkName") + private String parkName; + + /** + * 车牌号 + */ + @JsonProperty("plateNo") + private String plateNo; + + /** + * 车牌颜色 (1:蓝色, 2:黄色, 3:黑色, 4:白色, 5:绿色, 6:其他) + */ + @JsonProperty("plateColor") + private Integer plateColor; + + /** + * 入场时间 (时间戳) + */ + @JsonProperty("enterTime") + private Long enterTime; + + /** + * 离场时间 (时间戳) + */ + @JsonProperty("costTime") + private Long costTime; + + /** + * 停车时长 (分钟) + */ + @JsonProperty("parkPeriodTime") + private Integer parkPeriodTime; + + /** + * 总费用 (单位:分) + */ + @JsonProperty("totalCost") + private Integer totalCost; + + /** + * 抵扣金额 (单位:分) + */ + @JsonProperty("deductMoney") + private Integer deductMoney; + + /** + * 实付金额 (单位:分) + */ + @JsonProperty("payMoney") + private Integer payMoney; + + /** + * 入场记录唯一标识 + */ + @JsonProperty("inUnid") + private String inUnid; + + + public BigDecimal getTotalCostYuan() { + return totalCost != null ? BigDecimal.valueOf(totalCost).divide(BigDecimal.valueOf(100)) : null; + } + + public BigDecimal getDeductMoneyYuan() { + return deductMoney != null ? BigDecimal.valueOf(deductMoney).divide(BigDecimal.valueOf(100)) : null; + } + + public BigDecimal getPayMoneyYuan() { + return payMoney != null ? BigDecimal.valueOf(payMoney).divide(BigDecimal.valueOf(100)) : null; + } + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillInfo.java b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillInfo.java new file mode 100644 index 0000000..19d31e0 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillInfo.java @@ -0,0 +1,165 @@ +package com.ruoyi.database.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 com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 停车场账单表(ParkingBillInfo)实体类 + * + * @author makejava + * @since 2025-12-01 15:37:06 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "parking_bill_info") +@ApiModel(value = "ParkingBillInfo", description = "停车场账单表") +public class ParkingBillInfo { + + /** + * 主键ID + */ + @ApiModelProperty("主键") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 账单编号 + */ + @ApiModelProperty("账单编号") + @Excel(name = "账单编号") + private String billCode; + + /** + * 停车场编码 + */ + @ApiModelProperty("停车场编码") + @Excel(name = "停车场编码") + private String parkCode; + + /** + * 停车场名称 + */ + @ApiModelProperty("停车场名称") + @Excel(name = "停车场名称") + private String parkName; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @Excel(name = "车牌号") + private String plateNo; + + /** + * 车牌颜色 + */ + @ApiModelProperty("车牌颜色") + @Excel(name = "车牌颜色") + private Integer plateColor; + @TableField(exist = false) + private String plateColorCn; + + /** + * 入场时间戳(毫秒) + */ + @ApiModelProperty("入场时间戳(毫秒)") + @Excel(name = "入场时间戳(毫秒)") + private Long enterTime; + + /** + * 离场时间戳(毫秒) + */ + @ApiModelProperty("离场时间戳(毫秒)") + @Excel(name = "离场时间戳(毫秒)") + private Long costTime; + + /** + * 停车时长(分钟) + */ + @ApiModelProperty("停车时长(分钟)") + @Excel(name = "停车时长(分钟)") + private Integer parkPeriodTime; + + /** + * 总费用(分) + */ + @ApiModelProperty("总费用(分)") + @Excel(name = "总费用(分)") + private Integer totalCost; + + + /** + * 总费用(元) + */ + @ApiModelProperty("总费用(元)") + @Excel(name = "总费用(元)") + private BigDecimal totalCostYuan; + + + /** + * 抵扣金额(分) + */ + @ApiModelProperty("抵扣金额(分)") + @Excel(name = "抵扣金额(分)") + private Integer deductMoney; + + /** + * 抵扣金额(元) + */ + @ApiModelProperty("抵扣金额(元)") + @Excel(name = "抵扣金额(元)") + private BigDecimal deductMoneyYuan; + + /** + * 实付金额(分) + */ + @ApiModelProperty("实付金额(分)") + @Excel(name = "实付金额(分)") + private Integer payMoney; + + + /** + * 实付金额(元) + */ + @ApiModelProperty("实付金额(元)") + @Excel(name = "实付金额(元)") + private BigDecimal payMoneyYuan; + + /** + * 入场记录唯一标识 + */ + @ApiModelProperty("入场记录唯一标识") + @Excel(name = "入场记录唯一标识") + private String inUnid; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @Excel(name = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 更新时间 + */ + @ApiModelProperty("更新时间") + @Excel(name = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingLotOrderInfo.java b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillPaymentInfo.java similarity index 54% rename from gather-app/src/main/java/com/ruoyi/database/domain/ParkingLotOrderInfo.java rename to gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillPaymentInfo.java index 0fe5240..5e5f8fe 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingLotOrderInfo.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillPaymentInfo.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -15,24 +16,47 @@ import lombok.EqualsAndHashCode; import java.util.Date; /** - * 停车场订单表(ParkingLotOrderInfo)实体类 + * 停车订单支付状态表(ParkingBillPaymentInfo)实体类 * * @author makejava - * @since 2025-11-20 09:27:12 + * @since 2025-12-01 19:08:25 */ @Data @EqualsAndHashCode(callSuper = false) -@TableName(value = "parking_lot_order_info") -@ApiModel(value = "ParkingLotOrderInfo", description = "停车场订单表") -public class ParkingLotOrderInfo { +@TableName(value = "parking_bill_payment_info") +@ApiModel(value = "ParkingBillPaymentInfo", description = "停车订单支付状态表") +public class ParkingBillPaymentInfo { /** - * 主键 + * 主键ID */ @ApiModelProperty("主键") @TableId(value = "id", type = IdType.AUTO) private Long id; + /** + * 账单编号 + */ + @ApiModelProperty("账单编号") + @Excel(name = "账单编号") + private String billCode; + + /** + * 车牌号 + */ + @ApiModelProperty("车牌号") + @Excel(name = "车牌号") + private String plateNo; + + /** + * 车牌颜色 + */ + @ApiModelProperty("车牌颜色") + @Excel(name = "车牌颜色") + private Integer plateColor; + @TableField(exist = false) + private String plateColorCn; + /** * 创建时间 */ @@ -41,13 +65,6 @@ public class ParkingLotOrderInfo { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; - /** - * 创建者 - */ - @ApiModelProperty("创建者") - @Excel(name = "创建者") - private Integer createBy; - /** * 更新时间 */ @@ -57,18 +74,18 @@ public class ParkingLotOrderInfo { private Date updateTime; /** - * 更新者 + * 微信openid */ - @ApiModelProperty("更新者") - @Excel(name = "更新者") - private Integer updateBy; + @ApiModelProperty("微信openid") + @Excel(name = "微信openid") + private String openId; /** - * 车牌号 + * 支付宝用户ID */ - @ApiModelProperty("车牌号") - @Excel(name = "车牌号") - private String plateNo; + @ApiModelProperty("支付宝用户ID") + @Excel(name = "支付宝用户ID") + private String alipayUserId; /** * 手机号 @@ -78,43 +95,18 @@ public class ParkingLotOrderInfo { private String phone; /** - * 停车场名称 + * 支付状态 */ - @ApiModelProperty("停车场名称") - @Excel(name = "停车场名称") - private String name; + @ApiModelProperty("支付状态") + @Excel(name = "支付状态") + private Integer payStatus; /** - * 停车场编码 + * 支付订单号id */ - @ApiModelProperty("停车场编码") - @Excel(name = "停车场编码") - private String code; - - /** - * 入车时间 - */ - @ApiModelProperty("入车时间") - @Excel(name = "入车时间") - private Long entryTime; - @TableField(exist = false) - private String entryTimeCn; - - /** - * 出车时间 - */ - @ApiModelProperty("出车时间") - @Excel(name = "出车时间") - private Long departTime; - @TableField(exist = false) - private String departTimeCn; - - /** - * 停车时长 - */ - @ApiModelProperty("停车时长") - @Excel(name = "停车时长") - private String parkTime; + @ApiModelProperty("支付订单号id") + @Excel(name = "支付订单号id") + private String transactionId; } diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingLotInfo.java b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingLotInfo.java new file mode 100644 index 0000000..4eaa340 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingLotInfo.java @@ -0,0 +1,107 @@ +package com.ruoyi.database.domain; + +import lombok.Data; +import lombok.ToString; + +/** + * 停车场信息消息 + */ +@Data +@ToString +public class ParkingLotInfo { + + /** + * 停车场编码 + */ + private String parkCode; + + /** + * 停车场名称 + */ + private String parkName; + + /** + * 总车位数量 + */ + private Integer totalParkingSpaceNum; + + /** + * 剩余车位数量 + */ + private Integer leftParkingSpaceNum; + + /** + * 总固定车位数量 + */ + private Integer totalFixedSpaceNum; + + /** + * 剩余固定车位数量 + */ + private Integer leftFixedSpaceNum; + + /** + * 停车场描述 + */ + private String description; + + /** + * 停车场经度 + */ + private String parkLongitude; + + /** + * 停车场纬度 + */ + private String parkLatitude; + + /** + * 停车场类型 (1-路边停车场,2-封闭式场库) + */ + private Integer parkType; + + /** + * 停车场等级 + */ + private Integer parkLevel; + + /** + * 停车开始时间 (格式:HH:mm) + */ + private String parkingStartTime; + + /** + * 停车结束时间 (格式:HH:mm) + */ + private String parkingEndTime; + + /** + * 免费时长 (分钟) + */ + private String freeTime; + + /** + * 总充电桩数量 + */ + private Integer chargeTotalNum; + + /** + * 剩余可用充电桩数量 + */ + private Integer chargeLeftNum; + + /** + * 停车场地址 + */ + private String parkingAddress; + + /** + * 收费规则描述 + */ + private String payRuleDesc; + + /** + * 区域名称 + */ + private String areaName; +} diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRecord.java b/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRecord.java index 1083121..f6a288a 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRecord.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRecord.java @@ -1,6 +1,6 @@ package com.ruoyi.database.domain; -import com.alipay.api.domain.ImageInfo; + import lombok.Data; import java.util.List; diff --git a/gather-app/src/main/java/com/ruoyi/database/mapper/ParkingLotOrderInfoMapper.java b/gather-app/src/main/java/com/ruoyi/database/mapper/ParkingBillInfoMapper.java similarity index 50% rename from gather-app/src/main/java/com/ruoyi/database/mapper/ParkingLotOrderInfoMapper.java rename to gather-app/src/main/java/com/ruoyi/database/mapper/ParkingBillInfoMapper.java index fda8929..cd074d7 100644 --- a/gather-app/src/main/java/com/ruoyi/database/mapper/ParkingLotOrderInfoMapper.java +++ b/gather-app/src/main/java/com/ruoyi/database/mapper/ParkingBillInfoMapper.java @@ -1,16 +1,16 @@ package com.ruoyi.database.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.ruoyi.database.domain.ParkingLotOrderInfo; +import com.ruoyi.database.domain.ParkingBillInfo; import org.apache.ibatis.annotations.Mapper; /** - * 停车场订单表(ParkingLotOrderInfo) Mapper 接口 + * 停车场账单表(ParkingBillInfo) Mapper 接口 * * @author makejava * @since ${date} */ @Mapper -public interface ParkingLotOrderInfoMapper extends BaseMapper { +public interface ParkingBillInfoMapper extends BaseMapper { } diff --git a/gather-app/src/main/java/com/ruoyi/database/mapper/ParkingBillPaymentInfoMapper.java b/gather-app/src/main/java/com/ruoyi/database/mapper/ParkingBillPaymentInfoMapper.java new file mode 100644 index 0000000..3ee2c56 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/mapper/ParkingBillPaymentInfoMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.database.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.database.domain.ParkingBillPaymentInfo; +import org.apache.ibatis.annotations.Mapper; + +/** + * 停车订单支付状态表(ParkingBillPaymentInfo) Mapper 接口 + * + * @author makejava + * @since ${date} + */ +@Mapper +public interface ParkingBillPaymentInfoMapper extends BaseMapper { + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/service/ParkingBillInfoService.java b/gather-app/src/main/java/com/ruoyi/database/service/ParkingBillInfoService.java new file mode 100644 index 0000000..feaa92d --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/service/ParkingBillInfoService.java @@ -0,0 +1,14 @@ +package com.ruoyi.database.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.database.domain.ParkingBillInfo; + +/** + * (停车场账单表)Service + * + * @author makejava + * @since 2025-12-01 15:37:06 + */ +public interface ParkingBillInfoService extends IService { + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/service/ParkingBillPaymentInfoService.java b/gather-app/src/main/java/com/ruoyi/database/service/ParkingBillPaymentInfoService.java new file mode 100644 index 0000000..6503b8e --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/service/ParkingBillPaymentInfoService.java @@ -0,0 +1,14 @@ +package com.ruoyi.database.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.database.domain.ParkingBillPaymentInfo; + +/** + * (停车订单支付状态表)Service + * + * @author makejava + * @since 2025-12-01 19:08:25 + */ +public interface ParkingBillPaymentInfoService extends IService { + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/service/ParkingLotOrderInfoService.java b/gather-app/src/main/java/com/ruoyi/database/service/ParkingLotOrderInfoService.java deleted file mode 100644 index 0439797..0000000 --- a/gather-app/src/main/java/com/ruoyi/database/service/ParkingLotOrderInfoService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ruoyi.database.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.ruoyi.database.domain.ParkingLotOrderInfo; - -/** - * (停车场订单表)Service - * - * @author makejava - * @since 2025-11-20 09:27:12 - */ -public interface ParkingLotOrderInfoService extends IService { - -} diff --git a/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillInfoServiceImpl.java b/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillInfoServiceImpl.java new file mode 100644 index 0000000..bfd1844 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillInfoServiceImpl.java @@ -0,0 +1,19 @@ +package com.ruoyi.database.service.impl; + + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.database.domain.ParkingBillInfo; +import com.ruoyi.database.mapper.ParkingBillInfoMapper; +import com.ruoyi.database.service.ParkingBillInfoService; +import org.springframework.stereotype.Service; + +/** + * (停车场账单表)ServiceImpl + * + * @author makejava + * @since 2025-12-01 15:37:06 + */ +@Service +public class ParkingBillInfoServiceImpl extends ServiceImpl implements ParkingBillInfoService { + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillPaymentInfoServiceImpl.java b/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillPaymentInfoServiceImpl.java new file mode 100644 index 0000000..e642bd1 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillPaymentInfoServiceImpl.java @@ -0,0 +1,19 @@ +package com.ruoyi.database.service.impl; + + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.database.domain.ParkingBillPaymentInfo; +import com.ruoyi.database.mapper.ParkingBillPaymentInfoMapper; +import com.ruoyi.database.service.ParkingBillPaymentInfoService; +import org.springframework.stereotype.Service; + +/** + * (停车订单支付状态表)ServiceImpl + * + * @author makejava + * @since 2025-12-01 19:08:25 + */ +@Service +public class ParkingBillPaymentInfoServiceImpl extends ServiceImpl implements ParkingBillPaymentInfoService { + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingLotOrderInfoServiceImpl.java b/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingLotOrderInfoServiceImpl.java deleted file mode 100644 index cfd1369..0000000 --- a/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingLotOrderInfoServiceImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ruoyi.database.service.impl; - - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.ruoyi.database.domain.ParkingLotOrderInfo; -import com.ruoyi.database.mapper.ParkingLotOrderInfoMapper; -import com.ruoyi.database.service.ParkingLotOrderInfoService; -import org.springframework.stereotype.Service; - -/** - * (停车场订单表)ServiceImpl - * - * @author makejava - * @since 2025-11-20 09:27:12 - */ -@Service -public class ParkingLotOrderInfoServiceImpl extends ServiceImpl implements ParkingLotOrderInfoService { - -} diff --git a/gather-app/src/main/java/com/ruoyi/database/util/HaiKangApiUtils.java b/gather-app/src/main/java/com/ruoyi/database/util/HaiKangApiUtils.java new file mode 100644 index 0000000..37fc68e --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/util/HaiKangApiUtils.java @@ -0,0 +1,160 @@ +package com.ruoyi.database.util; + +import cn.hutool.json.JSONObject; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.ruoyi.common.core.redis.RedisCache; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.concurrent.TimeUnit; + + +@Component +@RequiredArgsConstructor +public class HaiKangApiUtils { + + private static final String HIK_URL = "https://artemis.hikparking.com"; + private static final String client_id = "25799436"; + private static final String client_secret = "eTe6Xy6iXFUiL9v2Qa2gTjZkqVHFK5bN"; + private static final String park_code = "101CX2ALLFGY329"; + private final RedisCache redisCache; + private static final int CONNECT_TIMEOUT = 5000; // 连接超时 5秒 + private static final int SOCKET_TIMEOUT = 10000; + private static final String HIK_TOKEN_KEY = "HIK_TOKEN_KEY"; + + private static Gson gson = new GsonBuilder().create(); + + private static CloseableHttpClient createHttpClient() { + RequestConfig config = RequestConfig.custom() + .setConnectTimeout(CONNECT_TIMEOUT) + .setSocketTimeout(SOCKET_TIMEOUT) + .build(); + + return HttpClients.custom() + .setDefaultRequestConfig(config) + .build(); + } + + + /** + * 获取海康云平台accessToken + * @return accessToken + */ + public String getAccessToken(){ + String accessToken = redisCache.getCacheObject(HIK_TOKEN_KEY); + if (accessToken != null) { + return accessToken; + } + String hikAccessToken = getHikAccessToken(); + if (hikAccessToken == null) { + return null; + } + JSONObject jsonObject = new JSONObject(hikAccessToken); + accessToken = jsonObject.getStr("access_token"); + if (accessToken == null) { + return null; + } + redisCache.setCacheObject(HIK_TOKEN_KEY, accessToken,43199, TimeUnit.SECONDS); + return accessToken; + } + + /** + * 调用海康云平台 + * 获取accessToken接口 + */ + public String getHikAccessToken(){ + try (CloseableHttpClient client = createHttpClient()) { + HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/oauth/token"); + HashMap map = new HashMap<>(); + map.put("client_id", client_id); + map.put("client_secret", client_secret); + String json = gson.toJson(map); + StringEntity entity = new StringEntity(json, "UTF-8"); + httpPost.setEntity(entity); + httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); + CloseableHttpResponse response = client.execute(httpPost); + HttpEntity entityResponse = response.getEntity(); + if (entityResponse != null) { + String res = EntityUtils.toString(entityResponse, "UTF-8"); + System.out.println(res); + return res; + } else { + // 处理空响应的情况 + System.err.println("Received empty response from server"); + return null; + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + + /** + * 根据停车场编码 + * 获取停车场详情 + */ + public String getHikParkInfo(){ + try (CloseableHttpClient client = createHttpClient()) { + HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/api/v1/dealer/parkinfo/" + park_code); + httpPost.setHeader("access_token", getAccessToken()); + CloseableHttpResponse response = client.execute(httpPost); + HttpEntity entityResponse = response.getEntity(); + if (entityResponse != null) { + String res = EntityUtils.toString(entityResponse, "UTF-8"); + System.out.println(res); + return res; + } else { + // 处理空响应的情况 + System.err.println("Received empty response from server"); + return null; + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + + /** + * 根据车牌获取车辆停车账单 + */ + public String getParkingPaymentInfo(String plateNo){ + try (CloseableHttpClient client = createHttpClient()) { + HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/api/v1/charge/getParkingPaymentInfo"); + HashMap map = new HashMap<>(); + map.put("plateNo", plateNo); + String json = gson.toJson(map); + StringEntity entity = new StringEntity(json, "UTF-8"); + httpPost.setEntity(entity); + httpPost.setHeader("Content-type", "application/json"); + httpPost.setHeader("access_token", getAccessToken()); + CloseableHttpResponse response = client.execute(httpPost); + HttpEntity entityResponse = response.getEntity(); + if (entityResponse != null) { + String res = EntityUtils.toString(entityResponse, "UTF-8"); + System.out.println(res); + return res; + } else { + // 处理空响应的情况 + System.err.println("Received empty response from server"); + return null; + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/gather-app/src/main/java/com/ruoyi/database/util/LicensePlateValidator.java b/gather-app/src/main/java/com/ruoyi/database/util/LicensePlateValidator.java new file mode 100644 index 0000000..53e94c8 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/util/LicensePlateValidator.java @@ -0,0 +1,178 @@ +package com.ruoyi.database.util; + +/** + * 车牌验证工具类(完整版) + * 来源:多个开源项目整合优化 + */ +public class LicensePlateValidator { + + /** + * 中国车牌正则表达式集合 + */ + public static class Patterns { + // 普通民用车牌 + public static final String COMMON_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{4,5}[A-Z0-9挂学警港澳]$"; + + // 新能源车牌 + public static final String NEW_ENERGY_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))$"; + + // 警车车牌 + public static final String POLICE_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][0-9]{4}警$"; + + // 武警车牌 + public static final String ARMED_POLICE_PLATE = "^WJ[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][0-9]{4}[TD]$"; + + // 使馆车牌 + public static final String EMBASSY_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][0-9]{4}使$"; + + // 教练车牌 + public static final String COACH_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][0-9]{4}学$"; + } + + /** + * 车牌类型枚举 + */ + public enum PlateType { + COMMON(1, "普通蓝牌"), + YELLOW(2, "黄牌"), + NEW_ENERGY(3, "新能源"), + POLICE(4, "警车"), + ARMED_POLICE(5, "武警"), + EMBASSY(6, "使馆"), + COACH(7, "教练"), + UNKNOWN(0, "未知"); + + private final int code; + private final String desc; + + PlateType(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public int getCode() { return code; } + public String getDesc() { return desc; } + } + + /** + * 验证车牌号是否有效 + * @param plateNo 车牌号 + * @return 是否有效 + */ + public static boolean isValid(String plateNo) { + if (plateNo == null || plateNo.trim().isEmpty()) { + return false; + } + + String formatted = formatPlateNo(plateNo); + + // 检查所有可能的车牌类型 + return isCommonPlate(formatted) || + isNewEnergyPlate(formatted) || + isPolicePlate(formatted) || + isArmedPolicePlate(formatted) || + isEmbassyPlate(formatted) || + isCoachPlate(formatted); + } + + /** + * 检测车牌类型 + * @param plateNo 车牌号 + * @return 车牌类型 + */ + public static PlateType detectType(String plateNo) { + if (plateNo == null || plateNo.trim().isEmpty()) { + return PlateType.UNKNOWN; + } + + String formatted = formatPlateNo(plateNo); + + if (isNewEnergyPlate(formatted)) { + return PlateType.NEW_ENERGY; + } else if (isCommonPlate(formatted)) { + // 区分蓝牌和黄牌(通过长度和内容判断) + if (formatted.length() >= 7 && formatted.matches(".*[0-9]{6}.*")) { + return PlateType.YELLOW; + } + return PlateType.COMMON; + } else if (isPolicePlate(formatted)) { + return PlateType.POLICE; + } else if (isArmedPolicePlate(formatted)) { + return PlateType.ARMED_POLICE; + } else if (isEmbassyPlate(formatted)) { + return PlateType.EMBASSY; + } else if (isCoachPlate(formatted)) { + return PlateType.COACH; + } + + return PlateType.UNKNOWN; + } + + /** + * 格式化车牌号(统一格式) + */ + public static String formatPlateNo(String plateNo) { + if (plateNo == null) return null; + // 去除所有空白字符,转为大写 + return plateNo.replaceAll("\\s+", "").toUpperCase(); + } + + // 各个类型的验证方法 + private static boolean isCommonPlate(String plateNo) { + return plateNo.matches(Patterns.COMMON_PLATE); + } + + private static boolean isNewEnergyPlate(String plateNo) { + return plateNo.matches(Patterns.NEW_ENERGY_PLATE); + } + + private static boolean isPolicePlate(String plateNo) { + return plateNo.matches(Patterns.POLICE_PLATE); + } + + private static boolean isArmedPolicePlate(String plateNo) { + return plateNo.matches(Patterns.ARMED_POLICE_PLATE); + } + + private static boolean isEmbassyPlate(String plateNo) { + return plateNo.matches(Patterns.EMBASSY_PLATE); + } + + private static boolean isCoachPlate(String plateNo) { + return plateNo.matches(Patterns.COACH_PLATE); + } + + /** + * 获取省份简称 + */ + public static String getProvince(String plateNo) { + if (plateNo == null || plateNo.length() < 1) { + return null; + } + return formatPlateNo(plateNo).substring(0, 1); + } + + /** + * 测试用例 + */ + public static void main(String[] args) { + String[] testPlates = { + "京A12345", + "沪AD12345", + "粤B88888", + "京A1234警", + "WJ京1234T", + "使A1234使", + "invalid" + }; + + for (String plate : testPlates) { + System.out.println("车牌: " + plate); + System.out.println("是否有效: " + isValid(plate)); + System.out.println("类型: " + detectType(plate)); + System.out.println("省份: " + getProvince(plate)); + System.out.println("格式化: " + formatPlateNo(plate)); + System.out.println("---"); + } + } +}