Explorar o código

feat: 停车优惠券门槛改为站点级配置,从全局常量迁移到 t_wash_station 表

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline hai 2 días
pai
achega
4289eed605

+ 12 - 2
admin-web-new/src/views/admin/station/dialog.vue

@@ -20,6 +20,7 @@ const state = reactive({
     stationType: "1",
     parkingFee: "",
     parkingQrCode: "",
+    parkingCouponMinAmount: 6.0,
     remark: "",
     pictures: [] as string[],
     stationLng: "",
@@ -41,6 +42,7 @@ const resetForm = () => {
     stationType: "1",
     parkingFee: "",
     parkingQrCode: "",
+    parkingCouponMinAmount: 6.0,
     remark: "",
     pictures: [],
     stationLng: "",
@@ -58,6 +60,7 @@ const open = async (type: "add" | "edit" | "view", row?: any) => {
     try {
       const res = await getStationDetail(row.id);
       Object.assign(state.ruleForm, res);
+      state.ruleForm.parkingCouponMinAmount = (res.parkingCouponMinAmount || 600) / 100;
     } catch (e) {
       ElMessage.error("加载站点详情失败");
     } finally {
@@ -79,11 +82,15 @@ const handleSubmit = async () => {
   
   loading.value = true;
   try {
+    const payload = {
+      ...state.ruleForm,
+      parkingCouponMinAmount: Math.round(state.ruleForm.parkingCouponMinAmount * 100)
+    };
     if (dialogType.value === "add") {
-      await addStation(state.ruleForm);
+      await addStation(payload);
       ElMessage.success("新增成功");
     } else {
-      await modifyStation(state.ruleForm);
+      await modifyStation(payload);
       ElMessage.success("修改成功");
     }
     handleClose();
@@ -135,6 +142,9 @@ defineExpose({ open });
       <el-form-item label="站点类型" prop="stationType">
         <ext-d-select v-model="state.ruleForm.stationType" type="Station.type" placeholder="请选择站点类型" />
       </el-form-item>
+      <el-form-item label="停车券最低消费金额(元)" prop="parkingCouponMinAmount">
+        <el-input-number v-model="state.ruleForm.parkingCouponMinAmount" :min="0" :precision="2" placeholder="默认6元" />
+      </el-form-item>
       <el-form-item label="停车减免规则" prop="parkingFee">
         <el-input
           v-model="state.ruleForm.parkingFee"

+ 12 - 0
admin-web/src/views/admin/station/list/dialog.vue

@@ -245,6 +245,16 @@
               </el-input>
             </el-form-item>
 
+            <el-form-item label="停车券最低消费金额(元):" prop="parkingCouponMinAmount">
+              <el-input-number
+                  v-model="state.ruleForm.parkingCouponMinAmount"
+                  placeholder="默认6元"
+                  :min="0"
+                  :precision="2"
+                  class="wd200">
+              </el-input-number>
+            </el-form-item>
+
             <el-form-item label="停车费减免二维码文本:" prop="parkingQrCode" class="w100">
               <el-input
                   v-model="state.ruleForm.parkingQrCode"
@@ -476,6 +486,7 @@ const onSubmit = () => {
       if (v) {
         state.btnLoading = true;
         state.ruleForm.location = JSON.stringify(state.location)
+        state.ruleForm.parkingCouponMinAmount = Math.round((state.ruleForm.parkingCouponMinAmount || 6) * 100);
         const url = !!state.ruleForm.id ? "washStation/modify" : "washStation/add"
         $body(url, state.ruleForm).then(() => {
           state.btnLoading = false;
@@ -515,6 +526,7 @@ const handleFormChange = (formData: any) => {
 const loadData = (id: number) => {
   $get(`washStation/detail/${id}`).then((res: any) => {
     state.ruleForm = res;
+    state.ruleForm.parkingCouponMinAmount = (res.parkingCouponMinAmount || 600) / 100;
     state.location = JSON.parse(res.location)
   })
 }

+ 0 - 5
car-wash-entity/src/main/java/com/kym/entity/WashOrder.java

@@ -38,11 +38,6 @@ public class WashOrder extends BaseEntity {
     public static final String START_CLOSE_TYPE_网络 = "network";
     public static final String START_CLOSE_TYPE_按键 = "button";
 
-    /**
-     * 领取停车券最低消费金额6元
-     */
-    public static final int PARKING_COUPON_MIN_AMOUNT = 600;
-
     private static final long serialVersionUID = 1L;
 
     private Long userId;

+ 5 - 0
car-wash-entity/src/main/java/com/kym/entity/WashStation.java

@@ -77,6 +77,11 @@ public class WashStation extends BaseEntity {
      */
     private String parkingQrCode;
 
+    /**
+     * 领取停车优惠券最低消费金额(单位:分,默认600即6元)
+     */
+    private Integer parkingCouponMinAmount;
+
     /**
      * 站点坐标
      */

+ 1 - 0
car-wash-entity/src/main/java/com/kym/entity/common/RedisKeys.java

@@ -10,6 +10,7 @@ public interface RedisKeys {
     String OFFLINE_EXPIRED = "OFFLINE_EXPIRED:";
     String STATION_ID_TO_NAME = "STATION_ID_TO_NAME:";
     String STATION_ID_TO_PARKING_QR_CODE_URL = "STATION_ID_TO_PARKING_QR_CODE_URL:";
+    String STATION_ID_TO_PARKING_COUPON_MIN_AMOUNT = "STATION_ID_TO_PARKING_COUPON_MIN_AMOUNT:";
     String ADMIN_USER_STATION_IDS = "ADMIN_USER_STATION_IDS:";
     String COUPON_ID_TO_USERS = "COUPON_ID_TO_USER_ID:";
 

+ 7 - 0
car-wash-entity/src/main/resources/sql/v11_parking_coupon_threshold.sql

@@ -0,0 +1,7 @@
+-- ====================================================
+-- 站点停车优惠券门槛配置
+-- 发布日期:2026-06-11
+-- ====================================================
+
+ALTER TABLE `t_wash_station`
+    ADD COLUMN `parking_coupon_min_amount` INT DEFAULT 600 COMMENT '领取停车优惠券最低消费金额(单位:分,默认600即6元)';

+ 18 - 0
car-wash-service/src/main/java/com/kym/service/cache/KymCache.java

@@ -121,6 +121,24 @@ public enum KymCache {
         return cleanNullBytes(url);
     }
 
+    /**
+     * 站点id与停车券最低消费金额
+     */
+    public void putStationId2ParkingCouponMinAmount(Map<String, Integer> map) {
+        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.STATION_ID_TO_PARKING_COUPON_MIN_AMOUNT + k, v.toString()));
+    }
+
+    /**
+     * 通过站点id获取停车券最低消费金额(单位:分),未配置时返回默认600
+     */
+    public int getParkingCouponMinAmountByStationId(String stationId) {
+        var v = KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.STATION_ID_TO_PARKING_COUPON_MIN_AMOUNT + stationId);
+        if (CommUtil.isNotEmptyAndNull(v)) {
+            return Integer.parseInt(v);
+        }
+        return 600;
+    }
+
 
     /**
      * 运营平台账号(包含运营,投资者,物业等)对应有权限的站点

+ 1 - 1
car-wash-service/src/main/java/com/kym/service/impl/OrderSettlementServiceImpl.java

@@ -132,7 +132,7 @@ public class OrderSettlementServiceImpl implements OrderSettlementService {
 
         washOrderService.updateById(washOrder);
 
-        if (orderInfo.getAmount() >= WashOrder.PARKING_COUPON_MIN_AMOUNT) {
+        if (orderInfo.getAmount() >= KymCache.INSTANCE.getParkingCouponMinAmountByStationId(washOrder.getStationId())) {
             var parkingCouponUrl = KymCache.INSTANCE.getParkingQrCodeUrlByStationId(washOrder.getStationId());
             var code = UUID.randomUUID().toString();
             KymCache.INSTANCE.setParkingCouponCode(code, parkingCouponUrl, 3600 * 2L);

+ 2 - 2
car-wash-service/src/main/java/com/kym/service/impl/WashOrderServiceImpl.java

@@ -516,7 +516,7 @@ public class WashOrderServiceImpl extends MyBaseServiceImpl<WashOrderMapper, Was
                 .ge(WashOrder::getEndTime, LocalDateTime.now().minusHours(2))
                 .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_已支付)
                 .orderByDesc(WashOrder::getId).list();
-        if (!orderList.isEmpty() && orderList.stream().collect(Collectors.summarizingInt(WashOrder::getAmount)).getSum() >= WashOrder.PARKING_COUPON_MIN_AMOUNT) {
+        if (!orderList.isEmpty() && orderList.stream().collect(Collectors.summarizingInt(WashOrder::getAmount)).getSum() >= KymCache.INSTANCE.getParkingCouponMinAmountByStationId(orderList.get(0).getStationId())) {
             var parkingCouponUrl = KymCache.INSTANCE.getParkingQrCodeUrlByStationId(orderList.get(0).getStationId());
             var code = UUID.randomUUID().toString();
             KymCache.INSTANCE.setParkingCouponCode(code, parkingCouponUrl, 3600 * 2L);
@@ -553,7 +553,7 @@ public class WashOrderServiceImpl extends MyBaseServiceImpl<WashOrderMapper, Was
                         .ge(WashOrder::getEndTime, LocalDateTime.now().minusHours(2))
                         .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_已支付)
                         .orderByDesc(WashOrder::getId).list();
-                if (!orderList.isEmpty() && orderList.stream().collect(Collectors.summarizingInt(WashOrder::getAmount)).getSum() >= WashOrder.PARKING_COUPON_MIN_AMOUNT) {
+                if (!orderList.isEmpty() && orderList.stream().collect(Collectors.summarizingInt(WashOrder::getAmount)).getSum() >= KymCache.INSTANCE.getParkingCouponMinAmountByStationId(orderList.get(0).getStationId())) {
                     var parkingCouponUrl = KymCache.INSTANCE.getParkingQrCodeUrlByStationId(orderList.get(0).getStationId());
                     var code = UUID.randomUUID().toString();
                     KymCache.INSTANCE.setParkingCouponCode(code, parkingCouponUrl, 3600 * 2L);

+ 1 - 0
car-wash-service/src/main/java/com/kym/service/impl/WashStationServiceImpl.java

@@ -35,6 +35,7 @@ public class WashStationServiceImpl extends MyBaseServiceImpl<WashStationMapper,
         var list = list();
         KymCache.INSTANCE.putStationId2Name(list.stream().collect(Collectors.toMap(WashStation::getStationId, WashStation::getStationName)));
         KymCache.INSTANCE.putStationId2ParkingQrCodeUrl(list.stream().collect(Collectors.toMap(WashStation::getStationId, WashStation::getParkingQrCode)));
+        KymCache.INSTANCE.putStationId2ParkingCouponMinAmount(list.stream().filter(s -> s.getParkingCouponMinAmount() != null).collect(Collectors.toMap(WashStation::getStationId, WashStation::getParkingCouponMinAmount)));
     }
 
     private final WashDeviceService washDeviceService;