From 22603b2519b8dcb7f9a7c7d9ba636d9aba240a59 Mon Sep 17 00:00:00 2001
From: jiangping <jp@doumee.com>
Date: 星期五, 18 七月 2025 09:15:01 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 server/admin/src/main/java/com/doumee/job/AutoCommentJob.java                                   |   34 +
 server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java                                |   34 +
 server/web/src/main/java/com/doumee/api/web/ConfigApi.java                                      |    2 
 server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java                           |    3 
 server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java               |    8 
 server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java                            |  456 +++++++++++++
 server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java                         |    6 
 server/services/src/main/java/com/doumee/config/wx/TransferToUser.java                          |  312 +++++++++
 server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java                             |   21 
 server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java          |    5 
 server/services/src/main/java/com/doumee/service/business/MemberService.java                    |    2 
 server/services/src/main/java/com/doumee/service/business/OrdersService.java                    |    9 
 small-program/pages/using-workers/using-workers.vue                                             |    2 
 server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java |  103 ++
 server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java                            |   15 
 server/services/src/main/java/com/doumee/api/common/PublicCloudController.java                  |    3 
 server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java                                |   34 +
 small-program/pages/packaging-worker/packaging-worker.vue                                       |    5 
 server/services/src/main/resources/application-dev.yml                                          |   16 
 server/web/src/main/java/com/doumee/api/web/AccountApi.java                                     |   13 
 server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java                                   |   34 +
 small-program/pages/sorting/sorting.vue                                                         |    2 
 server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java         |    5 
 server/web/src/main/java/com/doumee/api/web/UserApi.java                                        |   29 
 server/web/src/main/java/com/doumee/api/web/OrdersApi.java                                      |   12 
 server/pom.xml                                                                                  |    2 
 server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java                  |    2 
 server/services/src/main/java/com/doumee/dao/business/model/Orders.java                         |    6 
 server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java           |   19 
 small-program/pages/index/index.vue                                                             |  193 +++-
 server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java           |  152 +++-
 server/services/src/main/java/com/doumee/dao/business/model/Member.java                         |    7 
 small-program/pages/freight/freight.vue                                                         |  386 ++++++++++-
 33 files changed, 1,757 insertions(+), 175 deletions(-)

