From c1147646b9ef1d713a202d7ab8cf3ea8d677f142 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期六, 27 九月 2025 21:56:54 +0800
Subject: [PATCH] fix:优化评价

---
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/VehicleEvaluationQrcodeController.java |   21 ++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleEvaluationQrcodeServiceImpl.java     |   97 ++++++++++-
 ruoyi-system/src/main/java/com/ruoyi/system/service/IVehicleEvaluationQrcodeService.java             |    9 +
 ruoyi-ui/src/views/evaluation/qrcode/index.vue                                                       |   98 ++++++++++-
 ruoyi-system/src/main/java/com/ruoyi/system/config/QRCodeConfig.java                                 |   39 ++++
 ruoyi-admin/src/main/resources/application.yml                                                       |    6 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java                                   |   52 ++++++
 ruoyi-ui/src/views/evaluation/index.vue                                                              |  150 +++++++++++++++++-
 ruoyi-ui/src/api/evaluation.js                                                                       |    5 
 9 files changed, 430 insertions(+), 47 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/VehicleEvaluationQrcodeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/VehicleEvaluationQrcodeController.java
index 3aa5fa2..f36e2ca 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/VehicleEvaluationQrcodeController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/VehicleEvaluationQrcodeController.java
@@ -111,11 +111,16 @@
             if (StringUtils.isEmpty(vehicleNo)) {
                 return error("杞︾墝鍙蜂笉鑳戒负绌�");
             }
+            
+            VehicleEvaluationQrcode qrcode;
             if (StringUtils.isEmpty(qrcodeUrl)) {
-                return error("浜岀淮鐮乁RL涓嶈兘涓虹┖");
+                // 濡傛灉URL涓虹┖锛屼娇鐢ㄩ粯璁RL
+                qrcode = vehicleEvaluationQrcodeService.generateVehicleEvaluationQrcode(vehicleNo);
+            } else {
+                // 濡傛灉URL涓嶄负绌猴紝浣跨敤鎸囧畾鐨刄RL
+                qrcode = vehicleEvaluationQrcodeService.generateVehicleEvaluationQrcode(vehicleNo, qrcodeUrl);
             }
             
