longz
2026-04-27 4d4eb6e9addc4ce148e05f470beb016e507975ba
小程序二维码 支持改价 自主行程查询
18个文件已修改
604 ■■■■■ 已修改文件
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/CallbackController.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/DriverController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/CrossCityShiftController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/LineSiteController.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/OrderCrossCityController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/LineShiftDriverMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/DriverSelfTrip.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/OrderCrossCity.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/ILineSiteService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/LineShiftDriverServiceImpl.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/LineSiteServiceImpl.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/OrderCrossCityServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/AddSelfTripWarpper.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/OrderCrossCityOnBehalfWarpper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/ScanOrderDetailWarpper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IDriverService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/DriverServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/WeChatUtil.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/CallbackController.java
@@ -19,11 +19,9 @@
import com.stylefeng.guns.modular.system.util.rongyun.model.CloudRecordingCallback;
import com.stylefeng.guns.modular.taxi.model.OrderTaxi;
import com.stylefeng.guns.modular.taxi.service.IOrderTaxiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -39,6 +37,7 @@
/**
 * 第三方支付回调控制器
 */
@Slf4j
@RestController
@RequestMapping("/base")
public class CallbackController {
@@ -71,15 +70,20 @@
     */
    @ResponseBody
    @PostMapping("/cbyzxPayOrderTaxi")
    public Map<String, Object> cbyzxPayOrderTaxi(HttpServletRequest request) {
    public Map<String, Object> cbyzxPayOrderTaxi(@RequestBody String params, HttpServletRequest request) {
        try {
            JSONObject payload = cbyzxOrderPayHelper.parseCallbackRequest(request);
            JSONObject payload = JSONObject.parseObject(params);
            log.info("创博优完成订单支付回调,outRequestNo={}, paymentOrderId={}, paidTime={}, paidAmount={}",
                    cbyzxOrderPayHelper.extractOutRequestNo(payload),
                    cbyzxOrderPayHelper.extractThirdPartyOrderNo(payload),
                    payload == null ? null : payload.getString("paidTime"),
                    payload == null ? null : payload.getString("paidAmount"));
            if (payload == null) {
                return buildCbyzxCallbackResponse(1, "invalid request");
            }
            if (!cbyzxOrderPayHelper.isPaySuccess(payload)) {
                return buildCbyzxCallbackResponse(1, cbyzxOrderPayHelper.extractMessage(payload));
            }
//            if (!cbyzxOrderPayHelper.isPaySuccess(payload)) {
//                return buildCbyzxCallbackResponse(1, cbyzxOrderPayHelper.extractMessage(payload));
//            }
            String outTradeNo = cbyzxOrderPayHelper.extractOutRequestNo(payload);
            if (ToolUtil.isEmpty(outTradeNo)) {
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/DriverController.java
@@ -128,12 +128,6 @@
    
    @Autowired
    private WeChatUtil weChatUtil;
    @Value("${filePath}")
    private String filePath;
    @Value("${qyt.admin_url}")
    private String adminUrl;
    
    /**
     * 获取短信验证码
@@ -1836,19 +1830,11 @@
            if (driver != null) {
                String fileName = driver.getQrCode();
                if (fileName == null || "".equals(fileName)) {
                    String appletPath = "pages/home/scanPage/scanPage";
                    //HttpURLConnection httpURLConnection = weChatUtil.getwxacodeunlimit(appletPath, "d=" + driverId + "&k=" + 0, "release",driverId);
                    InputStream inputStream = weChatUtil.getwxacodeunlimit(appletPath, "driverId=" + driverId, "trial");
                    if (inputStream != null) {
                        File file = FileUtil.writeFromStream(inputStream, new File(filePath + "/" + UUID.randomUUID().toString() + ".png"));
                        HttpRequest post = HttpUtil.createPost(adminUrl + "/upload/image");
                        post.form("file", file);
                        HttpResponse execute = post.execute();
                        int status = execute.getStatus();
                        if(200 != status){
                            throw new RuntimeException("上传图片异常");
                        }
                        driver.setQrCode(execute.body());
                    String appletPath = "pages/index/index";
                    String scene = "driverId=" + driverId;
                    String unlimitQrcodeUrl = weChatUtil.getUnlimitQrcode(appletPath, scene);
                    if (unlimitQrcodeUrl != null) {
                        driver.setQrCode(unlimitQrcodeUrl);
                        driverService.updateById(driver);
                        fileName = driver.getQrCode();
                    }
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/CrossCityShiftController.java
@@ -139,7 +139,7 @@
            @ApiImplicitParam(value = "出发地地址", name = "startAddress", required = true, dataType = "String"),
            @ApiImplicitParam(value = "出发地经度", name = "startLon", required = true, dataType = "double"),
            @ApiImplicitParam(value = "出发地纬度", name = "startLat", required = true, dataType = "double"),
            @ApiImplicitParam(value = "目的地JSON数组(每项需包含endAddress/endLon/endLat/price)", name = "destJson", required = true, dataType = "String"),
            @ApiImplicitParam(value = "目的地JSON数组(每项需包含endCityCode/endCityName/endAddress/endLon/endLat/price)", name = "destJson", required = true, dataType = "String"),
            @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil<Map<String, Object>> addSelfTrip(AddSelfTripWarpper warpper, HttpServletRequest request) {
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/LineSiteController.java
@@ -1,6 +1,5 @@
package com.stylefeng.guns.modular.crossCity.controller;
import com.stylefeng.guns.modular.crossCity.server.ILineSiteService;
import com.stylefeng.guns.modular.crossCity.warpper.LineSiteWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.LocationWarpper;
@@ -132,6 +131,24 @@
        }
    }
    @ResponseBody
    @RequestMapping(value = "/api/selfLine/queryLocation", method = RequestMethod.POST)
    @ApiOperation(value = "自主行程获取上下车点区域范围", tags = {"司机端-首页"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "司机排班记录id", name = "lineShiftDriverId", required = true, dataType = "int"),
            @ApiImplicitParam(value = "类型(1=上车点,2=下车点)", name = "type", required = true, dataType = "int"),
            @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil<List<LocationWarpper>> querySelfLocation(Integer lineShiftDriverId, Integer type, HttpServletRequest request) {
        try {
            Integer driverId = driverService.getUserIdFormRedis(request);
            return lineSiteService.querySelfLocation(driverId, lineShiftDriverId, type);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 判断一个点是是否在区域范围内
@@ -159,4 +176,27 @@
        }
    }
    @ResponseBody
    @RequestMapping(value = "/api/selfLine/areaMonitoring", method = RequestMethod.POST)
    @ApiOperation(value = "判断自主行程点位是否在电子围栏内", tags = {"司机端-首页"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "司机排班记录id", name = "lineShiftDriverId", required = true, dataType = "int"),
            @ApiImplicitParam(value = "类型(1=上车点,2=下车点)", name = "type", required = true, dataType = "int"),
            @ApiImplicitParam(value = "经纬度(lon,lat)", name = "lonLat", required = true, dataType = "string"),
            @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil selfAreaMonitoring(Integer lineShiftDriverId, Integer type, String lonLat, HttpServletRequest request) {
        try {
            Integer driverId = driverService.getUserIdFormRedis(request);
            if (driverId == null) {
                return ResultUtil.tokenErr();
            }
            boolean b = lineSiteService.selfAreaMonitoring(driverId, lineShiftDriverId, type, lonLat);
            return ResultUtil.success(b ? 1 : -1);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/OrderCrossCityController.java
@@ -7,6 +7,8 @@
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.account.service.ITEnterpriseWithdrawalService;
import com.stylefeng.guns.modular.account.service.UserWithdrawalService;
@@ -34,13 +36,16 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.Map;
import java.util.UUID;
@@ -405,33 +410,21 @@
            // 3. 构建scene参数(最大32字符)
            StringBuilder sceneBuilder = new StringBuilder();
            sceneBuilder.append("id=").append(lineShiftDriverId);
            sceneBuilder.append("driverId=").append(driverId);
            if (ToolUtil.isNotEmpty(otherFee)) {
                sceneBuilder.append("&f=").append(otherFee);
            }
            String scene = sceneBuilder.toString();
            if (scene.length() > 32) {
                return ResultUtil.error("生成小程序码失败:scene参数超长");
            }
            // 4. 生成小程序码
            String page = "pages/scanOrder/scanOrder";  // 小程序跳转页面
            String envVersion = env.equals("prod") ? "release" : "trial";     // 正式版环境
            InputStream inputStream = weChatUtil.getwxacodeunlimit(page, scene, envVersion);
            if (null == inputStream) {
                return ResultUtil.error("生成小程序码失败");
            }
            // 5. 上传到服务器
            File file = FileUtil.writeFromStream(inputStream, new File(filePath + "/" + UUID.randomUUID().toString() + ".png"));
            HttpRequest post = HttpUtil.createPost(adminUrl + "/upload/image");
            post.form("file", file);
            HttpResponse execute = post.execute();
            int status = execute.getStatus();
            if (200 != status) {
                throw new RuntimeException("上传图片异常");
            }
            String page = "pages/index/index";  // 小程序跳转页面
            String unlimitQrcodeUrl = weChatUtil.getUnlimitQrcode(page, scene);
            // 6. 返回结果
            BaseWarpper baseWarpper = new BaseWarpper();
            baseWarpper.setContent(JSONObject.parseObject(execute.body()).get("data").toString());
            baseWarpper.setContent(unlimitQrcodeUrl);
            return ResultUtil.success(baseWarpper);
        } catch (Exception e) {
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/LineShiftDriverMapper.xml
@@ -67,6 +67,7 @@
            -- 司机信息
            d.headImgUrl as headImgUrl,
            CONCAT(LEFT(d.name, 1), '师傅') as driverName,
            d.sex as sex,
            c.carLicensePlate as carLicensePlate,
            CONCAT(cb.name, cm.name) as carBrand,
            c.carColor as carColor,
@@ -195,7 +196,7 @@
                lsd.totalSeat as totalSeat,
                st.startTime as startTime,
                st.startTime as endTime,
                '自主行程' as lineName,
                CONCAT(st.startCityName,'-',st.endCityName) as lineName,
                1 as assignType,
                NULL as orderId,
                NULL as orderType,
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/DriverSelfTrip.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
@@ -34,6 +35,12 @@
    @TableField("startCityName")
    private String startCityName;
    @TableField("endCityCode")
    private String endCityCode;
    @TableField("endCityName")
    private String endCityName;
    @TableField("startAddress")
    private String startAddress;
@@ -167,4 +174,20 @@
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public String getEndCityCode() {
        return endCityCode;
    }
    public void setEndCityCode(String endCityCode) {
        this.endCityCode = endCityCode;
    }
    public String getEndCityName() {
        return endCityName;
    }
    public void setEndCityName(String endCityName) {
        this.endCityName = endCityName;
    }
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/OrderCrossCity.java
@@ -401,6 +401,10 @@
     */
    private Integer isGenerateRecoveryOrder;
    /**
     * 是否司机改价(0=否,1=是)
     */
    private Integer hasChangePrice;
    /**
     * 原始订单id
     */
    private Integer oldOrderId;
@@ -1119,6 +1123,14 @@
        this.recoveryOrderCreateDate = recoveryOrderCreateDate;
    }
    public Integer getHasChangePrice() {
        return hasChangePrice;
    }
    public void setHasChangePrice(Integer hasChangePrice) {
        this.hasChangePrice = hasChangePrice;
    }
    @Override
    public String toString() {
        return "OrderCrossCity{" +
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/ILineSiteService.java
@@ -2,7 +2,9 @@
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.crossCity.model.LineSite;
import com.stylefeng.guns.modular.crossCity.warpper.LocationWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.SiteWarpper;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import java.util.List;
import java.util.Map;
@@ -58,6 +60,27 @@
     */
    List<Map<String, Object>> queryLocation(Integer siteId) throws Exception;
    /**
     * 根据司机自主行程获取上下车点区域范围
     * @param driverId 当前司机id
     * @param lineShiftDriverId 司机排班记录id
     * @param type 类型(1=上车点,2=下车点)
     * @return 区域范围
     * @throws Exception
     */
    ResultUtil<List<LocationWarpper>> querySelfLocation(Integer driverId, Integer lineShiftDriverId, Integer type) throws Exception;
    /**
     * 判断一个点是否在自主行程电子围栏内
     * @param driverId 当前司机id
     * @param lineShiftDriverId 司机排班记录id
     * @param type 类型(1=上车点,2=下车点)
     * @param lonLat 经纬度
     * @return 是否在围栏内
     * @throws Exception
     */
    boolean selfAreaMonitoring(Integer driverId, Integer lineShiftDriverId, Integer type, String lonLat) throws Exception;
    /**
     * 判断坐标点是否在站点范围内
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/LineShiftDriverServiceImpl.java
@@ -1,7 +1,5 @@
package com.stylefeng.guns.modular.crossCity.server.impl;
import cn.hutool.core.date.DateUnit;
import cn.hutool.cron.CronUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
@@ -18,16 +16,11 @@
import com.stylefeng.guns.modular.crossCity.model.OrderCrossCity;
import com.stylefeng.guns.modular.crossCity.server.ILineService;
import com.stylefeng.guns.modular.crossCity.server.ILineShiftDriverService;
import com.stylefeng.guns.modular.crossCity.server.ILineSiteService;
import com.stylefeng.guns.modular.crossCity.server.IOrderCrossCityService;
import com.stylefeng.guns.modular.crossCity.warpper.AddSelfTripWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.DriverShiftListWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.LineShiftItemWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.OtherDriverShiftWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.ScanOrderDetailWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.*;
import com.stylefeng.guns.modular.system.dao.CarModelMapper;
import com.stylefeng.guns.modular.system.dao.CarServiceMapper;
import com.stylefeng.guns.modular.system.dao.ServerCarModelMapper;
import com.stylefeng.guns.modular.system.dao.OrderEvaluateMapper;
import com.stylefeng.guns.modular.system.model.Car;
import com.stylefeng.guns.modular.system.model.CarModel;
import com.stylefeng.guns.modular.system.model.CarService;
@@ -46,7 +39,6 @@
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -78,6 +70,9 @@
    @Resource
    private DriverSelfTripMapper driverSelfTripMapper;
    @Resource
    private OrderEvaluateMapper orderEvaluateMapper;
    @Autowired
    private IOrderCrossCityService orderCrossCityService;
@@ -521,6 +516,8 @@
        trip.setSeat(warpper.getSeat());
        trip.setStartCityCode(warpper.getStartCityCode());
        trip.setStartCityName(warpper.getStartCityName());
        trip.setEndCityCode(warpper.getEndCityCode());
        trip.setEndCityName(warpper.getEndCityName());
        trip.setStartAddress(warpper.getStartAddress());
        trip.setStartLon(warpper.getStartLon());
        trip.setStartLat(warpper.getStartLat());
@@ -582,7 +579,11 @@
                Double endLon = item.getDouble("endLon");
                Double endLat = item.getDouble("endLat");
                Double price = item.getDouble("price");
                if (ToolUtil.isEmpty(endAddress) || endLon == null || endLat == null || price == null || price < 0) {
                if (ToolUtil.isEmpty(endAddress)
                        || endLon == null
                        || endLat == null
                        || price == null
                        || price < 0) {
                    return null;
                }
            }
@@ -605,6 +606,14 @@
    @Override
    public ResultUtil<ScanOrderDetailWarpper> getDetail(Integer lineShiftDriverId) {
        LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(lineShiftDriverId);
        if (lineShiftDriver == null) {
            return ResultUtil.error("班次信息不存在");
        }
        if (lineShiftDriver.getLineShiftId() != null && lineShiftDriver.getLineShiftId() == -1) {
            return buildSelfTripDetail(lineShiftDriver);
        }
        // 1. 查询基础数据
        Map<String, Object> data = lineShiftDriverMapper.getDetail(lineShiftDriverId);
        if (data == null || data.isEmpty()) {
@@ -617,6 +626,7 @@
        // 司机信息
        result.setHeadImgUrl(data.get("headImgUrl") != null ? data.get("headImgUrl").toString() : null);
        result.setDriverName(data.get("driverName") != null ? data.get("driverName").toString() : null);
        result.setSex(data.get("sex") != null ? Integer.parseInt(data.get("sex").toString()) : null);
        result.setCarLicensePlate(data.get("carLicensePlate") != null ? data.get("carLicensePlate").toString() : null);
        result.setCarBrand(data.get("carBrand") != null ? data.get("carBrand").toString() : null);
        result.setCarColor(data.get("carColor") != null ? data.get("carColor").toString() : null);
@@ -671,4 +681,116 @@
        return ResultUtil.success(result);
    }
    private ResultUtil<ScanOrderDetailWarpper> buildSelfTripDetail(LineShiftDriver lineShiftDriver) {
        if (lineShiftDriver.getCustomerId() == null) {
            return ResultUtil.error("自主行程信息不存在");
        }
        DriverSelfTrip trip = driverSelfTripMapper.selectById(lineShiftDriver.getCustomerId());
        if (trip == null || trip.getState() == null || trip.getState() != 1) {
            return ResultUtil.error("自主行程信息不存在");
        }
        Driver driver = driverService.selectById(lineShiftDriver.getDriverId());
        if (driver == null) {
            return ResultUtil.error("司机信息不存在");
        }
        Car car = null;
        CarModel carModel = null;
        CarService carServiceData = null;
        if (driver.getCarId() != null) {
            car = carService.selectById(driver.getCarId());
            if (car != null && car.getCarModelId() != null) {
                carModel = carModelMapper.selectById(car.getCarModelId());
            }
            carServiceData = carServiceMapper.query(3, driver.getCarId());
        }
        ScanOrderDetailWarpper result = new ScanOrderDetailWarpper();
        result.setHeadImgUrl(driver.getHeadImgUrl());
        String name = driver.getName();
        result.setDriverName(ToolUtil.isEmpty(name) ? "" : name.substring(0, 1) + "师傅");
        result.setSex(driver.getSex());
        result.setCarLicensePlate(car == null ? null : car.getCarLicensePlate());
        result.setCarBrand(carModel == null ? null : carModel.getName());
        result.setCarColor(car == null ? null : car.getCarColor());
        Double score = orderEvaluateMapper.queryCount(driver.getId());
        result.setScore(score == null ? 0D : score);
        int orderCount = orderCrossCityService.selectCount(
                new EntityWrapper<OrderCrossCity>()
                        .eq("driverId", driver.getId())
                        .eq("state", 9)
        );
        result.setOrderCount(orderCount);
        result.setLineId(-1);
        result.setLineName(trip.getStartCityName() + "-" + trip.getEndCityName());
        result.setUnitPrice(null);
        if (lineShiftDriver.getDay() != null) {
            result.setDay(new SimpleDateFormat("yyyy-MM-dd").format(lineShiftDriver.getDay()));
        }
        result.setStartTime(trip.getStartTime());
        result.setEndTime(trip.getStartTime());
        result.setTotalSeat(lineShiftDriver.getTotalSeat());
        result.setLaveSeat(lineShiftDriver.getLaveSeat());
        result.setLaveSeatNumber(lineShiftDriver.getLaveSeatNumber());
        result.setStartSiteId(null);
        result.setStartSiteName(trip.getStartAddress());
        result.setEndSiteId(null);
        result.setEndSiteName(null);
        result.setStartCityName(trip.getStartCityName());
        result.setEndCityName(null);
        result.setStartLonLat(trip.getStartLon() == null || trip.getStartLat() == null ? null : trip.getStartLon() + "," + trip.getStartLat());
        result.setEndLonLat(null);
        if (ToolUtil.isNotEmpty(trip.getDestJson())) {
            try {
                JSONArray array = JSON.parseArray(trip.getDestJson());
                if (array != null && !array.isEmpty()) {
                    JSONObject first = array.getJSONObject(0);
                    if (first != null) {
                        result.setEndSiteName(first.getString("endAddress"));
                        result.setEndCityName(first.getString("endCityName"));
                        Double endLon = first.getDouble("endLon");
                        Double endLat = first.getDouble("endLat");
                        if (endLon != null && endLat != null) {
                            result.setEndLonLat(endLon + "," + endLat);
                        }
                        Double price = first.getDouble("price");
                        if (price != null) {
                            result.setUnitPrice(price);
                        }
                    }
                    for (int i = 0; i < array.size(); i++) {
                        JSONObject jsonObject = array.getJSONObject(i);
                        jsonObject.put("range",3000D);
                    }
                    result.setEndDetailList(array);
                }
            } catch (Exception ignored) {
            }
        }
        result.setOtherFee(null);
        result.setServerCarModelId(carServiceData == null ? null : carServiceData.getServerCarModelId());
        result.setDriverId(driver.getId());
        result.setLineShiftDriverId(lineShiftDriver.getId());
        result.setStartDefaultPointAddress(trip.getStartAddress());
        result.setStartDefaultPointLon(trip.getStartLon());
        result.setStartDefaultPointLat(trip.getStartLat());
        result.setEndDefaultPointAddress(result.getEndSiteName());
        if (ToolUtil.isNotEmpty(result.getEndLonLat()) && result.getEndLonLat().contains(",")) {
            String[] split = result.getEndLonLat().split(",");
            if (split.length == 2) {
                try {
                    result.setEndDefaultPointLon(Double.valueOf(split[0]));
                    result.setEndDefaultPointLat(Double.valueOf(split[1]));
                } catch (Exception ignored) {
                }
            }
        }
        return ResultUtil.success(result);
    }
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/LineSiteServiceImpl.java
@@ -1,6 +1,7 @@
package com.stylefeng.guns.modular.crossCity.server.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
@@ -9,12 +10,14 @@
import com.stylefeng.guns.modular.crossCity.model.*;
import com.stylefeng.guns.modular.crossCity.server.ILineSiteService;
import com.stylefeng.guns.modular.crossCity.server.IOrderCrossCityService;
import com.stylefeng.guns.modular.crossCity.warpper.LocationWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.SiteWarpper;
import com.stylefeng.guns.modular.specialTrain.model.OrderPrivateCar;
import com.stylefeng.guns.modular.specialTrain.server.IOrderPrivateCarService;
import com.stylefeng.guns.modular.system.util.DateUtil;
import com.stylefeng.guns.modular.system.util.GDMapElectricFenceUtil;
import com.stylefeng.guns.modular.system.util.GDMapGeocodingUtil;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import com.stylefeng.guns.modular.system.util.SystemException;
import com.stylefeng.guns.modular.system.util.model.GeoFencingPolygon;
import com.stylefeng.guns.modular.taxi.model.OrderTaxi;
@@ -50,6 +53,9 @@
    
    @Resource
    private LocationMapper locationMapper;
    @Resource
    private DriverSelfTripMapper driverSelfTripMapper;
    
    @Autowired
    private DateUtil dateUtil;
@@ -287,6 +293,147 @@
        return locationMapper.queryLocation(siteId);
    }
    @Override
    public ResultUtil<List<LocationWarpper>> querySelfLocation(Integer driverId, Integer lineShiftDriverId, Integer type) throws Exception {
        if (driverId == null) {
            return ResultUtil.tokenErr();
        }
        if (lineShiftDriverId == null || type == null) {
            return ResultUtil.paranErr();
        }
        if (type != 1 && type != 2) {
            return ResultUtil.error("type参数错误");
        }
        LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(lineShiftDriverId);
        if (lineShiftDriver == null) {
            return ResultUtil.error("班次信息不存在");
        }
        if (!driverId.equals(lineShiftDriver.getDriverId())) {
            return ResultUtil.error("无权操作此班次");
        }
        if (lineShiftDriver.getCustomerId() == null) {
            return ResultUtil.error("自主行程信息不存在");
        }
        DriverSelfTrip selfTrip = driverSelfTripMapper.selectById(lineShiftDriver.getCustomerId());
        if (selfTrip == null || selfTrip.getState() == null || selfTrip.getState() != 1) {
            return ResultUtil.error("自主行程信息不存在");
        }
        List<LocationWarpper> data = new ArrayList<>();
        if (type == 1) {
            if (selfTrip.getStartLon() == null || selfTrip.getStartLat() == null) {
                return ResultUtil.error("上车点坐标不存在");
            }
            data.add(buildCircleLocation(selfTrip.getStartLon(), selfTrip.getStartLat()));
            return ResultUtil.success(data);
        }
        if (ToolUtil.isEmpty(selfTrip.getDestJson())) {
            return ResultUtil.success(data);
        }
        JSONArray array = JSON.parseArray(selfTrip.getDestJson());
        if (array == null) {
            return ResultUtil.success(data);
        }
        for (int i = 0; i < array.size(); i++) {
            JSONObject item = array.getJSONObject(i);
            if (item == null) {
                continue;
            }
            Double endLon = item.getDouble("endLon");
            Double endLat = item.getDouble("endLat");
            if (endLon == null || endLat == null) {
                continue;
            }
            data.add(buildCircleLocation(endLon, endLat));
        }
        return ResultUtil.success(data);
    }
    private LocationWarpper buildCircleLocation(Double lon, Double lat) {
        LocationWarpper locationWarpper = new LocationWarpper();
        locationWarpper.setType(2);
        locationWarpper.setCoordinate(lon + "," + lat + ";3000");
        locationWarpper.setProvince("");
        locationWarpper.setProvinceCode("");
        locationWarpper.setCity("");
        locationWarpper.setCityCode("");
        locationWarpper.setDistrict("");
        locationWarpper.setDistrictCode("");
        return locationWarpper;
    }
    @Override
    public boolean selfAreaMonitoring(Integer driverId, Integer lineShiftDriverId, Integer type, String lonLat) throws Exception {
        if (driverId == null || lineShiftDriverId == null || type == null || ToolUtil.isEmpty(lonLat)) {
            return false;
        }
        if (type != 1 && type != 2) {
            return false;
        }
        String[] pointArr = lonLat.split(",");
        if (pointArr.length != 2) {
            return false;
        }
        Double pointLon;
        Double pointLat;
        try {
            pointLon = Double.valueOf(pointArr[0]);
            pointLat = Double.valueOf(pointArr[1]);
        } catch (Exception e) {
            return false;
        }
        LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(lineShiftDriverId);
        if (lineShiftDriver == null || !driverId.equals(lineShiftDriver.getDriverId()) || lineShiftDriver.getCustomerId() == null) {
            return false;
        }
        DriverSelfTrip selfTrip = driverSelfTripMapper.selectById(lineShiftDriver.getCustomerId());
        if (selfTrip == null || selfTrip.getState() == null || selfTrip.getState() != 1) {
            return false;
        }
        if (type == 1) {
            return isWithinCircle(selfTrip.getStartLon(), selfTrip.getStartLat(), pointLon, pointLat, 3000D);
        }
        if (ToolUtil.isEmpty(selfTrip.getDestJson())) {
            return false;
        }
        JSONArray array = JSON.parseArray(selfTrip.getDestJson());
        if (array == null || array.isEmpty()) {
            return false;
        }
        for (int i = 0; i < array.size(); i++) {
            JSONObject item = array.getJSONObject(i);
            if (item == null) {
                continue;
            }
            Double endLon = item.getDouble("endLon");
            Double endLat = item.getDouble("endLat");
            if (isWithinCircle(endLon, endLat, pointLon, pointLat, 3000D)) {
                return true;
            }
        }
        return false;
    }
    private boolean isWithinCircle(Double centerLon, Double centerLat, Double pointLon, Double pointLat, Double radiusMeter) {
        if (centerLon == null || centerLat == null || pointLon == null || pointLat == null || radiusMeter == null) {
            return false;
        }
        double earthRadius = 6371000D;
        double lat1 = Math.toRadians(centerLat);
        double lat2 = Math.toRadians(pointLat);
        double deltaLat = lat2 - lat1;
        double deltaLon = Math.toRadians(pointLon - centerLon);
        double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)
                + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = earthRadius * c;
        return distance <= radiusMeter;
    }
    /**
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/OrderCrossCityServiceImpl.java
@@ -1286,6 +1286,9 @@
        if (warpper.getOtherFee() != null && warpper.getOtherFee().compareTo(BigDecimal.ZERO) < 0) {
            return ResultUtil.error("其他费用不能为负数");
        }
        if (warpper.getChangePrice() != null && warpper.getChangePrice().compareTo(BigDecimal.ZERO) < 0) {
            return ResultUtil.error("改价费用不能为负数");
        }
        // 2. 校验班次信息
        LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(warpper.getLineShiftDriverId());
@@ -1447,7 +1450,12 @@
        orderCrossCity.setEndAddress(endAddress);
        orderCrossCity.setMileage(0D);
        orderCrossCity.setOrderMoney(totalMoney);
        if (warpper.getChangePrice() != null) {
            orderCrossCity.setOrderMoney(warpper.getChangePrice().doubleValue());
            orderCrossCity.setHasChangePrice(1);
        } else {
            orderCrossCity.setOrderMoney(totalMoney);
        }
        orderCrossCity.setCompanyId(driver.getCompanyId());
        orderCrossCity.setPeopleNumber(warpper.getPeopleNumber());
        orderCrossCity.setSeatNumber(seatNumber);
@@ -1558,17 +1566,18 @@
            return ResultUtil.error("订单不在待支付,无法完成订单");
        }
        if (type == 1) {
            UserInfo userInfo = userInfoMapper.selectById(order.getUserId());
            if (userInfo == null) {
                return ResultUtil.error("乘客不存在");
//            UserInfo userInfo = userInfoMapper.selectById(order.getUserId());
            Driver driver = driverService.selectById(driverId);
            if (driver == null) {
                return ResultUtil.error("司机不存在");
            }
            if (ToolUtil.isEmpty(userInfo.getAppletsOpenId())) {
                return ResultUtil.errorOpenId("乘客未绑定微信小程序openid,无法发起微信支付");
            if (ToolUtil.isEmpty(driver.getAppletsOpenId())) {
                return ResultUtil.errorOpenId("司机未绑定微信小程序openid,无法发起微信支付");
            }
            String outTradeNo = buildCbyzxOnBehalfOutTradeNo(crossCityOrderId);
            JSONObject response = cbyzxOrderPayHelper.createOrder(
                    order.getUserId(),
                    userInfo.getAppletsOpenId(),
                    driver.getAppletsOpenId(),
                    outTradeNo,
                    order.getOrderMoney()
            );
@@ -1585,6 +1594,10 @@
            //添加交易明细
            transactionDetailsService.saveData(driverId, "跨城出行订单", order.getOrderMoney(), 2, 1, 2, 3, order.getId());
            return ResultUtil.success();
        } else if (type == 2) {
            String path = "pages/index/index";
            String unlimitQrcode = weChatUtil.getUnlimitQrcode(path, "default");
            return ResultUtil.success(unlimitQrcode);
        }
        return ResultUtil.error("支付失败");
    }
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/AddSelfTripWarpper.java
@@ -21,6 +21,12 @@
    @ApiModelProperty("出发城市名称")
    private String startCityName;
    @ApiModelProperty("到达城市编码")
    private String endCityCode;
    @ApiModelProperty("到达城市名称")
    private String endCityName;
    @ApiModelProperty("出发地地址")
    private String startAddress;
@@ -30,7 +36,7 @@
    @ApiModelProperty("出发地纬度")
    private Double startLat;
    @ApiModelProperty("目的地JSON数组(每项需包含endAddress/endLon/endLat/price)")
    @ApiModelProperty("目的地JSON数组(每项需包含endCityCode/endCityName/endAddress/endLon/endLat/price)")
    private String destJson;
    public String getDay() {
@@ -104,4 +110,20 @@
    public void setDestJson(String destJson) {
        this.destJson = destJson;
    }
    public String getEndCityCode() {
        return endCityCode;
    }
    public void setEndCityCode(String endCityCode) {
        this.endCityCode = endCityCode;
    }
    public String getEndCityName() {
        return endCityName;
    }
    public void setEndCityName(String endCityName) {
        this.endCityName = endCityName;
    }
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/OrderCrossCityOnBehalfWarpper.java
@@ -55,4 +55,7 @@
    @ApiModelProperty(value = "座位编号(1,3,4)", required = true, dataType = "string")
    private String seatNumber;
    @ApiModelProperty(value = "改价价格")
    private BigDecimal changePrice;
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/ScanOrderDetailWarpper.java
@@ -1,5 +1,6 @@
package com.stylefeng.guns.modular.crossCity.warpper;
import com.alibaba.fastjson.JSONArray;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -17,6 +18,9 @@
    @ApiModelProperty("司机名称(黄师傅格式)")
    private String driverName;
    @ApiModelProperty("司机性别(1男 2女)")
    private Integer sex;
    @ApiModelProperty("车牌号")
    private String carLicensePlate;
@@ -118,4 +122,9 @@
    @ApiModelProperty("终点默认点纬度")
    private Double endDefaultPointLat;
    // =========== 多个终点 =========
    @ApiModelProperty("终点列表")
    private JSONArray endDetailList;
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IDriverService.java
@@ -394,6 +394,4 @@
    DriverOrderPromotionDataVo queryOrderPromotionFromDriver(String time, Page<DriverOrderDataNextVo> driverOrderDataVoPage, Integer uid);
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/DriverServiceImpl.java
@@ -1,5 +1,9 @@
package com.stylefeng.guns.modular.system.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
@@ -40,6 +44,8 @@
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/WeChatUtil.java
@@ -1,21 +1,27 @@
package com.stylefeng.guns.modular.system.util;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.util.StringUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
 * 微信工具类
@@ -23,12 +29,21 @@
@Component
public class WeChatUtil {
    private String wxAppletsAppid="wxccaecee088db18d5";
    private String wxAppletsAppid="wx20301e30167d920e";
    private String wxAppletsAppSecret="c02390b36817fae7ccd27f084dfbd294";
    private String wxAppletsAppSecret="4b8fe5cea20c4309fa996caa06ac9b4c";
    @Autowired
    private RestTemplate restTemplate;
    @Value("${spring.profiles.active}")
    private String activeProfile;
    @Value("${filePath}")
    private String filePath;
    @Value("${qyt.admin_url}")
    private String adminUrl;
    /**
@@ -135,7 +150,7 @@
     * @param page      跳转页 例如 pages/index/index
     * @param scene     参数 a=1&b=2
     */
    public InputStream getwxacodeunlimit(String page, String scene, String envVersion) throws Exception{
    public InputStream getwxacodeunlimit(String page, String scene, String envVersion){
        try {
            //String wxAppletsAccessToken = redisUtil.getValue("wxAppletsAccessToken");
            String wxAppletsAccessToken = getAccessToken2();
@@ -148,17 +163,42 @@
            MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
            httpHeaders.setContentType(type);
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(param, httpHeaders);
            ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class, new Object[0]);
            String body1 = exchange.getBody();
//            ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class, new Object[0]);
//            String body1 = exchange.getBody();
//            System.err.println(body1);
            ResponseEntity<byte[]> entity  = restTemplate.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
            byte[] body = entity.getBody();
            System.err.println(JSON.toJSON(entity));
            System.err.println(Base64.encodeBase64String(body));
            return new ByteArrayInputStream(body);
            byte[] result = entity.getBody();
            if (result == null || result.length == 0) {
                return null;
            }
            MediaType contentType = entity.getHeaders().getContentType();
            // 微信成功返回image/*;失败通常返回application/json
            if (contentType != null && !StringUtils.startsWithIgnoreCase(contentType.toString(), "image/")) {
                String errorBody = new String(result, "UTF-8");
                System.err.println("getwxacodeunlimit返回非图片内容: " + errorBody);
                return null;
            }
            return new ByteArrayInputStream(result);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    public String getUnlimitQrcode(String appletPath, String scene){
        InputStream inputStream = getwxacodeunlimit(appletPath, scene, activeProfile.equals("prod") ? "release" : "trial");
        if (inputStream != null) {
            File file = FileUtil.writeFromStream(inputStream, new File(filePath + "/" + UUID.randomUUID().toString() + ".png"));
            HttpRequest post = HttpUtil.createPost(adminUrl + "/upload/image");
            post.form("file", file);
            try (HttpResponse execute = post.execute()) {
                int status = execute.getStatus();
                if (200 != status) {
                    throw new RuntimeException("上传图片异常");
                }
                return execute.body();
            }
        }
        return null;
    }
}