diff --git a/server/admin/src/main/java/com/doumee/job/AutoCommentJob.java b/server/admin/src/main/java/com/doumee/job/AutoCommentJob.java
new file mode 100644
index 0000000..402b5cb
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/AutoCommentJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷姩璇勪环
+ * @author  dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("AutoCommentJob")
+public class AutoCommentJob extends BaseJob {
+
+    @Autowired
+    private OrdersService ordersService;
+
+    @Override
+    public JobContext execute(JobParam param) {
+        JobContext jobContext = new JobContext();
+        try {
+            ordersService.autoComment();
+            jobContext.setContext("鑷姩璇勪环");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return jobContext;
+    }
+}
diff --git a/server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java b/server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java
new file mode 100644
index 0000000..74fe0fb
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/AutoConfirmJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷姩纭璁㈠崟淇敼
+ * @author  dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("AutoConfirmJob")
+public class AutoConfirmJob extends BaseJob {
+
+    @Autowired
+    private OrdersService ordersService;
+
+    @Override
+    public JobContext execute(JobParam param) {
+        JobContext jobContext = new JobContext();
+        try {
+            ordersService.autoConfirm();
+            jobContext.setContext("鑷姩纭璁㈠崟淇敼");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return jobContext;
+    }
+}
diff --git a/server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java b/server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java
new file mode 100644
index 0000000..5bcb7af
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/AutoGrabOrdersJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷姩娲惧崟
+ * @author  dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("AutoGrabOrdersJob")
+public class AutoGrabOrdersJob extends BaseJob {
+
+    @Autowired
+    private OrdersService ordersService;
+
+    @Override
+    public JobContext execute(JobParam param) {
+        JobContext jobContext = new JobContext();
+        try {
+            ordersService.autoGrabOrders();
+            jobContext.setContext("鑷姩娲惧崟");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return jobContext;
+    }
+}
diff --git a/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java b/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java
new file mode 100644
index 0000000..4d66167
--- /dev/null
+++ b/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java
@@ -0,0 +1,34 @@
+package com.doumee.job;
+
+import com.doumee.core.job.BaseJob;
+import com.doumee.core.job.JobContext;
+import com.doumee.core.job.JobParam;
+import com.doumee.service.business.OrdersService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鍒濆鍖栬鍗曠紪鍙�
+ * @author  dm
+ * @since 2025/03/31 16:44
+ */
+@Slf4j
+@Component("InitializeCodeJob")
+public class InitializeCodeJob extends BaseJob {
+
+    @Autowired
+    private OrdersService ordersService;
+
+    @Override
+    public JobContext execute(JobParam param) {
+        JobContext jobContext = new JobContext();
+        try {
+            ordersService.initializeCode();
+            jobContext.setContext("鍒濆鍖栬鍗曠紪鍙�");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return jobContext;
+    }
+}
diff --git a/server/pom.xml b/server/pom.xml
index 3c9dcf4..3ba17e0 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -262,6 +262,8 @@
       <artifactId>wechatpay-java</artifactId>
       <version>0.2.12</version>
     </dependency>
+
+
  <!--   <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>spring-cloud-azure-starter-storage-blob</artifactId>
diff --git a/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java b/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java
index 738848c..f4addb1 100644
--- a/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java
+++ b/server/services/src/main/java/com/doumee/api/common/PublicCloudController.java
@@ -61,7 +61,7 @@
     })
     @PostMapping(value = "/upload", headers = "content-type=multipart/form-data")
     @ResponseBody
-    public void upload(HttpServletRequest request, HttpServletResponse response, String folder) throws Exception {
+    public void upload(HttpServletRequest request, HttpServletResponse response, String folder,String flag) throws Exception {
         Date d1 = new Date();
         log.error("鎬诲緱涓婁紶鏂囦欢鎴愬姛=============寮�濮�========="+DateUtil.getPlusTime2(d1));
         if(Objects.isNull(folder)){
@@ -105,6 +105,7 @@
                         fileJSON.put("imgaddr", fName);
                         fileJSON.put("imgname", fileName);
                         fileJSON.put("originname", originname);
+                        fileJSON.put("flag", flag);
                         context.put("data",fileJSON);
                         context.put("message","璇锋眰鎴愬姛");
                         writerJson(response, context);
diff --git a/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java b/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
index f1e4399..06ec043 100644
--- a/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
+++ b/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
@@ -112,7 +112,8 @@
                 .setExpiration(expirationDate)
                 .signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret())
                 .compact();
-        redisTemplate.opsForValue().set(Constants.REDIS_TOKEN_KEY+token,JSONObject.toJSONString(member),jwtProperties.getExpiration(), TimeUnit.MILLISECONDS);
+        redisTemplate.opsForValue().set(Constants.REDIS_TOKEN_KEY+token,JSONObject.toJSONString(member),
+                jwtProperties.getExpiration(), TimeUnit.MILLISECONDS);
         return token;
     }
 
diff --git a/server/services/src/main/java/com/doumee/config/wx/TransferToUser.java b/server/services/src/main/java/com/doumee/config/wx/TransferToUser.java
new file mode 100644
index 0000000..af0b96e
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/config/wx/TransferToUser.java
@@ -0,0 +1,312 @@
+package com.doumee.config.wx;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @Author : Rk
+ * @create 2025/7/17 9:19
+ */
+public class TransferToUser {
+
+    private static String HOST = "https://api.mch.weixin.qq.com";
+    private static String METHOD = "POST";
+    private static String PATH = "/v3/fund-app/mch-transfer/transfer-bills";
+    private static String CANCEL_PATH = "/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}/cancel";
+
+
+    public static void main(String[] args) {
+        // TODO: 璇峰噯澶囧晢鎴峰紑鍙戝繀瑕佸弬鏁帮紝鍙傝�冿細https://pay.weixin.qq.com/doc/v3/merchant/4013070756
+        TransferToUser client = new TransferToUser(
+                "1229817002",                    // 鍟嗘埛鍙凤紝鏄敱寰俊鏀粯绯荤粺鐢熸垚骞跺垎閰嶇粰姣忎釜鍟嗘埛鐨勫敮涓�鏍囪瘑绗︼紝鍟嗘埛鍙疯幏鍙栨柟寮忓弬鑰� https://pay.weixin.qq.com/doc/v3/merchant/4013070756
+                "3FE90C2F3D40A56E1C51926F31B8A8D22426CCE0",         // 鍟嗘埛API璇佷功搴忓垪鍙凤紝濡備綍鑾峰彇璇峰弬鑰� https://pay.weixin.qq.com/doc/v3/merchant/4013053053
+                "d://wechatApiclient_key.pem",    // 鍟嗘埛API璇佷功绉侀挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+                "PUB_KEY_ID_0112298170022025071700291836000600",      // 寰俊鏀粯鍏挜ID锛屽浣曡幏鍙栬鍙傝�� https://pay.weixin.qq.com/doc/v3/merchant/4013038816
+                "d://pub_key.pem"          // 寰俊鏀粯鍏挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+        );
+
+        TransferToUserRequest request = new TransferToUserRequest();
+        request.appid = "wxcd2b89fd2ff065f8"; //灏忕▼搴廼d
+        request.outBillNo = "plfk2020042016";
+        request.transferSceneId = "1005";
+        request.openid = "oKKHU5IFKpss_DIbFX1lqghFJOEg";
+        request.userName = client.encrypt("鏂芥棴杈�");
+        request.transferAmount = 91L;
+        request.transferRemark = "~~~";
+        request.notifyUrl = "https://www.weixin.qq.com/wxpay/pay.php";
+        request.userRecvPerception = "鍔冲姟鎶ラ叕";
+        request.transferSceneReportInfos = new ArrayList<>();
+        {
+            TransferSceneReportInfo item0 = new TransferSceneReportInfo();
+            item0.infoType = "宀椾綅绫诲瀷";
+            item0.infoContent = "瀹屾垚璁㈠崟";
+            request.transferSceneReportInfos.add(item0);
+            TransferSceneReportInfo item1 = new TransferSceneReportInfo();
+            item1.infoType = "鎶ラ叕璇存槑";
+            item1.infoContent = "璁㈠崟鎶ラ叕";
+            request.transferSceneReportInfos.add(item1);
+        };
+        try {
+            TransferToUserResponse response = client.testRun(request);
+
+            // TODO: 璇锋眰鎴愬姛锛岀户缁笟鍔¢�昏緫
+            System.out.println(JSONObject.toJSONString(response));
+        } catch (WXPayUtility.ApiException e) {
+            // TODO: 璇锋眰澶辫触锛屾牴鎹姸鎬佺爜鎵ц涓嶅悓鐨勯�昏緫
+            e.printStackTrace();
+        }
+    }
+
+    private final String mchid;
+    private final String certificateSerialNo;
+    private final PrivateKey privateKey;
+    private final String wechatPayPublicKeyId;
+    private final PublicKey wechatPayPublicKey;
+
+    public TransferToUser(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
+        this.mchid = mchid;
+        this.certificateSerialNo = certificateSerialNo;
+        this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
+        this.wechatPayPublicKeyId = wechatPayPublicKeyId;
+        this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
+    }
+
+    public TransferToUserResponse testRun(TransferToUserRequest request) {
+        String uri = PATH;
+        String reqBody = WXPayUtility.toJson(request);
+
+        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
+        reqBuilder.addHeader("Accept", "application/json");
+        reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
+        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody));
+        reqBuilder.addHeader("Content-Type", "application/json");
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
+        reqBuilder.method(METHOD, requestBody);
+        Request httpRequest = reqBuilder.build();
+
+        // 鍙戦�丠TTP璇锋眰
+        OkHttpClient client = new OkHttpClient.Builder().build();
+        try (Response httpResponse = client.newCall(httpRequest).execute()) {
+            String respBody = WXPayUtility.extractBody(httpResponse);
+            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
+                // 2XX 鎴愬姛锛岄獙璇佸簲绛旂鍚�
+                WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
+                        httpResponse.headers(), respBody);
+
+                // 浠嶩TTP搴旂瓟鎶ユ枃鏋勫缓杩斿洖鏁版嵁
+                return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
+            } else {
+                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
+        }
+    }
+
+    public TransferToUserResponse run(TransferToUserRequest request,String name) {
+        String uri = PATH;
+        request.appid = WxMiniConfig.wxProperties.getSubAppId();
+        request.transferSceneId = "1005";
+        request.userRecvPerception = "鍔冲姟鎶ラ叕";
+        if(request.transferAmount >= 30){
+            request.userName = this.encrypt(name);
+        }
+
+        request.transferSceneReportInfos = new ArrayList<>();
+        {
+            TransferSceneReportInfo item0 = new TransferSceneReportInfo();
+            item0.infoType = "宀椾綅绫诲瀷";
+            item0.infoContent = "瀹屾垚璁㈠崟";
+            request.transferSceneReportInfos.add(item0);
+            TransferSceneReportInfo item1 = new TransferSceneReportInfo();
+            item1.infoType = "鎶ラ叕璇存槑";
+            item1.infoContent = "璁㈠崟鎶ラ叕";
+            request.transferSceneReportInfos.add(item1);
+        };
+        String reqBody = WXPayUtility.toJson(request);
+
+        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
+        reqBuilder.addHeader("Accept", "application/json");
+        reqBuilder.addHeader("Wechatpay-Serial", WxMiniConfig.wxProperties.getWechatPayPublicKeyId());
+        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(WxMiniConfig.wxProperties.getMchId(),
+                WxMiniConfig.wxProperties.getWechatSerialNumer(),
+                WXPayUtility.loadPrivateKeyFromPath(WxMiniConfig.wxProperties.getWechatPrivateKeyPath()),
+                METHOD, uri, reqBody));
+
+//        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody));
+        reqBuilder.addHeader("Content-Type", "application/json");
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
+        reqBuilder.method(METHOD, requestBody);
+        Request httpRequest = reqBuilder.build();
+
+        // 鍙戦�丠TTP璇锋眰
+        OkHttpClient client = new OkHttpClient.Builder().build();
+        try (Response httpResponse = client.newCall(httpRequest).execute()) {
+            String respBody = WXPayUtility.extractBody(httpResponse);
+            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
+                // 2XX 鎴愬姛锛岄獙璇佸簲绛旂鍚�
+                WXPayUtility.validateResponse(WxMiniConfig.wxProperties.getWechatPayPublicKeyId(), WXPayUtility.loadPublicKeyFromPath(WxMiniConfig.wxProperties.getWechatPubKeyPath()),
+                        httpResponse.headers(), respBody);
+
+                // 浠嶩TTP搴旂瓟鎶ユ枃鏋勫缓杩斿洖鏁版嵁
+                return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
+            } else {
+                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
+        }
+    }
+
+
+    public TransferToUser.CancelTransferResponse cancelRun(TransferToUser.CancelTransferRequest request) {
+        String uri = CANCEL_PATH;
+        uri = uri.replace("{out_bill_no}", WXPayUtility.urlEncode(request.outBillNo));
+
+        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
+        reqBuilder.addHeader("Accept", "application/json");
+        reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
+        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(WxMiniConfig.wxProperties.getMchId(),
+                WxMiniConfig.wxProperties.getWechatSerialNumer(),
+                WXPayUtility.loadPrivateKeyFromPath(WxMiniConfig.wxProperties.getWechatPrivateKeyPath()),
+                METHOD, uri, null));
+        reqBuilder.addHeader("Content-Type", "application/json");
+        RequestBody emptyBody = RequestBody.create(null, "");
+        reqBuilder.method(METHOD, emptyBody);
+        Request httpRequest = reqBuilder.build();
+
+        // 鍙戦�丠TTP璇锋眰
+        OkHttpClient client = new OkHttpClient.Builder().build();
+        try (Response httpResponse = client.newCall(httpRequest).execute()) {
+            String respBody = WXPayUtility.extractBody(httpResponse);
+            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
+                // 2XX 鎴愬姛锛岄獙璇佸簲绛旂鍚�
+                WXPayUtility.validateResponse(WxMiniConfig.wxProperties.getWechatPayPublicKeyId(), WXPayUtility.loadPublicKeyFromPath(WxMiniConfig.wxProperties.getWechatPubKeyPath()),
+                        httpResponse.headers(), respBody);
+
+                // 浠嶩TTP搴旂瓟鎶ユ枃鏋勫缓杩斿洖鏁版嵁
+                return WXPayUtility.fromJson(respBody, TransferToUser.CancelTransferResponse.class);
+            } else {
+                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
+        }
+    }
+
+
+
+    public String encrypt(String plainText) {
+        return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText);
+    }
+
+    public static class TransferToUserResponse {
+        @SerializedName("out_bill_no")
+        public String outBillNo;
+
+        @SerializedName("transfer_bill_no")
+        public String transferBillNo;
+
+        @SerializedName("create_time")
+        public String createTime;
+
+        @SerializedName("state")
+        public TransferBillStatus state;
+
+        @SerializedName("package_info")
+        public String packageInfo;
+    }
+
+    public enum TransferBillStatus {
+        @SerializedName("ACCEPTED")
+        ACCEPTED,
+        @SerializedName("PROCESSING")
+        PROCESSING,
+        @SerializedName("WAIT_USER_CONFIRM")
+        WAIT_USER_CONFIRM,
+        @SerializedName("TRANSFERING")
+        TRANSFERING,
+        @SerializedName("SUCCESS")
+        SUCCESS,
+        @SerializedName("FAIL")
+        FAIL,
+        @SerializedName("CANCELING")
+        CANCELING,
+        @SerializedName("CANCELLED")
+        CANCELLED
+    }
+
+    public static class TransferSceneReportInfo {
+        @SerializedName("info_type")
+        public String infoType;
+
+        @SerializedName("info_content")
+        public String infoContent;
+    }
+
+    public static class TransferToUserRequest {
+
+        @SerializedName("appid")
+        public String appid;
+
+        @SerializedName("out_bill_no")
+        public String outBillNo;
+
+        @SerializedName("transfer_scene_id")
+        public String transferSceneId;
+
+        @SerializedName("openid")
+        public String openid;
+
+        @SerializedName("user_name")
+        public String userName;
+
+        @SerializedName("transfer_amount")
+        public Long transferAmount;
+
+        @SerializedName("transfer_remark")
+        public String transferRemark;
+
+        @SerializedName("notify_url")
+        public String notifyUrl;
+
+        @SerializedName("user_recv_perception")
+        public String userRecvPerception;
+
+        @SerializedName("transfer_scene_report_infos")
+        public List<TransferSceneReportInfo> transferSceneReportInfos;
+    }
+
+    public static class CancelTransferResponse {
+        @SerializedName("out_bill_no")
+        public String outBillNo;
+
+        @SerializedName("transfer_bill_no")
+        public String transferBillNo;
+
+        @SerializedName("state")
+        public String state;
+
+        @SerializedName("update_time")
+        public String updateTime;
+    }
+
+    public static class CancelTransferRequest {
+        @SerializedName("out_bill_no")
+        @Expose(serialize = false)
+        public String outBillNo;
+    }
+
+}
diff --git a/server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java b/server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java
new file mode 100644
index 0000000..bf29e52
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/config/wx/WXPayUtility.java
@@ -0,0 +1,456 @@
+package com.doumee.config.wx;
+
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.annotations.Expose;
+import com.wechat.pay.java.core.util.GsonUtil;
+import okhttp3.Headers;
+import okhttp3.Response;
+import okio.BufferedSource;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.time.DateTimeException;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Base64;
+import java.util.Map;
+import java.util.Objects;
+
+public class WXPayUtility {
+    private static final Gson gson = new GsonBuilder()
+            .disableHtmlEscaping()
+            .addSerializationExclusionStrategy(new ExclusionStrategy() {
+                @Override
+                public boolean shouldSkipField(FieldAttributes fieldAttributes) {
+                    final Expose expose = fieldAttributes.getAnnotation(Expose.class);
+                    return expose != null && !expose.serialize();
+                }
+
+                @Override
+                public boolean shouldSkipClass(Class<?> aClass) {
+                    return false;
+                }
+            })
+            .addDeserializationExclusionStrategy(new ExclusionStrategy() {
+                @Override
+                public boolean shouldSkipField(FieldAttributes fieldAttributes) {
+                    final Expose expose = fieldAttributes.getAnnotation(Expose.class);
+                    return expose != null && !expose.deserialize();
+                }
+
+                @Override
+                public boolean shouldSkipClass(Class<?> aClass) {
+                    return false;
+                }
+            })
+            .create();
+    private static final char[] SYMBOLS =
+            "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+    private static final SecureRandom random = new SecureRandom();
+
+    /**
+     * 灏� Object 杞崲涓� JSON 瀛楃涓�
+     */
+    public static String toJson(Object object) {
+        return gson.toJson(object);
+    }
+
+    /**
+     * 灏� JSON 瀛楃涓茶В鏋愪负鐗瑰畾绫诲瀷鐨勫疄渚�
+     */
+    public static <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
+        return gson.fromJson(json, classOfT);
+    }
+
+    /**
+     * 浠庡叕绉侀挜鏂囦欢璺緞涓鍙栨枃浠跺唴瀹�
+     *
+     * @param keyPath 鏂囦欢璺緞
+     * @return 鏂囦欢鍐呭
+     */
+    private static String readKeyStringFromPath(String keyPath) {
+        try {
+            return new String(Files.readAllBytes(Paths.get(keyPath)), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    /**
+     * 璇诲彇 PKCS#8 鏍煎紡鐨勭閽ュ瓧绗︿覆骞跺姞杞戒负绉侀挜瀵硅薄
+     *
+     * @param keyString 绉侀挜鏂囦欢鍐呭锛屼互 -----BEGIN PRIVATE KEY----- 寮�澶�
+     * @return PrivateKey 瀵硅薄
+     */
+    public static PrivateKey loadPrivateKeyFromString(String keyString) {
+        try {
+            keyString = keyString.replace("-----BEGIN PRIVATE KEY-----", "")
+                    .replace("-----END PRIVATE KEY-----", "")
+                    .replaceAll("\\s+", "");
+            return KeyFactory.getInstance("RSA").generatePrivate(
+                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString)));
+        } catch (NoSuchAlgorithmException e) {
+            throw new UnsupportedOperationException(e);
+        } catch (InvalidKeySpecException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * 浠� PKCS#8 鏍煎紡鐨勭閽ユ枃浠朵腑鍔犺浇绉侀挜
+     *
+     * @param keyPath 绉侀挜鏂囦欢璺緞
+     * @return PrivateKey 瀵硅薄
+     */
+    public static PrivateKey loadPrivateKeyFromPath(String keyPath) {
+        return loadPrivateKeyFromString(readKeyStringFromPath(keyPath));
+    }
+
+    /**
+     * 璇诲彇 PKCS#8 鏍煎紡鐨勫叕閽ュ瓧绗︿覆骞跺姞杞戒负鍏挜瀵硅薄
+     *
+     * @param keyString 鍏挜鏂囦欢鍐呭锛屼互 -----BEGIN PUBLIC KEY----- 寮�澶�
+     * @return PublicKey 瀵硅薄
+     */
+    public static PublicKey loadPublicKeyFromString(String keyString) {
+        try {
+            keyString = keyString.replace("-----BEGIN PUBLIC KEY-----", "")
+                    .replace("-----END PUBLIC KEY-----", "")
+                    .replaceAll("\\s+", "");
+            return KeyFactory.getInstance("RSA").generatePublic(
+                    new X509EncodedKeySpec(Base64.getDecoder().decode(keyString)));
+        } catch (NoSuchAlgorithmException e) {
+            throw new UnsupportedOperationException(e);
+        } catch (InvalidKeySpecException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * 浠� PKCS#8 鏍煎紡鐨勫叕閽ユ枃浠朵腑鍔犺浇鍏挜
+     *
+     * @param keyPath 鍏挜鏂囦欢璺緞
+     * @return PublicKey 瀵硅薄
+     */
+    public static PublicKey loadPublicKeyFromPath(String keyPath) {
+        return loadPublicKeyFromString(readKeyStringFromPath(keyPath));
+    }
+
+    /**
+     * 鍒涘缓鎸囧畾闀垮害鐨勯殢鏈哄瓧绗︿覆锛屽瓧绗﹂泦涓篬0-9a-zA-Z]锛屽彲鐢ㄤ簬瀹夊叏鐩稿叧鐢ㄩ��
+     */
+    public static String createNonce(int length) {
+        char[] buf = new char[length];
+        for (int i = 0; i < length; ++i) {
+            buf[i] = SYMBOLS[random.nextInt(SYMBOLS.length)];
+        }
+        return new String(buf);
+    }
+
+    /**
+     * 浣跨敤鍏挜鎸夌収 RSA_PKCS1_OAEP_PADDING 绠楁硶杩涜鍔犲瘑
+     *
+     * @param publicKey 鍔犲瘑鐢ㄥ叕閽ュ璞�
+     * @param plaintext 寰呭姞瀵嗘槑鏂�
+     * @return 鍔犲瘑鍚庡瘑鏂�
+     */
+    public static String encrypt(PublicKey publicKey, String plaintext) {
+        final String transformation = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
+
+        try {
+            Cipher cipher = Cipher.getInstance(transformation);
+            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+            return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)));
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+            throw new IllegalArgumentException("The current Java environment does not support " + transformation, e);
+        } catch (InvalidKeyException e) {
+            throw new IllegalArgumentException("RSA encryption using an illegal publicKey", e);
+        } catch (BadPaddingException | IllegalBlockSizeException e) {
+            throw new IllegalArgumentException("Plaintext is too long", e);
+        }
+    }
+
+    /**
+     * 浣跨敤绉侀挜鎸夌収鎸囧畾绠楁硶杩涜绛惧悕
+     *
+     * @param message 寰呯鍚嶄覆
+     * @param algorithm 绛惧悕绠楁硶锛屽 SHA256withRSA
+     * @param privateKey 绛惧悕鐢ㄧ閽ュ璞�
+     * @return 绛惧悕缁撴灉
+     */
+    public static String sign(String message, String algorithm, PrivateKey privateKey) {
+        byte[] sign;
+        try {
+            Signature signature = Signature.getInstance(algorithm);
+            signature.initSign(privateKey);
+            signature.update(message.getBytes(StandardCharsets.UTF_8));
+            sign = signature.sign();
+        } catch (NoSuchAlgorithmException e) {
+            throw new UnsupportedOperationException("The current Java environment does not support " + algorithm, e);
+        } catch (InvalidKeyException e) {
+            throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e);
+        } catch (SignatureException e) {
+            throw new RuntimeException("An error occurred during the sign process.", e);
+        }
+        return Base64.getEncoder().encodeToString(sign);
+    }
+
+    /**
+     * 浣跨敤鍏挜鎸夌収鐗瑰畾绠楁硶楠岃瘉绛惧悕
+     *
+     * @param message 寰呯鍚嶄覆
+     * @param signature 寰呴獙璇佺殑绛惧悕鍐呭
+     * @param algorithm 绛惧悕绠楁硶锛屽锛歋HA256withRSA
+     * @param publicKey 楠岀鐢ㄥ叕閽ュ璞�
+     * @return 绛惧悕楠岃瘉鏄惁閫氳繃
+     */
+    public static boolean verify(String message, String signature, String algorithm,
+                                 PublicKey publicKey) {
+        try {
+            Signature sign = Signature.getInstance(algorithm);
+            sign.initVerify(publicKey);
+            sign.update(message.getBytes(StandardCharsets.UTF_8));
+            return sign.verify(Base64.getDecoder().decode(signature));
+        } catch (SignatureException e) {
+            return false;
+        } catch (InvalidKeyException e) {
+            throw new IllegalArgumentException("verify uses an illegal publickey.", e);
+        } catch (NoSuchAlgorithmException e) {
+            throw new UnsupportedOperationException("The current Java environment does not support" + algorithm, e);
+        }
+    }
+
+    /**
+     * 鏍规嵁寰俊鏀粯APIv3璇锋眰绛惧悕瑙勫垯鏋勯�� Authorization 绛惧悕
+     *
+     * @param mchid 鍟嗘埛鍙�
+     * @param certificateSerialNo 鍟嗘埛API璇佷功搴忓垪鍙�
+     * @param privateKey 鍟嗘埛API璇佷功绉侀挜
+     * @param method 璇锋眰鎺ュ彛鐨凥TTP鏂规硶锛岃浣跨敤鍏ㄥぇ鍐欒〃杩帮紝濡� GET銆丳OST銆丳UT銆丏ELETE
+     * @param uri 璇锋眰鎺ュ彛鐨刄RL
+     * @param body 璇锋眰鎺ュ彛鐨凚ody
+     * @return 鏋勯�犲ソ鐨勫井淇℃敮浠楢PIv3 Authorization 澶�
+     */
+    public static String buildAuthorization(String mchid, String certificateSerialNo,
+                                            PrivateKey privateKey,
+                                            String method, String uri, String body) {
+        String nonce = createNonce(32);
+        long timestamp = Instant.now().getEpochSecond();
+
+        String message = String.format("%s\n%s\n%d\n%s\n%s\n", method, uri, timestamp, nonce,
+                body == null ? "" : body);
+
+        String signature = sign(message, "SHA256withRSA", privateKey);
+
+        return String.format(
+                "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\"," +
+                        "timestamp=\"%d\",serial_no=\"%s\"",
+                mchid, nonce, signature, timestamp, certificateSerialNo);
+    }
+
+    /**
+     * 瀵瑰弬鏁拌繘琛� URL 缂栫爜
+     *
+     * @param content 鍙傛暟鍐呭
+     * @return 缂栫爜鍚庣殑鍐呭
+     */
+    public static String urlEncode(String content) {
+        try {
+            return URLEncoder.encode(content, StandardCharsets.UTF_8.name());
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 瀵瑰弬鏁癕ap杩涜 URL 缂栫爜锛岀敓鎴� QueryString
+     *
+     * @param params Query鍙傛暟Map
+     * @return QueryString
+     */
+    public static String urlEncode(Map<String, Object> params) {
+        if (params == null || params.isEmpty()) {
+            return "";
+        }
+
+        int index = 0;
+        StringBuilder result = new StringBuilder();
+        for (Map.Entry<String, Object> entry : params.entrySet()) {
+            result.append(entry.getKey())
+                    .append("=")
+                    .append(urlEncode(entry.getValue().toString()));
+            index++;
+            if (index < params.size()) {
+                result.append("&");
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * 浠庡簲绛斾腑鎻愬彇 Body
+     *
+     * @param response HTTP 璇锋眰搴旂瓟瀵硅薄
+     * @return 搴旂瓟涓殑Body鍐呭锛孊ody涓虹┖鏃惰繑鍥炵┖瀛楃涓�
+     */
+    public static String extractBody(Response response) {
+        if (response.body() == null) {
+            return "";
+        }
+
+        try {
+            BufferedSource source = response.body().source();
+            return source.readUtf8();
+        } catch (IOException e) {
+            throw new RuntimeException(String.format("An error occurred during reading response body. Status: %d", response.code()), e);
+        }
+    }
+
+    /**
+     * 鏍规嵁寰俊鏀粯APIv3搴旂瓟楠岀瑙勫垯瀵瑰簲绛旂鍚嶈繘琛岄獙璇侊紝楠岃瘉涓嶉�氳繃鏃舵姏鍑哄紓甯�
+     *
+     * @param wechatpayPublicKeyId 寰俊鏀粯鍏挜ID
+     * @param wechatpayPublicKey 寰俊鏀粯鍏挜瀵硅薄
+     * @param headers 寰俊鏀粯搴旂瓟 Header 鍒楄〃
+     * @param body 寰俊鏀粯搴旂瓟 Body
+     */
+    public static void validateResponse(String wechatpayPublicKeyId, PublicKey wechatpayPublicKey,
+                                        Headers headers,
+                                        String body) {
+        String timestamp = headers.get("Wechatpay-Timestamp");
+        try {
+            Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestamp));
+            // 鎷掔粷杩囨湡璇锋眰
+            if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= 5) {
+                throw new IllegalArgumentException(
+                        String.format("Validate http response,timestamp[%s] of httpResponse is expires, "
+                                        + "request-id[%s]",
+                                timestamp, headers.get("Request-ID")));
+            }
+        } catch (DateTimeException | NumberFormatException e) {
+            throw new IllegalArgumentException(
+                    String.format("Validate http response,timestamp[%s] of httpResponse is invalid, " +
+                                    "request-id[%s]", timestamp,
+                            headers.get("Request-ID")));
+        }
+        String message = String.format("%s\n%s\n%s\n", timestamp, headers.get("Wechatpay-Nonce"),
+                body == null ? "" : body);
+        String serialNumber = headers.get("Wechatpay-Serial");
+        if (!Objects.equals(serialNumber, wechatpayPublicKeyId)) {
+            throw new IllegalArgumentException(
+                    String.format("Invalid Wechatpay-Serial, Local: %s, Remote: %s", wechatpayPublicKeyId,
+                            serialNumber));
+        }
+        String signature = headers.get("Wechatpay-Signature");
+
+        boolean success = verify(message, signature, "SHA256withRSA", wechatpayPublicKey);
+        if (!success) {
+            throw new IllegalArgumentException(
+                    String.format("Validate response failed,the WechatPay signature is incorrect.%n"
+                                    + "Request-ID[%s]\tresponseHeader[%s]\tresponseBody[%.1024s]",
+                            headers.get("Request-ID"), headers, body));
+        }
+    }
+
+    /**
+     * 寰俊鏀粯API閿欒寮傚父锛屽彂閫丠TTP璇锋眰鎴愬姛锛屼絾杩斿洖鐘舵�佺爜涓嶆槸 2XX 鏃舵姏鍑烘湰寮傚父
+     */
+    public static class ApiException extends RuntimeException {
+        private static final long serialVersionUID = 2261086748874802175L;
+
+        private final int statusCode;
+        private final String body;
+        private final Headers headers;
+        private final String errorCode;
+        private final String errorMessage;
+
+        public ApiException(int statusCode, String body, Headers headers) {
+            super(String.format("寰俊鏀粯API璁块棶澶辫触锛孲tatusCode: [%s], Body: [%s], Headers: [%s]", statusCode, body, headers));
+            this.statusCode = statusCode;
+            this.body = body;
+            this.headers = headers;
+
+            if (body != null && !body.isEmpty()) {
+                JsonElement code;
+                JsonElement message;
+
+                try {
+                    JsonObject jsonObject = GsonUtil.getGson().fromJson(body, JsonObject.class);
+                    code = jsonObject.get("code");
+                    message = jsonObject.get("message");
+                } catch (JsonSyntaxException ignored) {
+                    code = null;
+                    message = null;
+                }
+                this.errorCode = code == null ? null : code.getAsString();
+                this.errorMessage = message == null ? null : message.getAsString();
+            } else {
+                this.errorCode = null;
+                this.errorMessage = null;
+            }
+        }
+
+        /**
+         * 鑾峰彇 HTTP 搴旂瓟鐘舵�佺爜
+         */
+        public int getStatusCode() {
+            return statusCode;
+        }
+
+        /**
+         * 鑾峰彇 HTTP 搴旂瓟鍖呬綋鍐呭
+         */
+        public String getBody() {
+            return body;
+        }
+
+        /**
+         * 鑾峰彇 HTTP 搴旂瓟 Header
+         */
+        public Headers getHeaders() {
+            return headers;
+        }
+
+        /**
+         * 鑾峰彇 閿欒鐮� 锛堥敊璇簲绛斾腑鐨� code 瀛楁锛�
+         */
+        public String getErrorCode() {
+            return errorCode;
+        }
+
+        /**
+         * 鑾峰彇 閿欒娑堟伅 锛堥敊璇簲绛斾腑鐨� message 瀛楁锛�
+         */
+        public String getErrorMessage() {
+            return errorMessage;
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java b/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
index 3c9cf04..e0b82bb 100644
--- a/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
+++ b/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
@@ -36,7 +36,7 @@
     public static JsapiServiceExtension jsapiExtService;
     public static BillDownloadService billDownloadService;
     public static WxPayProperties wxProperties;
-
+    public static  TransferToUser transferToUser;
     @Autowired
     private WxPayProperties wxPayProperties;
 
@@ -49,6 +49,8 @@
         this.load_WxMaService();
         this.load_wxPayService();
         this.load_wxPayV2Service();
+        this.load_transferToUser();
+        this.load_transferToUser();
         this.wxProperties = wxPayProperties;
     }
     /**
@@ -134,7 +136,18 @@
 //    }
 
 
+    public void load_transferToUser()
+    {
+        TransferToUser transferToUser = new TransferToUser(
+                StringUtils.trimToNull(wxPayProperties.getMchId()), //鍟嗘埛id
+                StringUtils.trimToNull(wxPayProperties.getWechatSerialNumer()), //鍟嗘埛API璇佷功搴忓垪鍙凤紝濡備綍鑾峰彇璇峰弬鑰� https://pay.weixin.qq.com/doc/v3/merchant/4013053053
+                StringUtils.trimToNull(wxPayProperties.getWechatPrivateKeyPath()), // 鍟嗘埛API璇佷功绉侀挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+                StringUtils.trimToNull(wxPayProperties.getWechatPayPublicKeyId()),   // 寰俊鏀粯鍏挜ID锛屽浣曡幏鍙栬鍙傝�� https://pay.weixin.qq.com/doc/v3/merchant/4013038816
+                StringUtils.trimToNull(wxPayProperties.getWechatPubKeyPath()) // 寰俊鏀粯鍏挜鏂囦欢璺緞锛屾湰鍦版枃浠惰矾寰�
+        );
 
+        this.transferToUser = transferToUser;
+    }
 
 
 }
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java b/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
index e5c948d..b9d5af5 100644
--- a/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
+++ b/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
@@ -63,4 +63,10 @@
     private String privateKeyPath ;
     private String privateCertPath;// gybike
 
+
+    private String wechatSerialNumer;
+    private String wechatPayPublicKeyId; // 寰俊鏀粯鍏挜ID
+    private String wechatPubKeyPath; //寰俊鏀粯鍏挜鏂囦欢璺緞
+    private String wechatPrivateKeyPath;
+
 }
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/Member.java b/server/services/src/main/java/com/doumee/dao/business/model/Member.java
index d041151..474874c 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/Member.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/Member.java
@@ -190,4 +190,11 @@
     @TableField(exist = false)
     private IdentityInfo chefIdentityModel;
 
+    @ApiModelProperty(value = "鎺ュ崟鏉冮噸", example = "1")
+    @TableField(exist = false)
+    private Integer level;
+
+    @ApiModelProperty(value = "璺濈", example = "1")
+    @TableField(exist = false)
+    private BigDecimal distance;
 }
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java b/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java
index 5415345..dd1f568 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/MemberRevenue.java
@@ -47,7 +47,7 @@
     @ApiModelProperty(value = "浼氬憳涓婚敭", example = "1")
     private Integer memberId;
 
-    @ApiModelProperty(value = "鍙樺姩绫诲瀷:0=鐢ㄥ伐鍗曟敹鍏ワ紱1=璐ц繍鍗曟敹鍏ワ紱2=渚涢鍗曟敹鍏ワ紱3=鎻愮幇鐢宠锛�", example = "1")
+    @ApiModelProperty(value = "鍙樺姩绫诲瀷:0=鐢ㄥ伐鍗曟敹鍏ワ紱1=璐ц繍鍗曟敹鍏ワ紱2=渚涢鍗曟敹鍏ワ紱3=鎻愮幇鐢宠锛�4=鎻愮幇澶辫触閫�鍥�", example = "1")
     private Integer type;
 
     @ApiModelProperty(value = "鏀舵敮绫诲瀷:1=鏀跺叆锛�-1=鏀嚭锛�", example = "1")
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/Orders.java b/server/services/src/main/java/com/doumee/dao/business/model/Orders.java
index 50289c1..a3f0a7b 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/Orders.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/Orders.java
@@ -90,10 +90,10 @@
     @ApiModelProperty(value = "鐢ㄥ伐绫诲瀷:0=閲囨憳宸ワ紱1=鍒嗘嫞宸ワ紱2=鍖呰宸ワ紱锛堢敤宸ヨ鍗曪級", example = "1")
     private Integer workType;
 
-    @ApiModelProperty(value = "璁′环鏁伴噺1(澶╂暟/鐢ㄨ溅娆℃暟/灏忔椂/鏂ゆ暟)", example = "1")
+    @ApiModelProperty(value = "璁′环鏁伴噺1((閲嶉噺/浜烘暟/锛堝ぉ鏁�/灏忔椂/閲嶉噺锛�/锛堝ぉ鏁�/娆℃暟锛�/鐢ㄩ澶╂暟)", example = "1")
     private Integer priceNum1;
 
-    @ApiModelProperty(value = "璁′环鏁伴噺2(浜烘暟/鐢ㄩ浠芥暟)", example = "1")
+    @ApiModelProperty(value = "璁′环鏁伴噺2(鍒嗘嫞宸�/鍖呰宸� 浜烘暟)", example = "1")
     private Integer priceNum2;
 
     @ApiModelProperty(value = "闇�姹傝ˉ鍏�")
@@ -102,10 +102,8 @@
     @ApiModelProperty(value = "璐圭敤鏍囧噯", example = "1")
     private Long price;
 
-
     @ApiModelProperty(value = "棰勪及璐圭敤", example = "1")
     private Long estimatedAccount;
-
 
     @ApiModelProperty(value = "瀹為檯鏀粯璐圭敤", example = "1")
     private Long payAccount;
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java b/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java
index 02ed5ef..4b5050e 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/WithdrawalOrders.java
@@ -27,7 +27,7 @@
 
     @ApiModelProperty(value = "鏄惁宸插垹闄� 0鏈垹闄� 1宸插垹闄�", example = "1")
     @ExcelColumn(name="鏄惁宸插垹闄� 0鏈垹闄� 1宸插垹闄�")
-    private Byte deleted;
+    private Integer deleted;
 
     @ApiModelProperty(value = "鍒涘缓浜虹紪鐮�", example = "1")
     @ExcelColumn(name="鍒涘缓浜虹紪鐮�")
@@ -84,4 +84,10 @@
     @ApiModelProperty(value = "鍏宠仈璁㈠崟涓婚敭 orders", example = "1")
     @ExcelColumn(name="鍏宠仈璁㈠崟涓婚敭 orders")
     private Integer objId;
+
+    @ApiModelProperty(value = "鎻愮幇鐢宠鍗曞彿")
+    @ExcelColumn(name="鎻愮幇鐢宠鍗曞彿")
+    private String outBillNo;
+
+
 }
diff --git a/server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java b/server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java
new file mode 100644
index 0000000..011b69e
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/vo/OrderReleaseVO.java
@@ -0,0 +1,21 @@
+package com.doumee.dao.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @Author : Rk
+ * @create 2025/7/10 15:09
+ */
+@Data
+public class OrderReleaseVO {
+
+    @ApiModelProperty(value = "璁㈠崟涓婚敭")
+    private Integer id;
+
+    @ApiModelProperty(value = "鏀粯璇︽儏")
+    private Object object;
+
+}
diff --git a/server/services/src/main/java/com/doumee/service/business/MemberService.java b/server/services/src/main/java/com/doumee/service/business/MemberService.java
index 3255553..c09bdf0 100644
--- a/server/services/src/main/java/com/doumee/service/business/MemberService.java
+++ b/server/services/src/main/java/com/doumee/service/business/MemberService.java
@@ -149,4 +149,6 @@
     Member getMemberInfo(Integer memberId);
 
     UserCenterVO getPlatformAboutUs();
+
+    void logOff(String token,Integer memberId);
 }
diff --git a/server/services/src/main/java/com/doumee/service/business/OrdersService.java b/server/services/src/main/java/com/doumee/service/business/OrdersService.java
index 4132624..283b40f 100644
--- a/server/services/src/main/java/com/doumee/service/business/OrdersService.java
+++ b/server/services/src/main/java/com/doumee/service/business/OrdersService.java
@@ -9,6 +9,7 @@
 import com.doumee.dao.dto.ConfirmUpdOrderDTO;
 import com.doumee.dao.dto.DoneOrderDTO;
 import com.doumee.dao.dto.UpdOrderDataDTO;
+import com.doumee.dao.vo.OrderReleaseVO;
 import com.wechat.pay.java.service.refund.model.RefundNotification;
 
 import java.util.List;
@@ -26,7 +27,7 @@
      * @param orders 瀹炰綋瀵硅薄
      * @return Integer
      */
-    Object create(Orders orders);
+    OrderReleaseVO create(Orders orders);
 
     /**
      * 涓婚敭鍒犻櫎
@@ -137,4 +138,10 @@
     void autoComment();
 
     void autoConfirm();
+
+    Long getTotal(Orders orders);
+
+    void autoGrabOrders();
+
+    void initializeCode();
 }
diff --git a/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java b/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java
index 3f99a0f..3ca45be 100644
--- a/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java
+++ b/server/services/src/main/java/com/doumee/service/business/WithdrawalOrdersService.java
@@ -1,5 +1,6 @@
 package com.doumee.service.business;
 
+import com.doumee.config.wx.TransferToUser;
 import com.doumee.core.model.PageData;
 import com.doumee.core.model.PageWrap;
 import com.doumee.dao.business.model.WithdrawalOrders;
@@ -97,6 +98,8 @@
      */
     long count(WithdrawalOrders withdrawalOrders);
 
-    void  applyWithdrawal(WithdrawalDTO withdrawalDTO);
+    TransferToUser.TransferToUserResponse  applyWithdrawal(WithdrawalDTO withdrawalDTO);
+
+    void cancelTransfer(TransferToUser.CancelTransferRequest request);
 
 }
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
index 9b1f873..fdab8b9 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
@@ -254,10 +254,15 @@
         List<Category> categoryList = categoryMapper.selectList(new QueryWrapper<Category>().lambda().eq(Category::getDeleted,Constants.ZERO).eq(Category::getStatus,Constants.ZERO)
                 .eq(Objects.nonNull(type),Category::getType,type));
         if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(categoryList)){
+            String path  = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.RESOURCE_PATH).getCode()
+                    +systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.CATEGORY_FILES).getCode();
             for (Category category:categoryList) {
                 if(StringUtils.isNotBlank(category.getDetail())){
                     category.setDetailList(JSONArray.parseArray(category.getDetail()));
                 }
+                if(StringUtils.isNotBlank(category.getIcon())){
+                    category.setIconFull(path + category.getIcon());
+                }
             }
         }
         return categoryList;
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
index 6602688..25d4e53 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -2,6 +2,7 @@
 
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
+import com.alibaba.fastjson.JSONObject;
 import com.doumee.biz.system.SystemDictDataBiz;
 import com.doumee.config.jwt.JwtTokenUtil;
 import com.doumee.config.wx.WxMiniConfig;