-            VehicleEvaluationQrcode qrcode = vehicleEvaluationQrcodeService.generateVehicleEvaluationQrcode(vehicleNo, qrcodeUrl);
             if (qrcode != null) {
                 return success(qrcode);
             } else {
@@ -133,9 +138,17 @@
     @PreAuthorize("@ss.hasPermi('evaluation:qrcode:batch')")
     @Log(title = "杞﹁締璇勪环浜岀淮鐮�", businessType = BusinessType.INSERT)
     @PostMapping("/batch")
-    public AjaxResult batchGenerateQrcode() {
+    public AjaxResult batchGenerateQrcode(@RequestBody JSONObject params) {
         try {
-            int count = vehicleEvaluationQrcodeService.batchGenerateVehicleEvaluationQrcode();
+            String qrcodeUrl = params.getString("qrcodeUrl");
+            @SuppressWarnings("unchecked")
+            List<String> vehicleNos = (List<String>) params.get("vehicleNos");
+            
+            if (vehicleNos == null || vehicleNos.isEmpty()) {
+                return error("杞︾墝鍙峰垪琛ㄤ笉鑳戒负绌�");
+            }
+            
+            int count = vehicleEvaluationQrcodeService.batchGenerateVehicleEvaluationQrcode(vehicleNos, qrcodeUrl);
             return success("鎴愬姛鐢熸垚 " + count + " 涓簩缁寸爜");
         } catch (Exception e) {
             logger.error("鎵归噺鐢熸垚浜岀淮鐮佸け璐�", e);
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 626c3a6..8fae9c6 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -154,4 +154,8 @@
   dev:
     enabled: true  # 鏄惁鍚敤寮�鍙戞ā寮�
     mockUserInfo: true  # 鏄惁妯℃嫙鐢ㄦ埛淇℃伅
-    ngrokUrl: http://your-ngrok-url.ngrok.io  # 鍐呯綉绌块�忓湴鍧�
\ No newline at end of file
+    ngrokUrl: http://your-ngrok-url.ngrok.io  # 鍐呯綉绌块�忓湴鍧�
+
+# 浜岀淮鐮侀厤缃�
+qrcode:
+  defaultUrl: http://localhost:81/evaluation?vehicle={vehicleNo}  # 榛樿浜岀淮鐮乁RL妯℃澘锛寋vehicleNo}浼氳鏇挎崲涓哄疄闄呰溅鐗屽彿
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java
index 5a28d53..cb983db 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java
@@ -9,6 +9,7 @@
 import org.slf4j.LoggerFactory;
 
 import javax.imageio.ImageIO;
+import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -95,4 +96,55 @@
         }
         return null;
     }
+
+    /**
+     * 鐢熸垚甯﹁溅鐗屽彿鐨凚ase64缂栫爜浜岀淮鐮�
+     * 
+     * @param content 浜岀淮鐮佸唴瀹�
+     * @param vehicleNo 杞︾墝鍙�
+     * @return Base64缂栫爜鐨勪簩缁寸爜
+     */
+    public static String generateQRCodeWithVehicleNoToBase64(String content, String vehicleNo) {
+        try {
+            Map<EncodeHintType, Object> hints = new HashMap<>();
+            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+            hints.put(EncodeHintType.MARGIN, 1);
+            
+            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);
+            BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
+            
+            // 鍒涘缓甯︽枃瀛楃殑鍥剧墖
+            int textHeight = 40; // 鏂囧瓧鍖哄煙楂樺害
+            int totalHeight = HEIGHT + textHeight;
+            BufferedImage finalImage = new BufferedImage(WIDTH, totalHeight, BufferedImage.TYPE_INT_RGB);
+            Graphics2D g2d = finalImage.createGraphics();
+            
+            // 璁剧疆鑳屾櫙涓虹櫧鑹�
+            g2d.setColor(Color.WHITE);
+            g2d.fillRect(0, 0, WIDTH, totalHeight);
+            
+            // 缁樺埗浜岀淮鐮�
+            g2d.drawImage(qrImage, 0, 0, null);
+            
+            // 缁樺埗杞︾墝鍙锋枃瀛�
+            g2d.setColor(Color.BLACK);
+            g2d.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 16));
+            FontMetrics fm = g2d.getFontMetrics();
+            int textWidth = fm.stringWidth(vehicleNo);
+            int x = (WIDTH - textWidth) / 2;
+            int y = HEIGHT + (textHeight + fm.getAscent()) / 2;
+            g2d.drawString(vehicleNo, x, y);
+            
+            g2d.dispose();
+            
+            // 杞崲涓築ase64
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(finalImage, FORMAT, baos);
+            return "data:image/png;base64," + java.util.Base64.getEncoder().encodeToString(baos.toByteArray());
+            
+        } catch (Exception e) {
+            log.error("鐢熸垚甯﹁溅鐗屽彿鐨勪簩缁寸爜澶辫触: {}", e.getMessage());
+            return null;
+        }
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/config/QRCodeConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/config/QRCodeConfig.java
new file mode 100644
index 0000000..d88fee4
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/config/QRCodeConfig.java
@@ -0,0 +1,39 @@
+package com.ruoyi.system.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 浜岀淮鐮侀厤缃�
+ * 
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "qrcode")
+public class QRCodeConfig {
+    /**
+     * 榛樿浜岀淮鐮乁RL妯℃澘
+     */
+    private String defaultUrl = "http://localhost:8080/evaluation?vehicle={vehicleNo}";
+
+    public String getDefaultUrl() {
+        return defaultUrl;
+    }
+
+    public void setDefaultUrl(String defaultUrl) {
+        this.defaultUrl = defaultUrl;
+    }
+    
+    /**
+     * 鏍规嵁杞︾墝鍙风敓鎴愪簩缁寸爜URL
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 浜岀淮鐮乁RL
+     */
+    public String generateUrl(String vehicleNo) {
+        if (defaultUrl != null && defaultUrl.contains("{vehicleNo}")) {
+            return defaultUrl.replace("{vehicleNo}", vehicleNo);
+        }
+        return defaultUrl + "?vehicle=" + vehicleNo;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IVehicleEvaluationQrcodeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IVehicleEvaluationQrcodeService.java
index ddaac80..f789d08 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/IVehicleEvaluationQrcodeService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IVehicleEvaluationQrcodeService.java
@@ -89,4 +89,13 @@
      * @return 缁撴灉
      */
     public int batchGenerateVehicleEvaluationQrcode();
+
+    /**
+     * 鎵归噺鐢熸垚杞﹁締璇勪环浜岀淮鐮侊紙鎸囧畾杞︾墝鍙峰垪琛級
+     * 
+     * @param vehicleNos 杞︾墝鍙峰垪琛�
+     * @param qrcodeUrl 浜岀淮鐮乁RL锛堝彲閫夛級
+     * @return 缁撴灉
+     */
+    public int batchGenerateVehicleEvaluationQrcode(List<String> vehicleNos, String qrcodeUrl);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleEvaluationQrcodeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleEvaluationQrcodeServiceImpl.java
index a36f68f..5de0d50 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleEvaluationQrcodeServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleEvaluationQrcodeServiceImpl.java
@@ -5,6 +5,7 @@
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.QRCodeUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.config.QRCodeConfig;
 import com.ruoyi.system.mapper.VehicleInfoMapper;
 import com.ruoyi.system.domain.VehicleInfo;
 import com.ruoyi.system.mapper.VehicleEvaluationQrcodeMapper;
@@ -27,6 +28,9 @@
 
     @Autowired
     private VehicleInfoMapper vehicleInfoMapper;
+
+    @Autowired
+    private QRCodeConfig qrCodeConfig;
 
     @Value("${ruoyi.profile}")
     private String uploadPath;
@@ -125,9 +129,48 @@
             return null;
         }
 
-        // 妫�鏌ヨ溅杈嗘槸鍚﹀瓨鍦�
-        VehicleInfo vehicleInfo = vehicleInfoMapper.selectVehicleInfoByVehicleNo(vehicleNo);
-        if (vehicleInfo == null) {
+        // 娉ㄦ剰锛氳繖閲屼笉妫�鏌ヨ溅杈嗕俊鎭〃锛屽厑璁镐负浠绘剰杞︾墝鍙风敓鎴愪簩缁寸爜
+
+        // 妫�鏌ユ槸鍚﹀凡瀛樺湪浜岀淮鐮�
+        VehicleEvaluationQrcode existingQrcode = vehicleEvaluationQrcodeMapper.selectVehicleEvaluationQrcodeByVehicleNo(vehicleNo);
+        if (existingQrcode != null) {
+            return existingQrcode;
+        }
+
+        // 鐢熸垚浜岀淮鐮佸唴瀹�
+        String qrcodeContent = "EVAL:" + vehicleNo;
+        String qrcodeUrl = qrCodeConfig.generateUrl(vehicleNo);
+
+        // 鐢熸垚甯﹁溅鐗屽彿鐨勪簩缁寸爜鍥剧墖涓篵ase64鏍煎紡
+        String qrcodeImageBase64 = QRCodeUtils.generateQRCodeWithVehicleNoToBase64(qrcodeUrl, vehicleNo);
+
+        if (qrcodeImageBase64 != null) {
+            VehicleEvaluationQrcode qrcode = new VehicleEvaluationQrcode();
+            qrcode.setVehicleNo(vehicleNo);
+            qrcode.setQrcodeUrl(qrcodeUrl);
+            qrcode.setQrcodeContent(qrcodeContent);
+            qrcode.setQrcodeImage(qrcodeImageBase64);
+            qrcode.setStatus("0");
+            qrcode.setCreateBy("system");
+            qrcode.setCreateTime(DateUtils.getNowDate());
+
+            int result = vehicleEvaluationQrcodeMapper.insertVehicleEvaluationQrcode(qrcode);
+            if (result > 0) {
+                return qrcode;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * 鐢熸垚杞﹁締璇勪环浜岀淮鐮侊紙涓嶆鏌ヨ溅杈嗕俊鎭〃锛�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 浜岀淮鐮佷俊鎭�
+     */
+    private VehicleEvaluationQrcode generateVehicleEvaluationQrcodeWithoutVehicleCheck(String vehicleNo) {
+        if (StringUtils.isEmpty(vehicleNo)) {
             return null;
         }
 
@@ -139,10 +182,10 @@
 
         // 鐢熸垚浜岀淮鐮佸唴瀹�
         String qrcodeContent = "EVAL:" + vehicleNo;
-        String qrcodeUrl = "http://localhost:" + serverPort + "/evaluation?vehicle=" + vehicleNo;
+        String qrcodeUrl = qrCodeConfig.generateUrl(vehicleNo);
 
-        // 鐢熸垚浜岀淮鐮佸浘鐗囦负base64鏍煎紡
-        String qrcodeImageBase64 = QRCodeUtils.generateQRCodeToBase64(qrcodeUrl);
+        // 鐢熸垚甯﹁溅鐗屽彿鐨勪簩缁寸爜鍥剧墖涓篵ase64鏍煎紡
+        String qrcodeImageBase64 = QRCodeUtils.generateQRCodeWithVehicleNoToBase64(qrcodeUrl, vehicleNo);
 
         if (qrcodeImageBase64 != null) {
             VehicleEvaluationQrcode qrcode = new VehicleEvaluationQrcode();
@@ -176,11 +219,7 @@
             return null;
         }
 
-        // 妫�鏌ヨ溅杈嗘槸鍚﹀瓨鍦�
-        VehicleInfo vehicleInfo = vehicleInfoMapper.selectVehicleInfoByVehicleNo(vehicleNo);
-        if (vehicleInfo == null) {
-            return null;
-        }
+        // 娉ㄦ剰锛氳繖閲屼笉妫�鏌ヨ溅杈嗕俊鎭〃锛屽厑璁镐负浠绘剰杞︾墝鍙风敓鎴愪簩缁寸爜
 
         // 妫�鏌ユ槸鍚﹀凡瀛樺湪浜岀淮鐮�
         VehicleEvaluationQrcode existingQrcode = vehicleEvaluationQrcodeMapper.selectVehicleEvaluationQrcodeByVehicleNo(vehicleNo);
@@ -191,8 +230,8 @@
             existingQrcode.setUpdateBy("system");
             existingQrcode.setUpdateTime(DateUtils.getNowDate());
             
-            // 閲嶆柊鐢熸垚浜岀淮鐮佸浘鐗囦负base64鏍煎紡
-            String qrcodeImageBase64 = QRCodeUtils.generateQRCodeToBase64(qrcodeUrl);
+            // 閲嶆柊鐢熸垚甯﹁溅鐗屽彿鐨勪簩缁寸爜鍥剧墖涓篵ase64鏍煎紡
+            String qrcodeImageBase64 = QRCodeUtils.generateQRCodeWithVehicleNoToBase64(qrcodeUrl, vehicleNo);
             
             if (qrcodeImageBase64 != null) {
                 existingQrcode.setQrcodeImage(qrcodeImageBase64);
@@ -205,8 +244,8 @@
         // 鐢熸垚浜岀淮鐮佸唴瀹�
         String qrcodeContent = "EVAL:" + vehicleNo;
 
-        // 鐢熸垚浜岀淮鐮佸浘鐗囦负base64鏍煎紡
-        String qrcodeImageBase64 = QRCodeUtils.generateQRCodeToBase64(qrcodeUrl);
+        // 鐢熸垚甯﹁溅鐗屽彿鐨勪簩缁寸爜鍥剧墖涓篵ase64鏍煎紡
+        String qrcodeImageBase64 = QRCodeUtils.generateQRCodeWithVehicleNoToBase64(qrcodeUrl, vehicleNo);
 
         if (qrcodeImageBase64 != null) {
             VehicleEvaluationQrcode qrcode = new VehicleEvaluationQrcode();
@@ -249,4 +288,32 @@
 
         return successCount;
     }
+
+    /**
+     * 鎵归噺鐢熸垚杞﹁締璇勪环浜岀淮鐮侊紙鎸囧畾杞︾墝鍙峰垪琛級
+     * 
+     * @param vehicleNos 杞︾墝鍙峰垪琛�
+     * @param qrcodeUrl 浜岀淮鐮乁RL锛堝彲閫夛級
+     * @return 缁撴灉
+     */
+    @Override
+    public int batchGenerateVehicleEvaluationQrcode(List<String> vehicleNos, String qrcodeUrl) {
+        int successCount = 0;
+        for (String vehicleNo : vehicleNos) {
+            if (StringUtils.isEmpty(vehicleNo)) {
+                continue; // 璺宠繃绌虹殑杞︾墝鍙�
+            }
+            
+            VehicleEvaluationQrcode qrcode;
+            if (StringUtils.isEmpty(qrcodeUrl)) {
+                qrcode = generateVehicleEvaluationQrcodeWithoutVehicleCheck(vehicleNo);
+            } else {
+                qrcode = generateVehicleEvaluationQrcode(vehicleNo, qrcodeUrl);
+            }
+            if (qrcode != null) {
+                successCount++;
+            }
+        }
+        return successCount;
+    }
 }
diff --git a/ruoyi-ui/src/api/evaluation.js b/ruoyi-ui/src/api/evaluation.js
index 41651b8..83a8e1f 100644
--- a/ruoyi-ui/src/api/evaluation.js
+++ b/ruoyi-ui/src/api/evaluation.js
@@ -88,10 +88,11 @@
 }
 
 // 鎵归噺鐢熸垚杞﹁締璇勪环浜岀淮鐮�
-export function batchGenerateQrcode() {
+export function batchGenerateQrcode(data) {
   return request({
     url: '/evaluation/qrcode/batch',
-    method: 'post'
+    method: 'post',
+    data: data
   })
 }
 
diff --git a/ruoyi-ui/src/views/evaluation/index.vue b/ruoyi-ui/src/views/evaluation/index.vue
index d4db6f1..e0fae2a 100644
--- a/ruoyi-ui/src/views/evaluation/index.vue
+++ b/ruoyi-ui/src/views/evaluation/index.vue
@@ -3,7 +3,7 @@
     <!-- 椤甸潰澶撮儴 -->
     <div class="evaluation-header">
       <h1>鏈嶅姟璇勪环</h1>
-      <p>鎰熻阿鎮ㄤ娇鐢ㄦ垜浠殑鏈嶅姟锛岃瀵规湰娆℃湇鍔¤繘琛岃瘎浠�</p>
+      <p>鎰熻阿鎮ㄤ娇鐢ㄦ垜浠殑闈�120鎬ユ晳鍖荤枟杞繍鏈嶅姟锛岃瀵规湰娆℃湇鍔¤繘琛岃瘎浠凤紒</p>
     </div>
 
     <!-- 杞﹁締淇℃伅 -->
@@ -19,7 +19,7 @@
       <el-form ref="evaluationForm" :model="evaluationForm" :rules="rules" label-width="80px" size="small">
         <!-- 瀹㈡埛淇℃伅 -->
         <div class="form-section">
-          <h3>瀹㈡埛淇℃伅</h3>
+          <h3>瀹㈡埛淇℃伅:</h3>
           
           <!-- 寰俊鎺堟潈淇℃伅鏄剧ず -->
           <div v-if="evaluationForm.wechatOpenid" class="wechat-info">
@@ -46,14 +46,13 @@
             <div class="wechat-tip">鐐瑰嚮鍙嚜鍔ㄨ幏鍙栨偍鐨勫井淇′俊鎭�</div>
           </div>
           
-          <el-form-item label="濮撳悕" prop="customerName">
+          <el-form-item label="绉板懠" prop="customerName">
             <el-input v-model="evaluationForm.customerName" placeholder="璇疯緭鍏ユ偍鐨勫鍚�" />
           </el-form-item>
           <el-form-item label="鎵嬫満鍙�" prop="customerPhone">
             <el-input v-model="evaluationForm.customerPhone" placeholder="璇疯緭鍏ユ偍鐨勬墜鏈哄彿" />
             <div v-if="evaluationForm.wechatOpenid" class="phone-tip">
-              <i class="el-icon-info"></i>
-              寰俊鎺堟潈鏃犳硶鐩存帴鑾峰彇鎵嬫満鍙凤紝璇锋墜鍔ㄨ緭鍏�
+             
             </div>
           </el-form-item>
         </div>
@@ -65,17 +64,16 @@
             <!-- 鏄熺骇璇勪环 - 鏍囬鍜岃瘎鍒嗗湪鍚屼竴琛� -->
             <div v-if="dimension.dimensionType === 'star'" class="star-rating-inline">
               <div class="dimension-title-inline">
-                <span>{{ dimension.dimensionName }}</span>
+                <span class="dimension-name-fixed">{{ dimension.dimensionName }}</span>
                 <span v-if="dimension.isRequired === '1'" class="required">*</span>
               </div>
               <div class="star-rating-content">
                 <el-rate
                   :value="getDimensionScore(dimension.dimensionId)"
                   :max="5"
-                  show-text
-                  :texts="['寰堝樊', '杈冨樊', '涓�鑸�', '婊℃剰', '闈炲父婊℃剰']"
                   @change="updateDimensionScore(dimension.dimensionId, $event)"
                   size="small"
+                  :aria-label="`璇勪环${dimension.dimensionName}`"
                 />
               </div>
             </div>
@@ -90,8 +88,16 @@
                 {{ dimension.dimensionDesc }}
               </div>
               <div class="select-rating">
-                <el-radio-group :value="getDimensionOption(dimension.dimensionId)" @change="updateDimensionOption(dimension.dimensionId, $event)" size="small">
-                  <el-radio v-for="option in getDimensionOptions(dimension)" :key="option.value" :label="option.value">
+                <el-radio-group 
+                  v-model="selectedOptions[dimension.dimensionId]"
+                  @change="(value) => handleOptionChange(dimension.dimensionId, value)"
+                  size="small"
+                  :aria-label="`閫夋嫨${dimension.dimensionName}`">
+                  <el-radio 
+                    v-for="option in getDimensionOptions(dimension)" 
+                    :key="option.value" 
+                    :label="option.value"
+                    :aria-label="option.label">
                     {{ option.label }}
                   </el-radio>
                 </el-radio-group>
@@ -115,6 +121,7 @@
                   placeholder="璇疯緭鍏ユ偍鐨勬剰瑙佹垨寤鸿"
                   @input="updateDimensionText(dimension.dimensionId, $event)"
                   size="small"
+                  :aria-label="`${dimension.dimensionName}璇勪环鎰忚`"
                 />
               </div>
             </div>
@@ -166,6 +173,8 @@
         wechatPhone: '',
         evaluationDetails: []
       },
+      // 鐢ㄤ簬瀛樺偍閫夋嫨绫诲瀷鐨勮瘎浠烽�夐」
+      selectedOptions: {},
       rules: {
         customerName: [
           { required: true, message: '璇疯緭鍏ユ偍鐨勫鍚�', trigger: 'blur' }
@@ -303,13 +312,37 @@
         detail = { dimensionId, score: 0 };
         this.evaluationForm.evaluationDetails.push(detail);
       }
-      detail.score = score;
+      // 浣跨敤Vue.set纭繚鍝嶅簲寮忔洿鏂�
+      this.$set(detail, 'score', score);
     },
 
     // 鑾峰彇缁村害閫夐」
     getDimensionOption(dimensionId) {
       const detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
       return detail ? detail.optionValue : '';
+    },
+
+    // 鑾峰彇缁村害閫夐」鍊硷紙鐢ㄤ簬v-model锛�
+    getDimensionOptionValue(dimensionId) {
+      const detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      if (!detail) {
+        // 濡傛灉涓嶅瓨鍦紝鍒涘缓涓�涓柊鐨刣etail瀵硅薄
+        const newDetail = { dimensionId, optionValue: '' };
+        this.evaluationForm.evaluationDetails.push(newDetail);
+        return newDetail;
+      }
+      return detail;
+    },
+
+    // 鑾峰彇缁村害閫夐」鐨剉-model瀵硅薄
+    getDimensionOptionModel(dimensionId) {
+      const detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      if (!detail) {
+        const newDetail = { dimensionId, optionValue: '' };
+        this.evaluationForm.evaluationDetails.push(newDetail);
+        return newDetail;
+      }
+      return detail;
     },
 
     // 鏇存柊缁村害閫夐」
@@ -319,7 +352,16 @@
         detail = { dimensionId, optionValue: '' };
         this.evaluationForm.evaluationDetails.push(detail);
       }
-      detail.optionValue = optionValue;
+      // 浣跨敤Vue.set纭繚鍝嶅簲寮忔洿鏂�
+      this.$set(detail, 'optionValue', optionValue);
+    },
+
+    // 澶勭悊閫夐」鍙樺寲
+    handleOptionChange(dimensionId, value) {
+      // 鏇存柊selectedOptions
+      this.$set(this.selectedOptions, dimensionId, value);
+      // 鍚屾椂鏇存柊evaluationDetails
+      this.updateDimensionOption(dimensionId, value);
     },
 
     // 鑾峰彇缁村害鏂囨湰
@@ -335,7 +377,8 @@
         detail = { dimensionId, textContent: '' };
         this.evaluationForm.evaluationDetails.push(detail);
       }
-      detail.textContent = textContent;
+      // 浣跨敤Vue.set纭繚鍝嶅簲寮忔洿鏂�
+      this.$set(detail, 'textContent', textContent);
     },
 
     // 鑾峰彇缁村害閫夐」閰嶇疆
