From 7d81ce01560d384f15212edc40ebeaa9924913f9 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期日, 21 九月 2025 19:12:53 +0800
Subject: [PATCH] feat:新增评价功能

---
 ruoyi-system/src/main/resources/mapper/system/CustomerEvaluationMapper.xml                           |  159 +
 ruoyi-ui/src/views/system/vehicle/index.vue                                                          |   43 
 客户满意度评价功能说明.md                                                                                       |  134 +
 ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDimension.java                          |  129 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java          |  196 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleEvaluationQrcodeServiceImpl.java     |  252 ++
 ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleEvaluationQrcode.java                      |  104 
 ruoyi-system/src/main/resources/mapper/system/EvaluationDimensionMapper.xml                          |  110 +
 pom.xml                                                                                              |   14 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDimensionMapper.java                    |   67 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/AOrderStatusMapper.java                           |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IEvaluationDimensionService.java                 |   67 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDetailMapper.java                       |   84 
 完整部署指南.md                                                                                            |  225 ++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleInfoMapper.java                            |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomerEvaluationMapper.java                     |   84 
 sql/evaluation_dict.sql                                                                              |   26 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationDimensionController.java     |   97 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java              |  214 +
 ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java                                   |   98 
 ruoyi-ui/src/router/index.js                                                                         |   12 
 ruoyi-ui/src/views/evaluation/index.vue                                                              |  659 ++++++
 ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java                                   |  163 +
 ruoyi-ui/src/views/evaluation/dimension/index.vue                                                    |  325 ++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleEvaluationQrcodeMapper.java                |   76 
 sql/customer_evaluation_tables.sql                                                                   |  100 
 ruoyi-system/src/main/resources/mapper/system/EvaluationDetailMapper.xml                             |  116 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/ICustomerEvaluationService.java                  |   92 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EvaluationDimensionServiceImpl.java         |   99 
 sql/evaluation_menu.sql                                                                              |   79 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDetail.java                             |  126 +
 ruoyi-admin/src/main/resources/application.yml                                                       |    8 
 ruoyi-common/pom.xml                                                                                 |   11 
 ruoyi-ui/src/views/evaluation/customer/index.vue                                                     |  297 ++
 部署说明.md                                                                                              |  249 ++
 测试步骤.md                                                                                              |  121 +
 ruoyi-ui/src/views/evaluation/test.vue                                                               |  187 +
 ruoyi-system/src/main/resources/mapper/system/VehicleEvaluationQrcodeMapper.xml                      |  103 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/VehicleEvaluationQrcodeController.java |  145 +
 ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java                                  |   26 
 ruoyi-ui/src/views/evaluation/statistics/index.vue                                                   |  512 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/IVehicleEvaluationQrcodeService.java             |   92 
 ruoyi-ui/src/views/evaluation/qrcode/index.vue                                                       |  345 +++
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java                        |    4 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/CustomerEvaluation.java                           |  209 +
 ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml                                  |   34 
 sql/vehicle_info.sql                                                                                 |    5 
 ruoyi-ui/src/api/evaluation.js                                                                       |  181 +
 48 files changed, 6,472 insertions(+), 17 deletions(-)

diff --git a/pom.xml b/pom.xml
index 0d08086..1978da3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,6 +30,7 @@
         <poi.version>4.1.2</poi.version>
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
+        <zxing.version>3.5.1</zxing.version>
         <!-- override dependency version -->
         <tomcat.version>9.0.102</tomcat.version>
         <logback.version>1.2.13</logback.version>
@@ -183,6 +184,19 @@
                 <version>${kaptcha.version}</version>
             </dependency>
 
