liujie
2026-04-27 588fd7b47b6caf30562e1267a27f5898a5c2671f
Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/YueKeDuo
4个文件已添加
39个文件已修改
1797 ■■■■■ 已修改文件
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 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/CrossCityShiftController.java 33 ●●●●● 补丁 | 查看 | 原始文档 | 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/DriverSelfTripMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/DriverSelfTripMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/LineShiftDriverMapper.xml 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/DriverSelfTrip.java 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/LineShiftDriver.java 14 ●●●●● 补丁 | 查看 | 原始文档 | 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/ILineShiftDriverService.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 297 ●●●●● 补丁 | 查看 | 原始文档 | 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 129 ●●●●● 补丁 | 查看 | 原始文档 | 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/OtherDriverShiftWarpper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | 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/CarServiceImpl.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/service/impl/ReassignServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/CbyzxPayUtil.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/WeChatUtil.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/config/web/ShiroConfig.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/util/UploadUtil.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_info.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/LineController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/OrderCrossCityController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/SiteController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/LineMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/LineMapper.xml 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/OrderCrossCityMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/OrderCrossCity.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/ILineService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/IOrderCrossCityService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/ISiteService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/LineServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/OrderCrossCityServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/SiteServiceImpl.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/OrderCrossCityWarpper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | 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
@@ -17,6 +17,7 @@
import com.stylefeng.guns.modular.smallLogistics.server.IOrderLogisticsService;
import com.stylefeng.guns.modular.specialTrain.model.OrderPrivateCar;
import com.stylefeng.guns.modular.specialTrain.server.IOrderPrivateCarService;
import com.stylefeng.guns.modular.system.dao.CarModelMapper;
import com.stylefeng.guns.modular.system.dao.RegionMapper;
import com.stylefeng.guns.modular.system.model.*;
import com.stylefeng.guns.modular.system.model.vo.*;
@@ -79,6 +80,9 @@
    
    @Autowired
    private ICarService carService;
    @Autowired
    private CarModelMapper carModelMapper;
    
    @Resource
    private RegionMapper regionMapper;