@@ -344,6 +387,7 @@
       try {
         return JSON.parse(dimension.options);
       } catch (error) {
+        console.error('Error parsing options for', dimension.dimensionName, ':', error);
         return [];
       }
     },
@@ -372,7 +416,7 @@
         // 鎻愪氦璇勪环
         const response = await submitEvaluation(this.evaluationForm);
         if (response.code === 200) {
-          this.resultMessage = response.msg;
+          this.resultMessage = "鎰熻阿鎮ㄧ殑鍙嶉锛屾偍鐨勫弽棣堝皢淇冧娇鎴戜滑涓嶆柇杩涙锛屾垜浠皢缁х画鎻愪緵鏇村ソ鐨勬湇鍔�";
           this.showResult = true;
         } else {
           this.$message.error(response.msg || '鎻愪氦澶辫触锛岃閲嶈瘯');
@@ -391,6 +435,7 @@
       this.evaluationForm.customerName = '';
       this.evaluationForm.customerPhone = '';
       this.evaluationForm.evaluationDetails = [];
+      this.selectedOptions = {};
       this.$refs.evaluationForm.resetFields();
     }
   }
@@ -513,6 +558,15 @@
   flex-shrink: 0;
 }
 
+.dimension-name-fixed {
+  display: inline-block;
+  width: 100px;
+  text-align: left;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
 .star-rating-content {
   flex: 1;
   min-width: 200px;
@@ -540,6 +594,69 @@
 
 .select-rating .el-radio__label {
   font-size: 13px;
+}
+
+/* 鏀瑰杽鏃犻殰纰嶈闂� */
+.select-rating .el-radio__original {
+  position: absolute !important;
+  opacity: 0 !important;
+  width: 0 !important;
+  height: 0 !important;
+  margin: 0 !important;
+  padding: 0 !important;
+  border: none !important;
+  outline: none !important;
+  clip: rect(0, 0, 0, 0) !important;
+  -webkit-appearance: none !important;
+  -moz-appearance: none !important;
+  appearance: none !important;
+}
+
+.select-rating .el-radio__input {
+  position: relative;
+  white-space: nowrap;
+  vertical-align: middle;
+  outline: none;
+  line-height: 1;
+}
+
+.select-rating .el-radio__inner {
+  border: 1px solid #dcdfe6;
+  border-radius: 100%;
+  width: 14px;
+  height: 14px;
+  background-color: #fff;
+  position: relative;
+  cursor: pointer;
+  display: inline-block;
+  box-sizing: border-box;
+  transition: border-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46), background-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46);
+}
+
+.select-rating .el-radio__inner:hover {
+  border-color: #409eff;
+}
+
+.select-rating .el-radio.is-checked .el-radio__inner {
+  border-color: #409eff;
+  background: #409eff;
+}
+
+.select-rating .el-radio.is-checked .el-radio__inner::after {
+  transform: translate(-50%, -50%) scale(1);
+}
+
+.select-rating .el-radio__inner::after {
+  width: 4px;
+  height: 4px;
+  border-radius: 100%;
+  background-color: #fff;
+  content: "";
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%) scale(0);
+  transition: transform 0.15s ease-in;
 }
 
 /* 浼樺寲鏂囨湰璇勪环鏄剧ず */