@@ -33,13 +34,16 @@
 import nonapi.io.github.classgraph.json.Id;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
+import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -342,7 +346,10 @@
     @Override
     public void editMemberInfo(Member member){
         if(Objects.isNull(member)
-            || ( StringUtils.isBlank(member.getCoverImage()) || StringUtils.isBlank(member.getName()) || StringUtils.isBlank(member.getNickName()) || Objects.isNull(member.getAutoReceiveStatus()) )){
+            || ( StringUtils.isBlank(member.getCoverImage())
+                && StringUtils.isBlank(member.getName())
+                && StringUtils.isBlank(member.getNickName())
+                && Objects.isNull(member.getAutoReceiveStatus()) )){
             throw new BusinessException(ResponseStatus.BAD_REQUEST);
         }
         memberMapper.update(new UpdateWrapper<Member>().lambda()
@@ -381,6 +388,11 @@
         Member member  = this.findById(memberId);
         if(Objects.isNull(member)){
             throw new BusinessException(ResponseStatus.DATA_EMPTY);
+        }
+        if(StringUtils.isNotBlank(member.getCoverImage())){
+            String path  = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.RESOURCE_PATH).getCode()
+                    +systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.MEMBER_FILES).getCode();
+            member.setFullCoverImage(path + member.getCoverImage());
         }
         UserCenterVO userCenterVO = new UserCenterVO();
         userCenterVO.setReleaseTaskTotal(Constants.ZERO);
