Pārlūkot izejas kodu

补充二维码

lutong 3 nedēļas atpakaļ
vecāks
revīzija
a8652d935a

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreTable.java

@@ -61,6 +61,10 @@ public class StoreTable {
     @TableField("qrcode_url")
     private String qrcodeUrl;
 
+    @ApiModelProperty(value = "APP扫码二维码URL(内容为门店ID+桌号JSON,非微信太阳码)")
+    @TableField("app_qrcode_url")
+    private String appQrcodeUrl;
+
     @ApiModelProperty(value = "状态(0:空闲, 1:就餐中, 2:其他, 3:加餐)")
     @TableField("status")
     private Integer status;

+ 3 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreBookingTableVo.java

@@ -57,4 +57,7 @@ public class StoreBookingTableVo {
 
     @ApiModelProperty(value = "二维码URL")
     private String qrcodeUrl;
+
+    @ApiModelProperty(value = "APP桌码二维码URL")
+    private String appQrcodeUrl;
 }

+ 16 - 0
alien-store/src/main/java/shop/alien/store/service/TableAppQrCodeService.java

@@ -0,0 +1,16 @@
+package shop.alien.store.service;
+
+/**
+ * APP 桌码二维码(普通 QR,内容为门店ID+桌号 JSON,供 APP 扫码识别)
+ */
+public interface TableAppQrCodeService {
+
+    /**
+     * 生成二维码图片并上传 OSS,内容为 {@code {"storeId":..,"tableNumber":".."}}
+     *
+     * @param storeId      商户/门店 ID
+     * @param tableNumber  桌号
+     * @return OSS 访问 URL
+     */
+    String generateTableAppQrCodeAndUpload(Integer storeId, String tableNumber);
+}

+ 49 - 17
alien-store/src/main/java/shop/alien/store/service/impl/StoreTableServiceImpl.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -20,6 +21,7 @@ import shop.alien.mapper.StoreTableLogMapper;
 import shop.alien.mapper.StoreTableMapper;
 import shop.alien.store.config.BaseRedisService;
 import shop.alien.store.service.StoreTableService;
+import shop.alien.store.service.TableAppQrCodeService;
 import shop.alien.store.service.WeChatMiniProgramQrCodeService;
 import shop.alien.util.common.JwtUtil;
 
@@ -41,6 +43,7 @@ public class StoreTableServiceImpl extends ServiceImpl<StoreTableMapper, StoreTa
 
     private final StoreTableLogMapper storeTableLogMapper;
     private final WeChatMiniProgramQrCodeService weChatMiniProgramQrCodeService;
+    private final TableAppQrCodeService tableAppQrCodeService;
     private final BaseRedisService baseRedisService;
 
     @Override
@@ -117,23 +120,37 @@ public class StoreTableServiceImpl extends ServiceImpl<StoreTableMapper, StoreTa
     public void asyncGenerateQrCodesForTables(Integer storeId, List<String> tableNumbers) {
         log.info("开始异步生成桌号二维码, storeId={}, tableNumbers={}", storeId, tableNumbers);
         try {
-            // 查询刚创建的桌号
             LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
             wrapper.eq(StoreTable::getStoreId, storeId)
-                    .in(StoreTable::getTableNumber, tableNumbers)
-                    .isNull(StoreTable::getQrcodeUrl);
+                    .in(StoreTable::getTableNumber, tableNumbers);
             List<StoreTable> tables = this.list(wrapper);
-            
+
             for (StoreTable table : tables) {
                 try {
-                    String qrCodeUrl = weChatMiniProgramQrCodeService.generateTableQrCode(table.getId(), storeId);
-                    if (qrCodeUrl != null && !qrCodeUrl.isEmpty()) {
-                        // 更新二维码URL
-                        LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
-                        updateWrapper.eq(StoreTable::getId, table.getId())
-                                .set(StoreTable::getQrcodeUrl, qrCodeUrl);
+                    LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
+                    updateWrapper.eq(StoreTable::getId, table.getId());
+                    boolean any = false;
+
+                    if (StringUtils.isBlank(table.getQrcodeUrl())) {
+                        String qrCodeUrl = weChatMiniProgramQrCodeService.generateTableQrCode(table.getId(), storeId);
+                        if (StringUtils.isNotBlank(qrCodeUrl)) {
+                            updateWrapper.set(StoreTable::getQrcodeUrl, qrCodeUrl);
+                            any = true;
+                            log.info("桌号小程序码生成成功, tableId={}, qrCodeUrl={}", table.getId(), qrCodeUrl);
+                        }
+                    }
+
+                    if (StringUtils.isBlank(table.getAppQrcodeUrl())) {
+                        String appUrl = tableAppQrCodeService.generateTableAppQrCodeAndUpload(storeId, table.getTableNumber());
+                        if (StringUtils.isNotBlank(appUrl)) {
+                            updateWrapper.set(StoreTable::getAppQrcodeUrl, appUrl);
+                            any = true;
+                            log.info("桌号APP码生成成功, tableId={}, appQrcodeUrl={}", table.getId(), appUrl);
+                        }
+                    }
+
+                    if (any) {
                         this.update(updateWrapper);
-                        log.info("桌号二维码生成成功, tableId={}, qrCodeUrl={}", table.getId(), qrCodeUrl);
                     }
                 } catch (Exception e) {
                     log.error("生成桌号二维码失败, tableId={}, error={}", table.getId(), e.getMessage(), e);
@@ -195,14 +212,29 @@ public class StoreTableServiceImpl extends ServiceImpl<StoreTableMapper, StoreTa
     public void asyncUpdateQrCodeForTable(Integer tableId, Integer storeId) {
         log.info("开始异步更新桌号二维码, tableId={}, storeId={}", tableId, storeId);
         try {
+            StoreTable table = this.getById(tableId);
+            if (table == null) {
+                log.warn("异步更新桌号二维码失败:桌号不存在, tableId={}", tableId);
+                return;
+            }
+
             String qrCodeUrl = weChatMiniProgramQrCodeService.generateTableQrCode(tableId, storeId);
-            if (qrCodeUrl != null && !qrCodeUrl.isEmpty()) {
-                // 更新二维码URL
-                LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
-                updateWrapper.eq(StoreTable::getId, tableId)
-                        .set(StoreTable::getQrcodeUrl, qrCodeUrl);
+            String appUrl = tableAppQrCodeService.generateTableAppQrCodeAndUpload(storeId, table.getTableNumber());
+
+            LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.eq(StoreTable::getId, tableId);
+            boolean any = false;
+            if (StringUtils.isNotBlank(qrCodeUrl)) {
+                updateWrapper.set(StoreTable::getQrcodeUrl, qrCodeUrl);
+                any = true;
+            }
+            if (StringUtils.isNotBlank(appUrl)) {
+                updateWrapper.set(StoreTable::getAppQrcodeUrl, appUrl);
+                any = true;
+            }
+            if (any) {
                 this.update(updateWrapper);
-                log.info("桌号二维码更新成功, tableId={}, qrCodeUrl={}", tableId, qrCodeUrl);
+                log.info("桌号二维码更新成功, tableId={}, qrCodeUrl={}, appQrcodeUrl={}", tableId, qrCodeUrl, appUrl);
             }
         } catch (Exception e) {
             log.error("更新桌号二维码失败, tableId={}, error={}", tableId, e.getMessage(), e);

+ 70 - 0
alien-store/src/main/java/shop/alien/store/service/impl/TableAppQrCodeServiceImpl.java

@@ -0,0 +1,70 @@
+package shop.alien.store.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+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 lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import shop.alien.store.service.TableAppQrCodeService;
+import shop.alien.util.ali.AliOSSUtil;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+/**
+ * APP 桌码:仅编码 storeId + tableNumber,不依赖微信接口
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class TableAppQrCodeServiceImpl implements TableAppQrCodeService {
+
+    private static final int QR_SIZE = 430;
+
+    private final AliOSSUtil aliOSSUtil;
+
+    @Override
+    public String generateTableAppQrCodeAndUpload(Integer storeId, String tableNumber) {
+        if (storeId == null || StringUtils.isBlank(tableNumber)) {
+            throw new IllegalArgumentException("storeId与tableNumber不能为空");
+        }
+
+        JSONObject payload = new JSONObject();
+        payload.put("storeId", storeId);
+        payload.put("tableNumber", tableNumber.trim());
+        String content = payload.toJSONString();
+
+        byte[] png = encodeQrPng(content, QR_SIZE);
+        String safeNum = tableNumber.trim().replaceAll("[^a-zA-Z0-9_-]", "_");
+        String ossPath = String.format(
+                "qrcode/table/app/%d_%s_%d.png",
+                storeId,
+                safeNum,
+                System.currentTimeMillis());
+
+        ByteArrayInputStream in = new ByteArrayInputStream(png);
+        String url = aliOSSUtil.uploadFile(in, ossPath);
+        if (StringUtils.isBlank(url)) {
+            log.error("上传APP桌码到OSS失败, ossPath={}", ossPath);
+            throw new RuntimeException("上传APP桌码到OSS失败");
+        }
+        log.info("APP桌码生成并上传成功, storeId={}, tableNumber={}, url={}", storeId, tableNumber, url);
+        return url;
+    }
+
+    private static byte[] encodeQrPng(String text, int size) {
+        try {
+            QRCodeWriter writer = new QRCodeWriter();
+            BitMatrix matrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            MatrixToImageWriter.writeToStream(matrix, "PNG", out);
+            return out.toByteArray();
+        } catch (Exception e) {
+            throw new RuntimeException("生成APP二维码失败: " + e.getMessage(), e);
+        }
+    }
+}