@@ -736,6 +853,11 @@
     font-size: 13px;
   }
   
+  .dimension-name-fixed {
+    width: 120px;
+    font-size: 13px;
+  }
+  
   .star-rating-content {
     min-width: auto;
     width: 100%;
diff --git a/ruoyi-ui/src/views/evaluation/qrcode/index.vue b/ruoyi-ui/src/views/evaluation/qrcode/index.vue
index be23c18..e29cf62 100644
--- a/ruoyi-ui/src/views/evaluation/qrcode/index.vue
+++ b/ruoyi-ui/src/views/evaluation/qrcode/index.vue
@@ -58,7 +58,7 @@
 
     <el-table v-loading="loading" :data="qrcodeList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="浜岀淮鐮両D" align="center" prop="qrcodeId" />
+    
       <el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" />
       <el-table-column label="浜岀淮鐮乁RL" align="center" prop="qrcodeUrl" width="200">
         <template slot-scope="scope">
@@ -128,7 +128,7 @@
           <el-input v-model="form.vehicleNo" placeholder="璇疯緭鍏ヨ溅鐗屽彿" />
         </el-form-item>
         <el-form-item label="浜岀淮鐮乁RL" prop="qrcodeUrl">
-          <el-input v-model="form.qrcodeUrl" placeholder="璇疯緭鍏ヤ簩缁寸爜URL" />
+          <el-input v-model="form.qrcodeUrl" placeholder="鍙�夛紝鐣欑┖鍒欎娇鐢ㄩ粯璁RL" />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -137,10 +137,30 @@
       </div>
     </el-dialog>
 
+    <!-- 鎵归噺鐢熸垚浜岀淮鐮佸璇濇 -->
+    <el-dialog title="鎵归噺鐢熸垚浜岀淮鐮�" :visible.sync="batchOpen" width="600px" append-to-body>
+      <el-form ref="batchForm" :model="batchForm" :rules="batchRules" label-width="100px">
+        <el-form-item label="杞︾墝鍙�" prop="vehicleNos">
+          <el-input 
+            v-model="batchForm.vehicleNos" 
+            type="textarea" 
+            :rows="6"
+            placeholder="璇疯緭鍏ヨ溅鐗屽彿锛屽涓溅鐗屽彿鐢ㄩ�楀彿鍒嗛殧锛屼緥濡傦細绮12345,绮67890,绮11111" />
+        </el-form-item>
+        <el-form-item label="浜岀淮鐮乁RL" prop="qrcodeUrl">
+          <el-input v-model="batchForm.qrcodeUrl" placeholder="鍙�夛紝鐣欑┖鍒欎娇鐢ㄩ粯璁RL" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitBatchForm">纭� 瀹�</el-button>
+        <el-button @click="cancelBatch">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+
     <!-- 浜岀淮鐮佽鎯呭璇濇 -->
     <el-dialog title="浜岀淮鐮佽鎯�" :visible.sync="viewOpen" width="600px" append-to-body>
       <el-descriptions :column="2" border>
-        <el-descriptions-item label="浜岀淮鐮両D">{{ viewForm.qrcodeId }}</el-descriptions-item>
+       
         <el-descriptions-item label="杞︾墝鍙�">{{ viewForm.vehicleNo }}</el-descriptions-item>
         <el-descriptions-item label="浜岀淮鐮乁RL" :span="2">
           <el-link :href="viewForm.qrcodeUrl" target="_blank" type="primary">{{ viewForm.qrcodeUrl }}</el-link>
@@ -194,6 +214,8 @@
       title: "",
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
+      // 鏄惁鏄剧ず鎵归噺鐢熸垚寮瑰嚭灞�
+      batchOpen: false,
       // 鏄惁鏄剧ず鏌ョ湅寮瑰嚭灞�
       viewOpen: false,
       // 鏌ヨ鍙傛暟
@@ -205,6 +227,8 @@
       },
       // 琛ㄥ崟鍙傛暟
       form: {},