@@ -422,6 +434,11 @@
         return userCenterVO;
     }
 
+    @Override
+    public void logOff(String token,Integer memberId){
+        memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" openid = null ").eq(Member::getId,memberId));
+        jwtTokenUtil.logoutForH5(token);
+    }
 
 
 
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
index 8bd112f..a640402 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -17,6 +17,7 @@
 import com.doumee.dao.business.*;
 import com.doumee.dao.business.model.*;
 import com.doumee.dao.dto.*;
+import com.doumee.dao.vo.OrderReleaseVO;
 import com.doumee.service.business.OrdersService;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -42,10 +43,7 @@
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -91,7 +89,8 @@
 
     @Override
     @Transactional(rollbackFor = {Exception.class,BusinessException.class})
-    public Object create(Orders orders) {
+    public OrderReleaseVO create(Orders orders) {
+        OrderReleaseVO orderReleaseVO = new OrderReleaseVO();
         Object objects = null;
         this.initVerification(orders);
         orders.setCreateTime(new Date());
@@ -120,15 +119,16 @@
             orders.setStatus(Constants.ordersStatus.waitPay.getKey());
             //鍞よ捣鏀粯涓氬姟
             objects = this.getWxPayResponse(orders,orders.getMember().getOpenid());
+            orderReleaseVO.setObject(objects);
         }else{
             orders.setStatus(Constants.ordersStatus.wait.getKey());
         }
         ordersMapper.insert(orders);
+        orderReleaseVO.setId(orders.getId());
         if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(orders.getMultifileList())){
             List<Multifile> multifileList = orders.getMultifileList();
             for (Multifile multifile:multifileList) {
                 if(Objects.isNull(multifile)
-                || Objects.isNull(multifile.getObjType())
                 || StringUtils.isEmpty(multifile.getFileurl())
                 || StringUtils.isEmpty(multifile.getName())){
                     throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"闄勪欢淇℃伅閿欒");
@@ -159,7 +159,7 @@
                 .replace("{param}",orderTypeInfo);
         this.saveOrderLog(orders,ordersLog,
                 logInfo,orders.getReleaseMemberId(),null);
-        return objects;
+        return orderReleaseVO;
     }
 
     private Object getWxPayResponse(Orders orders,String openid){
@@ -219,7 +219,7 @@
                 || Objects.isNull(orders.getStartDate())
                 || Objects.isNull(orders.getEndDate())
                 || StringUtil.isBlank(orders.getLocation())
-                || StringUtil.isBlank(orders.getLocationRemark())
+                || (!Constants.equalsInteger(Constants.ONE,orders.getType())&&StringUtil.isBlank(orders.getLocationRemark()))
                 || StringUtil.isBlank(orders.getLinkPhone())
                 || Objects.isNull(orders.getLat())
                 || Objects.isNull(orders.getLgt())
@@ -263,9 +263,9 @@
             for (WayInfoDTO wayInfoDTO:orders.getWayInfoDTOList()) {
                 if(Objects.isNull(wayInfoDTO)
                         ||StringUtils.isEmpty(wayInfoDTO.getLocation())
-                        ||StringUtils.isEmpty(wayInfoDTO.getProvince())
-                        ||StringUtils.isEmpty(wayInfoDTO.getCity())
-                        ||StringUtils.isEmpty(wayInfoDTO.getArea())
+//                        ||StringUtils.isEmpty(wayInfoDTO.getProvince())
+//                        ||StringUtils.isEmpty(wayInfoDTO.getCity())
+//                        ||StringUtils.isEmpty(wayInfoDTO.getArea())
                         ||Objects.isNull(wayInfoDTO.getLat())
                         ||Objects.isNull(wayInfoDTO.getLgt())
                 ){
@@ -298,6 +298,9 @@
             throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"閲戦璁$畻閿欒!");
         }
     }
+
+
+
 
 
 
@@ -600,12 +603,17 @@
                 throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"韬唤淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
             }
         }
-        orders.setUpdateTime(new Date());
-        orders.setAcceptType(Constants.ZERO);
-        orders.setAcceptTime(new Date());
-        orders.setAcceptMemberId(member.getId());
-        orders.setStatus(Constants.ordersStatus.accept.getKey());
-        ordersMapper.updateById(orders);
+
+        ordersMapper.update(new UpdateWrapper<Orders>().lambda().eq(Orders::getId,orders.getId())
+                .set(Orders::getUpdateTime,new Date())
+                .set(Orders::getAcceptType,Constants.ZERO)
+                .set(Orders::getAcceptTime,new Date())
+                .set(Orders::getAcceptMemberId,member.getId())
+                .set(Orders::getStatus,Constants.ordersStatus.accept.getKey())
+        );
+
+
+
         //鏇存柊鎺ュ崟閲�
         memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" publish_num = (publish_num + 1 )").eq(Member::getId,member.getId()));
 
@@ -701,8 +709,8 @@
                 .set(Orders::getEndDate,updOrderDataDTO.getEndDate())
                 .set(Orders::getTotalDays,updOrderDataDTO.getTotalDays())
                 .set(Orders::getIsUpdate,Constants.ONE)
-                .set(Orders::getIsUpdateTime,"now()")
-                .set(Orders::getUpdateTime,"now()")
+                .set(Orders::getIsUpdateTime,new Date())
+                .set(Orders::getUpdateTime,new Date())
                 .set(Orders::getEstimatedAccount,total)
                 .eq(Orders::getId,orders.getId())
         );
@@ -715,12 +723,22 @@
     }
 
 
+    @Override
     public Long getTotal(Orders orders){
+        if(Objects.isNull(orders)
+                ||Objects.isNull(orders.getPrice())
+                ||Objects.isNull(orders.getPriceNum1())){
+            throw new BusinessException(ResponseStatus.BAD_REQUEST);
+        }
         if(
             (Constants.equalsInteger(orders.getType(),Constants.ZERO) && Constants.equalsInteger(orders.getWorkType(),Constants.ZERO ))
             || Constants.equalsInteger(orders.getType(),Constants.ONE)
         ){
             orders.setPriceNum2(Constants.ONE);
+        }else{
+            if(Objects.isNull(orders.getPriceNum2())){
+                throw new BusinessException(ResponseStatus.BAD_REQUEST);
+            }
         }
         return orders.getPrice() * orders.getPriceNum1() * orders.getPriceNum2();
     }
@@ -757,7 +775,7 @@
         if( Constants.equalsInteger(confirmUpdOrderDTO.getStatus(),Constants.ONE)){
             ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                     .set(Orders::getIsUpdate,Constants.TWO)
-                    .set(Orders::getUpdateTime,"now()")
+                    .set(Orders::getUpdateTime,new Date())
                     .eq(Orders::getId,orders.getId())
             );
             //璁板綍鍚屾剰淇敼鐨勬棩蹇�
@@ -767,7 +785,7 @@
         }else{
             ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                     .set(Orders::getIsUpdate,Constants.TWO)
-                    .set(Orders::getUpdateTime,"now()")
+                    .set(Orders::getUpdateTime,new Date())
                     .set(Orders::getStatus,Constants.ordersStatus.wait.getKey())
                     .set(Orders::getAcceptMemberId,null)
                     .set(Orders::getAcceptType,null)
@@ -824,8 +842,8 @@
             }
             ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                     .set(Orders::getStatus,Constants.ordersStatus.cancel.getKey())
-                    .set(Orders::getUpdateTime,"now()")
-                    .set(Orders::getCancelTime,"now()")
+                    .set(Orders::getUpdateTime,new Date())
+                    .set(Orders::getCancelTime,new Date())
                     .set(Orders::getCancelType,Constants.ZERO)
                     .eq(Orders::getId,orders.getId())
             );
@@ -862,8 +880,8 @@
             }
             ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                     .set(Orders::getStatus,Constants.ordersStatus.cancel.getKey())
-                    .set(Orders::getUpdateTime,"now()")
-                    .set(Orders::getCancelTime,"now()")
+                    .set(Orders::getUpdateTime,new Date())
+                    .set(Orders::getCancelTime,new Date())
                     .set(Orders::getCancelType,Constants.ONE)
                     .eq(Orders::getId,orders.getId())
             );