@@ -124,12 +128,6 @@
    
    @Autowired
    private WeChatUtil weChatUtil;
    @Value("${filePath}")
    private String filePath;
    @Value("${qyt.admin_url}")
    private String adminUrl;
    
    /**
     * 获取短信验证码
@@ -942,6 +940,52 @@
                return ResultUtil.tokenErr();
            }
            Map<String, Object> map = carService.queryCars(uid);
            return ResultUtil.success(map);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 获取当前司机当前车车型
     * @param request
     * @return
     */
    @ResponseBody
    @PostMapping("/api/driver/queryMyCarModel")
    @ApiOperation(value = "获取当前司机当前车车型(主要用于获取座位数)", tags = {"司机端-个人中心"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil queryMyCarModel(HttpServletRequest request){
        try {
            Integer uid = driverService.getUserIdFormRedis(request);
            if (uid == null) {
                return ResultUtil.tokenErr();
            }
            Driver driver = driverService.selectById(uid);
            Map<String, Object> map = new HashMap<>(4);
            map.put("carId", null);
            map.put("carModelId", null);
            map.put("carModelName", null);
            map.put("seat", null);
            if (driver == null || driver.getCarId() == null) {
                return ResultUtil.success(map);
            }
            Integer carId = driver.getCarId();
            map.put("carId", carId);
            Car car = carService.selectById(carId);
            if (car == null || car.getCarModelId() == null) {
                return ResultUtil.success(map);
            }
            Integer carModelId = car.getCarModelId();
            map.put("carModelId", carModelId);
            CarModel carModel = carModelMapper.selectById(carModelId);
            if (carModel != null) {
                map.put("carModelName", carModel.getName());
                map.put("seat", carModel.getSeat());
            }
            return ResultUtil.success(map);
        }catch (Exception e){
            e.printStackTrace();
@@ -1786,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, "release");
                    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
@@ -7,6 +7,7 @@
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.AddSelfTripWarpper;
import com.stylefeng.guns.modular.system.service.IDriverService;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import io.swagger.annotations.Api;
@@ -20,6 +21,7 @@
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * 【202601】城际专线排班控制器
@@ -123,6 +125,37 @@
    }
    /**
     * 【202604】新增司机自主行程
     */
    @ResponseBody
    @PostMapping("/addSelfTrip")
    @ApiOperation(value = "【202604】新增司机自主行程", tags = {"司机端-首页"}, notes = "新增司机自主行程并写入排班主表")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "出发日期(yyyy-MM-dd)", name = "day", required = true, dataType = "String"),
            @ApiImplicitParam(value = "出发时间(HH:mm)", name = "startTime", required = true, dataType = "String"),
            @ApiImplicitParam(value = "座位数", name = "seat", required = true, dataType = "int"),
            @ApiImplicitParam(value = "出发城市编码", name = "startCityCode", required = false, dataType = "String"),
            @ApiImplicitParam(value = "出发城市名称", name = "startCityName", required = false, dataType = "String"),
            @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数组(每项需包含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) {
        try {
            Integer driverId = driverService.getUserIdFormRedis(request);
            if (null == driverId) {
                return ResultUtil.tokenErr();
            }
            return lineShiftDriverService.addSelfTrip(driverId, warpper);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 验证日期有效性
     * @param dateStr
     * @return
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/DriverSelfTripMapper.java
New file
@@ -0,0 +1,7 @@
package com.stylefeng.guns.modular.crossCity.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.modular.crossCity.model.DriverSelfTrip;
public interface DriverSelfTripMapper extends BaseMapper<DriverSelfTrip> {
}
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/DriverSelfTripMapper.xml
New file
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.crossCity.dao.DriverSelfTripMapper">
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.crossCity.model.DriverSelfTrip">
        <id column="id" property="id"/>
        <result column="driverId" property="driverId"/>
        <result column="day" property="day"/>
        <result column="startTime" property="startTime"/>
        <result column="seat" property="seat"/>
        <result column="startCityCode" property="startCityCode"/>
        <result column="startCityName" property="startCityName"/>
        <result column="startAddress" property="startAddress"/>
        <result column="startLon" property="startLon"/>
        <result column="startLat" property="startLat"/>
        <result column="destJson" property="destJson"/>
        <result column="state" property="state"/>
        <result column="insertTime" property="insertTime"/>
        <result column="updateTime" property="updateTime"/>
    </resultMap>
</mapper>
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/LineShiftDriverMapper.xml
@@ -13,6 +13,7 @@
        <result column="totalSeat" property="totalSeat"/>
        <result column="inserTime" property="inserTime"/>
        <result column="assignType" property="assignType"/>
        <result column="customerId" property="customerId"/>
    </resultMap>
@@ -26,7 +27,8 @@
        laveSeatNumber as laveSeatNumber,
        totalSeat as totalSeat,
        inserTime as inserTime,
        assignType as assignType
        assignType as assignType,
        customerId as customerId
        from t_line_shift_driver where 1 = 1
        <if test="null != driverId">
            and driverId = #{driverId}
@@ -35,7 +37,7 @@
            and lineShiftId = #{lineShiftId}
        </if>
        <if test="null != time">
            and DATE_FORMAT(`day`, '%Y-%m%-%d') = DATE_FORMAT(#{time}, '%Y-%m%-%d')
            and DATE_FORMAT(`day`, '%Y-%m-%d') = DATE_FORMAT(#{time}, '%Y-%m-%d')
        </if>
        order by `day`
    </select>
@@ -65,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,
@@ -150,42 +153,75 @@
    <!-- 【202604】查询司机本人已领取/被分配的排班列表(今天及之后) -->
    <select id="queryMyDriverShiftList" resultType="java.util.Map">
        SELECT
            lsd.id as lineShiftDriverId,
            lsd.lineShiftId as lineShiftId,
            lsd.laveSeat as laveSeat,
            lsd.totalSeat as totalSeat,
            ls.startTime as startTime,
            ls.endTime as endTime,
            l.name as lineName,
            IFNULL(lsd.assignType, 1) as assignType,
            occ.orderId as orderId,
            CASE WHEN occ.orderId IS NOT NULL THEN 3 ELSE NULL END as orderType,
            DATE_FORMAT(lsd.day, '%Y-%m-%d') as day
        FROM t_line_shift_driver lsd
        LEFT JOIN t_line_shift ls ON lsd.lineShiftId = ls.id
        LEFT JOIN t_line l ON ls.lineId = l.id
        LEFT JOIN (
            SELECT lineShiftDriverId, MIN(id) AS orderId
            FROM t_order_cross_city
            GROUP BY lineShiftDriverId
        ) occ ON occ.lineShiftDriverId = lsd.id
        WHERE lsd.driverId = #{driverId}
        <if test="startDate != null and startDate != ''">
          AND lsd.day = CAST(#{startDate} AS DATE)
        </if>
        <if test="startDate == null or startDate == ''">
          AND lsd.day &gt;= CURDATE()
        </if>
          AND ls.state = 1
          AND l.state = 1
        ORDER BY lsd.day ASC, ls.startTime ASC, lsd.id ASC
        SELECT *
        FROM (
            SELECT
                lsd.id as lineShiftDriverId,
                lsd.lineShiftId as lineShiftId,
                lsd.laveSeat as laveSeat,
                lsd.totalSeat as totalSeat,
                ls.startTime as startTime,
                ls.endTime as endTime,
                l.name as lineName,
                IFNULL(lsd.assignType, 1) as assignType,
                occ.orderId as orderId,
                CASE WHEN occ.orderId IS NOT NULL THEN 3 ELSE NULL END as orderType,
                DATE_FORMAT(lsd.day, '%Y-%m-%d') as day
            FROM t_line_shift_driver lsd
            LEFT JOIN t_line_shift ls ON lsd.lineShiftId = ls.id
            LEFT JOIN t_line l ON ls.lineId = l.id
            LEFT JOIN (
                SELECT lineShiftDriverId, MIN(id) AS orderId
                FROM t_order_cross_city
                WHERE state != 10
                GROUP BY lineShiftDriverId
            ) occ ON occ.lineShiftDriverId = lsd.id
            WHERE lsd.driverId = #{driverId}
              AND lsd.lineShiftId != -1
              <if test="startDate != null and startDate != ''">
                  AND lsd.day = #{startDate}
              </if>
              <if test="startDate == null or startDate == ''">
                  AND lsd.day &gt;= CURDATE()
              </if>
              AND ls.state = 1
              AND l.state = 1
            UNION ALL
            SELECT
                lsd.id as lineShiftDriverId,
                lsd.lineShiftId as lineShiftId,
                lsd.laveSeat as laveSeat,
                lsd.totalSeat as totalSeat,
                st.startTime as startTime,
                st.startTime as endTime,
                CONCAT(st.startCityName,'-',st.endCityName) as lineName,
                1 as assignType,
                NULL as orderId,
                NULL as orderType,
                DATE_FORMAT(lsd.day, '%Y-%m-%d') as day
            FROM t_line_shift_driver lsd
            INNER JOIN t_driver_self_trip st
                ON st.id = lsd.customerId
               AND st.state = 1
            WHERE lsd.driverId = #{driverId}
              AND lsd.lineShiftId = -1
              <if test="startDate != null and startDate != ''">
                  AND lsd.day = #{startDate}
              </if>
              <if test="startDate == null or startDate == ''">
                  AND lsd.day &gt;= CURDATE()
              </if>
        ) t
        ORDER BY t.day ASC, t.startTime ASC, t.lineShiftDriverId ASC
        LIMIT #{offset}, #{size}
    </select>
    <select id="queryOtherDriverShiftListWithShiftId" resultType="java.util.Map">
        SELECT
            other.id as lineShiftDriverId,
            other.driverId as driverId,
            d.headImgUrl as headImgUrl,
            d.name as driverName,
            c.carLicensePlate as carLicensePlate,
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/DriverSelfTrip.java
New file
@@ -0,0 +1,193 @@
package com.stylefeng.guns.modular.crossCity.model;
import com.baomidou.mybatisplus.annotations.TableField;
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;
/**
 * 司机自主行程
 */
@TableName("t_driver_self_trip")
public class DriverSelfTrip {
    @TableId(value = "id", type = IdType.AUTO)
    @TableField("id")
    private Integer id;
    @TableField("driverId")
    private Integer driverId;
    @TableField("day")
    private Date day;
    @TableField("startTime")
    private String startTime;
    @TableField("seat")
    private Integer seat;
    @TableField("startCityCode")
    private String startCityCode;
    @TableField("startCityName")
    private String startCityName;
    @TableField("endCityCode")
    private String endCityCode;
    @TableField("endCityName")
    private String endCityName;
    @TableField("startAddress")
    private String startAddress;
    @TableField("startLon")
    private Double startLon;
    @TableField("startLat")
    private Double startLat;
    @TableField("destJson")
    private String destJson;
    @TableField("state")
    private Integer state;
    @TableField("insertTime")
    private Date insertTime;
    @TableField("updateTime")
    private Date updateTime;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getDriverId() {
        return driverId;
    }
    public void setDriverId(Integer driverId) {
        this.driverId = driverId;
    }
    public Date getDay() {
        return day;
    }
    public void setDay(Date day) {
        this.day = day;
    }
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public Integer getSeat() {
        return seat;
    }
    public void setSeat(Integer seat) {
        this.seat = seat;
    }
    public String getStartCityCode() {
        return startCityCode;
    }
    public void setStartCityCode(String startCityCode) {
        this.startCityCode = startCityCode;
    }
    public String getStartCityName() {
        return startCityName;
    }
    public void setStartCityName(String startCityName) {
        this.startCityName = startCityName;
    }
    public String getStartAddress() {
        return startAddress;
    }
    public void setStartAddress(String startAddress) {
        this.startAddress = startAddress;
    }
    public Double getStartLon() {
        return startLon;
    }
    public void setStartLon(Double startLon) {
        this.startLon = startLon;
    }
    public Double getStartLat() {
        return startLat;
    }
    public void setStartLat(Double startLat) {
        this.startLat = startLat;
    }
    public String getDestJson() {
        return destJson;
    }
    public void setDestJson(String destJson) {
        this.destJson = destJson;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    public Date getInsertTime() {
        return insertTime;
    }
    public void setInsertTime(Date insertTime) {
        this.insertTime = insertTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    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/LineShiftDriver.java
@@ -58,6 +58,11 @@
     */
    @TableField("assignType")
    private Integer assignType;
    /**
     * 自主行程详情id
     */
    @TableField("customerId")
    private Integer customerId;
    public Integer getId() {
        return id;
@@ -131,6 +136,14 @@
        this.assignType = assignType;
    }
    public Integer getCustomerId() {
        return customerId;
    }
    public void setCustomerId(Integer customerId) {
        this.customerId = customerId;
    }
    @Override
    public String toString() {
        return "LineShiftDriver{" +
@@ -143,6 +156,7 @@
                ", totalSeat=" + totalSeat +
                ", inserTime=" + inserTime +
                ", assignType=" + assignType +
                ", customerId=" + customerId +
                '}';
    }
}
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/ILineShiftDriverService.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.crossCity.model.LineShiftDriver;
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;
@@ -9,6 +10,7 @@
import com.stylefeng.guns.modular.system.util.ResultUtil;
import java.util.List;
import java.util.Map;
public interface ILineShiftDriverService extends IService<LineShiftDriver> {
@@ -50,6 +52,16 @@
     * @throws Exception
     */
    List<OtherDriverShiftWarpper> queryOtherDriverShiftListWithShiftId(Long driverShiftId) throws Exception;
    /**
     * 【202604】新增司机自主行程
     * @param driverId 司机id
     * @param warpper 参数
     * @return lineShiftDriverId、customerId
     * @throws Exception
     */
    ResultUtil<Map<String, Object>> addSelfTrip(Integer driverId, AddSelfTripWarpper warpper) throws Exception;
    /**
     * 【202601】查询班次详情
     * @param lineShiftDriverId 班次id
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,42 +1,44 @@
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;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.crossCity.dao.DriverSelfTripMapper;
import com.stylefeng.guns.modular.crossCity.dao.LinePriceMapper;
import com.stylefeng.guns.modular.crossCity.dao.LineShiftDriverMapper;
import com.stylefeng.guns.modular.crossCity.dao.LineShiftMapper;
import com.stylefeng.guns.modular.crossCity.model.DriverSelfTrip;
import com.stylefeng.guns.modular.crossCity.model.LineShift;
import com.stylefeng.guns.modular.crossCity.model.LineShiftDriver;
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.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;
import com.stylefeng.guns.modular.system.model.Driver;
import com.stylefeng.guns.modular.system.service.ICarService;
import com.stylefeng.guns.modular.system.service.IDriverService;
import com.stylefeng.guns.modular.system.util.DateUtil;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -65,6 +67,12 @@
    @Resource
    private CarServiceMapper carServiceMapper;
    @Resource
    private DriverSelfTripMapper driverSelfTripMapper;
    @Resource
    private OrderEvaluateMapper orderEvaluateMapper;
    @Autowired
    private IOrderCrossCityService orderCrossCityService;
@@ -442,12 +450,170 @@
        if (driverShiftId == null) {
            return new ArrayList<>();
        }
        LineShiftDriver current = lineShiftDriverMapper.selectById(driverShiftId);
        if (current == null || (current.getLineShiftId() != null && current.getLineShiftId() == -1)) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> rows = lineShiftDriverMapper.queryOtherDriverShiftListWithShiftId(driverShiftId);
        return OtherDriverShiftWarpper.fromMaps(rows);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<Map<String, Object>> addSelfTrip(Integer driverId, AddSelfTripWarpper warpper) throws Exception {
        if (driverId == null) {
            return ResultUtil.tokenErr();
        }
        if (warpper == null) {
            return ResultUtil.paranErr();
        }
        if (!isSelfTripEnabled(driverId)) {
            return ResultUtil.error("未开启自主行程");
        }
        if (ToolUtil.isEmpty(warpper.getDay()) || ToolUtil.isEmpty(warpper.getStartTime())
                || warpper.getSeat() == null
                || ToolUtil.isEmpty(warpper.getStartAddress())
                || warpper.getStartLon() == null
                || warpper.getStartLat() == null
                || ToolUtil.isEmpty(warpper.getDestJson())) {
            return ResultUtil.paranErr();
        }
        LocalDate day;
        try {
            day = LocalDate.parse(warpper.getDay(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (DateTimeParseException e) {
            return ResultUtil.error("出发日期格式错误");
        }
        LocalDate today = LocalDate.now();
        if (day.isBefore(today)) {
            return ResultUtil.error("日期不能早于今天");
        }
        if (day.isAfter(today.plusDays(6))) {
            return ResultUtil.error("只能新增7天内的自主行程");
        }
        if (!warpper.getStartTime().matches("^([01]\\d|2[0-3]):[0-5]\\d$")) {
            return ResultUtil.error("出发时间格式错误");
        }
        Integer carSeat = getCurrentCarSeat(driverId);
        if (carSeat == null || carSeat <= 0) {
            return ResultUtil.error("当前车辆车型座位数异常");
        }
        if (warpper.getSeat() < 1 || warpper.getSeat() > carSeat) {
            return ResultUtil.error("座位数超出当前车型可用范围");
        }
        String normalizedDestJson = validateAndNormalizeDestJson(warpper.getDestJson());
        if (normalizedDestJson == null) {
            return ResultUtil.error("目的地信息格式不正确");
        }
        DriverSelfTrip trip = new DriverSelfTrip();
        trip.setDriverId(driverId);
        trip.setDay(java.sql.Date.valueOf(day));
        trip.setStartTime(warpper.getStartTime());
        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());
        trip.setDestJson(normalizedDestJson);
        trip.setState(1);
        trip.setInsertTime(new Date());
        trip.setUpdateTime(new Date());
        driverSelfTripMapper.insert(trip);
        LineShiftDriver lineShiftDriver = new LineShiftDriver();
        lineShiftDriver.setLineShiftId(-1);
        lineShiftDriver.setCustomerId(trip.getId());
        lineShiftDriver.setDriverId(driverId);
        lineShiftDriver.setDay(java.sql.Date.valueOf(day));
        lineShiftDriver.setLaveSeat(warpper.getSeat());
        lineShiftDriver.setTotalSeat(warpper.getSeat());
        lineShiftDriver.setLaveSeatNumber(buildSeatNumber(warpper.getSeat()));
        lineShiftDriver.setInserTime(new Date());
        lineShiftDriver.setAssignType(1);
        lineShiftDriverMapper.insert(lineShiftDriver);
        Map<String, Object> result = new HashMap<>(2);
        result.put("lineShiftDriverId", lineShiftDriver.getId());
        result.put("customerId", trip.getId());
        return ResultUtil.success(result);
    }
    private boolean isSelfTripEnabled(Integer driverId) throws Exception {
        Map<String, Object> info = driverService.queryInfo(driverId);
        Object value = info == null ? null : info.get("isOpenDriverSelfTrip");
        return value != null && "1".equals(String.valueOf(value));
    }
    private Integer getCurrentCarSeat(Integer driverId) {
        Driver driver = driverService.selectById(driverId);
        if (driver == null || driver.getCarId() == null) {
            return null;
        }
        Car car = carService.selectById(driver.getCarId());
        if (car == null || car.getCarModelId() == null) {
            return null;
        }
        CarModel carModel = carModelMapper.selectById(car.getCarModelId());
        return carModel == null ? null : carModel.getSeat();
    }
    private String validateAndNormalizeDestJson(String destJson) {
        try {
            JSONArray array = JSON.parseArray(destJson);
            if (array == null || array.isEmpty()) {
                return null;
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject item = array.getJSONObject(i);
                if (item == null) {
                    return null;
                }
                String endAddress = item.getString("endAddress");
                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) {
                    return null;
                }
            }
            return array.toJSONString();
        } catch (Exception e) {
            return null;
        }
    }
    private String buildSeatNumber(Integer seat) {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= seat; i++) {
            if (i > 1) {
                sb.append(",");
            }
            sb.append(i);
        }
        return sb.toString();
    }
    @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()) {
@@ -460,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);
@@ -514,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
New file
@@ -0,0 +1,129 @@
package com.stylefeng.guns.modular.crossCity.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("新增自主行程参数")
public class AddSelfTripWarpper {
    @ApiModelProperty("出发日期(yyyy-MM-dd)")
    private String day;
    @ApiModelProperty("出发时间(HH:mm)")
    private String startTime;
    @ApiModelProperty("座位数")
    private Integer seat;
    @ApiModelProperty("出发城市编码")
    private String startCityCode;
    @ApiModelProperty("出发城市名称")
    private String startCityName;
    @ApiModelProperty("到达城市编码")
    private String endCityCode;
    @ApiModelProperty("到达城市名称")
    private String endCityName;
    @ApiModelProperty("出发地地址")
    private String startAddress;
    @ApiModelProperty("出发地经度")
    private Double startLon;
    @ApiModelProperty("出发地纬度")
    private Double startLat;
    @ApiModelProperty("目的地JSON数组(每项需包含endCityCode/endCityName/endAddress/endLon/endLat/price)")
    private String destJson;
    public String getDay() {
        return day;
    }
    public void setDay(String day) {
        this.day = day;
    }
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public Integer getSeat() {
        return seat;
    }
    public void setSeat(Integer seat) {
        this.seat = seat;
    }
    public String getStartCityCode() {
        return startCityCode;
    }
    public void setStartCityCode(String startCityCode) {
        this.startCityCode = startCityCode;
    }
    public String getStartCityName() {
        return startCityName;
    }
    public void setStartCityName(String startCityName) {
        this.startCityName = startCityName;
    }
    public String getStartAddress() {
        return startAddress;
    }
    public void setStartAddress(String startAddress) {
        this.startAddress = startAddress;
    }
    public Double getStartLon() {
        return startLon;
    }
    public void setStartLon(Double startLon) {
        this.startLon = startLon;
    }
    public Double getStartLat() {
        return startLat;
    }
    public void setStartLat(Double startLat) {
        this.startLat = startLat;
    }
    public String getDestJson() {
        return destJson;
    }
    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/OtherDriverShiftWarpper.java
@@ -13,6 +13,9 @@
    @ApiModelProperty("司机排班记录id")
    private Integer lineShiftDriverId;
    @ApiModelProperty("司机id")
    private Integer driverId;
    @ApiModelProperty("司机头像")
    private String headImgUrl;
@@ -46,6 +49,14 @@
    public void setLineShiftDriverId(Integer lineShiftDriverId) {
        this.lineShiftDriverId = lineShiftDriverId;
    }
    public Integer getDriverId() {
        return driverId;
    }
    public void setDriverId(Integer driverId) {
        this.driverId = driverId;
    }
    public String getHeadImgUrl() {
@@ -126,6 +137,7 @@
            return warpper;
        }
        warpper.setLineShiftDriverId(map.get("lineShiftDriverId") == null ? null : Integer.valueOf(map.get("lineShiftDriverId").toString()));
        warpper.setDriverId(map.get("driverId") == null ? null : Integer.valueOf(map.get("driverId").toString()));
        warpper.setHeadImgUrl(map.get("headImgUrl") == null ? "" : map.get("headImgUrl").toString());
        warpper.setDriverName(map.get("driverName") == null ? "" : map.get("driverName").toString());
        warpper.setCarLicensePlate(map.get("carLicensePlate") == null ? "" : map.get("carLicensePlate").toString());
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/CarServiceImpl.java
@@ -51,6 +51,7 @@
        Integer carId = driver.getCarId();
        map.put("car", "");
        map.put("carModel", "");
        map.put("id", carId);
        if(carId!=null){
            Car car = carMapper.selectById(carId);
@@ -58,6 +59,7 @@
                CarBrand carBrand = carBrandMapper.selectById(car.getCarBrandId());
                CarModel carModel = carModelMapper.selectById(car.getCarModelId());
                map.put("car", car.getCarLicensePlate()+"-" + carBrand.getName() +carModel.getName()+ " " + car.getCarColor());
                map.put("carModel", carModel.getName());
            }
        }
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/service/impl/ReassignServiceImpl.java
@@ -6,15 +6,14 @@
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.account.service.ITEnterpriseWithdrawalService;
import com.stylefeng.guns.modular.account.service.UserWithdrawalService;
import com.stylefeng.guns.modular.account.unionpay.GetOpenBodySig;
import com.stylefeng.guns.modular.account.unionpay.QrCodeConfiguration;
import com.stylefeng.guns.modular.account.unionpay.Util;
import com.stylefeng.guns.modular.crossCity.dao.LineMapper;
import com.stylefeng.guns.modular.crossCity.dao.LineShiftDriverMapper;
import com.stylefeng.guns.modular.crossCity.dao.LineShiftMapper;
import com.stylefeng.guns.modular.crossCity.dao.LineSiteMapper;
import com.stylefeng.guns.modular.crossCity.model.LineShift;
import com.stylefeng.guns.modular.crossCity.model.LineSite;
import com.stylefeng.guns.modular.crossCity.model.LineShiftDriver;
import com.stylefeng.guns.modular.crossCity.model.OrderCrossCity;
import com.stylefeng.guns.modular.crossCity.server.IOrderCrossCityService;
import com.stylefeng.guns.modular.smallLogistics.model.OrderLogistics;
@@ -40,7 +39,6 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@@ -112,6 +110,8 @@
    @Value("${callbackPath}")
    private String callbackPath;
    @Autowired
    private LineShiftDriverMapper lineShiftDriverMapper;
    /**
@@ -509,6 +509,9 @@
                for (String id : split) {
                    Reassign query = reassignMapper.query(uid, null, Integer.valueOf(id), 3, 1);
                    query.setState(2);
                    if (reassign.getNowDriverId() != null) {
                        query.setState(3);
                    }
                    query.setPayTime(new Date());
                    reassignMapper.updateById(query);
                    //添加交易明细
@@ -536,9 +539,11 @@
                    if(reassign.getNowDriverId()==null){
                        orderCrossCity.setState(11);
                    }else {
                        orderCrossCity.setDriverId(reassign.getNowDriverId());
//                        orderCrossCity.setDriverId(reassign.getNowDriverId());
                        //reassign.getNowDriverId() 是lineShiftDriverId
                        driverReassignSelf(reassign, orderCrossCity);
                    }
                    orderCrossCity.setReassignNotice(2);
                    orderCrossCity.setIsReassign(2);
                    orderCrossCityService.updateById(orderCrossCity);
@@ -547,15 +552,20 @@
                    if(reassign.getNowDriverId()!=null){
                        // 推送用户消息
                        pushUtil.pushOrderReassign(orderCrossCity.getUserId(), 1, orderCrossCity.getId(), 3);
                        // 推送司机消息
                        pushUtil.pushOrderReassign(orderCrossCity.getDriverId(), 2, orderCrossCity.getId(), 3);
                        try {
                            // 推送用户消息
                            pushUtil.pushOrderReassign(orderCrossCity.getUserId(), 1, orderCrossCity.getId(), 3);
                            // 推送司机消息
                            pushUtil.pushOrderReassign(orderCrossCity.getDriverId(), 2, orderCrossCity.getId(), 3);
                        } catch (Exception ignore) {
                        }
                    }
                }
                systemNoticeService.addSystemNotice(2, "您已使用余额成功支付改派申请费用!", uid, 1);
                //开始推送调度单
//                Map<String, String> map = new HashMap<>();
//                map.put("orderId", reassign.getOrderId().toString());
@@ -652,6 +662,9 @@
//                        }
                    }
                    query.setState(2);
                    if (reassigns.get(0).getNowDriverId() != null) {
                        query.setState(3);
                    }
                    query.setCode(order_id);
                    paymentRecordService.updateById(query);
                    System.out.println("==============paymentRecord完毕===================" + query);
@@ -661,8 +674,10 @@
                        orderCrossCity1.setOldState(orderCrossCity1.getState());
                        if(reassign.getNowDriverId()==null){
                            orderCrossCity1.setState(11);
                        }else {
                            orderCrossCity1.setDriverId(reassign.getNowDriverId());
                        } else {
//                            orderCrossCity1.setDriverId(reassign.getNowDriverId());
                            //reassign.getNowDriverId() 是lineShiftDriverId
                            driverReassignSelf(reassign, orderCrossCity1);
                        }
                        orderCrossCity1.setReassignNotice(2);
                        orderCrossCity1.setIsReassign(2);
@@ -781,6 +796,33 @@
    }
    private void driverReassignSelf(Reassign reassign, OrderCrossCity orderCrossCity1) {
        // 交换人数 交换座位
        Integer oldLineShiftDriverId = orderCrossCity1.getLineShiftDriverId();
        LineShiftDriver oldLineShiftDriver = lineShiftDriverMapper.selectById(oldLineShiftDriverId);
        LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(reassign.getNowDriverId());
        orderCrossCity1.setDriverId(lineShiftDriver.getDriverId());
        orderCrossCity1.setLineShiftDriverId(reassign.getNowDriverId());
        Driver driver1 = driverService.selectById(lineShiftDriver.getDriverId());
        orderCrossCity1.setCarId(driver1.getCarId());
        Integer peopleNumber = orderCrossCity1.getPeopleNumber();
        oldLineShiftDriver.setLaveSeat(oldLineShiftDriver.getLaveSeat() + peopleNumber);
        lineShiftDriver.setLaveSeat(lineShiftDriver.getLaveSeat() - peopleNumber);
        String laveSeatNumber = Arrays.stream(lineShiftDriver.getLaveSeatNumber().split(",")).skip(peopleNumber).collect(Collectors.joining(","));
        Set<String> oldLaveSeatSet = Arrays.stream(oldLineShiftDriver.getLaveSeatNumber().split(",")).collect(Collectors.toSet());
        for (int i = 1; i <= 6; i++) {
            oldLaveSeatSet.add(String.valueOf(i));
            if (oldLaveSeatSet.size() == oldLineShiftDriver.getLaveSeat()) {
                break;
            }
        }
        String oldLaveSeatNumber = oldLaveSeatSet.stream().sorted().collect(Collectors.joining(","));
        oldLineShiftDriver.setLaveSeatNumber(oldLaveSeatNumber);
        lineShiftDriver.setLaveSeatNumber(laveSeatNumber);
        lineShiftDriverMapper.updateById(oldLineShiftDriver);
        lineShiftDriverMapper.updateById(lineShiftDriver);
    }
    @Override
    public List<Map<String, Object>> queryDriver(String orderId) throws Exception {
        OrderCrossCity orderCrossCity = orderCrossCityService.selectById(orderId);
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/CbyzxPayUtil.java
@@ -30,7 +30,7 @@
    private static final String PAYMENT_ORDER_TYPE = "PAYMENT_ORDER";
    private static final String DEFAULT_CURRENCY = "CNY";
    private static final String DEFAULT_PAY_CHANNEL_CODE = "ykdride-driver-wxmini";
    private static final String DEFAULT_PAY_CHANNEL_CODE = "ykdride-driver-wxapp";
    private static final String DEFAULT_TENANT = "gz.zuny.ykdride.platform";
    private CbyzxPayUtil() {
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;
/**
 * 微信工具类
@@ -29,6 +35,15 @@
    @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;
    }
}
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/config/web/ShiroConfig.java
@@ -166,6 +166,7 @@
       hashMap.put("/login", "anon");
       hashMap.put("/global/sessionError", "anon");
       hashMap.put("/kaptcha", "anon");
       hashMap.put("/upload/image", "anon");
       hashMap.put("/**", "user");
       shiroFilter.setFilterChainDefinitionMap(hashMap);
       return shiroFilter;
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/util/UploadUtil.java
@@ -19,6 +19,7 @@
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -38,7 +39,7 @@
    /**
     * 上传图片(上传到项目的webapp/static/img)
     */
   /* @RequestMapping("/image")
    @RequestMapping("/image")
    public String image(@RequestPart("file") MultipartFile picture) {
        String pictureName = UUID.randomUUID().toString() + ".jpg";
        try {
@@ -49,8 +50,8 @@
            log.error(e.getMessage(), e);
            throw new GunsException(BizExceptionEnum.UPLOAD_ERROR);
        }
        return pictureName;
    }*/
        return gunsProperties.getPictureServerAddress()+pictureName;
    }
    /**
     * 多图片上传使用
@@ -81,23 +82,23 @@
    private ITImgMidService itImgMidService;
    
    
    @RequestMapping("/image")
    @ResponseBody
    public ResultUtil image1(@RequestPart("file") MultipartFile file, HttpServletRequest request) {
        try {
            String pictureName = UUID.randomUUID().toString() + "." + ToolUtil.getFileSuffix(file.getOriginalFilename());
//            String pictureName = OssUploadUtil.ossUpload(request, file);
            System.out.println("mediaResp");
//            MediaResp mediaResp = MediaExample.uploadImage(picture);
//            System.out.println("------"+mediaResp);
//            String pictureName = ObsUploadUtil.obsUpload(super.getHttpServletRequest(), picture);
            return ResultUtil.success(pictureName);
        } catch (Exception e1) {
            e1.printStackTrace();
            return null;
        }
    }
//    @RequestMapping("/image")
//    @ResponseBody
//    public ResultUtil image1(@RequestPart("file") MultipartFile file, HttpServletRequest request) {
//        try {
//            String pictureName = UUID.randomUUID().toString() + "." + ToolUtil.getFileSuffix(file.getOriginalFilename());
//
////            String pictureName = OssUploadUtil.ossUpload(request, file);
//            System.out.println("mediaResp");
////            MediaResp mediaResp = MediaExample.uploadImage(picture);
////            System.out.println("------"+mediaResp);
////            String pictureName = ObsUploadUtil.obsUpload(super.getHttpServletRequest(), picture);
//            return ResultUtil.success(pictureName);
//        } catch (Exception e1) {
//            e1.printStackTrace();
//            return null;
//        }
//    }
    /**
     * 上传文件
ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_info.js
@@ -884,7 +884,7 @@
    }
}
TLineInfoDlg.clearDestinationFence = function () {
TLineInfoDlg.clearDestinationFence = function (keepValue) {
    if (TLineInfoDlg.destinationFenceOverlay) {
        TLineInfoDlg.destinationMap.remove(TLineInfoDlg.destinationFenceOverlay);
        TLineInfoDlg.destinationFenceOverlay = null;
@@ -893,9 +893,11 @@
        TLineInfoDlg.destinationMap.remove(TLineInfoDlg.destinationDefaultPointMarker);
        TLineInfoDlg.destinationDefaultPointMarker = null;
    }
    $("#destinationCoordinate").val("");
    $("#destinationDefaultPointLon").val("");
    $("#destinationDefaultPointLat").val("");
    if (!keepValue) {
        $("#destinationCoordinate").val("");
        $("#destinationDefaultPointLon").val("");
        $("#destinationDefaultPointLat").val("");
    }
    $("#destinationDefaultPointText").text("");
}
@@ -1045,7 +1047,7 @@
TLineInfoDlg.restoreDestinationMapFence = function () {
    TLineInfoDlg.initDestinationMap();
    TLineInfoDlg.clearDestinationFence();
    TLineInfoDlg.clearDestinationFence(true);
    var fenceType = $("input[name='destinationFenceType']:checked").val();
    var coordinate = $("#destinationCoordinate").val();
    if (!coordinate) {
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/LineController.java
@@ -59,6 +59,37 @@
        }
    }
    @ResponseBody
    @RequestMapping(value = "/base/line/queryFirstLineDestinations", method = RequestMethod.POST)
    @ApiOperation(value = "根据起始站点和终点站点获取第一条线路目的地列表", tags = {"用户端-跨城"}, notes = "可能为空")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "起始站点id", name = "startId", required = true, dataType = "int"),
            @ApiImplicitParam(value = "终点站点id", name = "endId", required = true, dataType = "int")
    })
    public ResultUtil<List<Map<String, Object>>> queryFirstLineDestinations(Integer startId, Integer endId){
        try {
            return ResultUtil.success(lineService.queryFirstLineDestinations(startId, endId));
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    @ResponseBody
    @RequestMapping(value = "/base/line/queryFutureLinesByDriver", method = RequestMethod.POST)
    @ApiOperation(value = "根据司机id获取当前时间之后发车的城际线路", tags = {"用户端-跨城"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "司机id", name = "driverId", required = true, dataType = "int")
    })
    public ResultUtil<List<Map<String, Object>>> queryFutureLinesByDriver(Integer driverId){
        try {
            return ResultUtil.success(lineService.queryFutureLinesByDriver(driverId));
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    @ResponseBody
    @RequestMapping(value = "/base/line/confirm", method = RequestMethod.POST)
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/OrderCrossCityController.java
@@ -44,14 +44,15 @@
            @ApiImplicitParam(value = "乘车人数", name = "peopleNumber", required = true, dataType = "int"),
            @ApiImplicitParam(value = "出行方式(1=拼车,2=包车)", name = "travelMode", required = true, dataType = "int"),
            @ApiImplicitParam(value = "线路id", name = "lineId", required = true, dataType = "int"),
            @ApiImplicitParam(value = "线路目的地id", name = "lineDestinationId", required = false, dataType = "int"),
            @ApiImplicitParam(value = "服务车型id", name = "serverCarModelId", required = true, dataType = "int"),
            @ApiImplicitParam(value = "车辆总座位数", name = "totalSeat", required = true, dataType = "int"),
            @ApiImplicitParam(value = "座位编号(1,3,4)", name = "seatNumber", required = true, dataType = "int")
    })
    public ResultUtil queryOrderMoney(String startLonLat, String endLonLat, Integer peopleNumber, Integer travelMode,
                                      Integer lineId, Integer serverCarModelId, Integer totalSeat, String seatNumber){
                                      Integer lineId, Integer lineDestinationId, Integer serverCarModelId, Integer totalSeat, String seatNumber){
        try {
            return orderCrossCityService.queryOrderMoney(startLonLat, endLonLat, peopleNumber, travelMode, lineId, serverCarModelId, totalSeat, seatNumber);
            return orderCrossCityService.queryOrderMoney(startLonLat, endLonLat, peopleNumber, travelMode, lineId, lineDestinationId, serverCarModelId, totalSeat, seatNumber);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/controller/SiteController.java
@@ -1,6 +1,7 @@
package com.stylefeng.guns.modular.crossCity.controller;
import com.stylefeng.guns.modular.crossCity.model.Site;
import com.stylefeng.guns.modular.crossCity.server.ISiteService;
import com.stylefeng.guns.modular.crossCity.warpper.LocationWarpper;
import com.stylefeng.guns.modular.crossCity.warpper.SiteWarpper;
@@ -91,6 +92,25 @@
        }
    }
    /**
     * 根据经纬度查询所在站点(可能为空,命中多个时返回第一个)
     */
    @ResponseBody
    @RequestMapping(value = "/base/site/querySiteByLonLat", method = RequestMethod.POST)
    @ApiOperation(value = "根据经纬度获取所在站点", tags = {"用户端-跨城"}, notes = "可能为空;命中多个时返回第一个")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "经度", name = "lon", required = true, dataType = "double"),
            @ApiImplicitParam(value = "纬度", name = "lat", required = true, dataType = "double")
    })
    public ResultUtil<Site> querySiteByLonLat(Double lon, Double lat){
        try {
            return ResultUtil.success(siteService.querySiteByLonLat(lon, lat));
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
}
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/LineMapper.java
@@ -25,4 +25,26 @@
     * @return
     */
    List<Map<String, Object>> scanCodeQueryLines(@Param("driverId") Integer driverId);
    /**
     * 根据司机id查询当前时间之后发车的城际线路
     * @param driverId
     * @return
     */
    List<Map<String, Object>> queryFutureLinesByDriver(@Param("driverId") Integer driverId);
    /**
     * 根据线路id查询目的地列表
     * @param lineId
     * @return
     */
    List<Map<String, Object>> queryLineDestinations(@Param("lineId") Integer lineId);
    /**
     * 根据目的地id查询目的地
     * @param id
     * @param lineId
     * @return
     */
    Map<String, Object> queryLineDestinationById(@Param("id") Integer id, @Param("lineId") Integer lineId);
}
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/LineMapper.xml
@@ -22,6 +22,7 @@
        left join t_line_site b on (a.id = b.lineId)
        left join t_site c on (b.siteId = c.id)
        where a.state = 1 and b.siteId = #{siteId} and b.type = #{type}
        order by a.id asc
    </select>
@@ -33,4 +34,71 @@
        left join t_line b on (a.lineId = b.id)
        where b.state = 1 and a.driverId = #{driverId}
    </select>
</mapper>
    <select id="queryFutureLinesByDriver" resultType="map">
        select
        startSite.id as startSiteId,
        startSite.`name` as startSiteName,
        endSite.id as endSiteId,
        endSite.`name` as endSiteName,
        l.`name` as lineName,
        date_format(lsd.`day`, '%Y-%m-%d') as `day`,
        ls.startTime as startTime,
        ls.endTime as endTime,
        l.id as lineId,
        ls.id as lineShiftId,
        lsd.id as lineShiftDriverId,
        lsd.laveSeat AS laveSeat,
        lsd.laveSeatNumber AS laveSeatNumber
        from t_line_shift_driver lsd
        left join t_line_shift ls on ls.id = lsd.lineShiftId
        left join t_line l on l.id = ls.lineId
        left join t_line_site startLineSite on startLineSite.lineId = l.id and startLineSite.type = 1
        left join t_site startSite on startSite.id = startLineSite.siteId
        left join t_line_site endLineSite on endLineSite.lineId = l.id and endLineSite.type = 2
        left join t_site endSite on endSite.id = endLineSite.siteId
        where lsd.driverId = #{driverId}
          and lsd.`day` is not null
          and ls.state = 1
          and l.state = 1
          and str_to_date(concat(date_format(lsd.`day`, '%Y-%m-%d'), ' ', ls.startTime), '%Y-%m-%d %H:%i') >= now()
        order by lsd.`day` asc, ls.startTime asc, lsd.id asc
    </select>
    <select id="queryLineDestinations" resultType="map">
        select
        id,
        lineId,
        `name`,
        fenceType,
        coordinate,
        defaultPointLon,
        defaultPointLat,
        price5,
        price7,
        `state`,
        isMain,
        addTime,
        insertTime
        from t_line_destination
        where lineId = #{lineId}
          and state != 3
        order by isMain desc, id asc
    </select>
    <select id="queryLineDestinationById" resultType="map">
        select
        id,
        lineId,
        price5,
        price7,
        state
        from t_line_destination
        where id = #{id}
          and state != 3
        <if test="lineId != null">
          and lineId = #{lineId}
        </if>
        limit 1
    </select>
</mapper>
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/dao/mapping/OrderCrossCityMapper.xml
@@ -9,6 +9,7 @@
        <result column="serverCarModelId" property="serverCarModelId"/>
        <result column="driverId" property="driverId"/>
        <result column="lineId" property="lineId"/>
        <result column="lineDestinationId" property="lineDestinationId"/>
        <result column="lineShiftDriverId" property="lineShiftDriverId"/>
        <result column="carId" property="carId"/>
        <result column="orderNum" property="orderNum"/>
@@ -82,6 +83,7 @@
        serverCarModelId as serverCarModelId,
        driverId as driverId,
        lineId as lineId,
        lineDestinationId as lineDestinationId,
        lineShiftDriverId as lineShiftDriverId,
        carId as carId,
        orderNum as orderNum,
@@ -159,6 +161,7 @@
        serverCarModelId as serverCarModelId,
        driverId as driverId,
        lineId as lineId,
        lineDestinationId as lineDestinationId,
        lineShiftDriverId as lineShiftDriverId,
        carId as carId,
        orderNum as orderNum,
@@ -231,6 +234,7 @@
        serverCarModelId as serverCarModelId,
        driverId as driverId,
        lineId as lineId,
        lineDestinationId as lineDestinationId,
        lineShiftDriverId as lineShiftDriverId,
        carId as carId,
        orderNum as orderNum,
@@ -457,6 +461,7 @@
        serverCarModelId as serverCarModelId,
        driverId as driverId,
        lineId as lineId,
        lineDestinationId as lineDestinationId,
        lineShiftDriverId as lineShiftDriverId,
        carId as carId,
        orderNum as orderNum,
@@ -538,6 +543,7 @@
        a.serverCarModelId as serverCarModelId,
        a.driverId as driverId,
        a.lineId as lineId,
        a.lineDestinationId as lineDestinationId,
        a.lineShiftDriverId as lineShiftDriverId,
        a.carId as carId,
        a.orderNum as orderNum,
@@ -661,4 +667,4 @@
        boardingLat
        from t_order_cross_city where userId = #{uid}  and state in (8, 9) order by insertTime desc
    </select>
</mapper>
</mapper>
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/model/OrderCrossCity.java
@@ -40,6 +40,11 @@
    @TableField("lineId")
    private Integer lineId;
    /**
     * 线路目的地id
     */
    @TableField("lineDestinationId")
    private Integer lineDestinationId;
    /**
     * 预约班次的id
     */
    @TableField("lineShiftDriverId")
@@ -561,6 +566,14 @@
    public void setLineId(Integer lineId) {
        this.lineId = lineId;
    }
    public Integer getLineDestinationId() {
        return lineDestinationId;
    }
    public void setLineDestinationId(Integer lineDestinationId) {
        this.lineDestinationId = lineDestinationId;
    }
    public Integer getLineShiftDriverId() {
@@ -1171,6 +1184,7 @@
                ", serverCarModelId=" + serverCarModelId +
                ", driverId=" + driverId +
                ", lineId=" + lineId +
                ", lineDestinationId=" + lineDestinationId +
                ", lineShiftDriverId=" + lineShiftDriverId +
                ", carId=" + carId +
                ", orderNum='" + orderNum + '\'' +
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/ILineService.java
@@ -27,4 +27,21 @@
     * @throws Exception
     */
    List<Map<String, Object>> scanCodeQueryLines(Integer driverId) throws Exception;
    /**
     * 根据司机id查询当前时间之后发车的城际线路
     * @param driverId
     * @return
     * @throws Exception
     */
    List<Map<String, Object>> queryFutureLinesByDriver(Integer driverId) throws Exception;
    /**
     * 根据起始站点和终点站点查询第一条线路的目的地列表
     * @param startId
     * @param endId
     * @return
     * @throws Exception
     */
    List<Map<String, Object>> queryFirstLineDestinations(Integer startId, Integer endId) throws Exception;
}
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/IOrderCrossCityService.java
@@ -32,7 +32,7 @@
     * @throws Exception
     */
    ResultUtil queryOrderMoney(String startLonLat, String endLonLat, Integer peopleNumber, Integer travelMode, Integer lineId,
                               Integer serverCarModelId, Integer totalSeat, String seatNumber) throws Exception;
                               Integer lineDestinationId, Integer serverCarModelId, Integer totalSeat, String seatNumber) throws Exception;
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/ISiteService.java
@@ -36,4 +36,13 @@
     * @throws Exception
     */
    boolean areaMonitoring(Integer siteId, Integer code, String lonLat) throws Exception;
    /**
     * 根据经纬度查询所在站点(命中多个时返回第一个)
     * @param lon 经度
     * @param lat 纬度
     * @return 站点(可能为空)
     * @throws Exception
     */
    Site querySiteByLonLat(Double lon, Double lat) throws Exception;
}
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/LineServiceImpl.java
@@ -8,6 +8,7 @@
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -70,4 +71,44 @@
    public List<Map<String, Object>> scanCodeQueryLines(Integer driverId) throws Exception {
        return lineMapper.scanCodeQueryLines(driverId);
    }
    /**
     * 根据司机id查询当前时间之后发车的城际线路
     */
    @Override
    public List<Map<String, Object>> queryFutureLinesByDriver(Integer driverId) throws Exception {
        if (driverId == null) {
            return new ArrayList<>();
        }
        return lineMapper.queryFutureLinesByDriver(driverId);
    }
    /**
     * 根据起始站点和终点站点查询第一条线路的目的地列表
     */
    @Override
    public List<Map<String, Object>> queryFirstLineDestinations(Integer startId, Integer endId) throws Exception {
        List<Map<String, Object>> lines = queryLines(startId, endId, null);
        if (lines == null || lines.size() <= 0) {
            return new ArrayList<>();
        }
        Map<String, Object> firstLine = lines.get(0);
        if (firstLine == null || firstLine.get("id") == null) {
            return new ArrayList<>();
        }
        Integer lineId = Integer.valueOf(firstLine.get("id").toString());
        List<Map<String, Object>> destinations = lineMapper.queryLineDestinations(lineId);
        if (destinations == null || destinations.size() <= 0) {
            return new ArrayList<>();
        }
        for (Map<String, Object> destination : destinations) {
            Map<String, Object> fenceInfo = new HashMap<>();
            fenceInfo.put("fenceType", destination.get("fenceType"));
            fenceInfo.put("coordinate", destination.get("coordinate"));
            fenceInfo.put("defaultPointLon", destination.get("defaultPointLon"));
            fenceInfo.put("defaultPointLat", destination.get("defaultPointLat"));
            destination.put("fenceInfo", fenceInfo);
        }
        return destinations;
    }
}
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/OrderCrossCityServiceImpl.java
@@ -8,6 +8,7 @@
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.account.controller.AppOrderController;
import com.stylefeng.guns.modular.crossCity.dao.LinePriceMapper;
import com.stylefeng.guns.modular.crossCity.dao.LineMapper;
import com.stylefeng.guns.modular.crossCity.dao.LineShiftDriverMapper;
import com.stylefeng.guns.modular.crossCity.dao.OrderCrossCityMapper;
import com.stylefeng.guns.modular.crossCity.model.Line;
@@ -70,6 +71,9 @@
    
    @Resource
    private LinePriceMapper linePriceMapper;
    @Resource
    private LineMapper lineMapper;
    
    @Resource
    private UserActivityDiscount1Mapper userActivityDiscount1Mapper;
@@ -234,7 +238,23 @@
     */
    @Override
    public ResultUtil queryOrderMoney(String startLonLat, String endLonLat, Integer peopleNumber, Integer travelMode, Integer lineId,
                                      Integer serverCarModelId, Integer totalSeat, String seatNumber) throws Exception {
                                      Integer lineDestinationId, Integer serverCarModelId, Integer totalSeat, String seatNumber) throws Exception {
        if (lineDestinationId != null) {
            Map<String, Object> destination = lineMapper.queryLineDestinationById(lineDestinationId, lineId);
            if (destination == null) {
                return ResultUtil.error("目的地不存在");
            }
            Object priceObj = (totalSeat != null && totalSeat <= 5) ? destination.get("price5") : destination.get("price7");
            if (priceObj == null) {
                return ResultUtil.error("目的地价格未配置");
            }
            double unitPrice = Double.valueOf(String.valueOf(priceObj));
            double totalPrice = new BigDecimal(unitPrice).multiply(new BigDecimal(peopleNumber)).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
            Map<String, Object> map = new HashMap<>();
            map.put("distance", 0);
            map.put("price", totalPrice);
            return ResultUtil.success(map);
        }
        // TODO: 2023/11/4 无法修改
        Map<String, String> distance = gdMapElectricFenceUtil.getDistance(startLonLat, endLonLat, 1);//调用高德计算距离
        if (null != distance) {
@@ -1273,6 +1293,7 @@
        orderCrossCity.setServerCarModelId(orderCrossCityWarpper.getServerCarModelId());
        orderCrossCity.setDriverId(orderCrossCityWarpper.getDriverId());
        orderCrossCity.setLineId(orderCrossCityWarpper.getLineId());
        orderCrossCity.setLineDestinationId(orderCrossCityWarpper.getLineDestinationId());
        orderCrossCity.setLineShiftDriverId(orderCrossCityWarpper.getLineShiftDriverId());
        orderCrossCity.setCarId(orderCrossCityWarpper.getCarId());
        orderCrossCity.setOrderNum(this.getOrderNum(orderCrossCityWarpper.getDriverId(), orderCrossCityWarpper.getLineShiftDriverId()));
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/server/impl/SiteServiceImpl.java
@@ -2,19 +2,21 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.crossCity.dao.LocationMapper;
import com.stylefeng.guns.modular.crossCity.dao.SiteMapper;
import com.stylefeng.guns.modular.crossCity.model.Site;
import com.stylefeng.guns.modular.crossCity.server.ISiteService;
import com.stylefeng.guns.modular.crossCity.warpper.SiteWarpper;
import com.stylefeng.guns.modular.system.util.GDMapElectricFenceUtil;
import com.stylefeng.guns.modular.system.util.model.GeoFencingPolygon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.*;
@@ -31,7 +33,12 @@
    private LocationMapper locationMapper;
    @Autowired
    private MongoTemplate mongoTemplate;
    private ObjectProvider<MongoTemplate> mongoTemplateProvider;
    @Autowired
    private RestTemplate restTemplate;
    private static final String AMAP_KEY = "6dd64582ed31b84134ac38b2355eb82b";
    /**
@@ -112,12 +119,7 @@
                }
            }
            if(Integer.valueOf(map.get("type").toString()) == 2){//电子围栏
                String[] split = lonLat.split(",");
                GeoJsonPoint point = new GeoJsonPoint(Double.valueOf(split[0]), Double.valueOf(split[1]));
                Query query = Query.query(Criteria.where("geoJsonPolygon").intersects(point));
                List<GeoFencingPolygon> geoFencingPolygons = mongoTemplate.find(query, GeoFencingPolygon.class);
                List<Integer> s_sites = geoFencingPolygons.stream().map(GeoFencingPolygon::getSiteId).collect(Collectors.toList());
                if(s_sites.contains(siteId)){
                if(matchAreaType2(siteId, lonLat)){
                    return true;
                }
            }
@@ -135,4 +137,112 @@
    public List<Map<String, Object>> queryLocation(Integer siteId) throws Exception {
        return locationMapper.queryLocation(siteId);
    }
    /**
     * 根据经纬度查询所在站点(命中多个时返回第一个)
     */
    @Override
    public Site querySiteByLonLat(Double lon, Double lat) throws Exception {
        if (lon == null || lat == null) {
            return null;
        }
        String adCode = getAdCodeByLonLat(lon, lat);
        String lonLat = lon + "," + lat;
        List<Site> siteList = this.selectList(new EntityWrapper<Site>().eq("state", 1).orderBy("id", true));
        if (siteList == null || siteList.size() <= 0) {
            return null;
        }
        for (Site site : siteList) {
            if (site == null || site.getId() == null) {
                continue;
            }
            List<Map<String, Object>> locations = queryLocation(site.getId());
            if (locations == null || locations.size() <= 0) {
                continue;
            }
            if (matchAreaType1(locations, adCode) || matchAreaType2(site.getId(), lonLat)) {
                return site;
            }
        }
        return null;
    }
    private boolean matchAreaType1(List<Map<String, Object>> locations, String adCode) {
        if (ToolUtil.isEmpty(adCode)) {
            return false;
        }
        if (adCode.length() < 4) {
            return false;
        }
        String province = adCode.substring(0, 2) + "0000";
        String city = adCode.substring(0, 4) + "00";
        for (Map<String, Object> map : locations) {
            if (map == null || map.get("type") == null) {
                continue;
            }
            if (Integer.valueOf(map.get("type").toString()) != 1) {
                continue;
            }
            if (map.get("districtCode") != null && adCode.equals(map.get("districtCode").toString())) {
                return true;
            }
            if (map.get("cityCode") != null && city.equals(map.get("cityCode").toString())) {
                return true;
            }
            if (map.get("provinceCode") != null && province.equals(map.get("provinceCode").toString())) {
                return true;
            }
        }
        return false;
    }
    private boolean matchAreaType2(Integer siteId, String lonLat) {
        MongoTemplate mongoTemplate;
        try {
            mongoTemplate = mongoTemplateProvider.getIfAvailable();
        } catch (Exception ex) {
            return false;
        }
        if (mongoTemplate == null || ToolUtil.isEmpty(lonLat)) {
            return false;
        }
        String[] split = lonLat.split(",");
        if (split.length != 2) {
            return false;
        }
        GeoJsonPoint point = new GeoJsonPoint(Double.valueOf(split[0]), Double.valueOf(split[1]));
        Query query = Query.query(Criteria.where("geoJsonPolygon").intersects(point));
        List<GeoFencingPolygon> geoFencingPolygons = mongoTemplate.find(query, GeoFencingPolygon.class);
        if (geoFencingPolygons == null || geoFencingPolygons.size() <= 0) {
            return false;
        }
        List<Integer> siteIds = geoFencingPolygons.stream().map(GeoFencingPolygon::getSiteId).collect(Collectors.toList());
        return siteIds.contains(siteId);
    }
    private String getAdCodeByLonLat(Double lon, Double lat) {
        try {
            String location = lon + "," + lat;
            String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + AMAP_KEY + "&location=" + location;
            String body = restTemplate.getForObject(url, String.class);
            if (ToolUtil.isEmpty(body)) {
                return null;
            }
            com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSON.parseObject(body);
            if (!"1".equals(jsonObject.getString("status"))) {
                return null;
            }
            com.alibaba.fastjson.JSONObject regeocode = jsonObject.getJSONObject("regeocode");
            if (regeocode == null) {
                return null;
            }
            com.alibaba.fastjson.JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
            if (addressComponent == null) {
                return null;
            }
            return addressComponent.getString("adcode");
        } catch (Exception ex) {
            return null;
        }
    }
}
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/crossCity/warpper/OrderCrossCityWarpper.java
@@ -15,6 +15,8 @@
    private Integer driverId;
    @ApiModelProperty(value = "线路id", required = true, dataType = "int")
    private Integer lineId;
    @ApiModelProperty(value = "线路目的地id(t_line_destination.id)", required = false, dataType = "int")
    private Integer lineDestinationId;
    @ApiModelProperty(value = "车辆id", required = true, dataType = "int")
    private Integer carId;
    @ApiModelProperty(value = "下单地点经度", required = true, dataType = "double")
@@ -84,6 +86,14 @@
        this.lineId = lineId;
    }
    public Integer getLineDestinationId() {
        return lineDestinationId;
    }
    public void setLineDestinationId(Integer lineDestinationId) {
        this.lineDestinationId = lineDestinationId;
    }
    public Integer getCarId() {
        return carId;
    }