+      // 鎵归噺鐢熸垚琛ㄥ崟鍙傛暟
+      batchForm: {},
       // 鏌ョ湅琛ㄥ崟鍙傛暟
       viewForm: {},
       // 琛ㄥ崟鏍¢獙
@@ -213,7 +237,15 @@
           { required: true, message: "杞︾墝鍙蜂笉鑳戒负绌�", trigger: "blur" }
         ],
         qrcodeUrl: [
-          { required: true, message: "浜岀淮鐮乁RL涓嶈兘涓虹┖", trigger: "blur" },
+          { type: 'url', message: '璇疯緭鍏ユ纭殑URL鏍煎紡', trigger: 'blur' }
+        ]
+      },
+      // 鎵归噺鐢熸垚琛ㄥ崟鏍¢獙
+      batchRules: {
+        vehicleNos: [
+          { required: true, message: "杞︾墝鍙蜂笉鑳戒负绌�", trigger: "blur" }
+        ],
+        qrcodeUrl: [
           { type: 'url', message: '璇疯緭鍏ユ纭殑URL鏍煎紡', trigger: 'blur' }
         ]
       }
@@ -249,6 +281,14 @@
       };
       this.resetForm("form");
     },
+    // 鎵归噺琛ㄥ崟閲嶇疆
+    resetBatch() {
+      this.batchForm = {
+        vehicleNos: null,
+        qrcodeUrl: null
+      };
+      this.resetForm("batchForm");
+    },
     /** 鎼滅储鎸夐挳鎿嶄綔 */
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -277,7 +317,7 @@
         if (valid) {
           const params = {
             vehicleNo: this.form.vehicleNo,
-            qrcodeUrl: this.form.qrcodeUrl
+            qrcodeUrl: this.form.qrcodeUrl || null
           };
           generateQrcode(params).then(response => {
             this.$modal.msgSuccess("鐢熸垚鎴愬姛");
@@ -289,12 +329,48 @@
     },
     /** 鎵归噺鐢熸垚鎸夐挳鎿嶄綔 */
     handleBatchGenerate() {
-      this.$modal.confirm('鏄惁纭鎵归噺鐢熸垚鎵�鏈夎溅杈嗙殑浜岀淮鐮侊紵').then(function() {
-        return batchGenerateQrcode();
-      }).then(() => {
-        this.getList();
-        this.$modal.msgSuccess("鎵归噺鐢熸垚鎴愬姛");
-      }).catch(() => {});
+      this.resetBatch();
+      this.batchOpen = true;
+    },
+    // 鍙栨秷鎵归噺鐢熸垚
+    cancelBatch() {
+      this.batchOpen = false;
+      this.resetBatch();
+    },
+    /** 鎵归噺鎻愪氦鎸夐挳 */
+    submitBatchForm() {
+      this.$refs["batchForm"].validate(valid => {
+        if (valid) {
+          const vehicleNos = this.batchForm.vehicleNos.split(',').map(no => no.trim()).filter(no => no);
+          if (vehicleNos.length === 0) {
+            this.$modal.msgError("璇疯緭鍏ユ湁鏁堢殑杞︾墝鍙�");
+            return;
+          }
+          
+          console.log('鎵归噺鐢熸垚杞︾墝鍙峰垪琛�:', vehicleNos);
+          
+          const params = {
+            vehicleNos: vehicleNos,
+            qrcodeUrl: this.batchForm.qrcodeUrl || null
+          };
+          
+          console.log('鎵归噺鐢熸垚鍙傛暟:', params);
+          
+          batchGenerateQrcode(params).then(response => {
+            console.log('鎵归噺鐢熸垚鍝嶅簲:', response);
+            if (response.code === 200) {
+              this.$modal.msgSuccess(response.msg || "鎵归噺鐢熸垚鎴愬姛");
+            } else {
+              this.$modal.msgError(response.msg || "鎵归噺鐢熸垚澶辫触");
+            }
+            this.batchOpen = false;
+            this.getList();
+          }).catch(error => {
+            console.error('鎵归噺鐢熸垚澶辫触:', error);
+            this.$modal.msgError("鎵归噺鐢熸垚澶辫触锛岃閲嶈瘯");
+          });
+        }
+      });
     },
     /** 鏌ョ湅鎸夐挳鎿嶄綔 */
     handleView(row) {

--
Gitblit v1.9.1