@@ -917,7 +935,7 @@
             throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璺濈璁㈠崟寮�濮嬫椂闂翠笉瓒�"+cancelTimeHour+"灏忔椂,鏃犳硶鍙栨秷璁㈠崟锛屽闇�澶勭悊璇疯仈绯诲鏈�");
         }
         ordersMapper.update(new UpdateWrapper<Orders>().lambda()
-                .set(Orders::getUpdateTime,"now()")
+                .set(Orders::getUpdateTime,new Date())
                 .set(Orders::getStatus,Constants.ordersStatus.wait.getKey())
                 .set(Orders::getAcceptMemberId,null)
                 .set(Orders::getAcceptType,null)
@@ -1059,8 +1077,8 @@
 
         ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                 .set(Orders::getCommentStatus,Constants.ONE)
-                .set(Orders::getUpdateTime,"now()")
-                .set(Orders::getCommentTime,"now()")
+                .set(Orders::getUpdateTime,new Date())
+                .set(Orders::getCommentTime,new Date())
                 .set(Orders::getCommentLevel,commentDTO.getLevel())
                 .set(Orders::getCommentType,Constants.ZERO)
                 .eq(Orders::getId,orders.getId())
@@ -1098,10 +1116,10 @@
             }else{
                 //澶勭悊鏀粯瀹屾垚閫昏緫
                 ordersMapper.update(new UpdateWrapper<Orders>().lambda()
-                        .set(Orders::getUpdateTime,"now()")
+                        .set(Orders::getUpdateTime,new Date())
                         .set(Orders::getStatus,Constants.ordersStatus.wait)
                         .set(Orders::getPayStatus,Constants.ONE)
-                        .set(Orders::getPayTime,"now()")
+                        .set(Orders::getPayTime,new Date())
                         .set(Orders::getPayMethod,Constants.ZERO)
                         .set(Orders::getWxExternalNo,paymentNo)
                         .eq(Orders::getId,orders.getId())
@@ -1119,13 +1137,13 @@
             }else{
                 //澶勭悊鏀粯瀹屾垚閫昏緫
                 ordersMapper.update(new UpdateWrapper<Orders>().lambda()
-                        .set(Orders::getUpdateTime,"now()")
+                        .set(Orders::getUpdateTime,new Date())
                         .set(Orders::getStatus,Constants.FOUR)
                         .set(Orders::getPayStatus,Constants.ONE)
-                        .set(Orders::getPayTime,"now()")
+                        .set(Orders::getPayTime,new Date())
                         .set(Orders::getPayMethod,Constants.ZERO)
                         .set(Orders::getWxExternalNo,paymentNo)
-                        .set(Orders::getFinishTime,"now()")
+                        .set(Orders::getFinishTime,new Date())
                         .eq(Orders::getId,orders.getId())
                 );
 
@@ -1367,19 +1385,60 @@
     }
 
 
-
-    //todo 鑷姩娲惧崟
+    /**
+     * 鑷姩娲惧崟
+     */
+    @Override
     public void autoGrabOrders(){
-//        String autoConfirmTime = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.AUTO_DISPATCH_DISTANCE).getCode();
-//        List<Orders> ordersList = ordersMapper.selectList(new QueryWrapper<Orders>().lambda()
-//                .eq(Orders::getStatus,Constants.FOUR).eq(Orders::getCommentStatus,Constants.ZERO)
-//                .apply(" DATE_ADD(finish_time, INTERVAL 7 DAY) < now() ")
-//                .last("limit 100")
-//        );
+        String autoConfirmTime = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.AUTO_DISPATCH).getCode();
+        List<Orders> ordersList = ordersMapper.selectList(new QueryWrapper<Orders>().lambda()
+                .eq(Orders::getStatus,Constants.ONE).eq(Orders::getCommentStatus,Constants.ZERO)
+                .apply(" DATE_ADD(create_time, INTERVAL "+autoConfirmTime+" MINUTE) < now() ")
+                .last("limit 100")
+        );
+        for (Orders orders:ordersList) {
+            BigDecimal lat = orders.getLat();
+            BigDecimal lgt = orders.getLgt();
+            //鏌ヨ鑼冨洿鍐呯殑浼氬憳
+            List<Member> memberList = memberMapper.selectList(new MPJLambdaWrapper<Member>().selectAll(Member.class)
+                            .select(" ifnull((select r.level from receive_weight r where r.RECEIVE_MAX > t.RECEIVE_NUM and t.RECEIVE_NUM > r.RECEIVE_MIN limit 1  ),0) " ,Member::getLevel)
+                            .select(  " ifnull( (select CONVERT( ST_Distance_Sphere ( POINT ( ii.lgt, ii.lat ), POINT ( "+lgt+", "+lat+" )) /1000,DECIMAL(15,2)) from identity_info ii where ii.AUDIT_STATUS = 2 and type = 0 and ii.member_id = t.ID limit  1 ),0) ",Member::getDistance )
 
+                    .apply(" id in (" +
+                            " select ii.member_id from identity_info ii where ii.AUDIT_STATUS = 2 and type = '"+orders.getType()+"' " +
+                            " and ( CONVERT( ST_Distance_Sphere ( POINT ( ii.lgt, ii.lat ), POINT ( "+lgt+", "+lat+" )) /1000,DECIMAL(15,2))) < 100 " +
+                            ") ")
+                    .orderByDesc(Member::getLevel)
+                    .orderByDesc(Member::getScore)
+                    .orderByAsc(Member::getDistance)
+                    .last(" limit 1 ")
+            );
+            if(CollectionUtils.isEmpty(memberList)){
+                continue;
+            }
+            Member member = memberList.get(Constants.ZERO);
+            //鑷姩娲惧崟
+            Orders model = ordersMapper.selectById(orders.getStatus());
+            if(!Constants.equalsInteger(model.getStatus(),Constants.ONE)){
+                continue;
+            }
+            ordersMapper.update(new UpdateWrapper<Orders>().lambda().eq(Orders::getId,model.getId())
+                    .set(Orders::getUpdateTime,new Date())
+                    .set(Orders::getAcceptType,Constants.ONE)
+                    .set(Orders::getAcceptTime,new Date())
+                    .set(Orders::getAcceptMemberId,member.getId())
+                    .set(Orders::getStatus,Constants.ordersStatus.accept.getKey())
+            );
 
+            //鏇存柊鎺ュ崟閲�
+            memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" publish_num = (publish_num + 1 )").eq(Member::getId,member.getId()));
 
+            //鍒涘缓鎿嶄綔鏃ュ織
+            Constants.OrdersLog ordersLog = Constants.OrdersLog.AUTO;
+            this.saveOrderLog(orders,ordersLog,
+                    ordersLog.getInfo(),member.getId(),null);
 
+        }
     }
 
     //鑷姩璇勪环 璁㈠崟瀹屾垚7澶╁悗鑷姩璇勪环4鏄�
@@ -1395,8 +1454,8 @@
         for (Orders orders:ordersList) {
             ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                     .set(Orders::getCommentStatus,Constants.ONE)
-                    .set(Orders::getUpdateTime,"now()")
-                    .set(Orders::getCommentTime,"now()")
+                    .set(Orders::getUpdateTime,new Date())
+                    .set(Orders::getCommentTime,new Date())
                     .set(Orders::getCommentLevel,Constants.FOUR)
                     .set(Orders::getCommentType,Constants.ZERO)
                     .eq(Orders::getId,orders.getId())
@@ -1430,7 +1489,7 @@
             for (Orders orders:ordersList) {
                 ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                         .set(Orders::getIsUpdate,Constants.TWO)
-                        .set(Orders::getUpdateTime,"now()")
+                        .set(Orders::getUpdateTime,new Date())
                         .eq(Orders::getId,orders.getId())
                 );
                 //璁板綍鍚屾剰淇敼鐨勬棩蹇�
@@ -1442,6 +1501,11 @@
     }
 
 
+    @Override
+    public  void initializeCode(){
+        //鏇存柊缂撳瓨
+        redisTemplate.opsForValue().set(Constants.RedisKeys.ORDER_CODE,0);
+    }
 
 
 
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
index 6c9445e..82c3236 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
@@ -1,5 +1,10 @@
 package com.doumee.service.business.impl;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.doumee.config.wx.TransferToUser;
+import com.doumee.config.wx.WXPayUtility;
+import com.doumee.config.wx.WxMiniConfig;
 import com.doumee.core.constants.Constants;
 import com.doumee.core.constants.ResponseStatus;
 import com.doumee.core.exception.BusinessException;
@@ -22,10 +27,12 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
+import java.util.UUID;
 
 /**
  * 鎻愮幇鐢宠璁板綍Service瀹炵幇
@@ -171,10 +178,9 @@
      * 鎻愮幇鐢宠
      * @param withdrawalDTO
      */
-
     @Override
     @Transactional(rollbackFor = {BusinessException.class,Exception.class})
-    public void  applyWithdrawal(WithdrawalDTO withdrawalDTO){
+    public TransferToUser.TransferToUserResponse  applyWithdrawal(WithdrawalDTO withdrawalDTO){
         if(Objects.isNull(withdrawalDTO)
         || Objects.isNull(withdrawalDTO.getAmount())){
             throw new BusinessException(ResponseStatus.BAD_REQUEST);
@@ -186,23 +192,108 @@
         if(member.getAmount() < withdrawalDTO.getAmount()){
             throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝鍙彁鐜颁綑棰濅笉瓒炽��");
         }
+        if(StringUtils.isEmpty(member.getName())){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璇峰厛鍘荤淮鎶ょ湡瀹炲鍚嶅悗杩涜鎻愮幇鐢宠");
+        }
         WithdrawalOrders withdrawalOrders = new WithdrawalOrders();
         withdrawalOrders.setCreateTime(new Date());
         withdrawalOrders.setMemberId(member.getId());
+        withdrawalOrders.setOutBillNo(UUID.randomUUID().toString().replace("-",""));
         withdrawalOrders.setAmount(withdrawalDTO.getAmount());
         withdrawalOrders.setStatus(Constants.ZERO);
         withdrawalOrders.setType(Constants.ZERO);
+        withdrawalOrders.setDeleted(Constants.ZERO);
 
-        //TODO 鍙戣捣鎻愮幇鐢宠
+        //鍙戣捣鎻愮幇鐢宠
+        TransferToUser.TransferToUserRequest transferToUserRequest = new TransferToUser.TransferToUserRequest();
+        transferToUserRequest.openid = member.getOpenid();
+        transferToUserRequest.outBillNo =  withdrawalOrders.getOutBillNo();
+        transferToUserRequest.transferAmount = withdrawalDTO.getAmount();
+        transferToUserRequest.transferRemark = "鎻愮幇鐢宠";
+//        transferToUserRequest.userName = member.getName();
+        try {
+            TransferToUser.TransferToUserResponse response =  WxMiniConfig.transferToUser.run(transferToUserRequest,member.getName());
+            withdrawalOrders.setRemark(JSONObject.toJSONString(response));
+            if(response.state.name().equals("WAIT_USER_CONFIRM") || response.state.name().equals("ACCEPTED")){
+                withdrawalOrders.setWxExternalNo(response.transferBillNo);
+            }
+            withdrawalOrdersMapper.insert(withdrawalOrders);
+            //鏇存柊鐢ㄦ埛浣欓
+            memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" AMOUNT = AMOUNT -  " + withdrawalDTO.getAmount() ).eq(Member::getId,member.getId()));
+
+            //瀛樺偍娴佹按璁板綍
+            MemberRevenue memberRevenue = new MemberRevenue();
+            memberRevenue.setCreateTime(new Date());
+            memberRevenue.setMemberId(member.getId());
+            memberRevenue.setType(Constants.THREE);
+            memberRevenue.setOptType(-Constants.ONE);
+            memberRevenue.setBeforeAmount(member.getAmount());
+            memberRevenue.setAmount(withdrawalOrders.getAmount());
+            memberRevenue.setAfterAmount(member.getAmount() - withdrawalOrders.getAmount());
+            memberRevenue.setObjId(withdrawalOrders.getId());
+            memberRevenue.setObjType(Constants.ONE);
+            memberRevenue.setDeleted(Constants.ZERO);
+            memberRevenue.setStatus(Constants.TWO);
+            memberRevenueMapper.insert(memberRevenue);
+            return response;
+        } catch (WXPayUtility.ApiException e) {
+            String message = JSONObject.parseObject(e.getBody()).getString("message");
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),message);
+        }
+    }
 
 
+    @Override
+    public void cancelTransfer(TransferToUser.CancelTransferRequest request){
+        if(Objects.isNull(request)
+        || StringUtils.isEmpty(request.outBillNo)){
+            throw new BusinessException(ResponseStatus.BAD_REQUEST);
+        }
+        WithdrawalOrders withdrawalOrders = withdrawalOrdersMapper.selectOne(new QueryWrapper<WithdrawalOrders>().lambda().eq(WithdrawalOrders::getOutBillNo,request.outBillNo).last("limit 1"));
+        if(Objects.isNull(withdrawalOrders)){
+            throw new BusinessException(ResponseStatus.DATA_EMPTY);
+        }
+        Member member = memberMapper.selectById(withdrawalOrders.getMemberId());
+        if(Objects.isNull(member)){
+            throw new BusinessException(ResponseStatus.DATA_EMPTY);
+        }
+        try {
+            TransferToUser.CancelTransferResponse response =  WxMiniConfig.transferToUser.cancelRun(request);
+            if(response.state.equals("CANCELING")){
+                //鏍囪鎻愮幇澶辫触 鍔犲洖瀵瑰簲鐨勬彁鐜伴噾棰�
+                withdrawalOrdersMapper.update(new UpdateWrapper<WithdrawalOrders>()
+                        .lambda().set(WithdrawalOrders::getStatus,Constants.TWO)
+                        .eq(WithdrawalOrders::getId,withdrawalOrders.getId()));
 
-        //鏇存柊鐢ㄦ埛浣欓
+                memberRevenueMapper.update(new UpdateWrapper<MemberRevenue>().lambda().set(MemberRevenue::getStatus,Constants.ONE)
+                                .set(MemberRevenue::getUpdateTime,new Date())
+                        .eq(MemberRevenue::getObjId,withdrawalOrders.getId()))
+                ;
 
+                //鏇存柊鐢ㄦ埛浣欓
+                memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" AMOUNT = AMOUNT + " + withdrawalOrders.getAmount() ).eq(Member::getId,withdrawalOrders.getMemberId()));
 
-        //瀛樺偍娴佹按璁板綍
+                //瀛樺偍娴佹按璁板綍
+                MemberRevenue memberRevenue = new MemberRevenue();
+                memberRevenue.setCreateTime(new Date());
+                memberRevenue.setMemberId(withdrawalOrders.getMemberId());
+                memberRevenue.setType(Constants.FOUR);
+                memberRevenue.setOptType(Constants.ONE);
+                memberRevenue.setBeforeAmount(member.getAmount());
+                memberRevenue.setAmount(withdrawalOrders.getAmount());
+                memberRevenue.setAfterAmount(member.getAmount() + withdrawalOrders.getAmount());
+                memberRevenue.setObjId(withdrawalOrders.getId());
+                memberRevenue.setObjType(Constants.ONE);
+                memberRevenue.setDeleted(Constants.ZERO);
+                memberRevenue.setStatus(Constants.ZERO);
+                memberRevenueMapper.insert(memberRevenue);
 
-
+            }
+            System.out.println(JSONObject.toJSONString(response));
+        } catch (WXPayUtility.ApiException e) {
+            String message = JSONObject.parseObject(e.getBody()).getString("message");
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),message);
+        }
 
     }
 
diff --git a/server/services/src/main/resources/application-dev.yml b/server/services/src/main/resources/application-dev.yml
index 0f36468..add081e 100644
--- a/server/services/src/main/resources/application-dev.yml
+++ b/server/services/src/main/resources/application-dev.yml
@@ -85,7 +85,7 @@
   pay:
     #鏈嶅姟鍟�---------start-------
     appId: wx48fd8faa35cc8277
-    mchId: 1661770902
+    mchId: 1229817002 #1661770902
     apiV3Key: iF3kC8pL8dZ9iU3hN5fX9zI6eF4xQ6fT
     serialNumer: 368B835A194384FD583B83B77977B84127D2F655
     mchKey: W97N53Q71326D6JZ2E9HY5M4VT4BAC8S
@@ -96,9 +96,17 @@
     #keyPath: /usr/local/aliConfig/bike/apiclient_cert.p12
     #privateCertPath: /usr/local/aliConfig/bike/apiclient_cert.pem
     #privateKeyPath: /usr/local/aliConfig/bike/apiclient_key.pem