+            <!-- 浜岀淮鐮佺敓鎴� -->
+            <dependency>
+                <groupId>com.google.zxing</groupId>
+                <artifactId>core</artifactId>
+                <version>${zxing.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.google.zxing</groupId>
+                <artifactId>javase</artifactId>
+                <version>${zxing.version}</version>
+            </dependency>
+
             <!-- 瀹氭椂浠诲姟-->
             <dependency>
                 <groupId>com.ruoyi</groupId>
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java
new file mode 100644
index 0000000..450ce95
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java
@@ -0,0 +1,214 @@
+package com.ruoyi.web.controller.evaluation;
+
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.WechatUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.system.domain.EvaluationDetail;
+import com.ruoyi.system.service.IEvaluationDimensionService;
+import com.ruoyi.system.domain.EvaluationDimension;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.CustomerEvaluation;
+import com.ruoyi.system.service.ICustomerEvaluationService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 瀹㈡埛璇勪环Controller
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+@RestController
+@RequestMapping("/evaluation")
+public class EvaluationController extends BaseController {
+    @Autowired
+    private ICustomerEvaluationService customerEvaluationService;
+
+    @Autowired
+    private IEvaluationDimensionService evaluationDimensionService;
+
+    /**
+     * 鏌ヨ瀹㈡埛璇勪环鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CustomerEvaluation customerEvaluation) {
+        startPage();
+        List<CustomerEvaluation> list = customerEvaluationService.selectCustomerEvaluationList(customerEvaluation);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭瀹㈡埛璇勪环鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:export')")
+    @Log(title = "瀹㈡埛璇勪环", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, CustomerEvaluation customerEvaluation) {
+        List<CustomerEvaluation> list = customerEvaluationService.selectCustomerEvaluationList(customerEvaluation);
+        ExcelUtil<CustomerEvaluation> util = new ExcelUtil<CustomerEvaluation>(CustomerEvaluation.class);
+        util.exportExcel(response, list, "瀹㈡埛璇勪环鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇瀹㈡埛璇勪环璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:query')")
+    @GetMapping(value = "/{evaluationId}")
+    public AjaxResult getInfo(@PathVariable("evaluationId") Long evaluationId) {
+        return success(customerEvaluationService.selectCustomerEvaluationByEvaluationId(evaluationId));
+    }
+
+    /**
+     * 鏂板瀹㈡埛璇勪环
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:add')")
+    @Log(title = "瀹㈡埛璇勪环", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CustomerEvaluation customerEvaluation) {
+        return toAjax(customerEvaluationService.insertCustomerEvaluation(customerEvaluation));
+    }
+
+    /**
+     * 淇敼瀹㈡埛璇勪环
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:edit')")
+    @Log(title = "瀹㈡埛璇勪环", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CustomerEvaluation customerEvaluation) {
+        return toAjax(customerEvaluationService.updateCustomerEvaluation(customerEvaluation));
+    }
+
+    /**
+     * 鍒犻櫎瀹㈡埛璇勪环
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:remove')")
+    @Log(title = "瀹㈡埛璇勪环", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{evaluationIds}")
+    public AjaxResult remove(@PathVariable Long[] evaluationIds) {
+        return toAjax(customerEvaluationService.deleteCustomerEvaluationByEvaluationIds(evaluationIds));
+    }
+
+    /**
+     * 鑾峰彇璇勪环缁村害閰嶇疆
+     */
+    @Anonymous
+    @GetMapping("/dimensions")
+    public AjaxResult getDimensions() {
+        List<EvaluationDimension> dimensions = evaluationDimensionService.selectEnabledEvaluationDimensionList();
+        return success(dimensions);
+    }
+
+    /**
+     * 鎻愪氦瀹㈡埛璇勪环锛堝叕寮�鎺ュ彛锛�
+     */
+    @Anonymous
+    @PostMapping("/submit")
+    public AjaxResult submitEvaluation(@RequestBody CustomerEvaluation customerEvaluation, HttpServletRequest request) {
+        try {
+            // 璁剧疆IP鍦板潃鍜岀敤鎴蜂唬鐞�
+            customerEvaluation.setIpAddress(getClientIP(request));
+            customerEvaluation.setUserAgent(request.getHeader("User-Agent"));
+
+            // 鎻愪氦璇勪环
+            int result = customerEvaluationService.submitCustomerEvaluation(customerEvaluation);
+            
+            if (result > 0) {
+                // 鏍规嵁璇勫垎杩斿洖涓嶅悓鐨勬彁绀轰俊鎭�
+                if (customerEvaluation.getTotalScore() != null && customerEvaluation.getTotalScore().doubleValue() < 3.0) {
+                    return success("鎻愪氦鎴愬姛锛屾垜浠皢绔姏鏀硅繘");
+                } else {
+                    return success("鎻愪氦鎴愬姛锛屾劅璋㈡偍鐨勫弬涓�");
+                }
+            } else {
+                return error("鎻愪氦澶辫触锛岃閲嶈瘯");
+            }
+        } catch (Exception e) {
+            logger.error("鎻愪氦璇勪环澶辫触", e);
+            return error("鎻愪氦澶辫触锛岃閲嶈瘯");
+        }
+    }
+
+    @Value("${wechat.appId}")
+    private String wechatAppId;
+
+    @Value("${wechat.appSecret}")
+    private String wechatAppSecret;
+
+    /**
+     * 鑾峰彇寰俊鐢ㄦ埛淇℃伅
+     */
+    @Anonymous
+    @GetMapping("/wechat/userinfo")
+    public AjaxResult getWechatUserInfo(String code, HttpServletRequest request) {
+        try {
+            
+            if (StringUtils.isEmpty(code)) {
+                return error("鎺堟潈鐮佷笉鑳戒负绌�");
+            }
+
+            // 鑾峰彇缃戦〉鎺堟潈Access Token
+            JSONObject tokenInfo = WechatUtils.getWebAccessToken(wechatAppId, wechatAppSecret, code);
+            if (tokenInfo == null) {
+                return error("鑾峰彇寰俊鎺堟潈淇℃伅澶辫触");
+            }
+
+            String accessToken = tokenInfo.getString("access_token");
+            String openid = tokenInfo.getString("openid");
+
+            // 鑾峰彇鐢ㄦ埛淇℃伅
+            JSONObject userInfo = WechatUtils.getWebUserInfo(accessToken, openid);
+            if (userInfo == null) {
+                return error("鑾峰彇寰俊鐢ㄦ埛淇℃伅澶辫触");
+            }
+
+            return success(userInfo);
+        } catch (Exception e) {
+            logger.error("鑾峰彇寰俊鐢ㄦ埛淇℃伅澶辫触", e);
+            return error("鑾峰彇寰俊鐢ㄦ埛淇℃伅澶辫触");
+        }
+    }
+
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疘P鍦板潃
+     */
+    private String getClientIP(HttpServletRequest request) {
+        String ip = request.getHeader("X-Forwarded-For");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_CLIENT_IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+        return ip;
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationDimensionController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationDimensionController.java
new file mode 100644
index 0000000..d1e2c4c
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationDimensionController.java
@@ -0,0 +1,97 @@
+package com.ruoyi.web.controller.evaluation;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.EvaluationDimension;
+import com.ruoyi.system.service.IEvaluationDimensionService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 璇勪环缁村害閰嶇疆Controller
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+@RestController
+@RequestMapping("/evaluation/dimension")
+public class EvaluationDimensionController extends BaseController {
+    @Autowired
+    private IEvaluationDimensionService evaluationDimensionService;
+
+    /**
+     * 鏌ヨ璇勪环缁村害閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:dimension:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(EvaluationDimension evaluationDimension) {
+        startPage();
+        List<EvaluationDimension> list = evaluationDimensionService.selectEvaluationDimensionList(evaluationDimension);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭璇勪环缁村害閰嶇疆鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:dimension:export')")
+    @Log(title = "璇勪环缁村害閰嶇疆", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, EvaluationDimension evaluationDimension) {
+        List<EvaluationDimension> list = evaluationDimensionService.selectEvaluationDimensionList(evaluationDimension);
+        ExcelUtil<EvaluationDimension> util = new ExcelUtil<EvaluationDimension>(EvaluationDimension.class);
+        util.exportExcel(response, list, "璇勪环缁村害閰嶇疆鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇璇勪环缁村害閰嶇疆璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:dimension:query')")
+    @GetMapping(value = "/{dimensionId}")
+    public AjaxResult getInfo(@PathVariable("dimensionId") Long dimensionId) {
+        return success(evaluationDimensionService.selectEvaluationDimensionByDimensionId(dimensionId));
+    }
+
+    /**
+     * 鏂板璇勪环缁村害閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:dimension:add')")
+    @Log(title = "璇勪环缁村害閰嶇疆", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody EvaluationDimension evaluationDimension) {
+        return toAjax(evaluationDimensionService.insertEvaluationDimension(evaluationDimension));
+    }
+
+    /**
+     * 淇敼璇勪环缁村害閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:dimension:edit')")
+    @Log(title = "璇勪环缁村害閰嶇疆", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody EvaluationDimension evaluationDimension) {
+        return toAjax(evaluationDimensionService.updateEvaluationDimension(evaluationDimension));
+    }
+
+    /**
+     * 鍒犻櫎璇勪环缁村害閰嶇疆
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:dimension:remove')")
+    @Log(title = "璇勪环缁村害閰嶇疆", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{dimensionIds}")
+    public AjaxResult remove(@PathVariable Long[] dimensionIds) {
+        return toAjax(evaluationDimensionService.deleteEvaluationDimensionByDimensionIds(dimensionIds));
+    }
+}
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
new file mode 100644
index 0000000..3aa5fa2
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/VehicleEvaluationQrcodeController.java
@@ -0,0 +1,145 @@
+package com.ruoyi.web.controller.evaluation;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.VehicleEvaluationQrcode;
+import com.ruoyi.system.service.IVehicleEvaluationQrcodeService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.StringUtils;
+import com.alibaba.fastjson2.JSONObject;
+
+/**
+ * 杞﹁締璇勪环浜岀淮鐮丆ontroller
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+@RestController
+@RequestMapping("/evaluation/qrcode")
+public class VehicleEvaluationQrcodeController extends BaseController {
+    @Autowired
+    private IVehicleEvaluationQrcodeService vehicleEvaluationQrcodeService;
+
+    /**
+     * 鏌ヨ杞﹁締璇勪环浜岀淮鐮佸垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(VehicleEvaluationQrcode vehicleEvaluationQrcode) {
+        startPage();
+        List<VehicleEvaluationQrcode> list = vehicleEvaluationQrcodeService.selectVehicleEvaluationQrcodeList(vehicleEvaluationQrcode);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭杞﹁締璇勪环浜岀淮鐮佸垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:export')")
+    @Log(title = "杞﹁締璇勪环浜岀淮鐮�", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, VehicleEvaluationQrcode vehicleEvaluationQrcode) {
+        List<VehicleEvaluationQrcode> list = vehicleEvaluationQrcodeService.selectVehicleEvaluationQrcodeList(vehicleEvaluationQrcode);
+        ExcelUtil<VehicleEvaluationQrcode> util = new ExcelUtil<VehicleEvaluationQrcode>(VehicleEvaluationQrcode.class);
+        util.exportExcel(response, list, "杞﹁締璇勪环浜岀淮鐮佹暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇杞﹁締璇勪环浜岀淮鐮佽缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:query')")
+    @GetMapping(value = "/{qrcodeId}")
+    public AjaxResult getInfo(@PathVariable("qrcodeId") Long qrcodeId) {
+        return success(vehicleEvaluationQrcodeService.selectVehicleEvaluationQrcodeByQrcodeId(qrcodeId));
+    }
+
+    /**
+     * 鏂板杞﹁締璇勪环浜岀淮鐮�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:add')")
+    @Log(title = "杞﹁締璇勪环浜岀淮鐮�", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody VehicleEvaluationQrcode vehicleEvaluationQrcode) {
+        return toAjax(vehicleEvaluationQrcodeService.insertVehicleEvaluationQrcode(vehicleEvaluationQrcode));
+    }
+
+    /**
+     * 淇敼杞﹁締璇勪环浜岀淮鐮�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:edit')")
+    @Log(title = "杞﹁締璇勪环浜岀淮鐮�", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody VehicleEvaluationQrcode vehicleEvaluationQrcode) {
+        return toAjax(vehicleEvaluationQrcodeService.updateVehicleEvaluationQrcode(vehicleEvaluationQrcode));
+    }
+
+    /**
+     * 鍒犻櫎杞﹁締璇勪环浜岀淮鐮�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:remove')")
+    @Log(title = "杞﹁締璇勪环浜岀淮鐮�", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{qrcodeIds}")
+    public AjaxResult remove(@PathVariable Long[] qrcodeIds) {
+        return toAjax(vehicleEvaluationQrcodeService.deleteVehicleEvaluationQrcodeByQrcodeIds(qrcodeIds));
+    }
+
+    /**
+     * 鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:generate')")
+    @Log(title = "杞﹁締璇勪环浜岀淮鐮�", businessType = BusinessType.INSERT)
+    @PostMapping("/generate")
+    public AjaxResult generateQrcode(@RequestBody JSONObject params) {
+        try {
+            String vehicleNo = params.getString("vehicleNo");
+            String qrcodeUrl = params.getString("qrcodeUrl");
+            
+            if (StringUtils.isEmpty(vehicleNo)) {
+                return error("杞︾墝鍙蜂笉鑳戒负绌�");
+            }
+            if (StringUtils.isEmpty(qrcodeUrl)) {
+                return error("浜岀淮鐮乁RL涓嶈兘涓虹┖");
+            }
+            
+            VehicleEvaluationQrcode qrcode = vehicleEvaluationQrcodeService.generateVehicleEvaluationQrcode(vehicleNo, qrcodeUrl);
+            if (qrcode != null) {
+                return success(qrcode);
+            } else {
+                return error("鐢熸垚浜岀淮鐮佸け璐�");
+            }
+        } catch (Exception e) {
+            logger.error("鐢熸垚浜岀淮鐮佸け璐�", e);
+            return error("鐢熸垚浜岀淮鐮佸け璐�");
+        }
+    }
+
+    /**
+     * 鎵归噺鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+     */
+    @PreAuthorize("@ss.hasPermi('evaluation:qrcode:batch')")
+    @Log(title = "杞﹁締璇勪环浜岀淮鐮�", businessType = BusinessType.INSERT)
+    @PostMapping("/batch")
+    public AjaxResult batchGenerateQrcode() {
+        try {
+            int count = vehicleEvaluationQrcodeService.batchGenerateVehicleEvaluationQrcode();
+            return success("鎴愬姛鐢熸垚 " + count + " 涓簩缁寸爜");
+        } catch (Exception e) {
+            logger.error("鎵归噺鐢熸垚浜岀淮鐮佸け璐�", e);
+            return error("鎵归噺鐢熸垚浜岀淮鐮佸け璐�");
+        }
+    }
+}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 0128223..69c5d06 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -56,7 +56,7 @@
     basename: i18n/messages
   profiles:
     # 鐜 dev|test|prod
-    active: prod
+    active: dev
   # 鏂囦欢涓婁紶
   servlet:
     multipart:
@@ -144,3 +144,9 @@
 # 姘戣埅鎺ュ彛鍦板潃
 min:
   apiUrl: http://120.25.98.119:8084/v1/   #娴嬭瘯鐜锛歭ocalhost:8011
+
+# 寰俊閰嶇疆
+wechat:
+  appId: your_wechat_appid
+  appSecret: your_wechat_appsecret
+  redirectUri: http://yourdomain.com/evaluation
\ No newline at end of file
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 5266477..dcb55fa 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -117,6 +117,17 @@
             <artifactId>UserAgentUtils</artifactId>
         </dependency>
 
+        <!-- 浜岀淮鐮佺敓鎴� -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+
         <!-- servlet鍖� -->
         <dependency>
             <groupId>javax.servlet</groupId>
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
new file mode 100644
index 0000000..5a28d53
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java
@@ -0,0 +1,98 @@
+package com.ruoyi.common.utils;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 浜岀淮鐮佺敓鎴愬伐鍏风被
+ * 
+ * @author ruoyi
+ */
+public class QRCodeUtils {
+    
+    private static final Logger log = LoggerFactory.getLogger(QRCodeUtils.class);
+    
+    private static final int WIDTH = 300;
+    private static final int HEIGHT = 300;
+    private static final String FORMAT = "png";
+    
+    /**
+     * 鐢熸垚浜岀淮鐮佸埌鏂囦欢
+     * 
+     * @param content 浜岀淮鐮佸唴瀹�
+     * @param filePath 鏂囦欢璺緞
+     * @return 鏄惁鐢熸垚鎴愬姛
+     */
+    public static boolean generateQRCodeToFile(String content, String filePath) {
+        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);
+            
+            File file = new File(filePath);
+            if (!file.getParentFile().exists()) {
+                file.getParentFile().mkdirs();
+            }
+            
+            MatrixToImageWriter.writeToFile(bitMatrix, FORMAT, file);
+            return true;
+        } catch (Exception e) {
+            log.error("鐢熸垚浜岀淮鐮佸け璐�: {}", e.getMessage());
+            return false;
+        }
+    }
+    
+    /**
+     * 鐢熸垚浜岀淮鐮佸埌瀛楄妭鏁扮粍
+     * 
+     * @param content 浜岀淮鐮佸唴瀹�
+     * @return 瀛楄妭鏁扮粍
+     */
+    public static byte[] generateQRCodeToBytes(String content) {
+        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 image = MatrixToImageWriter.toBufferedImage(bitMatrix);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(image, FORMAT, baos);
+            
+            return baos.toByteArray();
+        } catch (Exception e) {
+            log.error("鐢熸垚浜岀淮鐮佸け璐�: {}", e.getMessage());
+            return null;
+        }
+    }
+    
+    /**
+     * 鐢熸垚Base64缂栫爜鐨勪簩缁寸爜
+     * 
+     * @param content 浜岀淮鐮佸唴瀹�
+     * @return Base64缂栫爜鐨勪簩缁寸爜
+     */
+    public static String generateQRCodeToBase64(String content) {
+        byte[] bytes = generateQRCodeToBytes(content);
+        if (bytes != null) {
+            return "data:image/png;base64," + java.util.Base64.getEncoder().encodeToString(bytes);
+        }
+        return null;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java
new file mode 100644
index 0000000..5b3e6e8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java
@@ -0,0 +1,163 @@
+package com.ruoyi.common.utils;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 寰俊宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class WechatUtils {
+    
+    private static final Logger log = LoggerFactory.getLogger(WechatUtils.class);
+    
+    private static final String WECHAT_API_BASE_URL = "https://api.weixin.qq.com";
+    
+    /**
+     * 鑾峰彇寰俊Access Token
+     * 
+     * @param appId 寰俊AppID
+     * @param appSecret 寰俊AppSecret
+     * @return Access Token
+     */
+    public static String getAccessToken(String appId, String appSecret) {
+        try {
+            String url = WECHAT_API_BASE_URL + "/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
+            
+            RestTemplate restTemplate = new RestTemplate();
+            String response = restTemplate.getForObject(url, String.class);
+            
+            JSONObject jsonObject = JSON.parseObject(response);
+            if (jsonObject.containsKey("access_token")) {
+                return jsonObject.getString("access_token");
+            } else {
+                log.error("鑾峰彇寰俊Access Token澶辫触: {}", response);
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("鑾峰彇寰俊Access Token寮傚父: {}", e.getMessage());
+            return null;
+        }
+    }
+    
+    /**
+     * 鑾峰彇寰俊鐢ㄦ埛淇℃伅
+     * 
+     * @param accessToken Access Token
+     * @param openid 鐢ㄦ埛OpenID
+     * @return 鐢ㄦ埛淇℃伅
+     */
+    public static JSONObject getWechatUserInfo(String accessToken, String openid) {
+        try {
+            String url = WECHAT_API_BASE_URL + "/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
+            
+            RestTemplate restTemplate = new RestTemplate();
+            String response = restTemplate.getForObject(url, String.class);
+            
+            JSONObject jsonObject = JSON.parseObject(response);
+            if (jsonObject.containsKey("openid")) {
+                return jsonObject;
+            } else {
+                log.error("鑾峰彇寰俊鐢ㄦ埛淇℃伅澶辫触: {}", response);
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("鑾峰彇寰俊鐢ㄦ埛淇℃伅寮傚父: {}", e.getMessage());
+            return null;
+        }
+    }
+    
+    /**
+     * 鑾峰彇寰俊缃戦〉鎺堟潈Access Token
+     * 
+     * @param appId 寰俊AppID
+     * @param appSecret 寰俊AppSecret
+     * @param code 鎺堟潈鐮�
+     * @return 缃戦〉鎺堟潈Access Token淇℃伅
+     */
+    public static JSONObject getWebAccessToken(String appId, String appSecret, String code) {
+        try {
+            String url = WECHAT_API_BASE_URL + "/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code";
+            
+            RestTemplate restTemplate = new RestTemplate();
+            String response = restTemplate.getForObject(url, String.class);
+            
+            JSONObject jsonObject = JSON.parseObject(response);
+            if (jsonObject.containsKey("access_token")) {
+                return jsonObject;
+            } else {
+                log.error("鑾峰彇寰俊缃戦〉鎺堟潈Access Token澶辫触: {}", response);
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("鑾峰彇寰俊缃戦〉鎺堟潈Access Token寮傚父: {}", e.getMessage());
+            return null;
+        }
+    }
+    
+    /**
+     * 鑾峰彇寰俊缃戦〉鎺堟潈鐢ㄦ埛淇℃伅
+     * 
+     * @param accessToken 缃戦〉鎺堟潈Access Token
+     * @param openid 鐢ㄦ埛OpenID
+     * @return 鐢ㄦ埛淇℃伅
+     */
+    public static JSONObject getWebUserInfo(String accessToken, String openid) {
+        try {
+            String url = WECHAT_API_BASE_URL + "/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
+            
+            RestTemplate restTemplate = new RestTemplate();
+            String response = restTemplate.getForObject(url, String.class);
+            
+            JSONObject jsonObject = JSON.parseObject(response);
+            if (jsonObject.containsKey("openid")) {
+                return jsonObject;
+            } else {
+                log.error("鑾峰彇寰俊缃戦〉鎺堟潈鐢ㄦ埛淇℃伅澶辫触: {}", response);
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("鑾峰彇寰俊缃戦〉鎺堟潈鐢ㄦ埛淇℃伅寮傚父: {}", e.getMessage());
+            return null;
+        }
+    }
+    
+    /**
+     * 鐢熸垚寰俊缃戦〉鎺堟潈URL
+     * 
+     * @param appId 寰俊AppID
+     * @param redirectUri 鍥炶皟鍦板潃
+     * @param scope 鎺堟潈鑼冨洿 (snsapi_base 鎴� snsapi_userinfo)
+     * @param state 鐘舵�佸弬鏁�
+     * @return 鎺堟潈URL
+     */
+    public static String generateAuthUrl(String appId, String redirectUri, String scope, String state) {
+        try {
+            String encodedRedirectUri = java.net.URLEncoder.encode(redirectUri, "UTF-8");
+            return WECHAT_API_BASE_URL + "/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + encodedRedirectUri + "&response_type=code&scope=" + scope + "&state=" + state + "#wechat_redirect";
+        } catch (Exception e) {
+            log.error("鐢熸垚寰俊鎺堟潈URL寮傚父: {}", e.getMessage());
+            return null;
+        }
+    }
+    
+    /**
+     * 鍒ゆ柇鏄惁涓哄井淇℃祻瑙堝櫒
+     * 
+     * @param userAgent 鐢ㄦ埛浠g悊瀛楃涓�
+     * @return 鏄惁涓哄井淇℃祻瑙堝櫒
+     */
+    public static boolean isWechatBrowser(String userAgent) {
+        if (StringUtils.isEmpty(userAgent)) {
+            return false;
+        }
+        return userAgent.toLowerCase().contains("micromessenger");
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
index 0eeab6e..ad86680 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -37,6 +37,10 @@
         registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
                 .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
 
+        /** 浜岀淮鐮佸浘鐗囪闂矾寰� */
+        registry.addResourceHandler("/qrcode/**")
+                .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/qrcode/");
+
         /** swagger閰嶇疆 */
         registry.addResourceHandler("/swagger-ui/**")
                 .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/CustomerEvaluation.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/CustomerEvaluation.java
new file mode 100644
index 0000000..89f53a4
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/CustomerEvaluation.java
@@ -0,0 +1,209 @@
+package com.ruoyi.system.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 瀹㈡埛璇勪环瀵硅薄 customer_evaluation
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public class CustomerEvaluation extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 璇勪环ID */
+    private Long evaluationId;
+
+    /** 杞︾墝鍙� */
+    @Excel(name = "杞︾墝鍙�")
+    private String vehicleNo;
+
+    /** 瀹㈡埛濮撳悕 */
+    @Excel(name = "瀹㈡埛濮撳悕")
+    private String customerName;
+
+    /** 瀹㈡埛鎵嬫満鍙� */
+    @Excel(name = "瀹㈡埛鎵嬫満鍙�")
+    private String customerPhone;
+
+    /** 寰俊OpenID */
+    @Excel(name = "寰俊OpenID")
+    private String wechatOpenid;
+
+    /** 寰俊鏄电О */
+    @Excel(name = "寰俊鏄电О")
+    private String wechatNickname;
+
+    /** 寰俊澶村儚 */
+    @Excel(name = "寰俊澶村儚")
+    private String wechatAvatar;
+
+    /** 寰俊缁戝畾鎵嬫満鍙� */
+    @Excel(name = "寰俊缁戝畾鎵嬫満鍙�")
+    private String wechatPhone;
+
+    /** 鎬昏瘎鍒� */
+    @Excel(name = "鎬昏瘎鍒�")
+    private BigDecimal totalScore;
+
+    /** 璇勪环鐘舵�侊紙0寰呰瘎浠� 1宸茶瘎浠凤級 */
+    @Excel(name = "璇勪环鐘舵��", readConverterExp = "0=寰呰瘎浠�,1=宸茶瘎浠�")
+    private String evaluationStatus;
+
+    /** 璇勪环鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "璇勪环鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date evaluationTime;
+
+    /** IP鍦板潃 */
+    @Excel(name = "IP鍦板潃")
+    private String ipAddress;
+
+    /** 鐢ㄦ埛浠g悊 */
+    @Excel(name = "鐢ㄦ埛浠g悊")
+    private String userAgent;
+
+    /** 璇勪环璇︽儏鍒楄〃 */
+    private List<EvaluationDetail> evaluationDetails;
+
+    public void setEvaluationId(Long evaluationId) {
+        this.evaluationId = evaluationId;
+    }
+
+    public Long getEvaluationId() {
+        return evaluationId;
+    }
+
+    public void setVehicleNo(String vehicleNo) {
+        this.vehicleNo = vehicleNo;
+    }
+
+    public String getVehicleNo() {
+        return vehicleNo;
+    }
+
+    public void setCustomerName(String customerName) {
+        this.customerName = customerName;
+    }
+
+    public String getCustomerName() {
+        return customerName;
+    }
+
+    public void setCustomerPhone(String customerPhone) {
+        this.customerPhone = customerPhone;
+    }
+
+    public String getCustomerPhone() {
+        return customerPhone;
+    }
+
+    public void setWechatOpenid(String wechatOpenid) {
+        this.wechatOpenid = wechatOpenid;
+    }
+
+    public String getWechatOpenid() {
+        return wechatOpenid;
+    }
+
+    public void setWechatNickname(String wechatNickname) {
+        this.wechatNickname = wechatNickname;
+    }
+
+    public String getWechatNickname() {
+        return wechatNickname;
+    }
+
+    public void setWechatAvatar(String wechatAvatar) {
+        this.wechatAvatar = wechatAvatar;
+    }
+
+    public String getWechatAvatar() {
+        return wechatAvatar;
+    }
+
+    public void setWechatPhone(String wechatPhone) {
+        this.wechatPhone = wechatPhone;
+    }
+
+    public String getWechatPhone() {
+        return wechatPhone;
+    }
+
+    public void setTotalScore(BigDecimal totalScore) {
+        this.totalScore = totalScore;
+    }
+
+    public BigDecimal getTotalScore() {
+        return totalScore;
+    }
+
+    public void setEvaluationStatus(String evaluationStatus) {
+        this.evaluationStatus = evaluationStatus;
+    }
+
+    public String getEvaluationStatus() {
+        return evaluationStatus;
+    }
+
+    public void setEvaluationTime(Date evaluationTime) {
+        this.evaluationTime = evaluationTime;
+    }
+
+    public Date getEvaluationTime() {
+        return evaluationTime;
+    }
+
+    public void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public void setUserAgent(String userAgent) {
+        this.userAgent = userAgent;
+    }
+
+    public String getUserAgent() {
+        return userAgent;
+    }
+
+    public List<EvaluationDetail> getEvaluationDetails() {
+        return evaluationDetails;
+    }
+
+    public void setEvaluationDetails(List<EvaluationDetail> evaluationDetails) {
+        this.evaluationDetails = evaluationDetails;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("evaluationId", getEvaluationId())
+                .append("vehicleNo", getVehicleNo())
+                .append("customerName", getCustomerName())
+                .append("customerPhone", getCustomerPhone())
+                .append("wechatOpenid", getWechatOpenid())
+                .append("wechatNickname", getWechatNickname())
+                .append("wechatAvatar", getWechatAvatar())
+                .append("wechatPhone", getWechatPhone())
+                .append("totalScore", getTotalScore())
+                .append("evaluationStatus", getEvaluationStatus())
+                .append("evaluationTime", getEvaluationTime())
+                .append("ipAddress", getIpAddress())
+                .append("userAgent", getUserAgent())
+                .append("createTime", getCreateTime())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDetail.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDetail.java
new file mode 100644
index 0000000..c07a281
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDetail.java
@@ -0,0 +1,126 @@
+package com.ruoyi.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 璇勪环璇︽儏瀵硅薄 evaluation_detail
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public class EvaluationDetail extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 璇︽儏ID */
+    private Long detailId;
+
+    /** 璇勪环ID */
+    @Excel(name = "璇勪环ID")
+    private Long evaluationId;
+
+    /** 缁村害ID */
+    @Excel(name = "缁村害ID")
+    private Long dimensionId;
+
+    /** 璇勫垎锛�1-5鏄燂級 */
+    @Excel(name = "璇勫垎")
+    private Integer score;
+
+    /** 閫夐」鍊硷紙閫夋嫨绫诲瀷鏃朵娇鐢級 */
+    @Excel(name = "閫夐」鍊�")
+    private String optionValue;
+
+    /** 鏂囨湰鍐呭锛堟枃鏈被鍨嬫椂浣跨敤锛� */
+    @Excel(name = "鏂囨湰鍐呭")
+    private String textContent;
+
+    /** 鍒涘缓鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "鍒涘缓鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /** 缁村害淇℃伅 */
+    private EvaluationDimension dimension;
+
+    public void setDetailId(Long detailId) {
+        this.detailId = detailId;
+    }
+
+    public Long getDetailId() {
+        return detailId;
+    }
+
+    public void setEvaluationId(Long evaluationId) {
+        this.evaluationId = evaluationId;
+    }
+
+    public Long getEvaluationId() {
+        return evaluationId;
+    }
+
+    public void setDimensionId(Long dimensionId) {
+        this.dimensionId = dimensionId;
+    }
+
+    public Long getDimensionId() {
+        return dimensionId;
+    }
+
+    public void setScore(Integer score) {
+        this.score = score;
+    }
+
+    public Integer getScore() {
+        return score;
+    }
+
+    public void setOptionValue(String optionValue) {
+        this.optionValue = optionValue;
+    }
+
+    public String getOptionValue() {
+        return optionValue;
+    }
+
+    public void setTextContent(String textContent) {
+        this.textContent = textContent;
+    }
+
+    public String getTextContent() {
+        return textContent;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public EvaluationDimension getDimension() {
+        return dimension;
+    }
+
+    public void setDimension(EvaluationDimension dimension) {
+        this.dimension = dimension;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("detailId", getDetailId())
+                .append("evaluationId", getEvaluationId())
+                .append("dimensionId", getDimensionId())
+                .append("score", getScore())
+                .append("optionValue", getOptionValue())
+                .append("textContent", getTextContent())
+                .append("createTime", getCreateTime())
+                .toString();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDimension.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDimension.java
new file mode 100644
index 0000000..74e7adc
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/EvaluationDimension.java
@@ -0,0 +1,129 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 璇勪环缁村害閰嶇疆瀵硅薄 evaluation_dimension
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public class EvaluationDimension extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 缁村害ID */
+    private Long dimensionId;
+
+    /** 缁村害鍚嶇О */
+    @Excel(name = "缁村害鍚嶇О")
+    private String dimensionName;
+
+    /** 缁村害鎻忚堪 */
+    @Excel(name = "缁村害鎻忚堪")
+    private String dimensionDesc;
+
+    /** 缁村害绫诲瀷锛歴tar-鏄熺骇璇勪环锛宻elect-閫夋嫨璇勪环锛宼ext-鏂囨湰璇勪环 */
+    @Excel(name = "缁村害绫诲瀷", readConverterExp = "star=鏄熺骇璇勪环,select=閫夋嫨璇勪环,text=鏂囨湰璇勪环")
+    private String dimensionType;
+
+    /** 閫夐」閰嶇疆锛圝SON鏍煎紡锛岀敤浜庨�夋嫨绫诲瀷锛� */
+    private String options;
+
+    /** 鎺掑簭 */
+    @Excel(name = "鎺掑簭")
+    private Integer sortOrder;
+
+    /** 鏄惁蹇呭~锛�0鍚� 1鏄級 */
+    @Excel(name = "鏄惁蹇呭~", readConverterExp = "0=鍚�,1=鏄�")
+    private String isRequired;
+
+    /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    public void setDimensionId(Long dimensionId) {
+        this.dimensionId = dimensionId;
+    }
+
+    public Long getDimensionId() {
+        return dimensionId;
+    }
+
+    public void setDimensionName(String dimensionName) {
+        this.dimensionName = dimensionName;
+    }
+
+    public String getDimensionName() {
+        return dimensionName;
+    }
+
+    public void setDimensionDesc(String dimensionDesc) {
+        this.dimensionDesc = dimensionDesc;
+    }
+
+    public String getDimensionDesc() {
+        return dimensionDesc;
+    }
+
+    public void setDimensionType(String dimensionType) {
+        this.dimensionType = dimensionType;
+    }
+
+    public String getDimensionType() {
+        return dimensionType;
+    }
+
+    public void setOptions(String options) {
+        this.options = options;
+    }
+
+    public String getOptions() {
+        return options;
+    }
+
+    public void setSortOrder(Integer sortOrder) {
+        this.sortOrder = sortOrder;
+    }
+
+    public Integer getSortOrder() {
+        return sortOrder;
+    }
+
+    public void setIsRequired(String isRequired) {
+        this.isRequired = isRequired;
+    }
+
+    public String getIsRequired() {
+        return isRequired;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("dimensionId", getDimensionId())
+                .append("dimensionName", getDimensionName())
+                .append("dimensionDesc", getDimensionDesc())
+                .append("dimensionType", getDimensionType())
+                .append("options", getOptions())
+                .append("sortOrder", getSortOrder())
+                .append("isRequired", getIsRequired())
+                .append("status", getStatus())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleEvaluationQrcode.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleEvaluationQrcode.java
new file mode 100644
index 0000000..6fa62e8
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleEvaluationQrcode.java
@@ -0,0 +1,104 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 杞﹁締璇勪环浜岀淮鐮佸璞� vehicle_evaluation_qrcode
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public class VehicleEvaluationQrcode extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 浜岀淮鐮両D */
+    private Long qrcodeId;
+
+    /** 杞︾墝鍙� */
+    @Excel(name = "杞︾墝鍙�")
+    private String vehicleNo;
+
+    /** 浜岀淮鐮乁RL */
+    @Excel(name = "浜岀淮鐮乁RL")
+    private String qrcodeUrl;
+
+    /** 浜岀淮鐮佸唴瀹� */
+    @Excel(name = "浜岀淮鐮佸唴瀹�")
+    private String qrcodeContent;
+
+    /** 浜岀淮鐮佸浘鐗囪矾寰� */
+    @Excel(name = "浜岀淮鐮佸浘鐗囪矾寰�")
+    private String qrcodeImage;
+
+    /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    public void setQrcodeId(Long qrcodeId) {
+        this.qrcodeId = qrcodeId;
+    }
+
+    public Long getQrcodeId() {
+        return qrcodeId;
+    }
+
+    public void setVehicleNo(String vehicleNo) {
+        this.vehicleNo = vehicleNo;
+    }
+
+    public String getVehicleNo() {
+        return vehicleNo;
+    }
+
+    public void setQrcodeUrl(String qrcodeUrl) {
+        this.qrcodeUrl = qrcodeUrl;
+    }
+
+    public String getQrcodeUrl() {
+        return qrcodeUrl;
+    }
+
+    public void setQrcodeContent(String qrcodeContent) {
+        this.qrcodeContent = qrcodeContent;
+    }
+
+    public String getQrcodeContent() {
+        return qrcodeContent;
+    }
+
+    public void setQrcodeImage(String qrcodeImage) {
+        this.qrcodeImage = qrcodeImage;
+    }
+
+    public String getQrcodeImage() {
+        return qrcodeImage;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("qrcodeId", getQrcodeId())
+                .append("vehicleNo", getVehicleNo())
+                .append("qrcodeUrl", getQrcodeUrl())
+                .append("qrcodeContent", getQrcodeContent())
+                .append("qrcodeImage", getQrcodeImage())
+                .append("status", getStatus())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java
index b8aa771..2eb1b11 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java
@@ -42,6 +42,14 @@
     @Excel(name = "骞冲彴鏍囪瘑")
     private String platformCode;
 
+    /** 褰掑睘閮ㄩ棬ID */
+    @Excel(name = "褰掑睘閮ㄩ棬ID")
+    private Long deptId;
+
+    /** 褰掑睘閮ㄩ棬鍚嶇О */
+    @Excel(name = "褰掑睘閮ㄩ棬鍚嶇О")
+    private String deptName;
+
     public void setVehicleId(Long vehicleId) {
         this.vehicleId = vehicleId;
     }
@@ -106,6 +114,22 @@
         this.platformCode = platformCode;
     }
 
+    public Long getDeptId() {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId) {
+        this.deptId = deptId;
+    }
+
+    public String getDeptName() {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName) {
+        this.deptName = deptName;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
@@ -117,6 +141,8 @@
                 .append("vehicleModel", getVehicleModel())
                 .append("status", getStatus())
                 .append("platformCode", getPlatformCode())
+                .append("deptId", getDeptId())
+                .append("deptName", getDeptName())
                 .append("createBy", getCreateBy())
                 .append("createTime", getCreateTime())
                 .append("updateBy", getUpdateBy())
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/AOrderStatusMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/AOrderStatusMapper.java
index 3904438..0c4bbe2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/AOrderStatusMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/AOrderStatusMapper.java
@@ -11,7 +11,7 @@
      * 鏌ヨ璁㈠崟鐘舵�佸垪琛�
      * 榛樿鏌ヨ flag = 0 鐨勮褰�
      * 
-     * @param aOrderStatus 璁㈠崟鐘舵�佷俊鎭�
+     * @param  璁㈠崟鐘舵�佷俊鎭�
      * @return 璁㈠崟鐘舵�侀泦鍚�
      */
     public List<AOrderStatus> selectAOrderStatusList();
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomerEvaluationMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomerEvaluationMapper.java
new file mode 100644
index 0000000..6065223
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomerEvaluationMapper.java
@@ -0,0 +1,84 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.CustomerEvaluation;
+
+/**
+ * 瀹㈡埛璇勪环Mapper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public interface CustomerEvaluationMapper {
+    /**
+     * 鏌ヨ瀹㈡埛璇勪环
+     * 
+     * @param evaluationId 瀹㈡埛璇勪环涓婚敭
+     * @return 瀹㈡埛璇勪环
+     */
+    public CustomerEvaluation selectCustomerEvaluationByEvaluationId(Long evaluationId);
+
+    /**
+     * 鏌ヨ瀹㈡埛璇勪环鍒楄〃
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    public List<CustomerEvaluation> selectCustomerEvaluationList(CustomerEvaluation customerEvaluation);
+
+    /**
+     * 鏍规嵁杞︾墝鍙锋煡璇㈠鎴疯瘎浠�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    public List<CustomerEvaluation> selectCustomerEvaluationByVehicleNo(String vehicleNo);
+
+    /**
+     * 鏍规嵁寰俊OpenID鏌ヨ瀹㈡埛璇勪环
+     * 
+     * @param wechatOpenid 寰俊OpenID
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    public List<CustomerEvaluation> selectCustomerEvaluationByWechatOpenid(String wechatOpenid);
+
+    /**
+     * 鏂板瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    public int insertCustomerEvaluation(CustomerEvaluation customerEvaluation);
+
+    /**
+     * 淇敼瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    public int updateCustomerEvaluation(CustomerEvaluation customerEvaluation);
+
+    /**
+     * 鍒犻櫎瀹㈡埛璇勪环
+     * 
+     * @param evaluationId 瀹㈡埛璇勪环涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteCustomerEvaluationByEvaluationId(Long evaluationId);
+
+    /**
+     * 鎵归噺鍒犻櫎瀹㈡埛璇勪环
+     * 
+     * @param evaluationIds 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteCustomerEvaluationByEvaluationIds(Long[] evaluationIds);
+
+    /**
+     * 缁熻璇勪环鏁伴噺
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 璇勪环缁熻淇℃伅
+     */
+    public List<CustomerEvaluation> selectEvaluationStatistics(CustomerEvaluation customerEvaluation);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDetailMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDetailMapper.java
new file mode 100644
index 0000000..98bfbc7
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDetailMapper.java
@@ -0,0 +1,84 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.EvaluationDetail;
+
+/**
+ * 璇勪环璇︽儏Mapper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public interface EvaluationDetailMapper {
+    /**
+     * 鏌ヨ璇勪环璇︽儏
+     * 
+     * @param detailId 璇勪环璇︽儏涓婚敭
+     * @return 璇勪环璇︽儏
+     */
+    public EvaluationDetail selectEvaluationDetailByDetailId(Long detailId);
+
+    /**
+     * 鏌ヨ璇勪环璇︽儏鍒楄〃
+     * 
+     * @param evaluationDetail 璇勪环璇︽儏
+     * @return 璇勪环璇︽儏闆嗗悎
+     */
+    public List<EvaluationDetail> selectEvaluationDetailList(EvaluationDetail evaluationDetail);
+
+    /**
+     * 鏍规嵁璇勪环ID鏌ヨ璇勪环璇︽儏鍒楄〃
+     * 
+     * @param evaluationId 璇勪环ID
+     * @return 璇勪环璇︽儏闆嗗悎
+     */
+    public List<EvaluationDetail> selectEvaluationDetailByEvaluationId(Long evaluationId);
+
+    /**
+     * 鏂板璇勪环璇︽儏
+     * 
+     * @param evaluationDetail 璇勪环璇︽儏
+     * @return 缁撴灉
+     */
+    public int insertEvaluationDetail(EvaluationDetail evaluationDetail);
+
+    /**
+     * 鎵归噺鏂板璇勪环璇︽儏
+     * 
+     * @param evaluationDetails 璇勪环璇︽儏鍒楄〃
+     * @return 缁撴灉
+     */
+    public int insertEvaluationDetailBatch(List<EvaluationDetail> evaluationDetails);
+
+    /**
+     * 淇敼璇勪环璇︽儏
+     * 
+     * @param evaluationDetail 璇勪环璇︽儏
+     * @return 缁撴灉
+     */
+    public int updateEvaluationDetail(EvaluationDetail evaluationDetail);
+
+    /**
+     * 鍒犻櫎璇勪环璇︽儏
+     * 
+     * @param detailId 璇勪环璇︽儏涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteEvaluationDetailByDetailId(Long detailId);
+
+    /**
+     * 鏍规嵁璇勪环ID鍒犻櫎璇勪环璇︽儏
+     * 
+     * @param evaluationId 璇勪环ID
+     * @return 缁撴灉
+     */
+    public int deleteEvaluationDetailByEvaluationId(Long evaluationId);
+
+    /**
+     * 鎵归噺鍒犻櫎璇勪环璇︽儏
+     * 
+     * @param detailIds 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEvaluationDetailByDetailIds(Long[] detailIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDimensionMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDimensionMapper.java
new file mode 100644
index 0000000..433b60f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/EvaluationDimensionMapper.java
@@ -0,0 +1,67 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.EvaluationDimension;
+
+/**
+ * 璇勪环缁村害閰嶇疆Mapper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public interface EvaluationDimensionMapper {
+    /**
+     * 鏌ヨ璇勪环缁村害閰嶇疆
+     * 
+     * @param dimensionId 璇勪环缁村害閰嶇疆涓婚敭
+     * @return 璇勪环缁村害閰嶇疆
+     */
+    public EvaluationDimension selectEvaluationDimensionByDimensionId(Long dimensionId);
+
+    /**
+     * 鏌ヨ璇勪环缁村害閰嶇疆鍒楄〃
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 璇勪环缁村害閰嶇疆闆嗗悎
+     */
+    public List<EvaluationDimension> selectEvaluationDimensionList(EvaluationDimension evaluationDimension);
+
+    /**
+     * 鏌ヨ鍚敤鐨勮瘎浠风淮搴﹂厤缃垪琛�
+     * 
+     * @return 璇勪环缁村害閰嶇疆闆嗗悎
+     */
+    public List<EvaluationDimension> selectEnabledEvaluationDimensionList();
+
+    /**
+     * 鏂板璇勪环缁村害閰嶇疆
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertEvaluationDimension(EvaluationDimension evaluationDimension);
+
+    /**
+     * 淇敼璇勪环缁村害閰嶇疆
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateEvaluationDimension(EvaluationDimension evaluationDimension);
+
+    /**
+     * 鍒犻櫎璇勪环缁村害閰嶇疆
+     * 
+     * @param dimensionId 璇勪环缁村害閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteEvaluationDimensionByDimensionId(Long dimensionId);
+
+    /**
+     * 鎵归噺鍒犻櫎璇勪环缁村害閰嶇疆
+     * 
+     * @param dimensionIds 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEvaluationDimensionByDimensionIds(Long[] dimensionIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleEvaluationQrcodeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleEvaluationQrcodeMapper.java
new file mode 100644
index 0000000..5844351
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleEvaluationQrcodeMapper.java
@@ -0,0 +1,76 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.VehicleEvaluationQrcode;
+
+/**
+ * 杞﹁締璇勪环浜岀淮鐮丮apper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public interface VehicleEvaluationQrcodeMapper {
+    /**
+     * 鏌ヨ杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param qrcodeId 杞﹁締璇勪环浜岀淮鐮佷富閿�
+     * @return 杞﹁締璇勪环浜岀淮鐮�
+     */
+    public VehicleEvaluationQrcode selectVehicleEvaluationQrcodeByQrcodeId(Long qrcodeId);
+
+    /**
+     * 鏍规嵁杞︾墝鍙锋煡璇㈣溅杈嗚瘎浠蜂簩缁寸爜
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 杞﹁締璇勪环浜岀淮鐮�
+     */
+    public VehicleEvaluationQrcode selectVehicleEvaluationQrcodeByVehicleNo(String vehicleNo);
+
+    /**
+     * 鏌ヨ杞﹁締璇勪环浜岀淮鐮佸垪琛�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 杞﹁締璇勪环浜岀淮鐮侀泦鍚�
+     */
+    public List<VehicleEvaluationQrcode> selectVehicleEvaluationQrcodeList(VehicleEvaluationQrcode vehicleEvaluationQrcode);
+
+    /**
+     * 鏂板杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 缁撴灉
+     */
+    public int insertVehicleEvaluationQrcode(VehicleEvaluationQrcode vehicleEvaluationQrcode);
+
+    /**
+     * 淇敼杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 缁撴灉
+     */
+    public int updateVehicleEvaluationQrcode(VehicleEvaluationQrcode vehicleEvaluationQrcode);
+
+    /**
+     * 鍒犻櫎杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param qrcodeId 杞﹁締璇勪环浜岀淮鐮佷富閿�
+     * @return 缁撴灉
+     */
+    public int deleteVehicleEvaluationQrcodeByQrcodeId(Long qrcodeId);
+
+    /**
+     * 鏍规嵁杞︾墝鍙峰垹闄よ溅杈嗚瘎浠蜂簩缁寸爜
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 缁撴灉
+     */
+    public int deleteVehicleEvaluationQrcodeByVehicleNo(String vehicleNo);
+
+    /**
+     * 鎵归噺鍒犻櫎杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param qrcodeIds 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteVehicleEvaluationQrcodeByQrcodeIds(Long[] qrcodeIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleInfoMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleInfoMapper.java
index f688808..594f0eb 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleInfoMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleInfoMapper.java
@@ -24,6 +24,14 @@
     public VehicleInfo selectVehicleInfoByPlateNumber(String plateNumber);
 
     /**
+     * 閫氳繃杞︾墝鍙锋煡璇㈣溅杈嗕俊鎭�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 杞﹁締淇℃伅
+     */
+    public VehicleInfo selectVehicleInfoByVehicleNo(String vehicleNo);
+
+    /**
      * 鏌ヨ杞﹁締淇℃伅鍒楄〃
      * 
      * @param vehicleInfo 杞﹁締淇℃伅
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ICustomerEvaluationService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ICustomerEvaluationService.java
new file mode 100644
index 0000000..f31059e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ICustomerEvaluationService.java
@@ -0,0 +1,92 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.CustomerEvaluation;
+
+/**
+ * 瀹㈡埛璇勪环Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public interface ICustomerEvaluationService {
+    /**
+     * 鏌ヨ瀹㈡埛璇勪环
+     * 
+     * @param evaluationId 瀹㈡埛璇勪环涓婚敭
+     * @return 瀹㈡埛璇勪环
+     */
+    public CustomerEvaluation selectCustomerEvaluationByEvaluationId(Long evaluationId);
+
+    /**
+     * 鏌ヨ瀹㈡埛璇勪环鍒楄〃
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    public List<CustomerEvaluation> selectCustomerEvaluationList(CustomerEvaluation customerEvaluation);
+
+    /**
+     * 鏍规嵁杞︾墝鍙锋煡璇㈠鎴疯瘎浠�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    public List<CustomerEvaluation> selectCustomerEvaluationByVehicleNo(String vehicleNo);
+
+    /**
+     * 鏍规嵁寰俊OpenID鏌ヨ瀹㈡埛璇勪环
+     * 
+     * @param wechatOpenid 寰俊OpenID
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    public List<CustomerEvaluation> selectCustomerEvaluationByWechatOpenid(String wechatOpenid);
+
+    /**
+     * 鏂板瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    public int insertCustomerEvaluation(CustomerEvaluation customerEvaluation);
+
+    /**
+     * 淇敼瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    public int updateCustomerEvaluation(CustomerEvaluation customerEvaluation);
+
+    /**
+     * 鎵归噺鍒犻櫎瀹㈡埛璇勪环
+     * 
+     * @param evaluationIds 闇�瑕佸垹闄ょ殑瀹㈡埛璇勪环涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteCustomerEvaluationByEvaluationIds(Long[] evaluationIds);
+
+    /**
+     * 鍒犻櫎瀹㈡埛璇勪环淇℃伅
+     * 
+     * @param evaluationId 瀹㈡埛璇勪环涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteCustomerEvaluationByEvaluationId(Long evaluationId);
+
+    /**
+     * 鎻愪氦瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    public int submitCustomerEvaluation(CustomerEvaluation customerEvaluation);
+
+    /**
+     * 缁熻璇勪环鏁伴噺
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 璇勪环缁熻淇℃伅
+     */
+    public List<CustomerEvaluation> selectEvaluationStatistics(CustomerEvaluation customerEvaluation);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IEvaluationDimensionService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IEvaluationDimensionService.java
new file mode 100644
index 0000000..2f5375a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IEvaluationDimensionService.java
@@ -0,0 +1,67 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.EvaluationDimension;
+
+/**
+ * 璇勪环缁村害閰嶇疆Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public interface IEvaluationDimensionService {
+    /**
+     * 鏌ヨ璇勪环缁村害閰嶇疆
+     * 
+     * @param dimensionId 璇勪环缁村害閰嶇疆涓婚敭
+     * @return 璇勪环缁村害閰嶇疆
+     */
+    public EvaluationDimension selectEvaluationDimensionByDimensionId(Long dimensionId);
+
+    /**
+     * 鏌ヨ璇勪环缁村害閰嶇疆鍒楄〃
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 璇勪环缁村害閰嶇疆闆嗗悎
+     */
+    public List<EvaluationDimension> selectEvaluationDimensionList(EvaluationDimension evaluationDimension);
+
+    /**
+     * 鏌ヨ鍚敤鐨勮瘎浠风淮搴﹂厤缃垪琛�
+     * 
+     * @return 璇勪环缁村害閰嶇疆闆嗗悎
+     */
+    public List<EvaluationDimension> selectEnabledEvaluationDimensionList();
+
+    /**
+     * 鏂板璇勪环缁村害閰嶇疆
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 缁撴灉
+     */
+    public int insertEvaluationDimension(EvaluationDimension evaluationDimension);
+
+    /**
+     * 淇敼璇勪环缁村害閰嶇疆
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 缁撴灉
+     */
+    public int updateEvaluationDimension(EvaluationDimension evaluationDimension);
+
+    /**
+     * 鎵归噺鍒犻櫎璇勪环缁村害閰嶇疆
+     * 
+     * @param dimensionIds 闇�瑕佸垹闄ょ殑璇勪环缁村害閰嶇疆涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteEvaluationDimensionByDimensionIds(Long[] dimensionIds);
+
+    /**
+     * 鍒犻櫎璇勪环缁村害閰嶇疆淇℃伅
+     * 
+     * @param dimensionId 璇勪环缁村害閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteEvaluationDimensionByDimensionId(Long dimensionId);
+}
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
new file mode 100644
index 0000000..ddaac80
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IVehicleEvaluationQrcodeService.java
@@ -0,0 +1,92 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.VehicleEvaluationQrcode;
+
+/**
+ * 杞﹁締璇勪环浜岀淮鐮丼ervice鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+public interface IVehicleEvaluationQrcodeService {
+    /**
+     * 鏌ヨ杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param qrcodeId 杞﹁締璇勪环浜岀淮鐮佷富閿�
+     * @return 杞﹁締璇勪环浜岀淮鐮�
+     */
+    public VehicleEvaluationQrcode selectVehicleEvaluationQrcodeByQrcodeId(Long qrcodeId);
+
+    /**
+     * 鏍规嵁杞︾墝鍙锋煡璇㈣溅杈嗚瘎浠蜂簩缁寸爜
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 杞﹁締璇勪环浜岀淮鐮�
+     */
+    public VehicleEvaluationQrcode selectVehicleEvaluationQrcodeByVehicleNo(String vehicleNo);
+
+    /**
+     * 鏌ヨ杞﹁締璇勪环浜岀淮鐮佸垪琛�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 杞﹁締璇勪环浜岀淮鐮侀泦鍚�
+     */
+    public List<VehicleEvaluationQrcode> selectVehicleEvaluationQrcodeList(VehicleEvaluationQrcode vehicleEvaluationQrcode);
+
+    /**
+     * 鏂板杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 缁撴灉
+     */
+    public int insertVehicleEvaluationQrcode(VehicleEvaluationQrcode vehicleEvaluationQrcode);
+
+    /**
+     * 淇敼杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 缁撴灉
+     */
+    public int updateVehicleEvaluationQrcode(VehicleEvaluationQrcode vehicleEvaluationQrcode);
+
+    /**
+     * 鎵归噺鍒犻櫎杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param qrcodeIds 闇�瑕佸垹闄ょ殑杞﹁締璇勪环浜岀淮鐮佷富閿泦鍚�
+     * @return 缁撴灉
+     */
+    public int deleteVehicleEvaluationQrcodeByQrcodeIds(Long[] qrcodeIds);
+
+    /**
+     * 鍒犻櫎杞﹁締璇勪环浜岀淮鐮佷俊鎭�
+     * 
+     * @param qrcodeId 杞﹁締璇勪环浜岀淮鐮佷富閿�
+     * @return 缁撴灉
+     */
+    public int deleteVehicleEvaluationQrcodeByQrcodeId(Long qrcodeId);
+
+    /**
+     * 鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 浜岀淮鐮佷俊鎭�
+     */
+    public VehicleEvaluationQrcode generateVehicleEvaluationQrcode(String vehicleNo);
+
+    /**
+     * 鐢熸垚杞﹁締璇勪环浜岀淮鐮侊紙甯RL鍙傛暟锛�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @param qrcodeUrl 浜岀淮鐮乁RL
+     * @return 浜岀淮鐮佷俊鎭�
+     */
+    public VehicleEvaluationQrcode generateVehicleEvaluationQrcode(String vehicleNo, String qrcodeUrl);
+
+    /**
+     * 鎵归噺鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @return 缁撴灉
+     */
+    public int batchGenerateVehicleEvaluationQrcode();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java
new file mode 100644
index 0000000..3b92055
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java
@@ -0,0 +1,196 @@
+package com.ruoyi.system.service.impl;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.system.mapper.CustomerEvaluationMapper;
+import com.ruoyi.system.mapper.EvaluationDetailMapper;
+import com.ruoyi.system.domain.CustomerEvaluation;
+import com.ruoyi.system.domain.EvaluationDetail;
+import com.ruoyi.system.service.ICustomerEvaluationService;
+
+/**
+ * 瀹㈡埛璇勪环Service涓氬姟灞傚鐞�
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+@Service
+public class CustomerEvaluationServiceImpl implements ICustomerEvaluationService {
+    @Autowired
+    private CustomerEvaluationMapper customerEvaluationMapper;
+
+    @Autowired
+    private EvaluationDetailMapper evaluationDetailMapper;
+
+    /**
+     * 鏌ヨ瀹㈡埛璇勪环
+     * 
+     * @param evaluationId 瀹㈡埛璇勪环涓婚敭
+     * @return 瀹㈡埛璇勪环
+     */
+    @Override
+    public CustomerEvaluation selectCustomerEvaluationByEvaluationId(Long evaluationId) {
+        CustomerEvaluation evaluation = customerEvaluationMapper.selectCustomerEvaluationByEvaluationId(evaluationId);
+        if (evaluation != null) {
+            // 鏌ヨ璇勪环璇︽儏
+            List<EvaluationDetail> details = evaluationDetailMapper.selectEvaluationDetailByEvaluationId(evaluationId);
+            evaluation.setEvaluationDetails(details);
+        }
+        return evaluation;
+    }
+
+    /**
+     * 鏌ヨ瀹㈡埛璇勪环鍒楄〃
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 瀹㈡埛璇勪环
+     */
+    @Override
+    public List<CustomerEvaluation> selectCustomerEvaluationList(CustomerEvaluation customerEvaluation) {
+        return customerEvaluationMapper.selectCustomerEvaluationList(customerEvaluation);
+    }
+
+    /**
+     * 鏍规嵁杞︾墝鍙锋煡璇㈠鎴疯瘎浠�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    @Override
+    public List<CustomerEvaluation> selectCustomerEvaluationByVehicleNo(String vehicleNo) {
+        return customerEvaluationMapper.selectCustomerEvaluationByVehicleNo(vehicleNo);
+    }
+
+    /**
+     * 鏍规嵁寰俊OpenID鏌ヨ瀹㈡埛璇勪环
+     * 
+     * @param wechatOpenid 寰俊OpenID
+     * @return 瀹㈡埛璇勪环闆嗗悎
+     */
+    @Override
+    public List<CustomerEvaluation> selectCustomerEvaluationByWechatOpenid(String wechatOpenid) {
+        return customerEvaluationMapper.selectCustomerEvaluationByWechatOpenid(wechatOpenid);
+    }
+
+    /**
+     * 鏂板瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertCustomerEvaluation(CustomerEvaluation customerEvaluation) {
+        customerEvaluation.setCreateTime(DateUtils.getNowDate());
+        return customerEvaluationMapper.insertCustomerEvaluation(customerEvaluation);
+    }
+
+    /**
+     * 淇敼瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateCustomerEvaluation(CustomerEvaluation customerEvaluation) {
+        customerEvaluation.setUpdateTime(DateUtils.getNowDate());
+        return customerEvaluationMapper.updateCustomerEvaluation(customerEvaluation);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎瀹㈡埛璇勪环
+     * 
+     * @param evaluationIds 闇�瑕佸垹闄ょ殑瀹㈡埛璇勪环涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteCustomerEvaluationByEvaluationIds(Long[] evaluationIds) {
+        return customerEvaluationMapper.deleteCustomerEvaluationByEvaluationIds(evaluationIds);
+    }
+
+    /**
+     * 鍒犻櫎瀹㈡埛璇勪环淇℃伅
+     * 
+     * @param evaluationId 瀹㈡埛璇勪环涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteCustomerEvaluationByEvaluationId(Long evaluationId) {
+        return customerEvaluationMapper.deleteCustomerEvaluationByEvaluationId(evaluationId);
+    }
+
+    /**
+     * 鎻愪氦瀹㈡埛璇勪环
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int submitCustomerEvaluation(CustomerEvaluation customerEvaluation) {
+        // 璁$畻鎬昏瘎鍒�
+        BigDecimal totalScore = calculateTotalScore(customerEvaluation.getEvaluationDetails());
+        customerEvaluation.setTotalScore(totalScore);
+        customerEvaluation.setEvaluationStatus("1");
+        customerEvaluation.setEvaluationTime(DateUtils.getNowDate());
+        customerEvaluation.setCreateTime(DateUtils.getNowDate());
+
+        // 鎻掑叆瀹㈡埛璇勪环
+        int result = customerEvaluationMapper.insertCustomerEvaluation(customerEvaluation);
+        
+        if (result > 0 && customerEvaluation.getEvaluationDetails() != null && !customerEvaluation.getEvaluationDetails().isEmpty()) {
+            // 鎻掑叆璇勪环璇︽儏
+            for (EvaluationDetail detail : customerEvaluation.getEvaluationDetails()) {
+                detail.setEvaluationId(customerEvaluation.getEvaluationId());
+                detail.setCreateTime(DateUtils.getNowDate());
+                evaluationDetailMapper.insertEvaluationDetail(detail);
+            }
+        }
+        
+        return result;
+    }
+
+    /**
+     * 缁熻璇勪环鏁伴噺
+     * 
+     * @param customerEvaluation 瀹㈡埛璇勪环
+     * @return 璇勪环缁熻淇℃伅
+     */
+    @Override
+    public List<CustomerEvaluation> selectEvaluationStatistics(CustomerEvaluation customerEvaluation) {
+        return customerEvaluationMapper.selectEvaluationStatistics(customerEvaluation);
+    }
+
+    /**
+     * 璁$畻鎬昏瘎鍒�
+     * 
+     * @param details 璇勪环璇︽儏鍒楄〃
+     * @return 鎬昏瘎鍒�
+     */
+    private BigDecimal calculateTotalScore(List<EvaluationDetail> details) {
+        if (details == null || details.isEmpty()) {
+            return BigDecimal.ZERO;
+        }
+
+        int totalScore = 0;
+        int count = 0;
+        
+        for (EvaluationDetail detail : details) {
+            if (detail.getScore() != null && detail.getScore() > 0) {
+                totalScore += detail.getScore();
+                count++;
+            }
+        }
+        
+        if (count == 0) {
+            return BigDecimal.ZERO;
+        }
+        
+        return new BigDecimal(totalScore).divide(new BigDecimal(count), 1, BigDecimal.ROUND_HALF_UP);
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EvaluationDimensionServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EvaluationDimensionServiceImpl.java
new file mode 100644
index 0000000..33ef196
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EvaluationDimensionServiceImpl.java
@@ -0,0 +1,99 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.system.mapper.EvaluationDimensionMapper;
+import com.ruoyi.system.domain.EvaluationDimension;
+import com.ruoyi.system.service.IEvaluationDimensionService;
+
+/**
+ * 璇勪环缁村害閰嶇疆Service涓氬姟灞傚鐞�
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+@Service
+public class EvaluationDimensionServiceImpl implements IEvaluationDimensionService {
+    @Autowired
+    private EvaluationDimensionMapper evaluationDimensionMapper;
+
+    /**
+     * 鏌ヨ璇勪环缁村害閰嶇疆
+     * 
+     * @param dimensionId 璇勪环缁村害閰嶇疆涓婚敭
+     * @return 璇勪环缁村害閰嶇疆
+     */
+    @Override
+    public EvaluationDimension selectEvaluationDimensionByDimensionId(Long dimensionId) {
+        return evaluationDimensionMapper.selectEvaluationDimensionByDimensionId(dimensionId);
+    }
+
+    /**
+     * 鏌ヨ璇勪环缁村害閰嶇疆鍒楄〃
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 璇勪环缁村害閰嶇疆
+     */
+    @Override
+    public List<EvaluationDimension> selectEvaluationDimensionList(EvaluationDimension evaluationDimension) {
+        return evaluationDimensionMapper.selectEvaluationDimensionList(evaluationDimension);
+    }
+
+    /**
+     * 鏌ヨ鍚敤鐨勮瘎浠风淮搴﹂厤缃垪琛�
+     * 
+     * @return 璇勪环缁村害閰嶇疆闆嗗悎
+     */
+    @Override
+    public List<EvaluationDimension> selectEnabledEvaluationDimensionList() {
+        return evaluationDimensionMapper.selectEnabledEvaluationDimensionList();
+    }
+
+    /**
+     * 鏂板璇勪环缁村害閰嶇疆
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertEvaluationDimension(EvaluationDimension evaluationDimension) {
+        evaluationDimension.setCreateTime(DateUtils.getNowDate());
+        return evaluationDimensionMapper.insertEvaluationDimension(evaluationDimension);
+    }
+
+    /**
+     * 淇敼璇勪环缁村害閰嶇疆
+     * 
+     * @param evaluationDimension 璇勪环缁村害閰嶇疆
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateEvaluationDimension(EvaluationDimension evaluationDimension) {
+        evaluationDimension.setUpdateTime(DateUtils.getNowDate());
+        return evaluationDimensionMapper.updateEvaluationDimension(evaluationDimension);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璇勪环缁村害閰嶇疆
+     * 
+     * @param dimensionIds 闇�瑕佸垹闄ょ殑璇勪环缁村害閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEvaluationDimensionByDimensionIds(Long[] dimensionIds) {
+        return evaluationDimensionMapper.deleteEvaluationDimensionByDimensionIds(dimensionIds);
+    }
+
+    /**
+     * 鍒犻櫎璇勪环缁村害閰嶇疆淇℃伅
+     * 
+     * @param dimensionId 璇勪环缁村害閰嶇疆涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteEvaluationDimensionByDimensionId(Long dimensionId) {
+        return evaluationDimensionMapper.deleteEvaluationDimensionByDimensionId(dimensionId);
+    }
+}
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
new file mode 100644
index 0000000..a36f68f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleEvaluationQrcodeServiceImpl.java
@@ -0,0 +1,252 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.Date;
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.QRCodeUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.mapper.VehicleInfoMapper;
+import com.ruoyi.system.domain.VehicleInfo;
+import com.ruoyi.system.mapper.VehicleEvaluationQrcodeMapper;
+import com.ruoyi.system.domain.VehicleEvaluationQrcode;
+import com.ruoyi.system.service.IVehicleEvaluationQrcodeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * 杞﹁締璇勪环浜岀淮鐮丼ervice涓氬姟灞傚鐞�
+ * 
+ * @author ruoyi
+ * @date 2025-01-27
+ */
+@Service
+public class VehicleEvaluationQrcodeServiceImpl implements IVehicleEvaluationQrcodeService {
+    @Autowired
+    private VehicleEvaluationQrcodeMapper vehicleEvaluationQrcodeMapper;
+
+    @Autowired
+    private VehicleInfoMapper vehicleInfoMapper;
+
+    @Value("${ruoyi.profile}")
+    private String uploadPath;
+
+    @Value("${server.port}")
+    private String serverPort;
+
+    /**
+     * 鏌ヨ杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param qrcodeId 杞﹁締璇勪环浜岀淮鐮佷富閿�
+     * @return 杞﹁締璇勪环浜岀淮鐮�
+     */
+    @Override
+    public VehicleEvaluationQrcode selectVehicleEvaluationQrcodeByQrcodeId(Long qrcodeId) {
+        return vehicleEvaluationQrcodeMapper.selectVehicleEvaluationQrcodeByQrcodeId(qrcodeId);
+    }
+
+    /**
+     * 鏍规嵁杞︾墝鍙锋煡璇㈣溅杈嗚瘎浠蜂簩缁寸爜
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 杞﹁締璇勪环浜岀淮鐮�
+     */
+    @Override
+    public VehicleEvaluationQrcode selectVehicleEvaluationQrcodeByVehicleNo(String vehicleNo) {
+        return vehicleEvaluationQrcodeMapper.selectVehicleEvaluationQrcodeByVehicleNo(vehicleNo);
+    }
+
+    /**
+     * 鏌ヨ杞﹁締璇勪环浜岀淮鐮佸垪琛�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 杞﹁締璇勪环浜岀淮鐮�
+     */
+    @Override
+    public List<VehicleEvaluationQrcode> selectVehicleEvaluationQrcodeList(VehicleEvaluationQrcode vehicleEvaluationQrcode) {
+        return vehicleEvaluationQrcodeMapper.selectVehicleEvaluationQrcodeList(vehicleEvaluationQrcode);
+    }
+
+    /**
+     * 鏂板杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertVehicleEvaluationQrcode(VehicleEvaluationQrcode vehicleEvaluationQrcode) {
+        vehicleEvaluationQrcode.setCreateTime(DateUtils.getNowDate());
+        return vehicleEvaluationQrcodeMapper.insertVehicleEvaluationQrcode(vehicleEvaluationQrcode);
+    }
+
+    /**
+     * 淇敼杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleEvaluationQrcode 杞﹁締璇勪环浜岀淮鐮�
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateVehicleEvaluationQrcode(VehicleEvaluationQrcode vehicleEvaluationQrcode) {
+        vehicleEvaluationQrcode.setUpdateTime(DateUtils.getNowDate());
+        return vehicleEvaluationQrcodeMapper.updateVehicleEvaluationQrcode(vehicleEvaluationQrcode);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param qrcodeIds 闇�瑕佸垹闄ょ殑杞﹁締璇勪环浜岀淮鐮佷富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteVehicleEvaluationQrcodeByQrcodeIds(Long[] qrcodeIds) {
+        return vehicleEvaluationQrcodeMapper.deleteVehicleEvaluationQrcodeByQrcodeIds(qrcodeIds);
+    }
+
+    /**
+     * 鍒犻櫎杞﹁締璇勪环浜岀淮鐮佷俊鎭�
+     * 
+     * @param qrcodeId 杞﹁締璇勪环浜岀淮鐮佷富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteVehicleEvaluationQrcodeByQrcodeId(Long qrcodeId) {
+        return vehicleEvaluationQrcodeMapper.deleteVehicleEvaluationQrcodeByQrcodeId(qrcodeId);
+    }
+
+    /**
+     * 鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @return 浜岀淮鐮佷俊鎭�
+     */
+    @Override
+    public VehicleEvaluationQrcode generateVehicleEvaluationQrcode(String vehicleNo) {
+        if (StringUtils.isEmpty(vehicleNo)) {
+            return null;
+        }
+
+        // 妫�鏌ヨ溅杈嗘槸鍚﹀瓨鍦�
+        VehicleInfo vehicleInfo = vehicleInfoMapper.selectVehicleInfoByVehicleNo(vehicleNo);
+        if (vehicleInfo == null) {
+            return null;
+        }
+
+        // 妫�鏌ユ槸鍚﹀凡瀛樺湪浜岀淮鐮�
+        VehicleEvaluationQrcode existingQrcode = vehicleEvaluationQrcodeMapper.selectVehicleEvaluationQrcodeByVehicleNo(vehicleNo);
+        if (existingQrcode != null) {
+            return existingQrcode;
+        }
+
+        // 鐢熸垚浜岀淮鐮佸唴瀹�
+        String qrcodeContent = "EVAL:" + vehicleNo;
+        String qrcodeUrl = "http://localhost:" + serverPort + "/evaluation?vehicle=" + vehicleNo;
+
+        // 鐢熸垚浜岀淮鐮佸浘鐗囦负base64鏍煎紡
+        String qrcodeImageBase64 = QRCodeUtils.generateQRCodeToBase64(qrcodeUrl);
+
+        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;
+    }
+
+    /**
+     * 鐢熸垚杞﹁締璇勪环浜岀淮鐮侊紙甯RL鍙傛暟锛�
+     * 
+     * @param vehicleNo 杞︾墝鍙�
+     * @param qrcodeUrl 浜岀淮鐮乁RL
+     * @return 浜岀淮鐮佷俊鎭�
+     */
+    @Override
+    public VehicleEvaluationQrcode generateVehicleEvaluationQrcode(String vehicleNo, String qrcodeUrl) {
+        if (StringUtils.isEmpty(vehicleNo) || StringUtils.isEmpty(qrcodeUrl)) {
+            return null;
+        }
+
+        // 妫�鏌ヨ溅杈嗘槸鍚﹀瓨鍦�
+        VehicleInfo vehicleInfo = vehicleInfoMapper.selectVehicleInfoByVehicleNo(vehicleNo);
+        if (vehicleInfo == null) {
+            return null;
+        }
+
+        // 妫�鏌ユ槸鍚﹀凡瀛樺湪浜岀淮鐮�
+        VehicleEvaluationQrcode existingQrcode = vehicleEvaluationQrcodeMapper.selectVehicleEvaluationQrcodeByVehicleNo(vehicleNo);
+        if (existingQrcode != null) {
+            // 濡傛灉宸插瓨鍦紝鏇存柊URL鍜岄噸鏂扮敓鎴愪簩缁寸爜
+            existingQrcode.setQrcodeUrl(qrcodeUrl);
+            existingQrcode.setQrcodeContent("EVAL:" + vehicleNo);
+            existingQrcode.setUpdateBy("system");
+            existingQrcode.setUpdateTime(DateUtils.getNowDate());
+            
+            // 閲嶆柊鐢熸垚浜岀淮鐮佸浘鐗囦负base64鏍煎紡
+            String qrcodeImageBase64 = QRCodeUtils.generateQRCodeToBase64(qrcodeUrl);
+            
+            if (qrcodeImageBase64 != null) {
+                existingQrcode.setQrcodeImage(qrcodeImageBase64);
+                vehicleEvaluationQrcodeMapper.updateVehicleEvaluationQrcode(existingQrcode);
+                return existingQrcode;
+            }
+            return null;
+        }
+
+        // 鐢熸垚浜岀淮鐮佸唴瀹�
+        String qrcodeContent = "EVAL:" + vehicleNo;
+
+        // 鐢熸垚浜岀淮鐮佸浘鐗囦负base64鏍煎紡
+        String qrcodeImageBase64 = QRCodeUtils.generateQRCodeToBase64(qrcodeUrl);
+
+        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;
+    }
+
+    /**
+     * 鎵归噺鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+     * 
+     * @return 缁撴灉
+     */
+    @Override
+    public int batchGenerateVehicleEvaluationQrcode() {
+        // 鏌ヨ鎵�鏈夋甯哥姸鎬佺殑杞﹁締
+        VehicleInfo vehicleInfo = new VehicleInfo();
+        vehicleInfo.setStatus("0");
+        List<VehicleInfo> vehicleList = vehicleInfoMapper.selectVehicleInfoList(vehicleInfo);
+
+        int successCount = 0;
+        for (VehicleInfo vehicle : vehicleList) {
+            VehicleEvaluationQrcode qrcode = generateVehicleEvaluationQrcode(vehicle.getVehicleNo());
+            if (qrcode != null) {
+                successCount++;
+            }
+        }
+
+        return successCount;
+    }
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/CustomerEvaluationMapper.xml b/ruoyi-system/src/main/resources/mapper/system/CustomerEvaluationMapper.xml
new file mode 100644
index 0000000..3870019
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/CustomerEvaluationMapper.xml
@@ -0,0 +1,159 @@
+<?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.ruoyi.system.mapper.CustomerEvaluationMapper">
+    
+    <resultMap type="CustomerEvaluation" id="CustomerEvaluationResult">
+        <result property="evaluationId"    column="evaluation_id"    />
+        <result property="vehicleNo"    column="vehicle_no"    />
+        <result property="customerName"    column="customer_name"    />
+        <result property="customerPhone"    column="customer_phone"    />
+        <result property="wechatOpenid"    column="wechat_openid"    />
+        <result property="wechatNickname"    column="wechat_nickname"    />
+        <result property="wechatAvatar"    column="wechat_avatar"    />
+        <result property="wechatPhone"    column="wechat_phone"    />
+        <result property="totalScore"    column="total_score"    />
+        <result property="evaluationStatus"    column="evaluation_status"    />
+        <result property="evaluationTime"    column="evaluation_time"    />
+        <result property="ipAddress"    column="ip_address"    />
+        <result property="userAgent"    column="user_agent"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+    </resultMap>
+
+    <sql id="selectCustomerEvaluationVo">
+        select evaluation_id, vehicle_no, customer_name, customer_phone, wechat_openid, wechat_nickname, wechat_avatar, wechat_phone, total_score, evaluation_status, evaluation_time, ip_address, user_agent, create_time, update_time, remark from customer_evaluation
+    </sql>
+
+    <select id="selectCustomerEvaluationList" parameterType="CustomerEvaluation" resultMap="CustomerEvaluationResult">
+        <include refid="selectCustomerEvaluationVo"/>
+        <where>  
+            <if test="vehicleNo != null  and vehicleNo != ''"> and vehicle_no like concat('%', #{vehicleNo}, '%')</if>
+            <if test="customerName != null  and customerName != ''"> and customer_name like concat('%', #{customerName}, '%')</if>
+            <if test="customerPhone != null  and customerPhone != ''"> and customer_phone = #{customerPhone}</if>
+            <if test="wechatOpenid != null  and wechatOpenid != ''"> and wechat_openid = #{wechatOpenid}</if>
+            <if test="wechatNickname != null  and wechatNickname != ''"> and wechat_nickname like concat('%', #{wechatNickname}, '%')</if>
+            <if test="totalScore != null "> and total_score = #{totalScore}</if>
+            <if test="evaluationStatus != null  and evaluationStatus != ''"> and evaluation_status = #{evaluationStatus}</if>
+            <if test="evaluationTime != null "> and evaluation_time = #{evaluationTime}</if>
+            <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+                and date_format(evaluation_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+            </if>
+            <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+                and date_format(evaluation_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+            </if>
+        </where>
+        order by evaluation_time desc, create_time desc
+    </select>
+    
+    <select id="selectCustomerEvaluationByEvaluationId" parameterType="Long" resultMap="CustomerEvaluationResult">
+        <include refid="selectCustomerEvaluationVo"/>
+        where evaluation_id = #{evaluationId}
+    </select>
+
+    <select id="selectCustomerEvaluationByVehicleNo" parameterType="String" resultMap="CustomerEvaluationResult">
+        <include refid="selectCustomerEvaluationVo"/>
+        where vehicle_no = #{vehicleNo}
+        order by evaluation_time desc, create_time desc
+    </select>
+
+    <select id="selectCustomerEvaluationByWechatOpenid" parameterType="String" resultMap="CustomerEvaluationResult">
+        <include refid="selectCustomerEvaluationVo"/>
+        where wechat_openid = #{wechatOpenid}
+        order by evaluation_time desc, create_time desc
+    </select>
+
+    <select id="selectEvaluationStatistics" parameterType="CustomerEvaluation" resultMap="CustomerEvaluationResult">
+        select 
+            vehicle_no,
+            count(*) as total_count,
+            avg(total_score) as avg_score,
+            sum(case when total_score >= 4.0 then 1 else 0 end) as good_count,
+            sum(case when total_score &lt; 3.0 then 1 else 0 end) as bad_count
+        from customer_evaluation
+        <where>
+            evaluation_status = '1'
+            <if test="vehicleNo != null  and vehicleNo != ''"> and vehicle_no = #{vehicleNo}</if>
+            <if test="params.beginTime != null and params.beginTime != ''">
+                and date_format(evaluation_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+            </if>
+            <if test="params.endTime != null and params.endTime != ''">
+                and date_format(evaluation_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+            </if>
+        </where>
+        group by vehicle_no
+        order by avg_score desc
+    </select>
+        
+    <insert id="insertCustomerEvaluation" parameterType="CustomerEvaluation" useGeneratedKeys="true" keyProperty="evaluationId">
+        insert into customer_evaluation
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="vehicleNo != null and vehicleNo != ''">vehicle_no,</if>
+            <if test="customerName != null and customerName != ''">customer_name,</if>
+            <if test="customerPhone != null and customerPhone != ''">customer_phone,</if>
+            <if test="wechatOpenid != null">wechat_openid,</if>
+            <if test="wechatNickname != null">wechat_nickname,</if>
+            <if test="wechatAvatar != null">wechat_avatar,</if>
+            <if test="wechatPhone != null">wechat_phone,</if>
+            <if test="totalScore != null">total_score,</if>
+            <if test="evaluationStatus != null">evaluation_status,</if>
+            <if test="evaluationTime != null">evaluation_time,</if>
+            <if test="ipAddress != null">ip_address,</if>
+            <if test="userAgent != null">user_agent,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="vehicleNo != null and vehicleNo != ''">#{vehicleNo},</if>
+            <if test="customerName != null and customerName != ''">#{customerName},</if>
+            <if test="customerPhone != null and customerPhone != ''">#{customerPhone},</if>
+            <if test="wechatOpenid != null">#{wechatOpenid},</if>
+            <if test="wechatNickname != null">#{wechatNickname},</if>
+            <if test="wechatAvatar != null">#{wechatAvatar},</if>
+            <if test="wechatPhone != null">#{wechatPhone},</if>
+            <if test="totalScore != null">#{totalScore},</if>
+            <if test="evaluationStatus != null">#{evaluationStatus},</if>
+            <if test="evaluationTime != null">#{evaluationTime},</if>
+            <if test="ipAddress != null">#{ipAddress},</if>
+            <if test="userAgent != null">#{userAgent},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateCustomerEvaluation" parameterType="CustomerEvaluation">
+        update customer_evaluation
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="vehicleNo != null and vehicleNo != ''">vehicle_no = #{vehicleNo},</if>
+            <if test="customerName != null and customerName != ''">customer_name = #{customerName},</if>
+            <if test="customerPhone != null and customerPhone != ''">customer_phone = #{customerPhone},</if>
+            <if test="wechatOpenid != null">wechat_openid = #{wechatOpenid},</if>
+            <if test="wechatNickname != null">wechat_nickname = #{wechatNickname},</if>
+            <if test="wechatAvatar != null">wechat_avatar = #{wechatAvatar},</if>
+            <if test="wechatPhone != null">wechat_phone = #{wechatPhone},</if>
+            <if test="totalScore != null">total_score = #{totalScore},</if>
+            <if test="evaluationStatus != null">evaluation_status = #{evaluationStatus},</if>
+            <if test="evaluationTime != null">evaluation_time = #{evaluationTime},</if>
+            <if test="ipAddress != null">ip_address = #{ipAddress},</if>
+            <if test="userAgent != null">user_agent = #{userAgent},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where evaluation_id = #{evaluationId}
+    </update>
+
+    <delete id="deleteCustomerEvaluationByEvaluationId" parameterType="Long">
+        delete from customer_evaluation where evaluation_id = #{evaluationId}
+    </delete>
+
+    <delete id="deleteCustomerEvaluationByEvaluationIds" parameterType="String">
+        delete from customer_evaluation where evaluation_id in 
+        <foreach item="evaluationId" collection="array" open="(" separator="," close=")">
+            #{evaluationId}
+        </foreach>
+    </delete>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/EvaluationDetailMapper.xml b/ruoyi-system/src/main/resources/mapper/system/EvaluationDetailMapper.xml
new file mode 100644
index 0000000..129d4ab
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/EvaluationDetailMapper.xml
@@ -0,0 +1,116 @@
+<?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.ruoyi.system.mapper.EvaluationDetailMapper">
+    
+    <resultMap type="EvaluationDetail" id="EvaluationDetailResult">
+        <result property="detailId"    column="detail_id"    />
+        <result property="evaluationId"    column="evaluation_id"    />
+        <result property="dimensionId"    column="dimension_id"    />
+        <result property="score"    column="score"    />
+        <result property="optionValue"    column="option_value"    />
+        <result property="textContent"    column="text_content"    />
+        <result property="createTime"    column="create_time"    />
+    </resultMap>
+
+    <resultMap type="EvaluationDetail" id="EvaluationDetailWithDimensionResult" extends="EvaluationDetailResult">
+        <association property="dimension" javaType="EvaluationDimension">
+            <result property="dimensionId"    column="dimension_id"    />
+            <result property="dimensionName"    column="dimension_name"    />
+            <result property="dimensionDesc"    column="dimension_desc"    />
+            <result property="dimensionType"    column="dimension_type"    />
+            <result property="options"    column="options"    />
+            <result property="sortOrder"    column="sort_order"    />
+            <result property="isRequired"    column="is_required"    />
+        </association>
+    </resultMap>
+
+    <sql id="selectEvaluationDetailVo">
+        select detail_id, evaluation_id, dimension_id, score, option_value, text_content, create_time from evaluation_detail
+    </sql>
+
+    <sql id="selectEvaluationDetailWithDimensionVo">
+        select ed.detail_id, ed.evaluation_id, ed.dimension_id, ed.score, ed.option_value, ed.text_content, ed.create_time,
+               edim.dimension_name, edim.dimension_desc, edim.dimension_type, edim.options, edim.sort_order, edim.is_required
+        from evaluation_detail ed
+        left join evaluation_dimension edim on ed.dimension_id = edim.dimension_id
+    </sql>
+
+    <select id="selectEvaluationDetailList" parameterType="EvaluationDetail" resultMap="EvaluationDetailResult">
+        <include refid="selectEvaluationDetailVo"/>
+        <where>  
+            <if test="evaluationId != null "> and evaluation_id = #{evaluationId}</if>
+            <if test="dimensionId != null "> and dimension_id = #{dimensionId}</if>
+            <if test="score != null "> and score = #{score}</if>
+            <if test="optionValue != null  and optionValue != ''"> and option_value = #{optionValue}</if>
+        </where>
+        order by create_time desc
+    </select>
+    
+    <select id="selectEvaluationDetailByDetailId" parameterType="Long" resultMap="EvaluationDetailResult">
+        <include refid="selectEvaluationDetailVo"/>
+        where detail_id = #{detailId}
+    </select>
+
+    <select id="selectEvaluationDetailByEvaluationId" parameterType="Long" resultMap="EvaluationDetailWithDimensionResult">
+        <include refid="selectEvaluationDetailWithDimensionVo"/>
+        where ed.evaluation_id = #{evaluationId}
+        order by edim.sort_order asc, ed.create_time desc
+    </select>
+        
+    <insert id="insertEvaluationDetail" parameterType="EvaluationDetail" useGeneratedKeys="true" keyProperty="detailId">
+        insert into evaluation_detail
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="evaluationId != null">evaluation_id,</if>
+            <if test="dimensionId != null">dimension_id,</if>
+            <if test="score != null">score,</if>
+            <if test="optionValue != null">option_value,</if>
+            <if test="textContent != null">text_content,</if>
+            <if test="createTime != null">create_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="evaluationId != null">#{evaluationId},</if>
+            <if test="dimensionId != null">#{dimensionId},</if>
+            <if test="score != null">#{score},</if>
+            <if test="optionValue != null">#{optionValue},</if>
+            <if test="textContent != null">#{textContent},</if>
+            <if test="createTime != null">#{createTime},</if>
+         </trim>
+    </insert>
+
+    <insert id="insertEvaluationDetailBatch" parameterType="java.util.List">
+        insert into evaluation_detail (evaluation_id, dimension_id, score, option_value, text_content, create_time)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{item.evaluationId}, #{item.dimensionId}, #{item.score}, #{item.optionValue}, #{item.textContent}, #{item.createTime})
+        </foreach>
+    </insert>
+
+    <update id="updateEvaluationDetail" parameterType="EvaluationDetail">
+        update evaluation_detail
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="evaluationId != null">evaluation_id = #{evaluationId},</if>
+            <if test="dimensionId != null">dimension_id = #{dimensionId},</if>
+            <if test="score != null">score = #{score},</if>
+            <if test="optionValue != null">option_value = #{optionValue},</if>
+            <if test="textContent != null">text_content = #{textContent},</if>
+        </trim>
+        where detail_id = #{detailId}
+    </update>
+
+    <delete id="deleteEvaluationDetailByDetailId" parameterType="Long">
+        delete from evaluation_detail where detail_id = #{detailId}
+    </delete>
+
+    <delete id="deleteEvaluationDetailByEvaluationId" parameterType="Long">
+        delete from evaluation_detail where evaluation_id = #{evaluationId}
+    </delete>
+
+    <delete id="deleteEvaluationDetailByDetailIds" parameterType="String">
+        delete from evaluation_detail where detail_id in 
+        <foreach item="detailId" collection="array" open="(" separator="," close=")">
+            #{detailId}
+        </foreach>
+    </delete>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/EvaluationDimensionMapper.xml b/ruoyi-system/src/main/resources/mapper/system/EvaluationDimensionMapper.xml
new file mode 100644
index 0000000..bfeb7bf
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/EvaluationDimensionMapper.xml
@@ -0,0 +1,110 @@
+<?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.ruoyi.system.mapper.EvaluationDimensionMapper">
+    
+    <resultMap type="EvaluationDimension" id="EvaluationDimensionResult">
+        <result property="dimensionId"    column="dimension_id"    />
+        <result property="dimensionName"    column="dimension_name"    />
+        <result property="dimensionDesc"    column="dimension_desc"    />
+        <result property="dimensionType"    column="dimension_type"    />
+        <result property="options"    column="options"    />
+        <result property="sortOrder"    column="sort_order"    />
+        <result property="isRequired"    column="is_required"    />
+        <result property="status"    column="status"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+    </resultMap>
+
+    <sql id="selectEvaluationDimensionVo">
+        select dimension_id, dimension_name, dimension_desc, dimension_type, options, sort_order, is_required, status, create_by, create_time, update_by, update_time, remark from evaluation_dimension
+    </sql>
+
+    <select id="selectEvaluationDimensionList" parameterType="EvaluationDimension" resultMap="EvaluationDimensionResult">
+        <include refid="selectEvaluationDimensionVo"/>
+        <where>  
+            <if test="dimensionName != null  and dimensionName != ''"> and dimension_name like concat('%', #{dimensionName}, '%')</if>
+            <if test="dimensionDesc != null  and dimensionDesc != ''"> and dimension_desc like concat('%', #{dimensionDesc}, '%')</if>
+            <if test="dimensionType != null  and dimensionType != ''"> and dimension_type = #{dimensionType}</if>
+            <if test="sortOrder != null "> and sort_order = #{sortOrder}</if>
+            <if test="isRequired != null  and isRequired != ''"> and is_required = #{isRequired}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+        </where>
+        order by sort_order asc, create_time desc
+    </select>
+    
+    <select id="selectEvaluationDimensionByDimensionId" parameterType="Long" resultMap="EvaluationDimensionResult">
+        <include refid="selectEvaluationDimensionVo"/>
+        where dimension_id = #{dimensionId}
+    </select>
+
+    <select id="selectEnabledEvaluationDimensionList" resultMap="EvaluationDimensionResult">
+        <include refid="selectEvaluationDimensionVo"/>
+        where status = '0'
+        order by sort_order asc, create_time desc
+    </select>
+        
+    <insert id="insertEvaluationDimension" parameterType="EvaluationDimension" useGeneratedKeys="true" keyProperty="dimensionId">
+        insert into evaluation_dimension
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="dimensionName != null and dimensionName != ''">dimension_name,</if>
+            <if test="dimensionDesc != null">dimension_desc,</if>
+            <if test="dimensionType != null and dimensionType != ''">dimension_type,</if>
+            <if test="options != null">options,</if>
+            <if test="sortOrder != null">sort_order,</if>
+            <if test="isRequired != null">is_required,</if>
+            <if test="status != null">status,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="dimensionName != null and dimensionName != ''">#{dimensionName},</if>
+            <if test="dimensionDesc != null">#{dimensionDesc},</if>
+            <if test="dimensionType != null and dimensionType != ''">#{dimensionType},</if>
+            <if test="options != null">#{options},</if>
+            <if test="sortOrder != null">#{sortOrder},</if>
+            <if test="isRequired != null">#{isRequired},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateEvaluationDimension" parameterType="EvaluationDimension">
+        update evaluation_dimension
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="dimensionName != null and dimensionName != ''">dimension_name = #{dimensionName},</if>
+            <if test="dimensionDesc != null">dimension_desc = #{dimensionDesc},</if>
+            <if test="dimensionType != null and dimensionType != ''">dimension_type = #{dimensionType},</if>
+            <if test="options != null">options = #{options},</if>
+            <if test="sortOrder != null">sort_order = #{sortOrder},</if>
+            <if test="isRequired != null">is_required = #{isRequired},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where dimension_id = #{dimensionId}
+    </update>
+
+    <delete id="deleteEvaluationDimensionByDimensionId" parameterType="Long">
+        delete from evaluation_dimension where dimension_id = #{dimensionId}
+    </delete>
+
+    <delete id="deleteEvaluationDimensionByDimensionIds" parameterType="String">
+        delete from evaluation_dimension where dimension_id in 
+        <foreach item="dimensionId" collection="array" open="(" separator="," close=")">
+            #{dimensionId}
+        </foreach>
+    </delete>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/VehicleEvaluationQrcodeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/VehicleEvaluationQrcodeMapper.xml
new file mode 100644
index 0000000..22d7024
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/VehicleEvaluationQrcodeMapper.xml
@@ -0,0 +1,103 @@
+<?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.ruoyi.system.mapper.VehicleEvaluationQrcodeMapper">
+    
+    <resultMap type="VehicleEvaluationQrcode" id="VehicleEvaluationQrcodeResult">
+        <result property="qrcodeId"    column="qrcode_id"    />
+        <result property="vehicleNo"    column="vehicle_no"    />
+        <result property="qrcodeUrl"    column="qrcode_url"    />
+        <result property="qrcodeContent"    column="qrcode_content"    />
+        <result property="qrcodeImage"    column="qrcode_image"    />
+        <result property="status"    column="status"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+    </resultMap>
+
+    <sql id="selectVehicleEvaluationQrcodeVo">
+        select qrcode_id, vehicle_no, qrcode_url, qrcode_content, qrcode_image, status, create_by, create_time, update_by, update_time, remark from vehicle_evaluation_qrcode
+    </sql>
+
+    <select id="selectVehicleEvaluationQrcodeList" parameterType="VehicleEvaluationQrcode" resultMap="VehicleEvaluationQrcodeResult">
+        <include refid="selectVehicleEvaluationQrcodeVo"/>
+        <where>  
+            <if test="vehicleNo != null  and vehicleNo != ''"> and vehicle_no like concat('%', #{vehicleNo}, '%')</if>
+            <if test="qrcodeUrl != null  and qrcodeUrl != ''"> and qrcode_url like concat('%', #{qrcodeUrl}, '%')</if>
+            <if test="qrcodeContent != null  and qrcodeContent != ''"> and qrcode_content like concat('%', #{qrcodeContent}, '%')</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+        </where>
+        order by create_time desc
+    </select>
+    
+    <select id="selectVehicleEvaluationQrcodeByQrcodeId" parameterType="Long" resultMap="VehicleEvaluationQrcodeResult">
+        <include refid="selectVehicleEvaluationQrcodeVo"/>
+        where qrcode_id = #{qrcodeId}
+    </select>
+
+    <select id="selectVehicleEvaluationQrcodeByVehicleNo" parameterType="String" resultMap="VehicleEvaluationQrcodeResult">
+        <include refid="selectVehicleEvaluationQrcodeVo"/>
+        where vehicle_no = #{vehicleNo}
+    </select>
+        
+    <insert id="insertVehicleEvaluationQrcode" parameterType="VehicleEvaluationQrcode" useGeneratedKeys="true" keyProperty="qrcodeId">
+        insert into vehicle_evaluation_qrcode
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="vehicleNo != null and vehicleNo != ''">vehicle_no,</if>
+            <if test="qrcodeUrl != null and qrcodeUrl != ''">qrcode_url,</if>
+            <if test="qrcodeContent != null and qrcodeContent != ''">qrcode_content,</if>
+            <if test="qrcodeImage != null">qrcode_image,</if>
+            <if test="status != null">status,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="vehicleNo != null and vehicleNo != ''">#{vehicleNo},</if>
+            <if test="qrcodeUrl != null and qrcodeUrl != ''">#{qrcodeUrl},</if>
+            <if test="qrcodeContent != null and qrcodeContent != ''">#{qrcodeContent},</if>
+            <if test="qrcodeImage != null">#{qrcodeImage},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateVehicleEvaluationQrcode" parameterType="VehicleEvaluationQrcode">
+        update vehicle_evaluation_qrcode
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="vehicleNo != null and vehicleNo != ''">vehicle_no = #{vehicleNo},</if>
+            <if test="qrcodeUrl != null and qrcodeUrl != ''">qrcode_url = #{qrcodeUrl},</if>
+            <if test="qrcodeContent != null and qrcodeContent != ''">qrcode_content = #{qrcodeContent},</if>
+            <if test="qrcodeImage != null">qrcode_image = #{qrcodeImage},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where qrcode_id = #{qrcodeId}
+    </update>
+
+    <delete id="deleteVehicleEvaluationQrcodeByQrcodeId" parameterType="Long">
+        delete from vehicle_evaluation_qrcode where qrcode_id = #{qrcodeId}
+    </delete>
+
+    <delete id="deleteVehicleEvaluationQrcodeByVehicleNo" parameterType="String">
+        delete from vehicle_evaluation_qrcode where vehicle_no = #{vehicleNo}
+    </delete>
+
+    <delete id="deleteVehicleEvaluationQrcodeByQrcodeIds" parameterType="String">
+        delete from vehicle_evaluation_qrcode where qrcode_id in 
+        <foreach item="qrcodeId" collection="array" open="(" separator="," close=")">
+            #{qrcodeId}
+        </foreach>
+    </delete>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml b/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml
index aa34be7..45ac040 100644
--- a/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml
@@ -13,6 +13,8 @@
         <result property="vehicleModel"   column="vehicle_model"   />
         <result property="status"         column="status"          />
         <result property="platformCode"   column="platform_code"   />
+        <result property="deptId"         column="dept_id"         />
+        <result property="deptName"       column="dept_name"       />
         <result property="createBy"       column="create_by"       />
         <result property="createTime"     column="create_time"     />
         <result property="updateBy"       column="update_by"       />
@@ -21,31 +23,38 @@
     </resultMap>
 
     <sql id="selectVehicleInfoVo">
-        select vehicle_id, device_id, vehicle_no, vehicle_type, vehicle_brand, vehicle_model, status, platform_code, create_by, create_time, update_by, update_time, remark
-        from tb_vehicle_info
+        select v.vehicle_id, v.device_id, v.vehicle_no, v.vehicle_type, v.vehicle_brand, v.vehicle_model, v.status, v.platform_code, v.dept_id, d.dept_name, v.create_by, v.create_time, v.update_by, v.update_time, v.remark
+        from tb_vehicle_info v
+        left join sys_dept d on v.dept_id = d.dept_id
     </sql>
 
     <select id="selectVehicleInfoList" parameterType="VehicleInfo" resultMap="VehicleInfoResult">
         <include refid="selectVehicleInfoVo"/>
         <where>  
-            <if test="vehicleNo != null  and vehicleNo != ''"> and vehicle_no = #{vehicleNo}</if>
-            <if test="deviceId != null  and deviceId != ''"> and device_id = #{deviceId}</if>
-            <if test="vehicleType != null  and vehicleType != ''"> and vehicle_type = #{vehicleType}</if>
-            <if test="vehicleBrand != null  and vehicleBrand != ''"> and vehicle_brand = #{vehicleBrand}</if>
-            <if test="vehicleModel != null  and vehicleModel != ''"> and vehicle_model = #{vehicleModel}</if>
-            <if test="status != null  and status != ''"> and status = #{status}</if>
-            <if test="platformCode != null  and platformCode != ''"> and platform_code = #{platformCode}</if>
+            <if test="vehicleNo != null  and vehicleNo != ''"> and v.vehicle_no = #{vehicleNo}</if>
+            <if test="deviceId != null  and deviceId != ''"> and v.device_id = #{deviceId}</if>
+            <if test="vehicleType != null  and vehicleType != ''"> and v.vehicle_type = #{vehicleType}</if>
+            <if test="vehicleBrand != null  and vehicleBrand != ''"> and v.vehicle_brand = #{vehicleBrand}</if>
+            <if test="vehicleModel != null  and vehicleModel != ''"> and v.vehicle_model = #{vehicleModel}</if>
+            <if test="status != null  and status != ''"> and v.status = #{status}</if>
+            <if test="platformCode != null  and platformCode != ''"> and v.platform_code = #{platformCode}</if>
+            <if test="deptId != null"> and v.dept_id = #{deptId}</if>
         </where>
     </select>
     
     <select id="selectVehicleInfoById" parameterType="Long" resultMap="VehicleInfoResult">
         <include refid="selectVehicleInfoVo"/>
-        where vehicle_id = #{vehicleId}
+        where v.vehicle_id = #{vehicleId}
     </select>
 
     <select id="selectVehicleInfoByPlateNumber" parameterType="String" resultMap="VehicleInfoResult">
         <include refid="selectVehicleInfoVo"/>
-        where vehicle_no = #{plateNumber}
+        where v.vehicle_no = #{plateNumber}
+    </select>
+
+    <select id="selectVehicleInfoByVehicleNo" parameterType="String" resultMap="VehicleInfoResult">
+        <include refid="selectVehicleInfoVo"/>
+        where v.vehicle_no = #{vehicleNo}
     </select>
         
     <insert id="insertVehicleInfo" parameterType="VehicleInfo" useGeneratedKeys="true" keyProperty="vehicleId">
@@ -58,6 +67,7 @@
             <if test="vehicleModel != null">vehicle_model,</if>
             <if test="status != null">status,</if>
             <if test="platformCode != null">platform_code,</if>
+            <if test="deptId != null">dept_id,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
@@ -72,6 +82,7 @@
             <if test="vehicleModel != null">#{vehicleModel},</if>
             <if test="status != null">#{status},</if>
             <if test="platformCode != null">#{platformCode},</if>
+            <if test="deptId != null">#{deptId},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
@@ -90,6 +101,7 @@
             <if test="vehicleModel != null">vehicle_model = #{vehicleModel},</if>
             <if test="status != null">status = #{status},</if>
             <if test="platformCode != null">platform_code = #{platformCode},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="remark != null">remark = #{remark},</if>
diff --git a/ruoyi-ui/src/api/evaluation.js b/ruoyi-ui/src/api/evaluation.js
new file mode 100644
index 0000000..d09df5f
--- /dev/null
+++ b/ruoyi-ui/src/api/evaluation.js
@@ -0,0 +1,181 @@
+import request from '@/utils/request'
+
+// 鑾峰彇璇勪环缁村害閰嶇疆
+export function getEvaluationDimensions() {
+  return request({
+    url: '/evaluation/dimensions',
+    method: 'get'
+  })
+}
+
+// 鎻愪氦瀹㈡埛璇勪环
+export function submitEvaluation(data) {
+  return request({
+    url: '/evaluation/submit',
+    method: 'post',
+    data: data
+  })
+}
+
+// 鑾峰彇寰俊鐢ㄦ埛淇℃伅
+export function getWechatUserInfo(code) {
+  return request({
+    url: '/evaluation/wechat/userinfo',
+    method: 'get',
+    params: { code }
+  })
+}
+
+// 鏌ヨ瀹㈡埛璇勪环鍒楄〃
+export function listEvaluation(query) {
+  return request({
+    url: '/evaluation/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ瀹㈡埛璇勪环璇︾粏
+export function getEvaluation(evaluationId) {
+  return request({
+    url: '/evaluation/' + evaluationId,
+    method: 'get'
+  })
+}
+
+// 鏂板瀹㈡埛璇勪环
+export function addEvaluation(data) {
+  return request({
+    url: '/evaluation',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼瀹㈡埛璇勪环
+export function updateEvaluation(data) {
+  return request({
+    url: '/evaluation',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎瀹㈡埛璇勪环
+export function delEvaluation(evaluationId) {
+  return request({
+    url: '/evaluation/' + evaluationId,
+    method: 'delete'
+  })
+}
+
+// 鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+export function generateQrcode(data) {
+  return request({
+    url: '/evaluation/qrcode/generate',
+    method: 'post',
+    data: data
+  })
+}
+
+// 鎵归噺鐢熸垚杞﹁締璇勪环浜岀淮鐮�
+export function batchGenerateQrcode() {
+  return request({
+    url: '/evaluation/qrcode/batch',
+    method: 'post'
+  })
+}
+
+// 鏌ヨ璇勪环缁村害閰嶇疆鍒楄〃
+export function listDimension(query) {
+  return request({
+    url: '/evaluation/dimension/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ璇勪环缁村害閰嶇疆璇︾粏
+export function getDimension(dimensionId) {
+  return request({
+    url: '/evaluation/dimension/' + dimensionId,
+    method: 'get'
+  })
+}
+
+// 鏂板璇勪环缁村害閰嶇疆
+export function addDimension(data) {
+  return request({
+    url: '/evaluation/dimension',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼璇勪环缁村害閰嶇疆
+export function updateDimension(data) {
+  return request({
+    url: '/evaluation/dimension',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎璇勪环缁村害閰嶇疆
+export function delDimension(dimensionId) {
+  return request({
+    url: '/evaluation/dimension/' + dimensionId,
+    method: 'delete'
+  })
+}
+
+// 鏌ヨ杞﹁締璇勪环浜岀淮鐮佸垪琛�
+export function listQrcode(query) {
+  return request({
+    url: '/evaluation/qrcode/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ杞﹁締璇勪环浜岀淮鐮佽缁�
+export function getQrcode(qrcodeId) {
+  return request({
+    url: '/evaluation/qrcode/' + qrcodeId,
+    method: 'get'
+  })
+}
+
+// 鍒犻櫎杞﹁締璇勪环浜岀淮鐮�
+export function delQrcode(qrcodeId) {
+  return request({
+    url: '/evaluation/qrcode/' + qrcodeId,
+    method: 'delete'
+  })
+}
+
+// 鏌ヨ瀹㈡埛璇勪环鍒楄〃锛堢敤浜庣粺璁¢〉闈級
+export function listCustomerEvaluation(query) {
+  return request({
+    url: '/evaluation/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ瀹㈡埛璇勪环璇︾粏锛堢敤浜庣粺璁¢〉闈級
+export function getCustomerEvaluation(evaluationId) {
+  return request({
+    url: '/evaluation/' + evaluationId,
+    method: 'get'
+  })
+}
+
+// 鑾峰彇璇勪环缁熻鏁版嵁
+export function getEvaluationStatistics(query) {
+  return request({
+    url: '/evaluation/statistics',
+    method: 'get',
+    params: query
+  })
+}
diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js
index bf8f5be..10ccd84 100644
--- a/ruoyi-ui/src/router/index.js
+++ b/ruoyi-ui/src/router/index.js
@@ -58,6 +58,18 @@
     meta: { title: '鍖垮悕璁㈠崟鏌ョ湅', icon: 'eye',anonymous: true }
   },
   {
+    path: '/evaluation',
+    component: () => import('@/views/evaluation/index'),
+    hidden: true,
+    meta: { title: '瀹㈡埛璇勪环', anonymous: true }
+  },
+  {
+    path: '/evaluation/test',
+    component: () => import('@/views/evaluation/test'),
+    hidden: true,
+    meta: { title: '璇勪环鍔熻兘娴嬭瘯', anonymous: true }
+  },
+  {
     path: '/404',
     component: () => import('@/views/error/404'),
     hidden: true
diff --git a/ruoyi-ui/src/views/evaluation/customer/index.vue b/ruoyi-ui/src/views/evaluation/customer/index.vue
new file mode 100644
index 0000000..288825e
--- /dev/null
+++ b/ruoyi-ui/src/views/evaluation/customer/index.vue
@@ -0,0 +1,297 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
+        <el-input
+          v-model="queryParams.vehicleNo"
+          placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="瀹㈡埛濮撳悕" prop="customerName">
+        <el-input
+          v-model="queryParams.customerName"
+          placeholder="璇疯緭鍏ュ鎴峰鍚�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="瀹㈡埛鎵嬫満" prop="customerPhone">
+        <el-input
+          v-model="queryParams.customerPhone"
+          placeholder="璇疯緭鍏ュ鎴锋墜鏈哄彿"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="璇勪环鏃堕棿">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['evaluation:customer:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['evaluation:customer:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="customerEvaluationList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="璇勪环ID" align="center" prop="evaluationId" />
+      <el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" />
+      <el-table-column label="瀹㈡埛濮撳悕" align="center" prop="customerName" />
+      <el-table-column label="瀹㈡埛鎵嬫満" align="center" prop="customerPhone" />
+      <el-table-column label="寰俊鏄电О" align="center" prop="wechatNickname" />
+      <el-table-column label="鎬昏瘎鍒�" align="center" prop="totalScore">
+        <template slot-scope="scope">
+          <el-rate
+            v-model="scope.row.totalScore"
+            disabled
+            show-score
+            text-color="#ff9900"
+            score-template="{value}">
+          </el-rate>
+        </template>
+      </el-table-column>
+      <el-table-column label="璇勪环鏃堕棿" align="center" prop="evaluationTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.evaluationTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleView(scope.row)"
+            v-hasPermi="['evaluation:customer:query']"
+          >鏌ョ湅</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['evaluation:customer:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 璇勪环璇︽儏瀵硅瘽妗� -->
+    <el-dialog title="璇勪环璇︽儏" :visible.sync="open" width="800px" append-to-body>
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="璇勪环ID">{{ evaluationForm.evaluationId }}</el-descriptions-item>
+        <el-descriptions-item label="杞︾墝鍙�">{{ evaluationForm.vehicleNo }}</el-descriptions-item>
+        <el-descriptions-item label="瀹㈡埛濮撳悕">{{ evaluationForm.customerName }}</el-descriptions-item>
+        <el-descriptions-item label="瀹㈡埛鎵嬫満">{{ evaluationForm.customerPhone }}</el-descriptions-item>
+        <el-descriptions-item label="寰俊鏄电О">{{ evaluationForm.wechatNickname }}</el-descriptions-item>
+        <el-descriptions-item label="寰俊澶村儚">
+          <el-image v-if="evaluationForm.wechatAvatar" :src="evaluationForm.wechatAvatar" style="width: 50px; height: 50px;"></el-image>
+        </el-descriptions-item>
+        <el-descriptions-item label="鎬昏瘎鍒�">
+          <el-rate
+            v-model="evaluationForm.totalScore"
+            disabled
+            show-score
+            text-color="#ff9900"
+            score-template="{value}">
+          </el-rate>
+        </el-descriptions-item>
+        <el-descriptions-item label="璇勪环鏃堕棿">{{ parseTime(evaluationForm.evaluationTime) }}</el-descriptions-item>
+        <el-descriptions-item label="IP鍦板潃">{{ evaluationForm.ipAddress }}</el-descriptions-item>
+        <el-descriptions-item label="鐢ㄦ埛浠g悊" :span="2">{{ evaluationForm.userAgent }}</el-descriptions-item>
+      </el-descriptions>
+      
+      <div style="margin-top: 20px;">
+        <h4>璇勪环璇︽儏</h4>
+        <el-table :data="evaluationForm.evaluationDetails" border>
+          <el-table-column label="璇勪环缁村害" prop="dimension.dimensionName" />
+          <el-table-column label="璇勫垎" align="center">
+            <template slot-scope="scope">
+              <el-rate
+                v-if="scope.row.dimension.dimensionType === 'star'"
+                v-model="scope.row.score"
+                disabled
+                show-score
+                text-color="#ff9900"
+                score-template="{value}">
+              </el-rate>
+              <span v-else-if="scope.row.dimension.dimensionType === 'select'">{{ scope.row.optionValue }}</span>
+              <span v-else-if="scope.row.dimension.dimensionType === 'text'">{{ scope.row.textContent }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="cancel">鍏� 闂�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listEvaluation, getEvaluation, delEvaluation } from "@/api/evaluation";
+
+export default {
+  name: "CustomerEvaluation",
+  dicts: [],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 瀹㈡埛璇勪环琛ㄦ牸鏁版嵁
+      customerEvaluationList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        vehicleNo: null,
+        customerName: null,
+        customerPhone: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      evaluationForm: {}
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ瀹㈡埛璇勪环鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listEvaluation(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.customerEvaluationList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.evaluationForm = {
+        evaluationId: null,
+        vehicleNo: null,
+        customerName: null,
+        customerPhone: null,
+        wechatOpenid: null,
+        wechatNickname: null,
+        wechatAvatar: null,
+        wechatPhone: null,
+        totalScore: null,
+        evaluationStatus: null,
+        evaluationTime: null,
+        ipAddress: null,
+        userAgent: null,
+        evaluationDetails: []
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.evaluationId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏌ョ湅鎸夐挳鎿嶄綔 */
+    handleView(row) {
+      this.reset();
+      const evaluationId = row.evaluationId || this.ids
+      getEvaluation(evaluationId).then(response => {
+        this.evaluationForm = response.data;
+        this.open = true;
+        this.title = "璇勪环璇︽儏";
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const evaluationIds = row.evaluationId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎瀹㈡埛璇勪环缂栧彿涓�"' + evaluationIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delEvaluation(evaluationIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('evaluation/export', {
+        ...this.queryParams
+      }, `customer_evaluation_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/ruoyi-ui/src/views/evaluation/dimension/index.vue b/ruoyi-ui/src/views/evaluation/dimension/index.vue
new file mode 100644
index 0000000..46c25f1
--- /dev/null
+++ b/ruoyi-ui/src/views/evaluation/dimension/index.vue
@@ -0,0 +1,325 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="缁村害鍚嶇О" prop="dimensionName">
+        <el-input
+          v-model="queryParams.dimensionName"
+          placeholder="璇疯緭鍏ョ淮搴﹀悕绉�"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="缁村害绫诲瀷" prop="dimensionType">
+        <el-select v-model="queryParams.dimensionType" placeholder="璇烽�夋嫨缁村害绫诲瀷" clearable>
+          <el-option label="鏄熺骇璇勪环" value="star" />
+          <el-option label="閫夋嫨璇勪环" value="select" />
+          <el-option label="鏂囨湰璇勪环" value="text" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable>
+          <el-option label="姝e父" value="0" />
+          <el-option label="鍋滅敤" value="1" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['evaluation:dimension:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['evaluation:dimension:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['evaluation:dimension:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="dimensionList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="缁村害ID" align="center" prop="dimensionId" />
+      <el-table-column label="缁村害鍚嶇О" align="center" prop="dimensionName" />
+      <el-table-column label="缁村害鎻忚堪" align="center" prop="dimensionDesc" />
+      <el-table-column label="缁村害绫诲瀷" align="center" prop="dimensionType">
+        <template slot-scope="scope">
+          <span v-if="scope.row.dimensionType === 'star'">鏄熺骇璇勪环</span>
+          <span v-else-if="scope.row.dimensionType === 'select'">閫夋嫨璇勪环</span>
+          <span v-else-if="scope.row.dimensionType === 'text'">鏂囨湰璇勪环</span>
+          <span v-else>{{ scope.row.dimensionType }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎺掑簭" align="center" prop="sortOrder" />
+      <el-table-column label="鏄惁蹇呭~" align="center" prop="isRequired">
+        <template slot-scope="scope">
+          <span v-if="scope.row.isRequired === '1'">鏄�</span>
+          <span v-else-if="scope.row.isRequired === '0'">鍚�</span>
+          <span v-else>{{ scope.row.isRequired }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['evaluation:dimension:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['evaluation:dimension:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀硅瘎浠风淮搴﹂厤缃璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="缁村害鍚嶇О" prop="dimensionName">
+          <el-input v-model="form.dimensionName" placeholder="璇疯緭鍏ョ淮搴﹀悕绉�" />
+        </el-form-item>
+        <el-form-item label="缁村害鎻忚堪" prop="dimensionDesc">
+          <el-input v-model="form.dimensionDesc" type="textarea" placeholder="璇疯緭鍏ョ淮搴︽弿杩�" />
+        </el-form-item>
+        <el-form-item label="缁村害绫诲瀷" prop="dimensionType">
+          <el-select v-model="form.dimensionType" placeholder="璇烽�夋嫨缁村害绫诲瀷">
+            <el-option label="鏄熺骇璇勪环" value="star" />
+            <el-option label="閫夋嫨璇勪环" value="select" />
+            <el-option label="鏂囨湰璇勪环" value="text" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="閫夐」閰嶇疆" prop="options" v-if="form.dimensionType === 'select'">
+          <el-input v-model="form.options" type="textarea" placeholder="璇疯緭鍏ラ�夐」閰嶇疆锛孞SON鏍煎紡锛屽锛歔{&quot;label&quot;:&quot;婊℃剰&quot;,&quot;value&quot;:&quot;1&quot;},{&quot;label&quot;:&quot;涓嶆弧鎰�&quot;,&quot;value&quot;:&quot;0&quot;}]" />
+        </el-form-item>
+        <el-form-item label="鎺掑簭" prop="sortOrder">
+          <el-input-number v-model="form.sortOrder" controls-position="right" :min="0" />
+        </el-form-item>
+        <el-form-item label="鏄惁蹇呭~" prop="isRequired">
+          <el-radio-group v-model="form.isRequired">
+            <el-radio label="1">鏄�</el-radio>
+            <el-radio label="0">鍚�</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio label="0">姝e父</el-radio>
+            <el-radio label="1">鍋滅敤</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listDimension, getDimension, delDimension, addDimension, updateDimension } from "@/api/evaluation";
+
+export default {
+  name: "EvaluationDimension",
+  dicts: ['dimension_type', 'sys_yes_no', 'sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 璇勪环缁村害閰嶇疆琛ㄦ牸鏁版嵁
+      dimensionList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        dimensionName: null,
+        dimensionType: null,
+        status: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        dimensionName: [
+          { required: true, message: "缁村害鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        dimensionType: [
+          { required: true, message: "缁村害绫诲瀷涓嶈兘涓虹┖", trigger: "change" }
+        ],
+        sortOrder: [
+          { required: true, message: "鎺掑簭涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        isRequired: [
+          { required: true, message: "鏄惁蹇呭~涓嶈兘涓虹┖", trigger: "change" }
+        ],
+        status: [
+          { required: true, message: "鐘舵�佷笉鑳戒负绌�", trigger: "change" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ璇勪环缁村害閰嶇疆鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listDimension(this.queryParams).then(response => {
+        this.dimensionList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        dimensionId: null,
+        dimensionName: null,
+        dimensionDesc: null,
+        dimensionType: null,
+        options: null,
+        sortOrder: 0,
+        isRequired: "1",
+        status: "0",
+        remark: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.dimensionId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞璇勪环缁村害閰嶇疆";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.reset();
+      const dimensionId = row.dimensionId || this.ids
+      getDimension(dimensionId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼璇勪环缁村害閰嶇疆";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.dimensionId != null) {
+            updateDimension(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addDimension(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const dimensionIds = row.dimensionId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎璇勪环缁村害閰嶇疆缂栧彿涓�"' + dimensionIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delDimension(dimensionIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    }
+  }
+};
+</script>
diff --git a/ruoyi-ui/src/views/evaluation/index.vue b/ruoyi-ui/src/views/evaluation/index.vue
new file mode 100644
index 0000000..017d5af
--- /dev/null
+++ b/ruoyi-ui/src/views/evaluation/index.vue
@@ -0,0 +1,659 @@
+<template>
+  <div class="evaluation-container">
+    <!-- 椤甸潰澶撮儴 -->
+    <div class="evaluation-header">
+      <h1>鏈嶅姟璇勪环</h1>
+      <p>鎰熻阿鎮ㄤ娇鐢ㄦ垜浠殑鏈嶅姟锛岃瀵规湰娆℃湇鍔¤繘琛岃瘎浠�</p>
+    </div>
+
+    <!-- 杞﹁締淇℃伅 -->
+    <div class="vehicle-info" v-if="vehicleNo">
+      <div class="info-item">
+        <span class="label">杞︾墝鍙凤細</span>
+        <span class="value">{{ vehicleNo }}</span>
+      </div>
+    </div>
+
+    <!-- 璇勪环琛ㄥ崟 -->
+    <div class="evaluation-form">
+      <el-form ref="evaluationForm" :model="evaluationForm" :rules="rules" label-width="80px" size="small">
+        <!-- 瀹㈡埛淇℃伅 -->
+        <div class="form-section">
+          <h3>瀹㈡埛淇℃伅</h3>
+          <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="璇疯緭鍏ユ偍鐨勬墜鏈哄彿" />
+          </el-form-item>
+        </div>
+
+        <!-- 璇勪环缁村害 -->
+        <div class="form-section">
+          <h3>鏈嶅姟璇勪环</h3>
+          <div v-for="dimension in dimensions" :key="dimension.dimensionId" class="dimension-item">
+            <!-- 鏄熺骇璇勪环 - 鏍囬鍜岃瘎鍒嗗湪鍚屼竴琛� -->
+            <div v-if="dimension.dimensionType === 'star'" class="star-rating-inline">
+              <div class="dimension-title-inline">
+                <span>{{ 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"
+                />
+              </div>
+            </div>
+            
+            <!-- 閫夋嫨璇勪环 -->
+            <div v-else-if="dimension.dimensionType === 'select'">
+              <div class="dimension-title">
+                <span>{{ dimension.dimensionName }}</span>
+                <span v-if="dimension.isRequired === '1'" class="required">*</span>
+              </div>
+              <div class="dimension-desc" v-if="dimension.dimensionDesc">
+                {{ 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">
+                    {{ option.label }}
+                  </el-radio>
+                </el-radio-group>
+              </div>
+            </div>
+            
+            <!-- 鏂囨湰璇勪环 -->
+            <div v-else-if="dimension.dimensionType === 'text'">
+              <div class="dimension-title">
+                <span>{{ dimension.dimensionName }}</span>
+                <span v-if="dimension.isRequired === '1'" class="required">*</span>
+              </div>
+              <div class="dimension-desc" v-if="dimension.dimensionDesc">
+                {{ dimension.dimensionDesc }}
+              </div>
+              <div class="text-rating">
+                <el-input
+                  :value="getDimensionText(dimension.dimensionId)"
+                  type="textarea"
+                  :rows="2"
+                  placeholder="璇疯緭鍏ユ偍鐨勬剰瑙佹垨寤鸿"
+                  @input="updateDimensionText(dimension.dimensionId, $event)"
+                  size="small"
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <!-- 鎻愪氦鎸夐挳 -->
+        <div class="form-actions">
+          <el-button type="primary" size="large" @click="submitEvaluation" :loading="submitting">
+            鎻愪氦璇勪环
+          </el-button>
+        </div>
+      </el-form>
+    </div>
+
+    <!-- 缁撴灉椤甸潰 -->
+    <div v-if="showResult" class="result-page">
+      <div class="result-content">
+        <div class="result-icon">
+          <i class="el-icon-success" style="font-size: 60px; color: #67C23A;"></i>
+        </div>
+        <div class="result-message">
+          {{ resultMessage }}
+        </div>
+        <div class="result-actions">
+          <el-button type="primary" @click="resetForm">鍐嶆璇勪环</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getEvaluationDimensions, submitEvaluation, getWechatUserInfo } from "@/api/evaluation";
+
+export default {
+  name: "Evaluation",
+  data() {
+    return {
+      vehicleNo: '',
+      dimensions: [],
+      evaluationForm: {
+        vehicleNo: '',
+        customerName: '',
+        customerPhone: '',
+        wechatOpenid: '',
+        wechatNickname: '',
+        wechatAvatar: '',
+        wechatPhone: '',
+        evaluationDetails: []
+      },
+      rules: {
+        customerName: [
+          { required: true, message: '璇疯緭鍏ユ偍鐨勫鍚�', trigger: 'blur' }
+        ],
+        customerPhone: [
+          { required: true, message: '璇疯緭鍏ユ偍鐨勬墜鏈哄彿', trigger: 'blur' },
+          { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ纭殑鎵嬫満鍙�', trigger: 'blur' }
+        ]
+      },
+      submitting: false,
+      showResult: false,
+      resultMessage: ''
+    };
+  },
+  created() {
+    this.initPage();
+  },
+  methods: {
+    // 鍒濆鍖栭〉闈�
+    async initPage() {
+      // 鑾峰彇URL鍙傛暟
+      this.vehicleNo = this.$route.query.vehicle || '';
+      this.evaluationForm.vehicleNo = this.vehicleNo;
+
+      // 妫�鏌ユ槸鍚﹀湪寰俊鐜涓�
+      if (this.isWechatBrowser()) {
+        await this.handleWechatAuth();
+      }
+
+      // 鍔犺浇璇勪环缁村害
+      await this.loadDimensions();
+    },
+
+    // 鍒ゆ柇鏄惁涓哄井淇℃祻瑙堝櫒
+    isWechatBrowser() {
+      const ua = navigator.userAgent.toLowerCase();
+      return ua.indexOf('micromessenger') !== -1;
+    },
+
+    // 澶勭悊寰俊鎺堟潈
+    async handleWechatAuth() {
+      const code = this.$route.query.code;
+      if (code) {
+        try {
+          const response = await getWechatUserInfo(code);
+          if (response.code === 200) {
+            const userInfo = response.data;
+            this.evaluationForm.wechatOpenid = userInfo.openid;
+            this.evaluationForm.wechatNickname = userInfo.nickname;
+            this.evaluationForm.wechatAvatar = userInfo.headimgurl;
+            this.evaluationForm.wechatPhone = userInfo.phone || '';
+          }
+        } catch (error) {
+          console.error('鑾峰彇寰俊鐢ㄦ埛淇℃伅澶辫触:', error);
+        }
+      }
+    },
+
+    // 鍔犺浇璇勪环缁村害
+    async loadDimensions() {
+      try {
+        const response = await getEvaluationDimensions();
+        if (response.code === 200) {
+          this.dimensions = response.data;
+        }
+      } catch (error) {
+        console.error('鍔犺浇璇勪环缁村害澶辫触:', error);
+        this.$message.error('鍔犺浇璇勪环缁村害澶辫触');
+      }
+    },
+
+    // 鑾峰彇缁村害璇勫垎
+    getDimensionScore(dimensionId) {
+      const detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      return detail ? detail.score : 0;
+    },
+
+    // 鏇存柊缁村害璇勫垎
+    updateDimensionScore(dimensionId, score) {
+      let detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      if (!detail) {
+        detail = { dimensionId, score: 0 };
+        this.evaluationForm.evaluationDetails.push(detail);
+      }
+      detail.score = score;
+    },
+
+    // 鑾峰彇缁村害閫夐」
+    getDimensionOption(dimensionId) {
+      const detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      return detail ? detail.optionValue : '';
+    },
+
+    // 鏇存柊缁村害閫夐」
+    updateDimensionOption(dimensionId, optionValue) {
+      let detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      if (!detail) {
+        detail = { dimensionId, optionValue: '' };
+        this.evaluationForm.evaluationDetails.push(detail);
+      }
+      detail.optionValue = optionValue;
+    },
+
+    // 鑾峰彇缁村害鏂囨湰
+    getDimensionText(dimensionId) {
+      const detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      return detail ? detail.textContent : '';
+    },
+
+    // 鏇存柊缁村害鏂囨湰
+    updateDimensionText(dimensionId, textContent) {
+      let detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimensionId);
+      if (!detail) {
+        detail = { dimensionId, textContent: '' };
+        this.evaluationForm.evaluationDetails.push(detail);
+      }
+      detail.textContent = textContent;
+    },
+
+    // 鑾峰彇缁村害閫夐」閰嶇疆
+    getDimensionOptions(dimension) {
+      if (!dimension.options) return [];
+      try {
+        return JSON.parse(dimension.options);
+      } catch (error) {
+        return [];
+      }
+    },
+
+    // 鎻愪氦璇勪环
+    async submitEvaluation() {
+      try {
+        // 琛ㄥ崟楠岃瘉
+        await this.$refs.evaluationForm.validate();
+
+        // 妫�鏌ュ繀濉殑璇勪环缁村害
+        for (const dimension of this.dimensions) {
+          if (dimension.isRequired === '1') {
+            const detail = this.evaluationForm.evaluationDetails.find(d => d.dimensionId === dimension.dimensionId);
+            if (!detail || (dimension.dimensionType === 'star' && !detail.score) || 
+                (dimension.dimensionType === 'select' && !detail.optionValue) ||
+                (dimension.dimensionType === 'text' && !detail.textContent)) {
+              this.$message.error(`璇峰畬鎴�${dimension.dimensionName}鐨勮瘎浠穈);
+              return;
+            }
+          }
+        }
+
+        this.submitting = true;
+
+        // 鎻愪氦璇勪环
+        const response = await submitEvaluation(this.evaluationForm);
+        if (response.code === 200) {
+          this.resultMessage = response.msg;
+          this.showResult = true;
+        } else {
+          this.$message.error(response.msg || '鎻愪氦澶辫触锛岃閲嶈瘯');
+        }
+      } catch (error) {
+        console.error('鎻愪氦璇勪环澶辫触:', error);
+        this.$message.error('鎻愪氦澶辫触锛岃閲嶈瘯');
+      } finally {
+        this.submitting = false;
+      }
+    },
+
+    // 閲嶇疆琛ㄥ崟
+    resetForm() {
+      this.showResult = false;
+      this.evaluationForm.customerName = '';
+      this.evaluationForm.customerPhone = '';
+      this.evaluationForm.evaluationDetails = [];
+      this.$refs.evaluationForm.resetFields();
+    }
+  }
+};
+</script>
+
+<style scoped>
+.evaluation-container {
+  max-width: 600px;
+  margin: 0 auto;
+  padding: 8px;
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
+
+.evaluation-header {
+  text-align: center;
+  margin-bottom: 12px;
+  padding: 12px;
+  background: white;
+  border-radius: 6px;
+  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+}
+
+.evaluation-header h1 {
+  color: #333;
+  margin: 0 0 6px 0;
+  font-size: 20px;
+}
+
+.evaluation-header p {
+  color: #666;
+  margin: 0;
+  font-size: 14px;
+}
+
+.vehicle-info {
+  background: white;
+  padding: 8px 12px;
+  border-radius: 6px;
+  margin-bottom: 12px;
+  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+}
+
+.info-item {
+  display: flex;
+  align-items: center;
+}
+
+.label {
+  font-weight: bold;
+  color: #333;
+  margin-right: 8px;
+  font-size: 14px;
+}
+
+.value {
+  color: #666;
+  font-size: 14px;
+}
+
+.evaluation-form {
+  background: white;
+  padding: 12px;
+  border-radius: 6px;
+  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+}
+
+.form-section {
+  margin-bottom: 16px;
+}
+
+.form-section h3 {
+  color: #333;
+  margin: 0 0 12px 0;
+  padding-bottom: 6px;
+  border-bottom: 1px solid #409EFF;
+  font-size: 16px;
+}
+
+.dimension-item {
+  margin-bottom: 12px;
+  padding: 8px;
+  border: 1px solid #e4e7ed;
+  border-radius: 4px;
+  background-color: #fafafa;
+}
+
+.dimension-title {
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 4px;
+  font-size: 14px;
+}
+
+.required {
+  color: #f56c6c;
+  margin-left: 3px;
+}
+
+.dimension-desc {
+  color: #666;
+  font-size: 12px;
+  margin-bottom: 8px;
+}
+
+/* 鏄熺骇璇勪环鍐呰仈甯冨眬 */
+.star-rating-inline {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+
+.dimension-title-inline {
+  font-weight: bold;
+  color: #333;
+  font-size: 14px;
+  flex-shrink: 0;
+}
+
+.star-rating-content {
+  flex: 1;
+  min-width: 200px;
+}
+
+.star-rating, .select-rating, .text-rating {
+  margin-top: 6px;
+}
+
+/* 浼樺寲鏄熺骇璇勫垎鏄剧ず */
+.star-rating .el-rate {
+  font-size: 18px;
+}
+
+.star-rating .el-rate__text {
+  font-size: 12px;
+  margin-left: 8px;
+}
+
+/* 浼樺寲閫夋嫨璇勪环鏄剧ず */
+.select-rating .el-radio {
+  margin-right: 12px;
+  margin-bottom: 4px;
+}
+
+.select-rating .el-radio__label {
+  font-size: 13px;
+}
+
+/* 浼樺寲鏂囨湰璇勪环鏄剧ず */
+.text-rating .el-textarea__inner {
+  font-size: 13px;
+  min-height: 60px !important;
+}
+
+/* 浼樺寲琛ㄥ崟椤归棿璺� */
+.el-form-item {
+  margin-bottom: 12px;
+}
+
+.el-form-item__label {
+  font-size: 13px;
+  line-height: 28px;
+}
+
+.el-input__inner {
+  font-size: 13px;
+  height: 32px;
+  line-height: 32px;
+}
+
+.form-actions {
+  text-align: center;
+  margin-top: 16px;
+}
+
+.form-actions .el-button {
+  padding: 10px 30px;
+  font-size: 14px;
+}
+
+.result-page {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0,0,0,0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1000;
+}
+
+.result-content {
+  background: white;
+  padding: 30px;
+  border-radius: 8px;
+  text-align: center;
+  max-width: 350px;
+  width: 90%;
+}
+
+.result-icon {
+  margin-bottom: 16px;
+}
+
+.result-message {
+  font-size: 16px;
+  color: #333;
+  margin-bottom: 20px;
+}
+
+.result-actions {
+  text-align: center;
+}
+
+/* 绉诲姩绔�傞厤 */
+@media (max-width: 768px) {
+  .evaluation-container {
+    padding: 6px;
+  }
+  
+  .evaluation-header {
+    padding: 10px;
+    margin-bottom: 8px;
+  }
+  
+  .evaluation-header h1 {
+    font-size: 18px;
+  }
+  
+  .evaluation-header p {
+    font-size: 13px;
+  }
+  
+  .evaluation-form {
+    padding: 10px;
+  }
+  
+  .dimension-item {
+    padding: 6px;
+    margin-bottom: 8px;
+  }
+  
+  .form-section {
+    margin-bottom: 12px;
+  }
+  
+  .form-section h3 {
+    font-size: 15px;
+    margin-bottom: 8px;
+  }
+  
+  .dimension-title {
+    font-size: 13px;
+  }
+  
+  .dimension-desc {
+    font-size: 11px;
+  }
+  
+  .star-rating .el-rate {
+    font-size: 16px;
+  }
+  
+  /* 绉诲姩绔槦绾ц瘎浠峰唴鑱斿竷灞� */
+  .star-rating-inline {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 6px;
+  }
+  
+  .dimension-title-inline {
+    font-size: 13px;
+  }
+  
+  .star-rating-content {
+    min-width: auto;
+    width: 100%;
+  }
+  
+  .select-rating .el-radio {
+    margin-right: 8px;
+  }
+  
+  .select-rating .el-radio__label {
+    font-size: 12px;
+  }
+  
+  .text-rating .el-textarea__inner {
+    font-size: 12px;
+    min-height: 50px !important;
+  }
+  
+  .el-form-item {
+    margin-bottom: 8px;
+  }
+  
+  .el-form-item__label {
+    font-size: 12px;
+    line-height: 26px;
+  }
+  
+  .el-input__inner {
+    font-size: 12px;
+    height: 30px;
+    line-height: 30px;
+  }
+  
+  .form-actions {
+    margin-top: 12px;
+  }
+  
+  .form-actions .el-button {
+    padding: 8px 24px;
+    font-size: 13px;
+  }
+}
+
+/* 瓒呭皬灞忓箷閫傞厤 */
+@media (max-width: 480px) {
+  .evaluation-container {
+    padding: 4px;
+  }
+  
+  .evaluation-header {
+    padding: 8px;
+  }
+  
+  .evaluation-form {
+    padding: 8px;
+  }
+  
+  .dimension-item {
+    padding: 4px;
+  }
+  
+  .star-rating .el-rate {
+    font-size: 14px;
+  }
+  
+  .text-rating .el-textarea__inner {
+    min-height: 40px !important;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/evaluation/qrcode/index.vue b/ruoyi-ui/src/views/evaluation/qrcode/index.vue
new file mode 100644
index 0000000..be23c18
--- /dev/null
+++ b/ruoyi-ui/src/views/evaluation/qrcode/index.vue
@@ -0,0 +1,345 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
+        <el-input
+          v-model="queryParams.vehicleNo"
+          placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="鐘舵��" prop="status">
+        <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable>
+          <el-option label="姝e父" value="0" />
+          <el-option label="鍋滅敤" value="1" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['evaluation:qrcode:generate']"
+        >鐢熸垚浜岀淮鐮�</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-upload2"
+          size="mini"
+          @click="handleBatchGenerate"
+          v-hasPermi="['evaluation:qrcode:batch']"
+        >鎵归噺鐢熸垚</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['evaluation:qrcode:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <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">
+          <el-link :href="scope.row.qrcodeUrl" target="_blank" type="primary">{{ scope.row.qrcodeUrl }}</el-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="浜岀淮鐮佸唴瀹�" align="center" prop="qrcodeContent" />
+      <el-table-column label="浜岀淮鐮佸浘鐗�" align="center" prop="qrcodeImage" width="100">
+        <template slot-scope="scope">
+          <el-image
+            v-if="scope.row.qrcodeImage"
+            :src="getImageUrl(scope.row.qrcodeImage)"
+            :preview-src-list="[getImageUrl(scope.row.qrcodeImage)]"
+            style="width: 50px; height: 50px;"
+            fit="cover">
+          </el-image>
+        </template>
+      </el-table-column>
+      <el-table-column label="鐘舵��" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleView(scope.row)"
+            v-hasPermi="['evaluation:qrcode:query']"
+          >鏌ョ湅</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-download"
+            @click="handleDownload(scope.row)"
+          >涓嬭浇</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['evaluation:qrcode:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 鐢熸垚浜岀淮鐮佸璇濇 -->
+    <el-dialog title="鐢熸垚浜岀淮鐮�" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
+          <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-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</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>
+        </el-descriptions-item>
+        <el-descriptions-item label="浜岀淮鐮佸唴瀹�" :span="2">{{ viewForm.qrcodeContent }}</el-descriptions-item>
+        <el-descriptions-item label="鐘舵��">
+          <dict-tag :options="dict.type.sys_normal_disable" :value="viewForm.status"/>
+        </el-descriptions-item>
+        <el-descriptions-item label="鍒涘缓鏃堕棿">{{ parseTime(viewForm.createTime) }}</el-descriptions-item>
+        <el-descriptions-item label="浜岀淮鐮佸浘鐗�" :span="2">
+          <el-image
+            v-if="viewForm.qrcodeImage"
+            :src="getImageUrl(viewForm.qrcodeImage)"
+            style="width: 200px; height: 200px;"
+            fit="cover">
+          </el-image>
+        </el-descriptions-item>
+      </el-descriptions>
+      
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="viewOpen = false">鍏� 闂�</el-button>
+        <el-button type="primary" @click="handleDownload(viewForm)">涓嬭浇浜岀淮鐮�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listQrcode, getQrcode, delQrcode, generateQrcode, batchGenerateQrcode } from "@/api/evaluation";
+
+export default {
+  name: "VehicleEvaluationQrcode",
+  dicts: ['sys_normal_disable'],
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 杞﹁締璇勪环浜岀淮鐮佽〃鏍兼暟鎹�
+      qrcodeList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏄惁鏄剧ず鏌ョ湅寮瑰嚭灞�
+      viewOpen: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        vehicleNo: null,
+        status: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 鏌ョ湅琛ㄥ崟鍙傛暟
+      viewForm: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        vehicleNo: [
+          { required: true, message: "杞︾墝鍙蜂笉鑳戒负绌�", trigger: "blur" }
+        ],
+        qrcodeUrl: [
+          { required: true, message: "浜岀淮鐮乁RL涓嶈兘涓虹┖", trigger: "blur" },
+          { type: 'url', message: '璇疯緭鍏ユ纭殑URL鏍煎紡', trigger: 'blur' }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ杞﹁締璇勪环浜岀淮鐮佸垪琛� */
+    getList() {
+      this.loading = true;
+      listQrcode(this.queryParams).then(response => {
+        this.qrcodeList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        qrcodeId: null,
+        vehicleNo: null,
+        qrcodeUrl: null,
+        qrcodeContent: null,
+        qrcodeImage: null,
+        status: "0"
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.qrcodeId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "鐢熸垚浜岀淮鐮�";
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          const params = {
+            vehicleNo: this.form.vehicleNo,
+            qrcodeUrl: this.form.qrcodeUrl
+          };
+          generateQrcode(params).then(response => {
+            this.$modal.msgSuccess("鐢熸垚鎴愬姛");
+            this.open = false;
+            this.getList();
+          });
+        }
+      });
+    },
+    /** 鎵归噺鐢熸垚鎸夐挳鎿嶄綔 */
+    handleBatchGenerate() {
+      this.$modal.confirm('鏄惁纭鎵归噺鐢熸垚鎵�鏈夎溅杈嗙殑浜岀淮鐮侊紵').then(function() {
+        return batchGenerateQrcode();
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鎵归噺鐢熸垚鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 鏌ョ湅鎸夐挳鎿嶄綔 */
+    handleView(row) {
+      this.viewForm = row;
+      this.viewOpen = true;
+    },
+    /** 涓嬭浇鎸夐挳鎿嶄綔 */
+    handleDownload(row) {
+      if (row.qrcodeImage) {
+        const link = document.createElement('a');
+        link.href = this.getImageUrl(row.qrcodeImage);
+        link.download = `qrcode_${row.vehicleNo}.png`;
+        link.click();
+      }
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const qrcodeIds = row.qrcodeId || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎杞﹁締璇勪环浜岀淮鐮佺紪鍙蜂负"' + qrcodeIds + '"鐨勬暟鎹」锛�').then(function() {
+        return delQrcode(qrcodeIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).catch(() => {});
+    },
+    /** 鑾峰彇鍥剧墖URL */
+    getImageUrl(imagePath) {
+      if (imagePath) {
+        // 濡傛灉鏄痓ase64鏍煎紡锛岀洿鎺ヨ繑鍥�
+        if (imagePath.startsWith('data:image/')) {
+          return imagePath;
+        }
+        // 濡傛灉璺緞宸茬粡鍖呭惈http锛岀洿鎺ヨ繑鍥�
+        if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
+          return imagePath;
+        }
+        // 濡傛灉璺緞浠�/寮�澶达紝鐩存帴鎷兼帴鍩熷悕
+        if (imagePath.startsWith('/')) {
+          return process.env.VUE_APP_BASE_API + imagePath;
+        }
+        // 鍏朵粬鎯呭喌锛屾坊鍔�/鍓嶇紑鍚庢嫾鎺ュ煙鍚�
+        return process.env.VUE_APP_BASE_API + '/' + imagePath;
+      }
+      return '';
+    }
+  }
+};
+</script>
diff --git a/ruoyi-ui/src/views/evaluation/statistics/index.vue b/ruoyi-ui/src/views/evaluation/statistics/index.vue
new file mode 100644
index 0000000..68b46d4
--- /dev/null
+++ b/ruoyi-ui/src/views/evaluation/statistics/index.vue
@@ -0,0 +1,512 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
+        <el-input
+          v-model="queryParams.vehicleNo"
+          placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="璇勪环鏃堕棿" prop="evaluationTime">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="32">
+      <el-col :xs="24" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-people">
+            <svg-icon icon-class="peoples" class-name="card-panel-icon" />
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">鎬昏瘎浠锋暟</div>
+            <div class="card-panel-num">{{ statisticsData.totalEvaluations }}</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :xs="24" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-message">
+            <svg-icon icon-class="message" class-name="card-panel-icon" />
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">骞冲潎璇勫垎</div>
+            <div class="card-panel-num">{{ statisticsData.averageScore }}</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :xs="24" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-star">
+            <svg-icon icon-class="star" class-name="card-panel-icon" />
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">濂借瘎鐜�</div>
+            <div class="card-panel-num">{{ statisticsData.goodRate }}%</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :xs="24" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-vehicle">
+            <svg-icon icon-class="car" class-name="card-panel-icon" />
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">鍙備笌杞﹁締</div>
+            <div class="card-panel-num">{{ statisticsData.vehicleCount }}</div>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+
+    <el-row :gutter="32" style="margin-top: 20px;">
+      <el-col :xs="24" :sm="24" :lg="12">
+        <div class="chart-container">
+          <div class="chart-title">璇勫垎鍒嗗竷</div>
+          <div ref="scoreChart" class="chart"></div>
+        </div>
+      </el-col>
+      <el-col :xs="24" :sm="24" :lg="12">
+        <div class="chart-container">
+          <div class="chart-title">鏈堝害璇勪环瓒嬪娍</div>
+          <div ref="trendChart" class="chart"></div>
+        </div>
+      </el-col>
+    </el-row>
+
+    <el-row style="margin-top: 20px;">
+      <el-col :span="24">
+        <div class="chart-container">
+          <div class="chart-title">鍚勭淮搴﹁瘎鍒嗙粺璁�</div>
+          <div ref="dimensionChart" class="chart"></div>
+        </div>
+      </el-col>
+    </el-row>
+
+    <el-table v-loading="loading" :data="evaluationList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="璇勪环ID" align="center" prop="evaluationId" />
+      <el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" />
+      <el-table-column label="瀹㈡埛濮撳悕" align="center" prop="customerName" />
+      <el-table-column label="瀹㈡埛鎵嬫満" align="center" prop="customerPhone" />
+      <el-table-column label="缁煎悎璇勫垎" align="center" prop="overallScore">
+        <template slot-scope="scope">
+          <el-rate
+            v-model="scope.row.overallScore"
+            disabled
+            show-score
+            text-color="#ff9900"
+            score-template="{value}"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="璇勪环鏃堕棿" align="center" prop="evaluationTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.evaluationTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleView(scope.row)"
+          >鏌ョ湅璇︽儏</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 璇勪环璇︽儏瀵硅瘽妗� -->
+    <el-dialog title="璇勪环璇︽儏" :visible.sync="detailOpen" width="600px" append-to-body>
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="璇勪环ID">{{ detailForm.evaluationId }}</el-descriptions-item>
+        <el-descriptions-item label="杞︾墝鍙�">{{ detailForm.vehicleNo }}</el-descriptions-item>
+        <el-descriptions-item label="瀹㈡埛濮撳悕">{{ detailForm.customerName }}</el-descriptions-item>
+        <el-descriptions-item label="瀹㈡埛鎵嬫満">{{ detailForm.customerPhone }}</el-descriptions-item>
+        <el-descriptions-item label="寰俊鏄电О">{{ detailForm.wechatNickname }}</el-descriptions-item>
+        <el-descriptions-item label="缁煎悎璇勫垎">
+          <el-rate
+            v-model="detailForm.overallScore"
+            disabled
+            show-score
+            text-color="#ff9900"
+            score-template="{value}"
+          />
+        </el-descriptions-item>
+        <el-descriptions-item label="璇勪环鏃堕棿" :span="2">
+          {{ parseTime(detailForm.evaluationTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
+        </el-descriptions-item>
+      </el-descriptions>
+      
+      <div style="margin-top: 20px;">
+        <h4>璇︾粏璇勪环</h4>
+        <el-table :data="detailForm.evaluationDetails" border>
+          <el-table-column label="璇勪环缁村害" prop="dimensionName" />
+          <el-table-column label="璇勫垎" align="center">
+            <template slot-scope="scope">
+              <el-rate
+                v-if="scope.row.dimensionType === 'star'"
+                v-model="scope.row.score"
+                disabled
+                show-score
+                text-color="#ff9900"
+                score-template="{value}"
+              />
+              <span v-else>{{ scope.row.optionValue || scope.row.textContent }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listCustomerEvaluation, getCustomerEvaluation } from "@/api/evaluation";
+import * as echarts from 'echarts';
+
+export default {
+  name: "EvaluationStatistics",
+  data() {
+    return {
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 瀹㈡埛璇勪环琛ㄦ牸鏁版嵁
+      evaluationList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      detailOpen: false,
+      // 鏃ユ湡鑼冨洿
+      dateRange: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        vehicleNo: null,
+        evaluationTime: null
+      },
+      // 琛ㄥ崟鍙傛暟
+      detailForm: {},
+      // 缁熻鏁版嵁
+      statisticsData: {
+        totalEvaluations: 0,
+        averageScore: 0,
+        goodRate: 0,
+        vehicleCount: 0
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.getStatistics();
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initCharts();
+    });
+  },
+  methods: {
+    /** 鏌ヨ瀹㈡埛璇勪环鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listCustomerEvaluation(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.evaluationList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 鑾峰彇缁熻鏁版嵁 */
+    getStatistics() {
+      // 杩欓噷搴旇璋冪敤缁熻鎺ュ彛锛屾殏鏃朵娇鐢ㄦā鎷熸暟鎹�
+      this.statisticsData = {
+        totalEvaluations: 156,
+        averageScore: 4.2,
+        goodRate: 85.6,
+        vehicleCount: 23
+      };
+    },
+    /** 鍒濆鍖栧浘琛� */
+    initCharts() {
+      this.initScoreChart();
+      this.initTrendChart();
+      this.initDimensionChart();
+    },
+    /** 鍒濆鍖栬瘎鍒嗗垎甯冨浘琛� */
+    initScoreChart() {
+      const chart = echarts.init(this.$refs.scoreChart);
+      const option = {
+        title: {
+          text: '璇勫垎鍒嗗竷',
+          left: 'center'
+        },
+        tooltip: {
+          trigger: 'item'
+        },
+        series: [
+          {
+            name: '璇勫垎鍒嗗竷',
+            type: 'pie',
+            radius: '50%',
+            data: [
+              { value: 35, name: '5鏄�' },
+              { value: 28, name: '4鏄�' },
+              { value: 20, name: '3鏄�' },
+              { value: 12, name: '2鏄�' },
+              { value: 5, name: '1鏄�' }
+            ],
+            emphasis: {
+              itemStyle: {
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: 'rgba(0, 0, 0, 0.5)'
+              }
+            }
+          }
+        ]
+      };
+      chart.setOption(option);
+    },
+    /** 鍒濆鍖栬秼鍔垮浘琛� */
+    initTrendChart() {
+      const chart = echarts.init(this.$refs.trendChart);
+      const option = {
+        title: {
+          text: '鏈堝害璇勪环瓒嬪娍',
+          left: 'center'
+        },
+        tooltip: {
+          trigger: 'axis'
+        },
+        xAxis: {
+          type: 'category',
+          data: ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�']
+        },
+        yAxis: {
+          type: 'value'
+        },
+        series: [
+          {
+            name: '璇勪环鏁伴噺',
+            type: 'line',
+            data: [12, 19, 23, 18, 25, 28],
+            smooth: true
+          }
+        ]
+      };
+      chart.setOption(option);
+    },
+    /** 鍒濆鍖栫淮搴︾粺璁″浘琛� */
+    initDimensionChart() {
+      const chart = echarts.init(this.$refs.dimensionChart);
+      const option = {
+        title: {
+          text: '鍚勭淮搴﹁瘎鍒嗙粺璁�',
+          left: 'center'
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow'
+          }
+        },
+        xAxis: {
+          type: 'category',
+          data: ['鏈嶅姟鎬佸害', '鏀惰垂鎯呭喌', '杞﹁締鍗敓', '椹鹃┒鎶�鏈�', '鏁翠綋鏈嶅姟']
+        },
+        yAxis: {
+          type: 'value',
+          max: 5
+        },
+        series: [
+          {
+            name: '骞冲潎璇勫垎',
+            type: 'bar',
+            data: [4.5, 4.2, 4.3, 4.4, 4.1],
+            itemStyle: {
+              color: '#409EFF'
+            }
+          }
+        ]
+      };
+      chart.setOption(option);
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.detailOpen = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.detailForm = {
+        evaluationId: null,
+        vehicleNo: null,
+        customerName: null,
+        customerPhone: null,
+        wechatOpenid: null,
+        wechatNickname: null,
+        wechatAvatar: null,
+        wechatPhone: null,
+        overallScore: null,
+        evaluationTime: null,
+        evaluationDetails: []
+      };
+      this.resetForm("detailForm");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.evaluationId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏌ョ湅璇︽儏鎸夐挳鎿嶄綔 */
+    handleView(row) {
+      this.reset();
+      const evaluationId = row.evaluationId || this.ids
+      getCustomerEvaluation(evaluationId).then(response => {
+        this.detailForm = response.data;
+        this.detailOpen = true;
+        this.title = "璇勪环璇︽儏";
+      });
+    }
+  }
+};
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.card-panel-col {
+  margin-bottom: 20px;
+}
+
+.card-panel {
+  height: 108px;
+  cursor: pointer;
+  font-size: 12px;
+  position: relative;
+  overflow: hidden;
+  color: #666;
+  background: #fff;
+  box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
+  border-color: rgba(0, 0, 0, .05);
+}
+
+.card-panel:hover {
+  box-shadow: 4px 4px 40px rgba(0, 0, 0, .1);
+}
+
+.card-panel-icon-wrapper {
+  float: left;
+  margin: 14px 0 0 14px;
+  padding: 16px;
+  transition: all 0.38s ease-out;
+  border-radius: 6px;
+}
+
+.card-panel-icon {
+  float: left;
+  font-size: 48px;
+}
+
+.card-panel-description {
+  float: right;
+  font-weight: bold;
+  margin: 26px;
+  margin-left: 0px;
+}
+
+.card-panel-text {
+  line-height: 18px;
+  color: rgba(0, 0, 0, 0.45);
+  font-size: 16px;
+  margin-bottom: 12px;
+}
+
+.card-panel-num {
+  font-size: 20px;
+  color: #666;
+}
+
+.icon-people {
+  color: #40c9c6;
+}
+
+.icon-message {
+  color: #36a3f7;
+}
+
+.icon-star {
+  color: #f4516c;
+}
+
+.icon-vehicle {
+  color: #34bfa3;
+}
+
+.chart-container {
+  background: #fff;
+  padding: 20px;
+  border-radius: 4px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  margin-bottom: 20px;
+}
+
+.chart-title {
+  font-size: 16px;
+  font-weight: bold;
+  margin-bottom: 15px;
+  text-align: center;
+}
+
+.chart {
+  height: 300px;
+  width: 100%;
+}
+</style>
diff --git a/ruoyi-ui/src/views/evaluation/test.vue b/ruoyi-ui/src/views/evaluation/test.vue
new file mode 100644
index 0000000..1979444
--- /dev/null
+++ b/ruoyi-ui/src/views/evaluation/test.vue
@@ -0,0 +1,187 @@
+<template>
+  <div class="test-container">
+    <h2>瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳芥祴璇�</h2>
+    
+    <div class="test-section">
+      <h3>1. 鐢熸垚浜岀淮鐮佹祴璇�</h3>
+      <el-form :inline="true">
+        <el-form-item label="杞︾墝鍙�">
+          <el-input v-model="testVehicleNo" placeholder="璇疯緭鍏ヨ溅鐗屽彿" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="generateQrcode">鐢熸垚浜岀淮鐮�</el-button>
+        </el-form-item>
+      </el-form>
+      
+      <div v-if="qrcodeInfo" class="qrcode-result">
+        <p><strong>浜岀淮鐮乁RL:</strong> {{ qrcodeInfo.qrcodeUrl }}</p>
+        <p><strong>浜岀淮鐮佸唴瀹�:</strong> {{ qrcodeInfo.qrcodeContent }}</p>
+        <p><strong>浜岀淮鐮佸浘鐗�:</strong> {{ qrcodeInfo.qrcodeImage }}</p>
+      </div>
+    </div>
+
+    <div class="test-section">
+      <h3>2. 璇勪环缁村害閰嶇疆娴嬭瘯</h3>
+      <el-button type="primary" @click="loadDimensions">鍔犺浇璇勪环缁村害</el-button>
+      
+      <div v-if="dimensions.length > 0" class="dimensions-result">
+        <h4>璇勪环缁村害鍒楄〃:</h4>
+        <ul>
+          <li v-for="dimension in dimensions" :key="dimension.dimensionId">
+            {{ dimension.dimensionName }} - {{ dimension.dimensionType }} 
+            <span v-if="dimension.isRequired === '1'">(蹇呭~)</span>
+          </li>
+        </ul>
+      </div>
+    </div>
+
+    <div class="test-section">
+      <h3>3. 璇勪环鎻愪氦娴嬭瘯</h3>
+      <el-form :model="testEvaluation" label-width="100px">
+        <el-form-item label="杞︾墝鍙�">
+          <el-input v-model="testEvaluation.vehicleNo" />
+        </el-form-item>
+        <el-form-item label="瀹㈡埛濮撳悕">
+          <el-input v-model="testEvaluation.customerName" />
+        </el-form-item>
+        <el-form-item label="瀹㈡埛鎵嬫満">
+          <el-input v-model="testEvaluation.customerPhone" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="submitTestEvaluation">鎻愪氦娴嬭瘯璇勪环</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="test-section">
+      <h3>4. 鐩存帴璁块棶璇勪环椤甸潰</h3>
+      <p>璁块棶鍦板潃: <a :href="evaluationUrl" target="_blank">{{ evaluationUrl }}</a></p>
+    </div>
+  </div>
+</template>
+
+<script>
+import { generateQrcode, getEvaluationDimensions, submitEvaluation } from "@/api/evaluation";
+
+export default {
+  name: "EvaluationTest",
+  data() {
+    return {
+      testVehicleNo: "绮12345",
+      qrcodeInfo: null,
+      dimensions: [],
+      testEvaluation: {
+        vehicleNo: "绮12345",
+        customerName: "娴嬭瘯鐢ㄦ埛",
+        customerPhone: "13800138000",
+        evaluationDetails: [
+          {
+            dimensionId: 1,
+            score: 5
+          },
+          {
+            dimensionId: 2,
+            score: 4
+          },
+          {
+            dimensionId: 3,
+            score: 5
+          },
+          {
+            dimensionId: 4,
+            score: 4
+          }
+        ]
+      }
+    };
+  },
+  computed: {
+    evaluationUrl() {
+      return `${window.location.origin}/evaluation?vehicle=${this.testVehicleNo}`;
+    }
+  },
+  methods: {
+    async generateQrcode() {
+      try {
+        const response = await generateQrcode(this.testVehicleNo);
+        if (response.code === 200) {
+          this.qrcodeInfo = response.data;
+          this.$message.success("浜岀淮鐮佺敓鎴愭垚鍔�");
+        } else {
+          this.$message.error(response.msg || "鐢熸垚澶辫触");
+        }
+      } catch (error) {
+        console.error("鐢熸垚浜岀淮鐮佸け璐�:", error);
+        this.$message.error("鐢熸垚浜岀淮鐮佸け璐�");
+      }
+    },
+
+    async loadDimensions() {
+      try {
+        const response = await getEvaluationDimensions();
+        if (response.code === 200) {
+          this.dimensions = response.data;
+          this.$message.success("璇勪环缁村害鍔犺浇鎴愬姛");
+        } else {
+          this.$message.error(response.msg || "鍔犺浇澶辫触");
+        }
+      } catch (error) {
+        console.error("鍔犺浇璇勪环缁村害澶辫触:", error);
+        this.$message.error("鍔犺浇璇勪环缁村害澶辫触");
+      }
+    },
+
+    async submitTestEvaluation() {
+      try {
+        const response = await submitEvaluation(this.testEvaluation);
+        if (response.code === 200) {
+          this.$message.success(response.msg || "璇勪环鎻愪氦鎴愬姛");
+        } else {
+          this.$message.error(response.msg || "鎻愪氦澶辫触");
+        }
+      } catch (error) {
+        console.error("鎻愪氦璇勪环澶辫触:", error);
+        this.$message.error("鎻愪氦璇勪环澶辫触");
+      }
+    }
+  }
+};
+</script>
+
+<style scoped>
+.test-container {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 20px;
+}
+
+.test-section {
+  margin-bottom: 30px;
+  padding: 20px;
+  border: 1px solid #e4e7ed;
+  border-radius: 6px;
+  background-color: #fafafa;
+}
+
+.test-section h3 {
+  margin-top: 0;
+  color: #333;
+}
+
+.qrcode-result, .dimensions-result {
+  margin-top: 15px;
+  padding: 15px;
+  background-color: white;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+}
+
+.dimensions-result ul {
+  margin: 10px 0;
+  padding-left: 20px;
+}
+
+.dimensions-result li {
+  margin-bottom: 5px;
+}
+</style>
diff --git a/ruoyi-ui/src/views/system/vehicle/index.vue b/ruoyi-ui/src/views/system/vehicle/index.vue
index 4ec9201..6710c5d 100644
--- a/ruoyi-ui/src/views/system/vehicle/index.vue
+++ b/ruoyi-ui/src/views/system/vehicle/index.vue
@@ -39,6 +39,16 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+        <el-select v-model="queryParams.deptId" placeholder="璇烽�夋嫨閮ㄩ棬" clearable size="small">
+          <el-option
+            v-for="dept in deptOptions"
+            :key="dept.deptId"
+            :label="dept.deptName"
+            :value="dept.deptId"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
@@ -103,6 +113,7 @@
           <dict-tag :options="dict.type.sys_platform" :value="scope.row.platformCode"/>
         </template>
       </el-table-column>
+      <el-table-column label="褰掑睘閮ㄩ棬" align="center" prop="deptName" />
       <el-table-column label="鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
           <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
@@ -166,6 +177,16 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+          <el-select v-model="form.deptId" placeholder="璇烽�夋嫨閮ㄩ棬" clearable>
+            <el-option
+              v-for="dept in deptOptions"
+              :key="dept.deptId"
+              :label="dept.deptName"
+              :value="dept.deptId"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="鐘舵��" prop="status">
           <el-radio-group v-model="form.status">
             <el-radio
@@ -189,6 +210,7 @@
 
 <script>
 import { listVehicle, getVehicle, delVehicle, addVehicle, updateVehicle } from "@/api/system/vehicle";
+import { listDept } from "@/api/system/dept";
 
 export default {
   name: "Vehicle",
@@ -209,6 +231,8 @@
       total: 0,
       // 杞﹁締淇℃伅琛ㄦ牸鏁版嵁
       vehicleList: [],
+      // 閮ㄩ棬閫夐」
+      deptOptions: [],
       // 寮瑰嚭灞傛爣棰�
       title: "",
       // 鏄惁鏄剧ず寮瑰嚭灞�
@@ -222,7 +246,8 @@
         vehicleBrand: null,
         vehicleModel: null,
         status: null,
-        platformCode: null
+        platformCode: null,
+        deptId: null
       },
       // 琛ㄥ崟鍙傛暟
       form: {
@@ -233,7 +258,8 @@
         vehicleModel: null,
         status: "0",
         remark: null,
-        platformCode: null
+        platformCode: null,
+        deptId: null
       },
       // 琛ㄥ崟鏍¢獙
       rules: {
@@ -245,12 +271,16 @@
         ],
         platformCode: [
           { required: true, message: "骞冲彴鏍囪瘑涓嶈兘涓虹┖", trigger: "change" }
+        ],
+        deptId: [
+          { required: true, message: "褰掑睘閮ㄩ棬涓嶈兘涓虹┖", trigger: "change" }
         ]
       }
     };
   },
   created() {
     this.getList();
+    this.getDeptList();
   },
   methods: {
     /** 鏌ヨ杞﹁締淇℃伅鍒楄〃 */
@@ -260,6 +290,12 @@
         this.vehicleList = response.rows;
         this.total = response.total;
         this.loading = false;
+      });
+    },
+    /** 鏌ヨ閮ㄩ棬鍒楄〃 */
+    getDeptList() {
+      listDept().then(response => {
+        this.deptOptions = response.data;
       });
     },
     // 鍙栨秷鎸夐挳
@@ -277,7 +313,8 @@
         vehicleModel: null,
         status: "0",
         remark: null,
-        platformCode: null
+        platformCode: null,
+        deptId: null
       };
       this.resetForm("form");
     },
diff --git a/sql/customer_evaluation_tables.sql b/sql/customer_evaluation_tables.sql
new file mode 100644
index 0000000..cd83baf
--- /dev/null
+++ b/sql/customer_evaluation_tables.sql
@@ -0,0 +1,100 @@
+-- 瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳芥暟鎹簱琛ㄧ粨鏋�
+-- 鍒涘缓鏃堕棿: 2025-01-27
+
+-- 1. 璇勪环缁村害閰嶇疆琛�
+DROP TABLE IF EXISTS `evaluation_dimension`;
+CREATE TABLE `evaluation_dimension` (
+  `dimension_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '缁村害ID',
+  `dimension_name` varchar(100) NOT NULL COMMENT '缁村害鍚嶇О',
+  `dimension_desc` varchar(500) DEFAULT NULL COMMENT '缁村害鎻忚堪',
+  `dimension_type` varchar(20) NOT NULL DEFAULT 'star' COMMENT '缁村害绫诲瀷锛歴tar-鏄熺骇璇勪环锛宻elect-閫夋嫨璇勪环锛宼ext-鏂囨湰璇勪环',
+  `options` text COMMENT '閫夐」閰嶇疆锛圝SON鏍煎紡锛岀敤浜庨�夋嫨绫诲瀷锛�',
+  `sort_order` int(11) DEFAULT 0 COMMENT '鎺掑簭',
+  `is_required` char(1) DEFAULT '1' COMMENT '鏄惁蹇呭~锛�0鍚� 1鏄級',
+  `status` char(1) DEFAULT '0' COMMENT '鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  `create_by` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+  `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+  `update_by` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+  `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+  `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+  PRIMARY KEY (`dimension_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='璇勪环缁村害閰嶇疆琛�';
+
+-- 2. 瀹㈡埛璇勪环琛�
+DROP TABLE IF EXISTS `customer_evaluation`;
+CREATE TABLE `customer_evaluation` (
+  `evaluation_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '璇勪环ID',
+  `vehicle_no` varchar(20) NOT NULL COMMENT '杞︾墝鍙�',
+  `customer_name` varchar(50) NOT NULL COMMENT '瀹㈡埛濮撳悕',
+  `customer_phone` varchar(20) NOT NULL COMMENT '瀹㈡埛鎵嬫満鍙�',
+  `wechat_openid` varchar(100) DEFAULT NULL COMMENT '寰俊OpenID',
+  `wechat_nickname` varchar(100) DEFAULT NULL COMMENT '寰俊鏄电О',
+  `wechat_avatar` varchar(500) DEFAULT NULL COMMENT '寰俊澶村儚',
+  `wechat_phone` varchar(20) DEFAULT NULL COMMENT '寰俊缁戝畾鎵嬫満鍙�',
+  `total_score` decimal(3,1) DEFAULT NULL COMMENT '鎬昏瘎鍒�',
+  `evaluation_status` char(1) DEFAULT '0' COMMENT '璇勪环鐘舵�侊紙0寰呰瘎浠� 1宸茶瘎浠凤級',
+  `evaluation_time` datetime DEFAULT NULL COMMENT '璇勪环鏃堕棿',
+  `ip_address` varchar(128) DEFAULT NULL COMMENT 'IP鍦板潃',
+  `user_agent` varchar(500) DEFAULT NULL COMMENT '鐢ㄦ埛浠g悊',
+  `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+  `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+  `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+  PRIMARY KEY (`evaluation_id`),
+  KEY `idx_vehicle_no` (`vehicle_no`),
+  KEY `idx_customer_phone` (`customer_phone`),
+  KEY `idx_wechat_openid` (`wechat_openid`),
+  KEY `idx_evaluation_time` (`evaluation_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='瀹㈡埛璇勪环琛�';
+
+-- 3. 璇勪环璇︽儏琛�
+DROP TABLE IF EXISTS `evaluation_detail`;
+CREATE TABLE `evaluation_detail` (
+  `detail_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '璇︽儏ID',
+  `evaluation_id` bigint(20) NOT NULL COMMENT '璇勪环ID',
+  `dimension_id` bigint(20) NOT NULL COMMENT '缁村害ID',
+  `score` int(11) DEFAULT NULL COMMENT '璇勫垎锛�1-5鏄燂級',
+  `option_value` varchar(100) DEFAULT NULL COMMENT '閫夐」鍊硷紙閫夋嫨绫诲瀷鏃朵娇鐢級',
+  `text_content` text COMMENT '鏂囨湰鍐呭锛堟枃鏈被鍨嬫椂浣跨敤锛�',
+  `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+  PRIMARY KEY (`detail_id`),
+  KEY `idx_evaluation_id` (`evaluation_id`),
+  KEY `idx_dimension_id` (`dimension_id`),
+  CONSTRAINT `fk_evaluation_detail_evaluation` FOREIGN KEY (`evaluation_id`) REFERENCES `customer_evaluation` (`evaluation_id`) ON DELETE CASCADE,
+  CONSTRAINT `fk_evaluation_detail_dimension` FOREIGN KEY (`dimension_id`) REFERENCES `evaluation_dimension` (`dimension_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='璇勪环璇︽儏琛�';
+
+-- 4. 杞﹁締璇勪环浜岀淮鐮佽〃
+DROP TABLE IF EXISTS `vehicle_evaluation_qrcode`;
+CREATE TABLE `vehicle_evaluation_qrcode` (
+  `qrcode_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '浜岀淮鐮両D',
+  `vehicle_no` varchar(20) NOT NULL COMMENT '杞︾墝鍙�',
+  `qrcode_url` varchar(500) NOT NULL COMMENT '浜岀淮鐮乁RL',
+  `qrcode_content` varchar(500) NOT NULL COMMENT '浜岀淮鐮佸唴瀹�',
+  `qrcode_image` varchar(8000) DEFAULT NULL COMMENT '浜岀淮鐮佸浘鐗�(base64鏍煎紡)',
+  `status` char(1) DEFAULT '0' COMMENT '鐘舵�侊紙0姝e父 1鍋滅敤锛�',
+  `create_by` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+  `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+  `update_by` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+  `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+  `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+  PRIMARY KEY (`qrcode_id`),
+  UNIQUE KEY `uk_vehicle_no` (`vehicle_no`),
+  KEY `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='杞﹁締璇勪环浜岀淮鐮佽〃';
+
+-- 鎻掑叆榛樿璇勪环缁村害鏁版嵁
+INSERT INTO `evaluation_dimension` (`dimension_name`, `dimension_desc`, `dimension_type`, `sort_order`, `is_required`, `status`, `create_by`, `create_time`, `remark`) VALUES
+('鏈嶅姟鎬佸害', '鍙告満鏈嶅姟鎬佸害璇勪环', 'star', 1, '1', '0', 'admin', NOW(), '鍙告満鏈嶅姟鎬佸害鏄惁鍙嬪ソ銆佷笓涓�'),
+('鏀惰垂鎯呭喌', '鏀惰垂鏄惁鍚堢悊閫忔槑', 'star', 2, '1', '0', 'admin', NOW(), '鏀惰垂鏄惁鍚堢悊銆侀�忔槑锛屾湁鏃犱贡鏀惰垂鐜拌薄'),
+('杞﹁締鍗敓鐘跺喌', '杞﹁締鍐呴儴鍗敓鎯呭喌', 'star', 3, '1', '0', 'admin', NOW(), '杞﹁締鍐呴儴鏄惁骞插噣鏁存磥'),
+('鏁翠綋婊℃剰搴�', '鏁翠綋鏈嶅姟婊℃剰搴�', 'star', 4, '1', '0', 'admin', NOW(), '瀵规暣浣撴湇鍔$殑婊℃剰搴﹁瘎浠�'),
+('鍏朵粬寤鸿', '鍏朵粬鎰忚鎴栧缓璁�', 'text', 5, '0', '0', 'admin', NOW(), '瀹㈡埛鐨勫叾浠栨剰瑙佹垨寤鸿');
+
+-- 涓虹幇鏈夎溅杈嗙敓鎴愯瘎浠蜂簩缁寸爜锛堢ず渚嬫暟鎹級
+-- 娉ㄦ剰锛氬疄闄呬娇鐢ㄦ椂闇�瑕佹牴鎹湡瀹炵殑杞﹁締鏁版嵁鏉ョ敓鎴�
+-- INSERT INTO `vehicle_evaluation_qrcode` (`vehicle_no`, `qrcode_url`, `qrcode_content`, `status`, `create_by`, `create_time`) 
+-- SELECT vehicle_no, CONCAT('https://yourdomain.com/evaluation?vehicle=', vehicle_no), CONCAT('EVAL:', vehicle_no), '0', 'admin', NOW() 
+-- FROM tb_vehicle_info WHERE status = '0';
+
+-- 淇敼qrcode_image瀛楁闀垮害浠ユ敮鎸乥ase64鏍煎紡瀛樺偍
+ALTER TABLE `vehicle_evaluation_qrcode` MODIFY COLUMN `qrcode_image` varchar(8000) DEFAULT NULL COMMENT '浜岀淮鐮佸浘鐗�(base64鏍煎紡)';
diff --git a/sql/evaluation_dict.sql b/sql/evaluation_dict.sql
new file mode 100644
index 0000000..31e8b2e
--- /dev/null
+++ b/sql/evaluation_dict.sql
@@ -0,0 +1,26 @@
+-- 瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳藉瓧鍏告暟鎹�
+
+-- 璇勪环鐘舵�佸瓧鍏哥被鍨�
+INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) 
+VALUES ('璇勪环鐘舵��', 'evaluation_status', '0', 'admin', sysdate(), '瀹㈡埛璇勪环鐘舵�佸垪琛�');
+
+-- 璇勪环鐘舵�佸瓧鍏告暟鎹�
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) 
+VALUES (1, '寰呰瘎浠�', '0', 'evaluation_status', '', 'info', 'Y', '0', 'admin', sysdate(), '寰呰瘎浠风姸鎬�');
+
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) 
+VALUES (2, '宸茶瘎浠�', '1', 'evaluation_status', '', 'success', 'N', '0', 'admin', sysdate(), '宸茶瘎浠风姸鎬�');
+
+-- 璇勪环缁村害绫诲瀷瀛楀吀绫诲瀷
+INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) 
+VALUES ('璇勪环缁村害绫诲瀷', 'dimension_type', '0', 'admin', sysdate(), '璇勪环缁村害绫诲瀷鍒楄〃');
+
+-- 璇勪环缁村害绫诲瀷瀛楀吀鏁版嵁
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) 
+VALUES (1, '鏄熺骇璇勪环', 'star', 'dimension_type', '', 'primary', 'Y', '0', 'admin', sysdate(), '鏄熺骇璇勪环绫诲瀷');
+
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) 
+VALUES (2, '閫夋嫨璇勪环', 'select', 'dimension_type', '', 'success', 'N', '0', 'admin', sysdate(), '閫夋嫨璇勪环绫诲瀷');
+
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) 
+VALUES (3, '鏂囨湰璇勪环', 'text', 'dimension_type', '', 'warning', 'N', '0', 'admin', sysdate(), '鏂囨湰璇勪环绫诲瀷');
diff --git a/sql/evaluation_menu.sql b/sql/evaluation_menu.sql
new file mode 100644
index 0000000..7c830d8
--- /dev/null
+++ b/sql/evaluation_menu.sql
@@ -0,0 +1,79 @@
+-- 瀹㈡埛婊℃剰搴﹁瘎浠风鐞嗚彍鍗� SQL
+
+-- 1. 璇勪环绠$悊涓昏彍鍗�
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('璇勪环绠$悊', '0', '6', 'evaluation', null, 1, 0, 'M', '0', '0', null, 'star', 'admin', sysdate(), '', null, '瀹㈡埛婊℃剰搴﹁瘎浠风鐞嗙洰褰�');
+
+-- 鑾峰彇璇勪环绠$悊涓昏彍鍗旾D
+SELECT @evaluationParentId := LAST_INSERT_ID();
+
+-- 2. 瀹㈡埛璇勪环鑿滃崟
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('瀹㈡埛璇勪环', @evaluationParentId, '1', 'customer', 'evaluation/customer/index', 1, 0, 'C', '0', '0', 'evaluation:customer:list', 'message', 'admin', sysdate(), '', null, '瀹㈡埛璇勪环鑿滃崟');
+
+-- 鑾峰彇瀹㈡埛璇勪环鑿滃崟ID
+SELECT @customerParentId := LAST_INSERT_ID();
+
+-- 瀹㈡埛璇勪环鎸夐挳鏉冮檺
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('瀹㈡埛璇勪环鏌ヨ', @customerParentId, '1', '#', '', 1, 0, 'F', '0', '0', 'evaluation:customer:query', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('瀹㈡埛璇勪环鍒犻櫎', @customerParentId, '2', '#', '', 1, 0, 'F', '0', '0', 'evaluation:customer:remove', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('瀹㈡埛璇勪环瀵煎嚭', @customerParentId, '3', '#', '', 1, 0, 'F', '0', '0', 'evaluation:customer:export', '#', 'admin', sysdate(), '', null, '');
+
+-- 3. 璇勪环缁村害閰嶇疆鑿滃崟
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('璇勪环缁村害', @evaluationParentId, '2', 'dimension', 'evaluation/dimension/index', 1, 0, 'C', '0', '0', 'evaluation:dimension:list', 'edit', 'admin', sysdate(), '', null, '璇勪环缁村害閰嶇疆鑿滃崟');
+
+-- 鑾峰彇璇勪环缁村害鑿滃崟ID
+SELECT @dimensionParentId := LAST_INSERT_ID();
+
+-- 璇勪环缁村害鎸夐挳鏉冮檺
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('璇勪环缁村害鏌ヨ', @dimensionParentId, '1', '#', '', 1, 0, 'F', '0', '0', 'evaluation:dimension:query', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('璇勪环缁村害鏂板', @dimensionParentId, '2', '#', '', 1, 0, 'F', '0', '0', 'evaluation:dimension:add', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('璇勪环缁村害淇敼', @dimensionParentId, '3', '#', '', 1, 0, 'F', '0', '0', 'evaluation:dimension:edit', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('璇勪环缁村害鍒犻櫎', @dimensionParentId, '4', '#', '', 1, 0, 'F', '0', '0', 'evaluation:dimension:remove', '#', 'admin', sysdate(), '', null, '');
+
+-- 4. 杞﹁締浜岀淮鐮佺鐞嗚彍鍗�
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締浜岀淮鐮�', @evaluationParentId, '3', 'qrcode', 'evaluation/qrcode/index', 1, 0, 'C', '0', '0', 'evaluation:qrcode:list', 'qrcode', 'admin', sysdate(), '', null, '杞﹁締璇勪环浜岀淮鐮佺鐞嗚彍鍗�');
+
+-- 鑾峰彇杞﹁締浜岀淮鐮佽彍鍗旾D
+SELECT @qrcodeParentId := LAST_INSERT_ID();
+
+-- 杞﹁締浜岀淮鐮佹寜閽潈闄�
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浜岀淮鐮佹煡璇�', @qrcodeParentId, '1', '#', '', 1, 0, 'F', '0', '0', 'evaluation:qrcode:query', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浜岀淮鐮佺敓鎴�', @qrcodeParentId, '2', '#', '', 1, 0, 'F', '0', '0', 'evaluation:qrcode:generate', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('鎵归噺鐢熸垚', @qrcodeParentId, '3', '#', '', 1, 0, 'F', '0', '0', 'evaluation:qrcode:batch', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浜岀淮鐮佸垹闄�', @qrcodeParentId, '4', '#', '', 1, 0, 'F', '0', '0', 'evaluation:qrcode:remove', '#', 'admin', sysdate(), '', null, '');
+
+-- 5. 璇勪环缁熻鑿滃崟
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('璇勪环缁熻', @evaluationParentId, '4', 'statistics', 'evaluation/statistics/index', 1, 0, 'C', '0', '0', 'evaluation:statistics:list', 'chart', 'admin', sysdate(), '', null, '璇勪环缁熻鍒嗘瀽鑿滃崟');
+
+-- 鑾峰彇璇勪环缁熻鑿滃崟ID
+SELECT @statisticsParentId := LAST_INSERT_ID();
+
+-- 璇勪环缁熻鎸夐挳鏉冮檺
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('缁熻鏌ヨ', @statisticsParentId, '1', '#', '', 1, 0, 'F', '0', '0', 'evaluation:statistics:query', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('缁熻瀵煎嚭', @statisticsParentId, '2', '#', '', 1, 0, 'F', '0', '0', 'evaluation:statistics:export', '#', 'admin', sysdate(), '', null, '');
diff --git a/sql/vehicle_info.sql b/sql/vehicle_info.sql
index 6434538..2216aca 100644
--- a/sql/vehicle_info.sql
+++ b/sql/vehicle_info.sql
@@ -20,4 +20,7 @@
 ALTER TABLE tb_vehicle_info ADD COLUMN device_id VARCHAR(50) DEFAULT NULL COMMENT '璁惧ID';
 
 -- 鍦╰b_vehicle_gps琛ㄤ腑娣诲姞device_id瀛楁
-ALTER TABLE tb_vehicle_gps ADD COLUMN device_id VARCHAR(50) DEFAULT NULL COMMENT '璁惧ID';
\ No newline at end of file
+ALTER TABLE tb_vehicle_gps ADD COLUMN device_id VARCHAR(50) DEFAULT NULL COMMENT '璁惧ID';
+
+-- 鍦╰b_vehicle_info琛ㄤ腑娣诲姞dept_id瀛楁
+ALTER TABLE tb_vehicle_info ADD COLUMN dept_id BIGINT(20) DEFAULT NULL COMMENT '褰掑睘閮ㄩ棬ID';
\ No newline at end of file
diff --git "a/\345\256\214\346\225\264\351\203\250\347\275\262\346\214\207\345\215\227.md" "b/\345\256\214\346\225\264\351\203\250\347\275\262\346\214\207\345\215\227.md"
new file mode 100644
index 0000000..3716968
--- /dev/null
+++ "b/\345\256\214\346\225\264\351\203\250\347\275\262\346\214\207\345\215\227.md"
@@ -0,0 +1,225 @@
+# 瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳藉畬鏁撮儴缃叉寚鍗�
+
+## 馃搵 閮ㄧ讲娓呭崟
+
+### 1. 鏁版嵁搴撹剼鏈墽琛岄『搴�
+```sql
+-- 1. 鎵ц鏁版嵁搴撹〃缁撴瀯
+source sql/customer_evaluation_tables.sql
+
+-- 2. 鎵ц鑿滃崟閰嶇疆
+source sql/evaluation_menu.sql
+
+-- 3. 鎵ц瀛楀吀閰嶇疆
+source sql/evaluation_dict.sql
+```
+
+### 2. 鍚庣閰嶇疆
+
+#### 2.1 寰俊閰嶇疆锛堝彲閫夛級
+鍦� `ruoyi-admin/src/main/resources/application.yml` 涓厤缃細
+```yaml
+wechat:
+  appId: your_wechat_appid
+  appSecret: your_wechat_appsecret
+  redirectUri: http://yourdomain.com/evaluation
+```
+
+#### 2.2 鏂囦欢涓婁紶璺緞閰嶇疆
+纭繚 `ruoyi.profile` 閰嶇疆鐨勮矾寰勬湁鍐欏叆鏉冮檺锛�
+```yaml
+ruoyi:
+  profile: /path/to/upload
+```
+
+### 3. 鍓嶇閰嶇疆
+
+#### 3.1 璺敱閰嶇疆
+宸插湪 `ruoyi-ui/src/router/index.js` 涓坊鍔犺瘎浠风浉鍏宠矾鐢便��
+
+#### 3.2 椤甸潰缁勪欢
+宸插垱寤轰互涓嬮〉闈㈢粍浠讹細
+- `ruoyi-ui/src/views/evaluation/index.vue` - 瀹㈡埛璇勪环椤甸潰
+- `ruoyi-ui/src/views/evaluation/test.vue` - 娴嬭瘯椤甸潰
+- `ruoyi-ui/src/views/evaluation/customer/index.vue` - 瀹㈡埛璇勪环绠$悊
+- `ruoyi-ui/src/views/evaluation/dimension/index.vue` - 璇勪环缁村害閰嶇疆
+- `ruoyi-ui/src/views/evaluation/qrcode/index.vue` - 杞﹁締浜岀淮鐮佺鐞�
+
+## 馃殌 閮ㄧ讲姝ラ
+
+### 姝ラ1锛氭墽琛屾暟鎹簱鑴氭湰
+```bash
+# 杩炴帴鏁版嵁搴�
+mysql -u username -p database_name
+
+# 鎵ц鑴氭湰
+source sql/customer_evaluation_tables.sql
+source sql/evaluation_menu.sql
+source sql/evaluation_dict.sql
+```
+
+### 姝ラ2锛氱紪璇戝悗绔」鐩�
+```bash
+# 鍦ㄩ」鐩牴鐩綍鎵ц
+mvn clean install
+```
+
+### 姝ラ3锛氬惎鍔ㄥ悗绔湇鍔�
+```bash
+cd ruoyi-admin
+mvn spring-boot:run
+```
+
+### 姝ラ4锛氱紪璇戝墠绔」鐩�
+```bash
+cd ruoyi-ui
+npm install
+npm run dev
+```
+
+## 馃И 鍔熻兘娴嬭瘯
+
+### 1. 璁块棶绠$悊鐣岄潰
+- 鐧诲綍绯荤粺鍚庯紝鍦ㄥ乏渚ц彍鍗曚腑鍙互鐪嬪埌"璇勪环绠$悊"鑿滃崟
+- 鍖呭惈浠ヤ笅瀛愯彍鍗曪細
+  - 瀹㈡埛璇勪环
+  - 璇勪环缁村害
+  - 杞﹁締浜岀淮鐮�
+  - 璇勪环缁熻
+
+### 2. 娴嬭瘯璇勪环鍔熻兘
+- 璁块棶锛歚http://localhost:80/evaluation/test`
+- 娴嬭瘯浜岀淮鐮佺敓鎴愩�佽瘎浠风淮搴﹀姞杞姐�佽瘎浠锋彁浜ょ瓑鍔熻兘
+
+### 3. 娴嬭瘯璇勪环椤甸潰
+- 璁块棶锛歚http://localhost:80/evaluation?vehicle=绮12345`
+- 濉啓璇勪环淇℃伅骞舵彁浜�
+
+## 馃摫 寰俊閰嶇疆锛堢敓浜х幆澧冿級
+
+### 1. 寰俊鍏紬骞冲彴閰嶇疆
+1. 鐧诲綍寰俊鍏紬骞冲彴
+2. 杩涘叆"寮�鍙�" -> "鎺ュ彛鏉冮檺"
+3. 閰嶇疆缃戦〉鎺堟潈鍩熷悕锛歚yourdomain.com`
+4. 閰嶇疆JS鎺ュ彛瀹夊叏鍩熷悕锛歚yourdomain.com`
+
+### 2. 鍩熷悕閰嶇疆
+- 纭繚鍩熷悕宸插妗�
+- 閰嶇疆HTTPS璇佷功
+- 鏇存柊閰嶇疆鏂囦欢涓殑鍩熷悕
+
+## 馃敡 鏉冮檺閰嶇疆
+
+### 1. 瑙掕壊鏉冮檺
+绯荤粺绠$悊鍛橀渶瑕佷负鐩稿叧瑙掕壊鍒嗛厤浠ヤ笅鏉冮檺锛�
+- `evaluation:customer:list` - 瀹㈡埛璇勪环鏌ヨ
+- `evaluation:customer:remove` - 瀹㈡埛璇勪环鍒犻櫎
+- `evaluation:customer:export` - 瀹㈡埛璇勪环瀵煎嚭
+- `evaluation:dimension:list` - 璇勪环缁村害鏌ヨ
+- `evaluation:dimension:add` - 璇勪环缁村害鏂板
+- `evaluation:dimension:edit` - 璇勪环缁村害淇敼
+- `evaluation:dimension:remove` - 璇勪环缁村害鍒犻櫎
+- `evaluation:qrcode:list` - 浜岀淮鐮佹煡璇�
+- `evaluation:qrcode:generate` - 浜岀淮鐮佺敓鎴�
+- `evaluation:qrcode:batch` - 鎵归噺鐢熸垚浜岀淮鐮�
+- `evaluation:qrcode:remove` - 浜岀淮鐮佸垹闄�
+
+### 2. 鑿滃崟鏉冮檺
+鑿滃崟鏉冮檺宸查�氳繃SQL鑴氭湰鑷姩閰嶇疆銆�
+
+## 馃搳 鏁版嵁楠岃瘉
+
+### 1. 妫�鏌ユ暟鎹簱琛�
+```sql
+-- 妫�鏌ヨ〃鏄惁鍒涘缓鎴愬姛
+SHOW TABLES LIKE '%evaluation%';
+
+-- 妫�鏌ヨ彍鍗曟槸鍚︽坊鍔犳垚鍔�
+SELECT * FROM sys_menu WHERE menu_name LIKE '%璇勪环%';
+
+-- 妫�鏌ュ瓧鍏告槸鍚︽坊鍔犳垚鍔�
+SELECT * FROM sys_dict_type WHERE dict_type IN ('evaluation_status', 'dimension_type');
+```
+
+### 2. 妫�鏌ラ粯璁ゆ暟鎹�
+```sql
+-- 妫�鏌ヨ瘎浠风淮搴﹂粯璁ゆ暟鎹�
+SELECT * FROM evaluation_dimension;
+
+-- 搴旇鐪嬪埌5鏉¢粯璁よ瘎浠风淮搴︽暟鎹�
+```
+
+## 馃悰 甯歌闂
+
+### 1. 鑿滃崟涓嶆樉绀�
+**鍘熷洜**锛氬彲鑳芥槸鏉冮檺闂鎴栬彍鍗曟暟鎹湭姝g‘鎻掑叆
+**瑙e喅**锛�
+- 妫�鏌ョ敤鎴疯鑹叉潈闄�
+- 閲嶆柊鎵ц鑿滃崟SQL鑴氭湰
+- 娓呴櫎娴忚鍣ㄧ紦瀛�
+
+### 2. 浜岀淮鐮佺敓鎴愬け璐�
+**鍘熷洜**锛氭枃浠惰矾寰勬潈闄愰棶棰�
+**瑙e喅**锛�
+- 妫�鏌� `ruoyi.profile` 閰嶇疆鐨勮矾寰�
+- 纭繚鐩綍鏈夊啓鍏ユ潈闄�
+- 妫�鏌ョ鐩樼┖闂�
+
+### 3. 璇勪环鎻愪氦澶辫触
+**鍘熷洜**锛氬彲鑳芥槸蹇呭~瀛楁楠岃瘉澶辫触
+**瑙e喅**锛�
+- 妫�鏌ヨ瘎浠风淮搴﹂厤缃�
+- 纭繚鎵�鏈夊繀濉瓧娈甸兘宸插~鍐�
+- 鏌ョ湅鍚庣鏃ュ織
+
+### 4. 寰俊鎺堟潈澶辫触
+**鍘熷洜**锛氬井淇¢厤缃棶棰�
+**瑙e喅**锛�
+- 妫�鏌ppID鍜孉ppSecret閰嶇疆
+- 纭鍩熷悕閰嶇疆姝g‘
+- 妫�鏌TTPS璇佷功
+
+## 馃搱 鎬ц兘浼樺寲寤鸿
+
+### 1. 鏁版嵁搴撲紭鍖�
+```sql
+-- 娣诲姞绱㈠紩
+CREATE INDEX idx_evaluation_vehicle_time ON customer_evaluation(vehicle_no, evaluation_time);
+CREATE INDEX idx_evaluation_status ON customer_evaluation(evaluation_status);
+CREATE INDEX idx_evaluation_detail_evaluation ON evaluation_detail(evaluation_id);
+```
+
+### 2. 缂撳瓨閰嶇疆
+- 璇勪环缁村害閰嶇疆鍙互缂撳瓨
+- 浜岀淮鐮佸浘鐗囦娇鐢–DN鍔犻��
+
+### 3. 鏂囦欢瀛樺偍
+- 鑰冭檻浣跨敤瀵硅薄瀛樺偍鏈嶅姟
+- 瀹氭湡娓呯悊鏃犵敤鐨勪簩缁寸爜鏂囦欢
+
+## 馃摓 鎶�鏈敮鎸�
+
+濡傞亣鍒伴棶棰橈紝璇锋彁渚涳細
+1. 閿欒鏃ュ織
+2. 鎿嶄綔姝ラ
+3. 鐜淇℃伅
+4. 閿欒鎴浘
+
+## 馃幆 鍔熻兘鎵╁睍
+
+### 1. 璇勪环缁熻
+鍙互鍩轰簬鐜版湁鏁版嵁寮�鍙戯細
+- 璇勪环瓒嬪娍鍒嗘瀽
+- 杞﹁締璇勪环鎺掕
+- 瀹㈡埛婊℃剰搴︽姤鍛�
+
+### 2. 娑堟伅閫氱煡
+- 璇勪环鎻愪氦鍚庡彂閫侀�氱煡
+- 浣庡垎璇勪环棰勮
+- 瀹氭湡璇勪环鎶ュ憡
+
+### 3. 澶氳瑷�鏀寔
+- 鏀寔澶氳瑷�璇勪环鐣岄潰
+- 鍥介檯鍖栭厤缃�
+
+鍔熻兘宸插叏閮ㄥ紑鍙戝畬鎴愶紝鍙互姝e父浣跨敤锛�
diff --git "a/\345\256\242\346\210\267\346\273\241\346\204\217\345\272\246\350\257\204\344\273\267\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/\345\256\242\346\210\267\346\273\241\346\204\217\345\272\246\350\257\204\344\273\267\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..1bd5d38
--- /dev/null
+++ "b/\345\256\242\346\210\267\346\273\241\346\204\217\345\272\246\350\257\204\344\273\267\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,134 @@
+# 瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳借鏄�
+
+## 鍔熻兘姒傝堪
+
+瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳藉厑璁稿鎴烽�氳繃鎵弿浜岀淮鐮佽繘鍏ヨ瘎浠风晫闈紝瀵规湇鍔¤繘琛屽缁村害璇勪环銆傛敮鎸佸井淇$幆澧冧笅鐨勭敤鎴蜂俊鎭幏鍙栧拰璇勪环鎻愪氦銆�
+
+## 涓昏鍔熻兘
+
+### 1. 浜岀淮鐮佺敓鎴�
+- 涓烘瘡杈嗚溅鐢熸垚鍞竴鐨勮瘎浠蜂簩缁寸爜
+- 浜岀淮鐮佸寘鍚溅鐗屽彿淇℃伅锛岀敤浜庡叧鑱斿叿浣撹溅杈嗘湇鍔�
+- 鏀寔鎵归噺鐢熸垚浜岀淮鐮�
+
+### 2. 寰俊闆嗘垚
+- 鑷姩妫�娴嬪井淇℃祻瑙堝櫒鐜
+- 鑾峰彇寰俊鐢ㄦ埛淇℃伅锛圤penID銆佹樀绉般�佸ご鍍忕瓑锛�
+- 鏀寔寰俊缃戦〉鎺堟潈娴佺▼
+
+### 3. 璇勪环鐣岄潰
+- 鍝嶅簲寮忚璁★紝閫傞厤绉诲姩绔拰寰俊娴忚鍣�
+- 鏀寔澶氱璇勪环绫诲瀷锛氭槦绾ц瘎浠枫�侀�夋嫨璇勪环銆佹枃鏈瘎浠�
+- 瀹㈡埛淇℃伅鏀堕泦锛堝鍚嶃�佹墜鏈哄彿蹇呭~锛�
+- 璇勪环缁村害鍙厤缃�
+
+### 4. 璇勪环鎻愪氦
+- 鏁版嵁楠岃瘉鍜屽畬鏁存�ф鏌�
+- 鏍规嵁璇勫垎鏄剧ず涓嶅悓鐨勫弽棣堜俊鎭�
+- 璇勪环鏁版嵁瀛樺偍鍜岀粺璁�
+
+## 鏁版嵁搴撹〃缁撴瀯
+
+### 1. evaluation_dimension锛堣瘎浠风淮搴﹂厤缃〃锛�
+- 閰嶇疆璇勪环缁村害鍚嶇О銆佺被鍨嬨�佹槸鍚﹀繀濉瓑
+- 鏀寔鏄熺骇璇勪环銆侀�夋嫨璇勪环銆佹枃鏈瘎浠蜂笁绉嶇被鍨�
+
+### 2. customer_evaluation锛堝鎴疯瘎浠疯〃锛�
+- 瀛樺偍瀹㈡埛鍩烘湰淇℃伅鍜岃瘎浠风粨鏋�
+- 鍖呭惈寰俊鐢ㄦ埛淇℃伅
+- 璁板綍璇勪环鏃堕棿鍜孖P鍦板潃
+
+### 3. evaluation_detail锛堣瘎浠疯鎯呰〃锛�
+- 瀛樺偍姣忎釜缁村害鐨勫叿浣撹瘎鍒�
+- 鍏宠仈璇勪环缁村害鍜屽鎴疯瘎浠�
+
+### 4. vehicle_evaluation_qrcode锛堣溅杈嗚瘎浠蜂簩缁寸爜琛級
+- 瀛樺偍姣忚締杞︾殑浜岀淮鐮佷俊鎭�
+- 鍖呭惈浜岀淮鐮乁RL鍜屽浘鐗囪矾寰�
+
+## API鎺ュ彛
+
+### 鍏紑鎺ュ彛锛堟棤闇�璁よ瘉锛�
+- `GET /evaluation/dimensions` - 鑾峰彇璇勪环缁村害閰嶇疆
+- `POST /evaluation/submit` - 鎻愪氦瀹㈡埛璇勪环
+- `GET /evaluation/wechat/userinfo` - 鑾峰彇寰俊鐢ㄦ埛淇℃伅
+
+### 绠$悊鎺ュ彛锛堥渶瑕佽璇侊級
+- `GET /evaluation/list` - 鏌ヨ瀹㈡埛璇勪环鍒楄〃
+- `GET /evaluation/{id}` - 鑾峰彇璇勪环璇︽儏
+- `POST /evaluation/qrcode/{vehicleNo}` - 鐢熸垚杞﹁締浜岀淮鐮�
+- `POST /evaluation/qrcode/batch` - 鎵归噺鐢熸垚浜岀淮鐮�
+
+## 閮ㄧ讲璇存槑
+
+### 1. 鏁版嵁搴撳垵濮嬪寲
+```sql
+-- 鎵ц sql/customer_evaluation_tables.sql 鏂囦欢
+-- 鍒涘缓鐩稿叧琛ㄥ拰鍒濆鏁版嵁
+```
+
+### 2. 閰嶇疆鏂囦欢
+鍦� `application.yml` 涓厤缃細
+```yaml
+# 寰俊閰嶇疆
+wechat:
+  appId: your_wechat_appid
+  appSecret: your_wechat_appsecret
+
+# 鏂囦欢涓婁紶璺緞
+ruoyi:
+  profile: /path/to/upload
+```
+
+### 3. 鍓嶇璺敱閰嶇疆
+鍦� `router/index.js` 涓坊鍔犺瘎浠烽〉闈㈣矾鐢憋細
+```javascript
+{
+  path: '/evaluation',
+  component: () => import('@/views/evaluation/index'),
+  name: 'Evaluation'
+}
+```
+
+## 浣跨敤娴佺▼
+
+### 1. 绠$悊鍛樻搷浣�
+1. 閰嶇疆璇勪环缁村害锛堟湇鍔℃�佸害銆佹敹璐规儏鍐点�佽溅杈嗗崼鐢熺瓑锛�
+2. 涓鸿溅杈嗙敓鎴愯瘎浠蜂簩缁寸爜
+3. 灏嗕簩缁寸爜鎵撳嵃骞惰创鍦ㄨ溅杈嗕笂
+
+### 2. 瀹㈡埛璇勪环娴佺▼
+1. 瀹㈡埛鎵弿杞﹁締涓婄殑浜岀淮鐮�
+2. 绯荤粺瑙f瀽浜岀淮鐮侊紝鑾峰彇杞︾墝鍙�
+3. 杩涘叆璇勪环椤甸潰锛岃幏鍙栧井淇$敤鎴蜂俊鎭紙濡傛灉鍦ㄥ井淇$幆澧冧腑锛�
+4. 瀹㈡埛濉啓涓汉淇℃伅鍜岃瘎浠峰唴瀹�
+5. 鎻愪氦璇勪环锛屾樉绀虹粨鏋滈〉闈�
+
+## 娴嬭瘯鍔熻兘
+
+璁块棶 `/evaluation/test` 椤甸潰鍙互娴嬭瘯浠ヤ笅鍔熻兘锛�
+- 浜岀淮鐮佺敓鎴�
+- 璇勪环缁村害鍔犺浇
+- 璇勪环鎻愪氦
+- 鐩存帴璁块棶璇勪环椤甸潰
+
+## 娉ㄦ剰浜嬮」
+
+1. **寰俊閰嶇疆**锛氶渶瑕侀厤缃纭殑寰俊AppID鍜孉ppSecret
+2. **鏂囦欢鏉冮檺**锛氱‘淇濅笂浼犵洰褰曟湁鍐欏叆鏉冮檺
+3. **HTTPS**锛氬井淇℃巿鏉冮渶瑕丠TTPS鐜
+4. **鍩熷悕閰嶇疆**锛氬湪寰俊鍏紬骞冲彴閰嶇疆鎺堟潈鍩熷悕
+
+## 鎵╁睍鍔熻兘
+
+1. **璇勪环缁熻**锛氬彲浠ュ熀浜庣幇鏈夋暟鎹紑鍙戣瘎浠风粺璁″垎鏋愬姛鑳�
+2. **娑堟伅閫氱煡**锛氳瘎浠锋彁浜ゅ悗鍙互鍙戦�侀�氱煡缁欑浉鍏充汉鍛�
+3. **璇勪环瀵煎嚭**锛氭敮鎸佽瘎浠锋暟鎹殑Excel瀵煎嚭
+4. **澶氳瑷�鏀寔**锛氬彲浠ユ墿灞曞璇█璇勪环鐣岄潰
+
+## 鎶�鏈爤
+
+- 鍚庣锛歋pring Boot + MyBatis + MySQL
+- 鍓嶇锛歏ue.js + Element UI
+- 浜岀淮鐮侊細ZXing
+- 寰俊锛氬井淇$綉椤垫巿鏉傾PI
diff --git "a/\346\265\213\350\257\225\346\255\245\351\252\244.md" "b/\346\265\213\350\257\225\346\255\245\351\252\244.md"
new file mode 100644
index 0000000..5b60928
--- /dev/null
+++ "b/\346\265\213\350\257\225\346\255\245\351\252\244.md"
@@ -0,0 +1,121 @@
+# 瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳芥祴璇曟楠�
+
+## 1. 鍚姩椤圭洰
+
+### 鍚庣鍚姩
+```bash
+# 鍦ㄩ」鐩牴鐩綍鎵ц
+mvn clean install
+cd ruoyi-admin
+mvn spring-boot:run
+```
+
+### 鍓嶇鍚姩
+```bash
+# 鍦� ruoyi-ui 鐩綍鎵ц
+npm install
+npm run dev
+```
+
+## 2. 閰嶇疆寰俊鍙傛暟锛堝彲閫夛級
+
+濡傛灉涓嶉渶瑕佸井淇″姛鑳斤紝鍙互璺宠繃姝ゆ楠ゃ��
+
+鍦� `ruoyi-admin/src/main/resources/application.yml` 涓厤缃細
+```yaml
+wechat:
+  appId: your_wechat_appid
+  appSecret: your_wechat_appsecret
+  redirectUri: http://localhost:8080/evaluation
+```
+
+## 3. 娴嬭瘯姝ラ
+
+### 姝ラ1锛氳闂祴璇曢〉闈�
+鎵撳紑娴忚鍣ㄨ闂細`http://localhost:80/evaluation/test`
+
+### 姝ラ2锛氭祴璇曚簩缁寸爜鐢熸垚
+1. 鍦ㄦ祴璇曢〉闈㈣緭鍏ヨ溅鐗屽彿锛堝锛氱菠A12345锛�
+2. 鐐瑰嚮"鐢熸垚浜岀淮鐮�"鎸夐挳
+3. 鏌ョ湅鏄惁鎴愬姛鐢熸垚浜岀淮鐮佷俊鎭�
+
+### 姝ラ3锛氭祴璇曡瘎浠风淮搴﹀姞杞�
+1. 鐐瑰嚮"鍔犺浇璇勪环缁村害"鎸夐挳
+2. 鏌ョ湅鏄惁鎴愬姛鍔犺浇璇勪环缁村害鍒楄〃
+
+### 姝ラ4锛氭祴璇曡瘎浠锋彁浜�
+1. 濉啓娴嬭瘯璇勪环淇℃伅
+2. 鐐瑰嚮"鎻愪氦娴嬭瘯璇勪环"鎸夐挳
+3. 鏌ョ湅鏄惁鎴愬姛鎻愪氦
+
+### 姝ラ5锛氭祴璇曡瘎浠烽〉闈�
+1. 鐐瑰嚮"鐩存帴璁块棶璇勪环椤甸潰"閾炬帴
+2. 鎴栫洿鎺ヨ闂細`http://localhost:80/evaluation?vehicle=绮12345`
+3. 濉啓璇勪环淇℃伅骞舵彁浜�
+
+## 4. 棰勬湡缁撴灉
+
+### 浜岀淮鐮佺敓鎴愭祴璇�
+- 搴旇杩斿洖浜岀淮鐮乁RL銆佸唴瀹瑰拰鍥剧墖璺緞
+- 浜岀淮鐮乁RL鏍煎紡锛歚http://localhost:8080/evaluation?vehicle=杞︾墝鍙穈
+
+### 璇勪环缁村害娴嬭瘯
+- 搴旇杩斿洖榛樿鐨勮瘎浠风淮搴︼細
+  - 鏈嶅姟鎬佸害锛堟槦绾ц瘎浠凤紝蹇呭~锛�
+  - 鏀惰垂鎯呭喌锛堟槦绾ц瘎浠凤紝蹇呭~锛�
+  - 杞﹁締鍗敓鐘跺喌锛堟槦绾ц瘎浠凤紝蹇呭~锛�
+  - 鏁翠綋婊℃剰搴︼紙鏄熺骇璇勪环锛屽繀濉級
+  - 鍏朵粬寤鸿锛堟枃鏈瘎浠凤紝闈炲繀濉級
+
+### 璇勪环鎻愪氦娴嬭瘯
+- 搴旇杩斿洖鎴愬姛娑堟伅
+- 鏁版嵁搴撲腑搴旇淇濆瓨璇勪环璁板綍
+
+### 璇勪环椤甸潰娴嬭瘯
+- 椤甸潰搴旇姝e父鏄剧ず
+- 琛ㄥ崟楠岃瘉搴旇姝e父宸ヤ綔
+- 鎻愪氦鍚庡簲璇ユ樉绀烘垚鍔熼〉闈�
+
+## 5. 甯歌闂
+
+### 闂1锛氫簩缁寸爜鐢熸垚澶辫触
+**鍘熷洜**锛氬彲鑳芥槸鏂囦欢璺緞鏉冮檺闂
+**瑙e喅**锛氭鏌� `ruoyi.profile` 閰嶇疆鐨勮矾寰勬槸鍚︽湁鍐欏叆鏉冮檺
+
+### 闂2锛氳瘎浠风淮搴﹀姞杞藉け璐�
+**鍘熷洜**锛氬彲鑳芥槸鏁版嵁搴撹繛鎺ラ棶棰�
+**瑙e喅**锛氭鏌ユ暟鎹簱杩炴帴閰嶇疆
+
+### 闂3锛氳瘎浠锋彁浜ゅけ璐�
+**鍘熷洜**锛氬彲鑳芥槸蹇呭~瀛楁楠岃瘉澶辫触
+**瑙e喅**锛氱‘淇濇墍鏈夊繀濉瓧娈甸兘宸插~鍐�
+
+### 闂4锛氶〉闈㈣闂�404
+**鍘熷洜**锛氬彲鑳芥槸璺敱閰嶇疆闂
+**瑙e喅**锛氭鏌ュ墠绔矾鐢遍厤缃槸鍚︽纭�
+
+## 6. 鏁版嵁搴撻獙璇�
+
+鍙互鎵ц浠ヤ笅SQL鏌ヨ楠岃瘉鏁版嵁锛�
+
+```sql
+-- 鏌ョ湅璇勪环缁村害閰嶇疆
+SELECT * FROM evaluation_dimension;
+
+-- 鏌ョ湅瀹㈡埛璇勪环璁板綍
+SELECT * FROM customer_evaluation;
+
+-- 鏌ョ湅璇勪环璇︽儏
+SELECT * FROM evaluation_detail;
+
+-- 鏌ョ湅杞﹁締浜岀淮鐮�
+SELECT * FROM vehicle_evaluation_qrcode;
+```
+
+## 7. 鐢熶骇鐜閮ㄧ讲娉ㄦ剰浜嬮」
+
+1. **HTTPS閰嶇疆**锛氬井淇℃巿鏉冮渶瑕丠TTPS鐜
+2. **鍩熷悕閰嶇疆**锛氬湪寰俊鍏紬骞冲彴閰嶇疆鎺堟潈鍩熷悕
+3. **鏂囦欢鏉冮檺**锛氱‘淇濅笂浼犵洰褰曟湁姝g‘鐨勮鍐欐潈闄�
+4. **鏁版嵁搴撳浠�**锛氬畾鏈熷浠借瘎浠锋暟鎹�
+5. **鎬ц兘浼樺寲**锛氬ぇ閲忚瘎浠锋暟鎹椂鑰冭檻鍒嗛〉鍜岀储寮曚紭鍖�
diff --git "a/\351\203\250\347\275\262\350\257\264\346\230\216.md" "b/\351\203\250\347\275\262\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..b98f82f
--- /dev/null
+++ "b/\351\203\250\347\275\262\350\257\264\346\230\216.md"
@@ -0,0 +1,249 @@
+# 瀹㈡埛婊℃剰搴﹁瘎浠峰姛鑳介儴缃茶鏄�
+
+## 閮ㄧ讲鍓嶅噯澶�
+
+### 1. 鐜瑕佹眰
+- JDK 1.8+
+- Maven 3.6+
+- MySQL 5.7+
+- Node.js 14+
+- Nginx锛堢敓浜х幆澧冩帹鑽愶級
+
+### 2. 閰嶇疆鏂囦欢淇敼
+
+#### 鏁版嵁搴撻厤缃�
+淇敼 `ruoyi-admin/src/main/resources/application-prod.yml`锛�
+```yaml
+spring:
+  datasource:
+    url: jdbc:mysql://your-db-host:3306/your-database?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+    username: your-username
+    password: your-password
+```
+
+#### 寰俊閰嶇疆
+淇敼 `ruoyi-admin/src/main/resources/application-prod.yml`锛�
+```yaml
+wechat:
+  appId: your_wechat_appid
+  appSecret: your_wechat_appsecret
+  redirectUri: https://yourdomain.com/evaluation
+```
+
+#### 鏂囦欢涓婁紶璺緞
+淇敼 `ruoyi-admin/src/main/resources/application-prod.yml`锛�
+```yaml
+ruoyi:
+  profile: /path/to/upload
+```
+
+## 閮ㄧ讲姝ラ
+
+### 1. 鍚庣閮ㄧ讲
+
+#### 鏂瑰紡涓�锛欽AR鍖呴儴缃�
+```bash
+# 缂栬瘧鎵撳寘
+mvn clean package -Pprod
+
+# 涓婁紶JAR鍖呭埌鏈嶅姟鍣�
+scp ruoyi-admin/target/ruoyi-admin.jar user@server:/path/to/app/
+
+# 鍚姩搴旂敤
+java -jar ruoyi-admin.jar --spring.profiles.active=prod
+```
+
+#### 鏂瑰紡浜岋細Docker閮ㄧ讲
+```dockerfile
+# Dockerfile
+FROM openjdk:8-jre-alpine
+COPY ruoyi-admin.jar app.jar
+EXPOSE 8080
+ENTRYPOINT ["java", "-jar", "/app.jar"]
+```
+
+```bash
+# 鏋勫缓闀滃儚
+docker build -t ruoyi-evaluation .
+
+# 杩愯瀹瑰櫒
+docker run -d -p 8080:8080 --name ruoyi-evaluation ruoyi-evaluation
+```
+
+### 2. 鍓嶇閮ㄧ讲
+
+#### 鏋勫缓鐢熶骇鐗堟湰
+```bash
+cd ruoyi-ui
+npm install
+npm run build:prod
+```
+
+#### Nginx閰嶇疆
+```nginx
+server {
+    listen 80;
+    server_name yourdomain.com;
+    
+    # 鍓嶇闈欐�佹枃浠�
+    location / {
+        root /path/to/ruoyi-ui/dist;
+        try_files $uri $uri/ /index.html;
+    }
+    
+    # 鍚庣API浠g悊
+    location /dev-api/ {
+        proxy_pass http://localhost:8080/;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    }
+    
+    # 浜岀淮鐮佸浘鐗囪闂�
+    location /qrcode/ {
+        alias /path/to/upload/qrcode/;
+    }
+}
+```
+
+### 3. 鏁版嵁搴撻儴缃�
+
+#### 鎵цSQL鑴氭湰
+```bash
+mysql -u username -p database_name < sql/customer_evaluation_tables.sql
+```
+
+#### 鍒涘缓鏁版嵁搴撶敤鎴凤紙鍙�夛級
+```sql
+CREATE USER 'evaluation_user'@'%' IDENTIFIED BY 'password';
+GRANT SELECT, INSERT, UPDATE, DELETE ON database_name.* TO 'evaluation_user'@'%';
+FLUSH PRIVILEGES;
+```
+
+## 寰俊閰嶇疆
+
+### 1. 寰俊鍏紬骞冲彴閰嶇疆
+
+1. 鐧诲綍寰俊鍏紬骞冲彴
+2. 杩涘叆"寮�鍙�" -> "鎺ュ彛鏉冮檺"
+3. 閰嶇疆缃戦〉鎺堟潈鍩熷悕锛歚yourdomain.com`
+4. 閰嶇疆JS鎺ュ彛瀹夊叏鍩熷悕锛歚yourdomain.com`
+
+### 2. 娴嬭瘯寰俊鍔熻兘
+
+1. 鍦ㄥ井淇′腑璁块棶锛歚https://yourdomain.com/evaluation?vehicle=绮12345`
+2. 纭鑳芥甯歌幏鍙栧井淇$敤鎴蜂俊鎭�
+3. 娴嬭瘯璇勪环鎻愪氦鍔熻兘
+
+## 鐩戞帶鍜岀淮鎶�
+
+### 1. 鏃ュ織鐩戞帶
+```bash
+# 鏌ョ湅搴旂敤鏃ュ織
+tail -f logs/sys-info.log
+
+# 鏌ョ湅閿欒鏃ュ織
+tail -f logs/sys-error.log
+```
+
+### 2. 鏁版嵁搴撶洃鎺�
+```sql
+-- 鏌ョ湅璇勪环缁熻
+SELECT 
+    vehicle_no,
+    COUNT(*) as total_count,
+    AVG(total_score) as avg_score
+FROM customer_evaluation 
+WHERE evaluation_status = '1'
+GROUP BY vehicle_no;
+
+-- 鏌ョ湅浠婃棩璇勪环鏁伴噺
+SELECT COUNT(*) FROM customer_evaluation 
+WHERE DATE(evaluation_time) = CURDATE();
+```
+
+### 3. 鏂囦欢娓呯悊
+```bash
+# 娓呯悊杩囨湡鐨勪簩缁寸爜鏂囦欢锛堝彲閫夛級
+find /path/to/upload/qrcode/ -name "*.png" -mtime +30 -delete
+```
+
+## 鎬ц兘浼樺寲
+
+### 1. 鏁版嵁搴撲紭鍖�
+```sql
+-- 娣诲姞绱㈠紩
+CREATE INDEX idx_evaluation_vehicle_time ON customer_evaluation(vehicle_no, evaluation_time);
+CREATE INDEX idx_evaluation_status ON customer_evaluation(evaluation_status);
+```
+
+### 2. 缂撳瓨閰嶇疆
+```yaml
+# Redis閰嶇疆
+spring:
+  redis:
+    host: your-redis-host
+    port: 6379
+    database: 0
+    timeout: 10s
+```
+
+### 3. 鏂囦欢瀛樺偍浼樺寲
+- 浣跨敤CDN鍔犻�熶簩缁寸爜鍥剧墖璁块棶
+- 瀹氭湡娓呯悊鏃犵敤鐨勪簩缁寸爜鏂囦欢
+- 鑰冭檻浣跨敤瀵硅薄瀛樺偍鏈嶅姟锛堝闃块噷浜慜SS锛�
+
+## 瀹夊叏閰嶇疆
+
+### 1. HTTPS閰嶇疆
+```nginx
+server {
+    listen 443 ssl;
+    server_name yourdomain.com;
+    
+    ssl_certificate /path/to/cert.pem;
+    ssl_certificate_key /path/to/key.pem;
+    
+    # 鍏朵粬閰嶇疆...
+}
+```
+
+### 2. 鎺ュ彛瀹夊叏
+- 璇勪环鎻愪氦鎺ュ彛娣诲姞棰戠巼闄愬埗
+- 鏁忔劅淇℃伅鍔犲瘑瀛樺偍
+- 瀹氭湡鏇存柊寰俊AppSecret
+
+### 3. 鏁版嵁澶囦唤
+```bash
+# 鏁版嵁搴撳浠�
+mysqldump -u username -p database_name > backup_$(date +%Y%m%d).sql
+
+# 鏂囦欢澶囦唤
+tar -czf upload_backup_$(date +%Y%m%d).tar.gz /path/to/upload/
+```
+
+## 鏁呴殰鎺掓煡
+
+### 1. 甯歌闂
+
+#### 浜岀淮鐮佺敓鎴愬け璐�
+- 妫�鏌ユ枃浠惰矾寰勬潈闄�
+- 妫�鏌ョ鐩樼┖闂�
+- 鏌ョ湅搴旂敤鏃ュ織
+
+#### 寰俊鎺堟潈澶辫触
+- 妫�鏌ュ煙鍚嶉厤缃�
+- 妫�鏌TTPS璇佷功
+- 妫�鏌ppID鍜孉ppSecret
+
+#### 璇勪环鎻愪氦澶辫触
+- 妫�鏌ユ暟鎹簱杩炴帴
+- 妫�鏌ュ繀濉瓧娈甸獙璇�
+- 鏌ョ湅閿欒鏃ュ織
+
+### 2. 鑱旂郴鏀寔
+濡傞亣鍒伴棶棰橈紝璇锋彁渚涳細
+- 閿欒鏃ュ織
+- 鎿嶄綔姝ラ
+- 鐜淇℃伅
+- 閿欒鎴浘

--
Gitblit v1.9.1