-    #    keyPath: d://apiclient_cert.p12
-    #    privateCertPath: d://apiclient_cert.pem
-    #    privateKeyPath: d://apiclient_key.pem
+    keyPath: d://apiclient_cert.p12
+    privateCertPath: d://apiclient_cert.pem
+    privateKeyPath: d://apiclient_key.pem
+
+
+    #鍟嗘埛淇℃伅
+    wechatSerialNumer: 3FE90C2F3D40A56E1C51926F31B8A8D22426CCE0
+    wechatPayPublicKeyId: PUB_KEY_ID_0112298170022025071700291836000600
+    wechatPubKeyPath: d://pub_key.pem
+    wechatPrivateKeyPath: d://wechatApiclient_key.pem
+
     #鏈嶅姟鍟�-------------end---
     existsSub: 1
     appSecret: 1ceb7c9dff3c4330d653adc3ca55ea24
diff --git a/server/web/src/main/java/com/doumee/api/web/AccountApi.java b/server/web/src/main/java/com/doumee/api/web/AccountApi.java
index 66c5721..df272ad 100644
--- a/server/web/src/main/java/com/doumee/api/web/AccountApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/AccountApi.java
@@ -1,5 +1,6 @@
 package com.doumee.api.web;
 
+import com.doumee.config.jwt.JwtTokenUtil;
 import com.doumee.core.annotation.LoginRequired;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
@@ -53,6 +54,16 @@
         return  ApiResponse.success("鎿嶄綔鎴愬姛",memberService.wxAuthPhone(wxPhoneRequest));
     }
 
-
+    @LoginRequired
+    @ApiOperation(value = "閫�鍑虹櫥褰�", notes = "灏忕▼搴忕")
+    @GetMapping("/logOff")
+    @ApiImplicitParams({
+            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+    })
+    public ApiResponse logOff() {
+        String token = this.getRequest().getHeader(JwtTokenUtil.HEADER_KEY);
+        memberService.logOff(token,getMemberId());
+        return  ApiResponse.success("鎿嶄綔鎴愬姛");
+    }
 
 }
diff --git a/server/web/src/main/java/com/doumee/api/web/ConfigApi.java b/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
index 187160a..17e8ed7 100644
--- a/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
@@ -1,5 +1,6 @@
 package com.doumee.api.web;
 
+import com.doumee.core.annotation.LoginRequired;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
 import com.doumee.dao.business.model.Category;
@@ -34,6 +35,7 @@
     @Autowired
     private CategoryService categoryService;
 
+    @LoginRequired
     @ApiOperation(value = "鑾峰彇鍒嗙被鍒楄〃", notes = "灏忕▼搴忕")
     @GetMapping("/getCategoryList")
     @ApiImplicitParams({
diff --git a/server/web/src/main/java/com/doumee/api/web/OrdersApi.java b/server/web/src/main/java/com/doumee/api/web/OrdersApi.java
index 6ca26a2..38571fa 100644
--- a/server/web/src/main/java/com/doumee/api/web/OrdersApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/OrdersApi.java
@@ -13,6 +13,7 @@
 import com.doumee.dao.dto.ConfirmUpdOrderDTO;
 import com.doumee.dao.dto.DoneOrderDTO;
 import com.doumee.dao.dto.UpdOrderDataDTO;
+import com.doumee.dao.vo.OrderReleaseVO;
 import com.doumee.service.business.IdentityInfoService;
 import com.doumee.service.business.MemberService;
 import com.doumee.service.business.OrdersService;
@@ -51,7 +52,7 @@
     @ApiImplicitParams({
             @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
     })
-    public ApiResponse<Object> release(@RequestBody Orders orders) {
+    public ApiResponse<OrderReleaseVO> release(@RequestBody Orders orders) {
         orders.setMember(this.getMemberResponse());
         return  ApiResponse.success("鎿嶄綔鎴愬姛",ordersService.create(orders));
     }
@@ -185,6 +186,15 @@
         return  ApiResponse.success("鎿嶄綔鎴愬姛",ordersService.getDetail(orderId,this.getMemberResponse().getUseIdentity()));
     }
 
+    @LoginRequired
+    @ApiOperation("鑾峰彇棰勮閲戦锛堝垎锛�")
+    @PostMapping("/getTotal")
+    @ApiImplicitParams({
+            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+    })
+    public ApiResponse<Long> getTotal(@RequestBody Orders orders) {
+        return ApiResponse.success(ordersService.getTotal(orders));
+    }
 
 
 }
diff --git a/server/web/src/main/java/com/doumee/api/web/UserApi.java b/server/web/src/main/java/com/doumee/api/web/UserApi.java
index 8e97ae8..30cac74 100644
--- a/server/web/src/main/java/com/doumee/api/web/UserApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/UserApi.java
@@ -1,5 +1,6 @@
 package com.doumee.api.web;
 
+import com.doumee.config.wx.TransferToUser;
 import com.doumee.core.annotation.LoginRequired;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
@@ -8,12 +9,14 @@
 import com.doumee.dao.business.model.IdentityInfo;
 import com.doumee.dao.business.model.Member;
 import com.doumee.dao.business.model.MemberRevenue;
+import com.doumee.dao.dto.WithdrawalDTO;
 import com.doumee.dao.dto.WxPhoneRequest;
 import com.doumee.dao.vo.AccountResponse;
 import com.doumee.dao.vo.UserCenterVO;
 import com.doumee.service.business.IdentityInfoService;
 import com.doumee.service.business.MemberRevenueService;
 import com.doumee.service.business.MemberService;
+import com.doumee.service.business.WithdrawalOrdersService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -46,6 +49,9 @@
 
     @Autowired
     private MemberRevenueService memberRevenueService;
+
+    @Autowired
+    private WithdrawalOrdersService withdrawalOrdersService;
 
 
     @ApiOperation(value = "鑾峰彇绯荤粺閰嶇疆", notes = "灏忕▼搴忕")
@@ -153,6 +159,29 @@
         return ApiResponse.success(memberRevenueService.findPage(pageWrap));
     }
 
+    @LoginRequired
+    @ApiOperation("鎻愮幇鐢宠")
+    @PostMapping("/applyWithdrawal")
+    @ApiImplicitParams({
+            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+    })
+    public ApiResponse<TransferToUser.TransferToUserResponse> applyWithdrawal (@RequestBody WithdrawalDTO withdrawalDTO) {
+        withdrawalDTO.setMember(this.getMemberResponse());
+        return ApiResponse.success("鎿嶄綔鎴愬姛",withdrawalOrdersService.applyWithdrawal(withdrawalDTO));
+    }
+
+
+
+    @LoginRequired
+    @ApiOperation("鎾ら攢鎻愮幇鐢宠")
+    @PostMapping("/cancelTransfer")
+    @ApiImplicitParams({
+            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+    })
+    public ApiResponse cancelTransfer (@RequestBody TransferToUser.CancelTransferRequest request) {
+        withdrawalOrdersService.cancelTransfer(request);
+        return ApiResponse.success("鎿嶄綔鎴愬姛");
+    }
 
 
 }
diff --git a/small-program/pages/freight/freight.vue b/small-program/pages/freight/freight.vue
index 29b5dd7..aedbe08 100644
--- a/small-program/pages/freight/freight.vue
+++ b/small-program/pages/freight/freight.vue
@@ -6,51 +6,54 @@
 					<view class="list-item-label-x"></view>
 					<text>杞﹁締鍙婅矾绾�</text>
 				</view>
-				<view class="list-item-row">
+				<view class="list-item-row" @click="show = true">
 					<view class="list-item-row-label">杞﹁締绫诲瀷<b>*</b></view>
 					<view class="list-item-row-val">
-						<text>璇烽�夋嫨</text>
+						<text :style="{ color: form.categoryName ? '#111111' : '' }">{{form.categoryName ? form.categoryName : '璇烽�夋嫨'}}</text>
 						<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 					</view>
 				</view>
-				<view class="list-item-row">
+				<view class="list-item-row" @click="show3 = true">
 					<view class="list-item-row-label">璐ц溅鍨嬪彿<b>*</b></view>
 					<view class="list-item-row-val">
-						<text>璇烽�夋嫨</text>
+						<text :style="{ color: form.carUnit ? '#111111' : '' }">{{form.carUnit ? form.carUnit : '璇烽�夋嫨'}}</text>
 						<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 					</view>
 				</view>
-				<view class="list-item-row">
+				<view class="list-item-row" @click="show2 = true">
 					<view class="list-item-row-label">鐢ㄨ溅鏃堕棿<b>*</b></view>
 					<view class="list-item-row-val">
-						<text>璇烽�夋嫨</text>
+						<text :style="{ color: form.startDate ? '#111111' : '' }">{{form.startDate ? form.startDate + ' 鑷� ' + form.endDate + ' (' + form.priceNum1 + '澶�) ' : '璇烽�夋嫨'}}</text>
 						<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 					</view>
 				</view>
 				<view class="list-item-row">
 					<view class="list-item-row-label">
 						杩愯揣鍦板潃<b>*</b>
-						<view class="list-item-row-label-add">+澧炲姞閫旂粡鐐�</view>
+						<view class="list-item-row-label-add" @click="addAddr">+澧炲姞閫旂粡鐐�</view>
 					</view>
 					<view class="address">
-						<view class="address-item">
+						<view class="address-item" @click="selectAddress(2)">
 							<view class="address-item-img">
 								<image src="/static/icon/ic_qidian@2x.png" mode="widthFix"></image>
-								<text>璇烽�夋嫨璧风偣</text>
+								<text :style="{color: form.location ? '#111111' : ''}">{{form.location ? form.location : '璇烽�夋嫨璧风偣'}}</text>
 							</view>
 							<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 						</view>
-						<view class="address-item">
+						<view class="address-item" v-for="(item, index) in form.wayInfoDTOList" :key="index" @click="selectAddress(4, index)">
 							<view class="address-item-img">
 								<image src="/static/icon/ic_jingguo@2x.png" mode="widthFix"></image>
-								<text>璇烽�夋嫨閫旂粡鍦扮偣</text>
+								<text :style="{color: item.location ? '#111111' : ''}">{{item.location ? item.location : '璇烽�夋嫨閫旂粡鍦扮偣'}}</text>
 							</view>
-							<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
+							<view style="display: flex; align-items: center; flex-shrink: 0;">
+								<image src="/static/icon/ic_delete@2x.png" style="margin-right: 22rpx; width: 32rpx; height: 32rpx;" @click.stop="form.wayInfoDTOList.splice(index, 1)" mode="widthFix"></image>
+								<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
+							</view>
 						</view>
-						<view class="address-item">
+						<view class="address-item" @click="selectAddress(3)">
 							<view class="address-item-img">
 								<image src="/static/icon/ic_zhongdian@2x.png" mode="widthFix"></image>
-								<text>璇烽�夋嫨缁堢偣</text>
+								<text :style="{color: form.locationEnd ? '#111111' : ''}">{{form.locationEnd ? form.locationEnd : '璇烽�夋嫨缁堢偣'}}</text>
 							</view>
 							<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 						</view>
@@ -62,49 +65,50 @@
 					<view class="list-item-label-x"></view>
 					<text>闇�姹�</text>
 				</view>
-				<view class="list-item-row">
+				<view class="list-item-row" @click="show1 = true">
 					<view class="list-item-row-label">杩愯緭鍝佺<b>*</b></view>
 					<view class="list-item-row-val">
-						<text>璇烽�夋嫨</text>
+						<text :style="{ color: form.transportTypeName ? '#111111' : '' }">{{form.transportTypeName ? form.transportTypeName : '璇烽�夋嫨'}}</text>
 						<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 					</view>
 				</view>
 				<view class="list-item-row">
 					<view class="list-item-row-label">鐢ㄨ溅鏁伴噺<b>*</b></view>
 					<view class="list-item-row-val">
-						<text>璇烽�夋嫨</text>
-						<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
+						<input type="number" v-model="form.priceNum2" disabled placeholder="1" />
+						<text>杈�</text>
 					</view>
 				</view>
 				<view class="list-item-row">
 					<view class="list-item-row-label">杩愯緭閲嶉噺/鏁伴噺<b>*</b></view>
 					<view class="list-item-row-val">
-						<input type="text" placeholder="璇疯緭鍏�" />
-						<text>涓�</text>
+						<input type="text" v-model="form.transportNum" placeholder="璇疯緭鍏�" />
+						<text @click="show4 = true">{{form.transportUnit}}</text>
 						<u-icon name="arrow-down" color="#111111" size="16"></u-icon>
 					</view>
 				</view>
-				<view class="list-item-row">
+				<view class="list-item-row" v-if="viewStatus">
 					<view class="list-item-row-label">闇�姹傝ˉ鍏�</view>
 					<view class="list-item-row-val">
-						<textarea cols="30" rows="10" placeholder="璇疯緭鍏�" maxlength="200"></textarea>
+						<textarea cols="30" v-model="form.supplement" rows="10" placeholder="璇疯緭鍏�" maxlength="200"></textarea>
 					</view>
 				</view>
-				<view class="list-item-row">
+				<view class="list-item-row" v-if="viewStatus">
 					<view class="list-item-row-label">鍥剧墖</view>
 					<view class="list-item-row-upload">
-						<view class="upload-item">
-							<image src="/static/logo.png" mode="widthFix"></image>
+						<view class="upload-item" v-for="(item, index) in form.multifileList" :key="index">
+							<image :src="item.url" mode="widthFix"></image>
+							<image class="upload-item-dele" @click="form.multifileList.splice(index, 1)" src="/static/icon/ic_delete1@2x.png" mode="widthFix"></image>
 						</view>
-						<view class="upload-item">
+						<view class="upload-item" @click="uploadImg">
 							<u-icon name="plus" color="#999999" size="24"></u-icon>
 							<text>鐐瑰嚮涓婁紶</text>
 						</view>
 					</view>
 				</view>
-				<view class="list-item-zk">
-					<text>琛ュ厖闇�姹�</text>
-					<u-icon name="arrow-down" color="#00BC12" size="16"></u-icon>
+				<view class="list-item-zk" @click="viewStatus = !viewStatus">
+					<text>{{viewStatus ? '鏀惰捣' : '琛ュ厖闇�姹�'}}</text>
+					<u-icon :name="viewStatus ? 'arrow-up' : 'arrow-down'" color="#00BC12" size="16"></u-icon>
 				</view>
 			</view>
 			<view class="list-item">
@@ -113,21 +117,39 @@
 					<text>璐圭敤</text>
 				</view>
 				<view class="list-item-cate">
-					<view class="list-item-cate-item active">鎸夊ぉ浠樿垂</view>
-					<view class="list-item-cate-item">鎸夋浠樿垂</view>
+					<view :class="item.id === form.carType ? 'list-item-cate-item active' : 'list-item-cate-item'" v-for="(item, index) in ff" :key="index" @click="form.carType = item.id">鎸夊ぉ浠樿垂</view>
 				</view>
 				<view class="list-item-row">
 					<view class="list-item-row-label">澶╂暟</view>
 					<view class="list-item-row-val">
-						<input type="text" placeholder="璇疯緭鍏�" />
+						<input type="number" v-model="form.priceNum1" disabled placeholder="璇疯緭鍏�" />
 						<text>澶�</text>
 					</view>
 				</view>
 				<view class="list-item-row">
 					<view class="list-item-row-label">璐圭敤鏍囧噯<b>*</b></view>
 					<view class="list-item-row-val">
-						<input type="text" placeholder="璇疯緭鍏�" />
-						<text>鍏�/杈�*澶�</text>
+						<input type="number" @blur="getPrice" v-model="form.price" placeholder="璇疯緭鍏�" />
+						<text>{{form.priceUnit}}</text>
+					</view>
+				</view>
+			</view>
+			<view class="list-item">
+				<view class="list-item-label">
+					<view class="list-item-label-x"></view>
+					<text>鑱旂郴浜轰俊鎭�</text>
+					<text class="list-item-label-info">榛樿鍙戝崟鏂硅仈绯绘柟寮忥紝鍙慨鏀硅仈绯讳汉</text>
+				</view>
+				<view class="list-item-row">
+					<view class="list-item-row-label">鑱旂郴浜哄鍚�</view>
+					<view class="list-item-row-val">
+						<input type="text" v-model="form.linkName" placeholder="璇疯ˉ鍏�" />
+					</view>
+				</view>
+				<view class="list-item-row">
+					<view class="list-item-row-label">鑱旂郴鐢佃瘽<b>*</b></view>
+					<view class="list-item-row-val">
+						<input type="text" v-model="form.linkPhone" maxlength="11" placeholder="璇疯ˉ鍏�" />
 					</view>
 				</view>
 			</view>
@@ -137,27 +159,296 @@
 			<view class="footer-price">
 				<view class="footer-price-info">棰勪及鎬昏垂鐢�</view>
 				<view class="footer-price-num">
-					<text>0</text>
+					<text>{{totalPrice || 0}}</text>
 					<text>鍏�</text>
 				</view>
 			</view>
 			<view class="footer-bottom">
-				<div class="footer-bottom-btn">
+				<div class="footer-bottom-btn" @click="submit">
 					<text>绔嬪嵆涓嬪崟</text>
 					<text>锛堟湇鍔″畬鎴愬悗浠樻锛�</text>
 				</div>
 			</view>
 			<view style="width: 100%; height: env(safe-area-inset-bottom);"></view>
 		</view>
+		
+		<!-- 閫夋嫨杞﹁締绫诲瀷 -->
+		<u-picker
+			:show="show"
+			:columns="car"
+			confirmColor="#00BC12"
+			keyName="name"
+			@confirm="confirmCategary"
+			@cancel="show = false"/>
+			
+		<!-- 閫夋嫨鍝佺 -->
+		<u-picker
+			:show="show1"
+			:columns="variety"
+			confirmColor="#00BC12"
+			keyName="name"
+			@confirm="confirmVariety"
+			@cancel="show1 = false"/>
+			
+		<!-- 璐ц溅鍨嬪彿 -->
+		<u-picker
+			:show="show3"
+			:columns="carArr"
+			confirmColor="#00BC12"
+			@confirm="confirmCarArr"
+			@cancel="show3 = false"/>
+			
+		<!-- 鍗曚綅 -->
+		<u-picker
+			:show="show4"
+			:columns="dw"
+			confirmColor="#00BC12"
+			@confirm="confirmDw"
+			@cancel="show4 = false"/>
+			
+		<!-- 閫夋嫨鏃ユ湡鑼冨洿 -->
+		<u-calendar
+			:show="show2"
+			color="#00BC12"
+			mode="range"
+			@close="show2 = false"
+			@confirm="confirmDate" />
+			
 	</view>
 </template>
 
 <script>
+	import { mapState } from 'vuex'
 	export default {
+		computed: {
+			...mapState(['userInfo']),
+			totalPrice() {
+				return this.form.estimatedAccount / 100
+			}
+		},
 		data() {
 			return {
-				
+				show: false,
+				show1: false,
+				show2: false,
+				show3: false,
+				show4: false,
+				form: {
+					startDate: '',
+					endDate: '',
+					lat: '',
+					lgt: '',
+					location: '',
+					latEnd: '',
+					lgtEnd: '',
+					locationEnd: '',
+					carUnit: '',
+					categoryId: '',
+					categoryName: '',
+					wayInfoDTOList: [],
+					priceNum1: '',
+					priceNum2: 1,
+					transportNum: '',
+					transportTypeId: '',
+					transportTypeName: '',
+					carType: 0,
+					supplement: '',
+					multifileList: [],
+					priceUnit: '鍏�/澶�',
+					linkName: '',
+					linkPhone: '',
+					price: '',
+					type: 1,
+					transportUnit: '涓�',
+					estimatedAccount: ''
+				},
+				car: [],
+				variety: [],
+				ff: [
+					{ name: '鎸夊ぉ浠樿垂', id: 0 },
+					{ name: '鎸夋浠樿垂', id: 1 }
+				],
+				dw: [['涓�', '鏂�']],
+				carArr: [],
+				viewStatus: false
 			};
+		},
+		watch: {
+			'form.carType': {
+				handler(news, olds) {
+					if (news === 0) {
+						this.form.priceUnit = '鍏�/澶�'
+					} else if (news === 1) {
+						this.form.priceUnit = '鍏�/娆�'
+					}
+				}
+			}
+		},
+		onLoad() {
+			const res = uni.getStorageSync('carData');
+			this.form.linkPhone = this.userInfo.telephone
+			this.form.startDate = res.startDate
+			this.form.endDate = res.endDate
+			this.form.lat = res.lat
+			this.form.lgt = res.lgt
+			this.form.priceNum1 = res.days
+			this.form.categoryId = res.categoryId
+			this.form.categoryName = res.categoryName
+			this.form.location = res.location
+			this.form.latEnd = res.latEnd
+			this.form.lgtEnd = res.lgtEnd
+			this.form.locationEnd = res.locationEnd
+			this.form.wayInfoDTOList = res.wayInfoDTOList
+			uni.removeStorageSync('carData');
+			this.getCategoryLists()
+		},
+		methods: {
+			confirmDw(e) {
+				this.form.transportUnit = e.value[0]
+				this.show4 = false
+			},
+			// 鎻愪氦璁㈠崟
+			submit() {
+				if (!this.form.transportTypeName) {
+					return uni.showToast({ title: '璇烽�夋嫨杩愯緭鍝佺', icon: 'none' })
+				}
+				if (!this.form.priceNum2) {
+					return uni.showToast({ title: '璇疯緭鍏ョ敤杞︽暟閲�', icon: 'none' })
+				}
+				if (!this.form.transportNum) {
+					return uni.showToast({ title: '璇疯緭鍏ヨ繍杈撻噸閲�/鏁伴噺', icon: 'none' })
+				}
+				if (!this.form.price) {
+					return uni.showToast({ title: '璇疯緭鍏ヨ垂鐢ㄦ爣鍑�', icon: 'none' })
+				}
+				if (!this.form.linkPhone) {
+					return uni.showToast({ title: '璇疯緭鍏ヨ仈绯荤數璇�', icon: 'none' })
+				}
+				this.$u.api.release({ 
+					...this.form,
+					price: Number(this.form.price) * 100,
+					wayInfoDTOList: [
+						{
+							lat: this.form.lat,
+							lgt: this.form.lgt,
+							location: this.form.location
+						},
+						...this.form.wayInfoDTOList,
+						{
+							lat: this.form.latEnd,
+							lgt: this.form.lgtEnd,
+							location: this.form.locationEnd
+						}
+					]
+				}).then(res => {
+					if (res.code == 200) {
+						uni.navigateTo({
+							url: `/pages/success/success?orderId=${res.data.id}`
+						})
+					}
+				})
+			},
+			uploadImg() {
+				uni.chooseImage({
+					success: (chooseImageRes) => {
+						const tempFilePaths = chooseImageRes.tempFilePaths;
+						uni.uploadFile({
+							url: this.$baseUrl + '/web/public/upload',
+							filePath: tempFilePaths[0],
+							name: 'file',
+							formData: {
+								'folder': 'orders'
+							},
+							success: (uploadFileRes) => {
+								const res = JSON.parse(uploadFileRes.data)
+								this.form.multifileList.push({
+									fileurl: res.data.imgaddr,
+									name: res.data.originname,
+									url: res.data.url,
+									type: 0
+								})
+							}
+						});
+					}
+				});
+			},
+			// 璁$畻閲戦
+			getPrice() {
+				if (this.form.price && this.form.priceNum1 && this.form.priceNum2) {
+					this.$u.api.getTotal({
+						price: Number(this.form.price) * 100,
+						priceUnit: this.form.priceUnit,
+						priceNum1: this.form.priceNum1,
+						priceNum2: this.form.priceNum2,
+						type: 1
+					}).then(res => {
+						this.form.estimatedAccount = res.data
+					})
+				}
+			},
+			getCategoryLists() {
+				this.$u.api.getCategoryList({ type: 1 })
+					.then(res => {
+						this.car = [res.data]
+						res.data.forEach(item => {
+							if (item.id === this.form.categoryId) {
+								this.carArr = [item.detailList]
+							}
+						})
+					})
+				this.$u.api.getCategoryList({ type: 0 })
+					.then(res => {
+						this.variety = [res.data]
+					})
+			},
+			confirmCategary(e) {
+				this.form.categoryId = e.value[0].id
+				this.form.categoryName = e.value[0].name
+				this.carArr = [e.value[0].detailList]
+				this.form.carUnit = ''
+				this.show = false
+			},
+			confirmVariety(e) {
+				this.form.transportTypeId = e.value[0].id
+				this.form.transportTypeName = e.value[0].name
+				this.show1 = false
+			},
+			confirmCarArr(e) {
+				this.form.carUnit = e.value[0]
+				this.show3 = false
+			},
+			confirmDate(e) {
+				this.form.startDate = e[0]
+				this.form.endDate = e[e.length - 1]
+				this.form.priceNum1 = e.length;
+				this.show2 = false
+			},
+			addAddr() {
+				this.form.wayInfoDTOList.push({
+					lat: '',
+					lgt: '',
+					location: ''
+				})
+			},
+			selectAddress(type, index) {
+				uni.chooseLocation({
+					success: (res) => {
+						if ([2].includes(type)) {
+							this.form.latitude = res.latitude
+							this.form.longitude = res.longitude
+							this.form.address = res.address
+						} else if (type === 3) {
+							this.form.locationEnd = res.address
+							this.form.latEnd = res.latitude
+							this.form.lgtEnd = res.longitude
+						} else if (type === 4) {
+							this.form.wayInfoDTOList[0].lat = res.latitude
+							this.form.wayInfoDTOList[0].lgt = res.longitude
+							this.form.wayInfoDTOList[0].location = res.address
+						}
+					}
+				});
+			},
 		}
 	}
 </script>
@@ -323,6 +614,12 @@
 						border-radius: 4rpx;
 						margin-right: 20rpx;
 					}
+					.list-item-label-info {
+						font-weight: 400;
+						font-size: 26rpx;
+						color: #999999;
+						margin-left: 26rpx;
+					}
 				}
 				.list-item-zk {
 					width: 100%;
@@ -354,7 +651,9 @@
 						margin-top: 20rpx;
 						.address-item {
 							width: 100%;
-							height: 100rpx;
+							// height: 100rpx;
+							padding: 30rpx 0;
+							box-sizing: border-box;
 							display: flex;
 							align-items: center;
 							justify-content: space-between;
@@ -524,6 +823,7 @@
 							border-radius: 8rpx;
 							margin-right: 20rpx;
 							border: 2rpx solid #EEEEEE;
+							position: relative;
 							&:last-child {
 								margin: 0 !important;
 							}
@@ -535,6 +835,14 @@
 								font-size: 26rpx;
 								color: #666666;
 								margin-top: 16rpx;
+							}
+							.upload-item-dele {
+								position: absolute;
+								top: -20rpx;
+								right: -20rpx;
+								width: 40rpx;
+								height: 40rpx;
+								z-index: 9;
 							}
 						}
 					}
@@ -549,7 +857,7 @@
 							flex-shrink: 0;
 							font-weight: 400;
 							font-size: 30rpx;
-							color: #111111;
+							color: #999999;
 						}
 						input {
 							width: 100%;
diff --git a/small-program/pages/index/index.vue b/small-program/pages/index/index.vue
index 02cd67c..e775a3e 100644
--- a/small-program/pages/index/index.vue
+++ b/small-program/pages/index/index.vue
@@ -323,10 +323,10 @@
 							</view>
 							<view class="box-hz-list-item" @click="selectAddress(1)">
 								<view class="box-hz-list-item-label"><text>鐢ㄥ伐鍦扮偣锛�</text></view>
-								<view :class="form.address ? 'box-hz-list-item-val active' :'box-hz-list-item-val'">
+								<view :class="form.location ? 'box-hz-list-item-val active' :'box-hz-list-item-val'">
 									<view class="box-hz-list-item-val-left">
 										<image class="icon" src="/static/icon/ic_location@2x.png" mode="widthFix"></image>
-										<text>{{form.address ? form.address : '璇烽�夋嫨鐢ㄥ伐鍦扮偣'}}</text>
+										<text>{{form.location ? form.location : '璇烽�夋嫨鐢ㄥ伐鍦扮偣'}}</text>
 									</view>
 									<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 								</view>
@@ -337,65 +337,64 @@
 					<!-- 杩愯揣 -->
 					<template v-if="typeId === 1">
 						<view class="box-hz-cate">
-							<view :class="carId === item.id ? 'box-hz-cate-item active' : 'box-hz-cate-item'" v-for="(item, index) in car" :key="index" @click="clickCar(item.id)">
+							<view :class="form.categoryId === item.id ? 'box-hz-cate-item active' : 'box-hz-cate-item'" v-for="(item, index) in car" :key="index" @click="clickCar(item)">
 								<text>{{item.name}}</text>
-								<view class="box-hz-cate-item-x" v-if="carId === item.id"></view>
+								<view class="box-hz-cate-item-x" v-if="form.categoryId === item.id"></view>
 							</view>
 						</view>
 						<view class="box-hz-car">
 							<view class="box-hz-car-image">
-								<image src="/static/image/ic_sanlunche@2x.png" mode="widthFix" v-if="carId === 1"></image>
-								<image src="/static/image/ic_xiaohuoche@2x.png" mode="widthFix" v-else-if="carId === 2"></image>
+								<image :src="carImage" mode="widthFix"></image>
 							</view>
-							<view class="box-hz-car-info" v-if="carId === 1">
-								鍘㈤暱3.8锝�4.0绫�  杞介噸1.5锝�2.0鍚�  杞芥柟12.3锝�18.4鏂�
-							</view>
-							<view class="box-hz-car-info" v-else-if="carId === 2">
-								鍘㈤暱3.8锝�4.0绫�  杞介噸1.5锝�2.0鍚�  杞芥柟12.3锝�18.4鏂�
+							<view class="box-hz-car-info" v-if="carRemark">
+								{{carRemark || ''}}
 							</view>
 						</view>
 						<view class="box-hz-list">
-							<view class="box-hz-list-item">
+							<view class="box-hz-list-item" @click="show = true">
 								<view class="box-hz-list-item-label"><text>鐢ㄨ溅鏃堕棿锛�</text></view>
-								<view class="box-hz-list-item-val">
+								<view :class="form.startDate ? 'box-hz-list-item-val active' : 'box-hz-list-item-val'">
 									<view class="box-hz-list-item-val-left">
 										<image class="icon" src="/static/icon/ic_time@2x.png" mode="widthFix"></image>
-										<text>璇烽�夋嫨鐢ㄨ溅鏃堕棿</text>
+										<text>{{ form.startDate ? form.startDate + ' 鑷� ' + form.endDate : '璇烽�夋嫨鐢ㄥ伐鏃堕棿'}}</text>
 									</view>
-									<image class="icon1" src="/static/icon/home_ar_next@2x.png" mode="widthFix"></image>
+									<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 								</view>
 							</view>
 							<view class="box-hz-list-item">
 								<view class="box-hz-list-item-label">
 									<text>鐢ㄨ溅鏃堕棿锛�</text>
-									<text>+澧炲姞閫旂粡鐐�</text>
+									<text @click="addAddr">+澧炲姞閫旂粡鐐�</text>
 								</view>
 								<view class="item-d">
-									<view class="item-d-row">
+									<view class="item-d-row" @click="selectAddress(2)">
 										<view class="item-d-row-icon">
 											<image src="/static/icon/ic_qidian@2x.png" mode="widthFix"></image>
 										</view>
 										<view class="item-d-row-val">
-											<text>璇烽�夋嫨鐢ㄨ溅璧风偣</text>
-											<image src="/static/icon/home_ar_next@2x.png" mode="widthFix"></image>
+											<text>{{form.address ? form.address : '璇烽�夋嫨鐢ㄨ溅璧风偣'}}</text>
+											<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 										</view>
 									</view>
-									<view class="item-d-row">
+									<view class="item-d-row" v-for="(item, index) in form.wayInfoDTOList" :key="index" @click="selectAddress(4, index)">
 										<view class="item-d-row-icon">
 											<image src="/static/icon/ic_jingguo@2x.png" mode="widthFix"></image>
 										</view>
 										<view class="item-d-row-val">
-											<text style="color: #999999;">璇烽�夋嫨閫旂粡鍦扮偣</text>
-											<image src="/static/icon/home_ar_next@2x.png" mode="widthFix"></image>
+											<text>{{item.location ? item.location : '璇烽�夋嫨閫旂粡鍦扮偣'}}</text>
+											<view style="display: flex; align-items: center; flex-shrink: 0;">
+												<image src="/static/icon/ic_delete@2x.png" style="margin-right: 22rpx; width: 32rpx; height: 32rpx;" @click.stop="form.wayInfoDTOList.splice(index, 1)" mode="widthFix"></image>
+												<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
+											</view>
 										</view>
 									</view>
-									<view class="item-d-row">
+									<view class="item-d-row" @click="selectAddress(3)">
 										<view class="item-d-row-icon">
 											<image src="/static/icon/ic_zhongdian@2x.png" mode="widthFix"></image>
 										</view>
 										<view class="item-d-row-val">
-											<text>璇烽�夋嫨鐢ㄨ溅缁堢偣</text>
-											<image src="/static/icon/home_ar_next@2x.png" mode="widthFix"></image>
+											<text>{{form.locationEnd ? form.locationEnd : '璇烽�夋嫨鐢ㄨ溅缁堢偣'}}</text>
+											<u-icon name="arrow-right" color="#111111" size="16"></u-icon>
 										</view>
 									</view>
 								</view>
@@ -439,7 +438,6 @@
 				show: false,
 				isLogin: false,
 				typeId: 0,
-				carId: 1,
 				type: [
 					{ name: '鐢ㄥ伐', id: 0 },
 					{ name: '杩愯揣', id: 1 },
@@ -450,47 +448,62 @@
 					{ name: '鍒嗘嫞宸�', id: 1 },
 					{ name: '鍖呰宸�', id: 2 }
 				],
-				car: [
-					{ name: '涓夎疆杞�', id: 1 },
-					{ name: '灏忚揣杞�', id: 2 }
-				],
+				car: [],
 				btn: require('@/static/image/btn.png'),
 				typeViewId: 0,
+				carImage: '',
+				carRemark: '',
 				
 				form: {
 					startDate: '',
 					endDate: '',
 					latitude: '',
 					longitude: '',
-					address: '',
+					location: '',
+					locationEnd: '',
+					wayInfoDTOList: [],
 					workType: 0,
+					categoryId: '',
+					categoryName: '',
 					days: ''
 				}
 			}
 		},
+		onLoad() {
+			this.getCategoryLists()
+		},
 		methods: {
+			addAddr() {
+				this.form.wayInfoDTOList.push({
+					lat: '',
+					lgt: '',
+					location: ''
+				})
+			},
 			confirmDate(e) {
 				this.form.startDate = e[0]
 				this.form.endDate = e[e.length - 1]
 				this.form.days = e.length;
 				this.show = false
 			},
-			selectAddress(type) {
+			selectAddress(type, index) {
 				uni.chooseLocation({
 					success: (res) => {
-						if (type === 1) {
+						if ([1,2].includes(type)) {
 							this.form.latitude = res.latitude
 							this.form.longitude = res.longitude
 							this.form.address = res.address
+						} else if (type === 3) {
+							this.form.locationEnd = res.address
+							this.form.latEnd = res.latitude
+							this.form.lgtEnd = res.longitude
+						} else if (type === 4) {
+							this.form.wayInfoDTOList[0].lat = res.latitude
+							this.form.wayInfoDTOList[0].lgt = res.longitude
+							this.form.wayInfoDTOList[0].location = res.address
 						}
 					}
 				});
-				// uni.getLocation({
-				// 	type: 'gcj02',
-				// 	success: function (res) {
-				// 		console.log(res)
-				// 	}
-				// });
 			},
 			clickType(e) {
 				this.typeId = e
@@ -498,8 +511,11 @@
 			clickTypeWork(e) {
 				this.form.workType = e
 			},
-			clickCar(e) {
-				this.carId = e
+			clickCar(item) {
+				this.form.categoryId = item.id
+				this.form.categoryName = item.name
+				this.carImage = item.iconFull
+				this.carRemark = item.remark
 			},
 			jump() {
 				if(!this.userInfo || !this.token){
@@ -511,31 +527,76 @@
 				
 				const { form } = this;
 				
-				if (!form.startDate || !form.endDate) {
-					return uni.showToast({ title: '璇烽�夋嫨鐢ㄥ伐鏃堕棿', icon: 'none' })
-				} else if (!form.latitude || !form.longitude) {
-					return uni.showToast({ title: '璇烽�夋嫨鐢ㄥ伐鍦扮偣', icon: 'none' })
-				}
-				
-				// 閲囨憳宸�
-				if (this.form.workType === 0) {
+				// 鐢ㄥ伐
+				if (this.typeId === 0) {
+					
+					if (!form.startDate || !form.endDate) {
+						return uni.showToast({ title: '璇烽�夋嫨鐢ㄥ伐鏃堕棿', icon: 'none' })
+					} else if (!form.latitude || !form.longitude) {
+						return uni.showToast({ title: '璇烽�夋嫨鐢ㄥ伐鍦扮偣', icon: 'none' })
+					}
+					
+					// 閲囨憳宸�
+					if (this.form.workType === 0) {
+						uni.navigateTo({
+							url: `/pages/using-workers/using-workers?days=${form.days}&startDate=${form.startDate}&endDate=${form.endDate}&latitude=${form.latitude}&longitude=${form.longitude}&address=${form.location}&workType=${form.workType}`
+						})
+					// 鍒嗘嫞宸�
+					} else if (this.form.workType === 1) {
+						uni.navigateTo({
+							url: `/pages/sorting/sorting?days=${form.days}&startDate=${form.startDate}&endDate=${form.endDate}&latitude=${form.latitude}&longitude=${form.longitude}&address=${form.location}&workType=${form.workType}`
+						})
+					// 鍖呰宸�
+					} else if (this.form.workType === 2) {
+						uni.navigateTo({
+							url: `/pages/packaging-worker/packaging-worker?days=${form.days}&startDate=${form.startDate}&endDate=${form.endDate}&latitude=${form.latitude}&longitude=${form.longitude}&address=${form.location}&workType=${form.workType}`
+						})
+					}
+				// 杩愯揣
+				} else if (this.typeId === 1) {
+					
+					if (!form.startDate || !form.endDate) {
+						return uni.showToast({ title: '璇烽�夋嫨鐢ㄨ溅鏃堕棿', icon: 'none' })
+					} else if (!form.latitude || !form.longitude) {
+						return uni.showToast({ title: '璇烽�夋嫨鐢ㄨ溅璧风偣', icon: 'none' })
+					} else if (!form.latEnd || !form.lgtEnd) {
+						return uni.showToast({ title: '璇烽�夋嫨鐢ㄨ溅缁堢偣', icon: 'none' })
+					}
+					
+					let carData = {
+						startDate: form.startDate,
+						endDate: form.endDate,
+						lat: form.latitude,
+						lgt: form.longitude,
+						location: form.address,
+						latEnd: form.latEnd,
+						lgtEnd: form.lgtEnd,
+						locationEnd: form.locationEnd,
+						wayInfoDTOList: form.wayInfoDTOList,
+						categoryId: form.categoryId,
+						categoryName: form.categoryName,
+						days: form.days
+					}
+					
+					uni.setStorageSync('carData', carData);
+					
 					uni.navigateTo({
-						url: `/pages/using-workers/using-workers?days=${form.days}&startDate=${form.startDate}&endDate=${form.endDate}&latitude=${form.latitude}&longitude=${form.longitude}&address=${form.address}&workType=${form.workType}`
-					})
-				// 鍒嗘嫞宸�
-				} else if (this.form.workType === 1) {
-					uni.navigateTo({
-						url: `/pages/sorting/sorting?days=${form.days}&startDate=${form.startDate}&endDate=${form.endDate}&latitude=${form.latitude}&longitude=${form.longitude}&address=${form.address}&workType=${form.workType}`
-					})
-				// 鍖呰宸�
-				} else if (this.form.workType === 2) {
-					uni.navigateTo({
-						url: `/pages/packaging-worker/packaging-worker?days=${form.days}&startDate=${form.startDate}&endDate=${form.endDate}&latitude=${form.latitude}&longitude=${form.longitude}&address=${form.address}&workType=${form.workType}`
+						url: `/pages/freight/freight`
 					})
 				}
 			},
 			mverify(e){
 				console.log('楠岃瘉缁撴灉:',e);
+			},
+			getCategoryLists() {
+				this.$u.api.getCategoryList({ type: 1 })
+					.then(res => {
+						this.car = res.data
+						this.form.categoryId = res.data[0].id
+						this.form.categoryName = res.data[0].name
+						this.carRemark = res.data[0].remark
+						this.carImage = res.data[0].iconFull
+					})
 			}
 		}
 	}
@@ -1179,9 +1240,12 @@
 						.box-hz-car-image {
 							width: 432rpx;
 							height: 200rpx;
+							display: flex;
+							align-items: center;
+							justify-content: center;
+							overflow: hidden;
 							image {
 								width: 100%;
-								height: 100%;
 							}
 						}
 						.box-hz-car-info {
@@ -1244,7 +1308,8 @@
 								border: 2rpx solid #FD9E24;
 								.item-d-row {
 									width: 100%;
-									height: 100rpx;
+									// height: 100rpx;
+									height: auto;
 									display: flex;
 									align-items: center;
 									justify-content: space-between;
@@ -1260,7 +1325,9 @@
 									}
 									.item-d-row-val {
 										flex: 1;
-										height: 100%;
+										// height: 100%;
+										padding: 30rpx 0;
+										box-sizing: border-box;
 										display: flex;
 										align-items: center;
 										justify-content: space-between;
diff --git a/small-program/pages/packaging-worker/packaging-worker.vue b/small-program/pages/packaging-worker/packaging-worker.vue
index f66dcfa..82fe0a7 100644
--- a/small-program/pages/packaging-worker/packaging-worker.vue
+++ b/small-program/pages/packaging-worker/packaging-worker.vue
@@ -89,7 +89,7 @@
 					<view class="list-item-row-label">璐圭敤鏍囧噯<b>*</b></view>
 					<view class="list-item-row-val">
 						<input v-model="form.price" type="number" @blur="getPrice" placeholder="璇疯緭鍏�" />
-						<text>鍏�/浜�/澶�</text>
+						<text>{{form.priceUnit}}</text>
 					</view>
 				</view>
 			</view>
@@ -226,7 +226,7 @@
 					.then(res => {
 						if (res.code == 200) {
 							uni.navigateTo({
-								url: `/pages/success/success?orderId=${res.data}`
+								url: `/pages/success/success?orderId=${res.data.id}`
 							})
 						}
 					})
@@ -236,7 +236,6 @@
 				if (this.form.price && this.form.priceNum1 && this.form.priceNum2) {
 					this.$u.api.getTotal({
 						price: Number(this.form.price) * 100,
-						priceUnit: this.form.priceUnit,
 						priceNum1: this.form.priceNum1,
 						priceNum2: this.form.priceNum2,
 						type: this.form.type,
diff --git a/small-program/pages/sorting/sorting.vue b/small-program/pages/sorting/sorting.vue
index aaa01f8..b7e942b 100644
--- a/small-program/pages/sorting/sorting.vue
+++ b/small-program/pages/sorting/sorting.vue
@@ -217,7 +217,7 @@
 					.then(res => {
 						if (res.code == 200) {
 							uni.navigateTo({
-								url: `/pages/success/success?orderId=${res.data}`
+								url: `/pages/success/success?orderId=${res.data.id}`
 							})
 						}
 					})
diff --git a/small-program/pages/using-workers/using-workers.vue b/small-program/pages/using-workers/using-workers.vue
index 451b52a..712b0e2 100644
--- a/small-program/pages/using-workers/using-workers.vue
+++ b/small-program/pages/using-workers/using-workers.vue
@@ -209,7 +209,7 @@
 					.then(res => {
 						if (res.code == 200) {
 							uni.navigateTo({
-								url: `/pages/success/success?orderId=${res.data}`
+								url: `/pages/success/success?orderId=${res.data.id}`
 							})
 						}
 					})

--
Gitblit v1.9.3