18582019636
2024-06-25 ca497f8389174bb81e91f840cab70c9579bcdd29
feat: 代码初始化
46个文件已修改
49个文件已添加
2881 ■■■■■ 已修改文件
ruoyi-api/ruoyi-api-admin/src/main/java/com/ruoyi/admin/api/entity/ServeAdvantage.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/WechatConstants.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/GaoDeMapUtil.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/GaoDeMap.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/Path.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/Route.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/Steps.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerWebConfiguration.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/RouterFunctionConfiguration.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/config/MyDateObjectHandler.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/FranchiseeController.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/MasterWorkerController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/MenuController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/OssController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/PrizeController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RecoveryClassifyController.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RecoveryServeController.java 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RegionController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RoleController.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RoleMenuController.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RotateController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/SysUserController.java 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/UserController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/UserRoleController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Franchisee.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Menu.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/RecoveryClassify.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/RecoveryServe.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Role.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/RoleMenu.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Rotate.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/ServeAdvantage.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/SysUser.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/User.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/UserRole.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/MenuMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/RoleMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/RoleMenuMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/SysUserMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/UserRoleMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/MasterWorkerRequest.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/RecoveryServePriceRequest.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/RecoveryServeRequest.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/RoleRequest.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/SysUserRequest.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/UserDataCountRequest.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/MenuService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/RoleMenuService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/RoleService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/SysUserService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/UserRoleService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/MenuServiceImpl.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/RoleMenuServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/RoleServiceImpl.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/SendSmsServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/SysUserServiceImpl.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/UserRoleServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/UserServiceImpl.java 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/utils/GeneratorCodeConfig.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/vo/RecoveryServeResultVO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/vo/RoleDetailVO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/vo/SysUserDetailVO.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/MenuMapper.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RecoveryClassifyMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RecoveryServeMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RoleMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RoleMenuMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RotateMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/ServeAdvantageMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/SysUserMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/UserRoleMapper.xml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-admin/src/main/resources/template/订单记录.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/entity/RecoveryClassify.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/service/impl/WithdrawServiceImpl.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/vo/WechatEntPayForm.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/vx/HttpUtil.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/vx/WechatPayV3Util.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/resources/mapper/user/RecoveryClassifyMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/resources/vx/apiclient_cert.p12 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/resources/vx/apiclient_cert.pem 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-user/src/main/resources/vx/apiclient_key.pem 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/controller/MasterWorkerController.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/controller/OrderController.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/entity/RecoveryClassify.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/MasterWorkerService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/OrderService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/impl/MasterWorkerServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/impl/OrderServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/vo/OrderListVO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-worker/src/main/resources/mapper/worker/RecoveryClassifyMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-admin/src/main/java/com/ruoyi/admin/api/entity/ServeAdvantage.java
@@ -31,7 +31,7 @@
    private String title;
    @ApiModelProperty("描述")
    @TableField("describe")
    private String describe;
    @TableField("describe_detail")
    private String describeDetail;
}
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
@@ -233,6 +233,11 @@
    public static final Integer EIGHT = 18;
    /**
     * 数字100
     */
    public static final Integer ONE_HUNDRED = 100;
    /**
     * 数字 3000
     */
    public static final Integer THREE_THOUSAND = 3000;
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/WechatConstants.java
New file
@@ -0,0 +1,74 @@
package com.ruoyi.common.core.constant;
/**
 * @author HJL
 * @version 1.0
 * @since 2024-06-24 14:27
 */
public class WechatConstants {
    /**
     * 小程序id
     */
    public static final String APP_ID = "appid";
    public static final String OUT_BATCH_NO = "out_batch_no";
    /**
     * 转账名称
     */
    public static final String BATCH_NAME = "batch_name";
    /**
     * 转账说明
     */
    public static final String BATCH_REMARK = "batch_remark";
    /**
     * 总金额
     */
    public static final String TOTAL_AMOUNT = "total_amount";
    /**
     * 转账数量
     */
    public static final String TOTAL_NUM = "total_num";
    /**
     * 商家明细编号
     */
    public static final String OUT_DETAIL_NO = "out_detail_no";
    /**
     * 转账金额
     */
    public static final String TRANSFER_AMOUNT = "transfer_amount";
    /**
     * 转账备注
     */
    public static final String TRANSFER_REMARK = "transfer_remark";
    /**
     * 用户所关联vx
     */
    public static final String OPEN_ID = "openId";
    /**
     * 转账列表
     */
    public static final String TRANSFER_DETAIL_LIST = "transfer_detail_list";
    /**
     * 微信商家转账到用户零钱接口地址(前缀)
     */
    public static final String WE_CHAT_URL_PRE = "https://api.mch.weixin.qq.com/v3/transfer/batches";
    /**
     * 微信商家转账到用户零钱接口地址(后缀)
     */
    public static final String WE_CHAT_URL_SUF = "/v3/transfer/batches";
    /**
     * 微信转账接口调用所返回的成功参数之一
     */
    public static final String CREATE_TIME = "create_time";
}
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -26,10 +27,12 @@
    @TableField(value = "createTime", fill = FieldFill.INSERT)
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty("修改时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    @TableField(value = "is_delete", fill = FieldFill.INSERT)
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/GaoDeMapUtil.java
@@ -5,12 +5,14 @@
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.common.core.enums.GaoDeEnum;
import com.ruoyi.common.core.vo.GaoDeMap;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
/**
 * @author HJL
@@ -146,4 +148,33 @@
        return result.toString();
    }
    /**
     * 从出发地触发到目的地路线规划
     *
     * @param origin      出发地经纬度
     * @param destination 目的地经纬度
     * @return 路线规划信息
     */
    public static Object routing(String origin, String destination) {
        String baseUrl = "https://restapi.amap.com/v3/direction/driving?origin=%s&destination=%s" +
                "&extensions=all&output=json&key=%s";
        String requestUrl = String.format(baseUrl, origin, destination, GAO_DE_KEY);
        StringBuilder json = new StringBuilder();
        try {
            URL url = new URL(requestUrl);
            URLConnection urlConnection = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),
                    StandardCharsets.UTF_8));
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                json.append(inputLine);
            }
            in.close();
        } catch (IOException ignored) {
        }
        String data = json.toString();
        GaoDeMap gaoDeMap = JSONObject.parseObject(data, GaoDeMap.class);
        return gaoDeMap.getRoute().getPaths().get(0);
    }
}
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/GaoDeMap.java
New file
@@ -0,0 +1,19 @@
/**
 * Copyright 2024 json.cn
 */
package com.ruoyi.common.core.vo;
import lombok.Data;
/**
 * @author HJL
 */
@Data
public class GaoDeMap {
    private String status;
    private String info;
    private String count;
    private Route route;
}
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/Path.java
New file
@@ -0,0 +1,58 @@
package com.ruoyi.common.core.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
 * @author HJL
 * @version 1.0
 * @since 2024-06-24 17:05
 */
@Data
public class Path {
    /**
     * 行驶距离
     */
    private Integer distance;
    /**
     * 预计行驶时间
     */
    private Integer duration;
    /**
     * 导航策略
     */
    private String strategy;
    /**
     * 此导航方案道路收费
     */
    private Integer tolls;
    /**
     * 限行结果
     */
    private Integer restriction;
    /**
     * 红绿灯个数
     */
    @JsonProperty("traffic_lights")
    private Integer trafficLights;
    /**
     * 收费路段距离
     */
    @JsonProperty("toll_distance")
    private Integer tollDistance;
    /**
     * 导航路段
     */
    private List<Steps> steps;
}
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/Route.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.common.core.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
 * @author HJL
 * @version 1.0
 * @since 2024-06-24 16:58
 */
@Data
public class Route {
    /**
     * 出发地
     */
    private String origin;
    /**
     * 目的地
     */
    private String destination;
    /**
     * 打车费用
     */
    @JsonProperty("taxi_cost")
    private String taxiCost;
    /**
     * 驾车换乘方案
     */
    private List<Path> paths;
}
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/vo/Steps.java
New file
@@ -0,0 +1,43 @@
package com.ruoyi.common.core.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
 * @author HJL
 */
@Data
public class Steps {
    /**
     * 描述
     */
    private String instruction;
    /**
     * 方向
     */
    private String orientation;
    /**
     * 距离
     */
    private String distance;
    private String tolls;
    @JsonProperty("toll_distance")
    private String tollDistance;
    @JsonProperty("toll_road")
    private List<String> tollRoad;
    private String duration;
    private String polyline;
    /**
     * 转向
     */
    private String action;
    /**
     * 路段
     */
    @JsonProperty("assistant_action")
    private String assistantAction;
}
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java
@@ -13,6 +13,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
@@ -122,16 +123,6 @@
    }
    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return AjaxResult.error(message);
    }
    /**
     * 内部认证异常
     */
    @ExceptionHandler(InnerAuthException.class)
@@ -148,11 +139,24 @@
    }
    /**
     * 演示模式异常
     * 自定义异常
     */
    @ExceptionHandler(GlobalException.class)
    public R<String> handleDemoModeException(GlobalException g) {
        return R.fail(g.getDetailMessage());
        return R.fail(g.getMessage());
    }
    /**
     * 捕获jsr303参数校验异常
     *
     * @author hjl
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<String> methodArgumentNotValidExceptionExceptionException(MethodArgumentNotValidException e) {
        FieldError fieldError = e.getBindingResult().getFieldError();
        assert fieldError != null;
        String defaultMessage = fieldError.getDefaultMessage();
        return R.fail(defaultMessage);
    }
}
ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerWebConfiguration.java
@@ -5,16 +5,14 @@
/**
 * swagger 资源映射路径
 *
 *
 * @author ruoyi
 */
public class SwaggerWebConfiguration implements WebMvcConfigurer
{
public class SwaggerWebConfiguration implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /** swagger-ui 地址 */
        registry.addResourceHandler("/swagger-ui/**","*/doc.html")
        registry.addResourceHandler("/swagger-ui/**", "*/doc.html")
                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
    }
}
ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/RouterFunctionConfiguration.java
@@ -3,11 +3,21 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import com.ruoyi.gateway.handler.ValidateCodeHandler;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
/**
 * 路由配置信息
@@ -19,6 +29,15 @@
    @Autowired
    private ValidateCodeHandler validateCodeHandler;
    /**
     * 这里为支持的请求头,如果有自定义的header字段请自己添加
     */
    private static final String ALLOWED_HEADERS = "X-Requested-With, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client, request-origion";
    private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
    private static final String ALLOWED_ORIGIN = "*";
    private static final String ALLOWED_EXPOSE = "*";
    private static final String MAX_AGE = "18000L";
    @SuppressWarnings("rawtypes")
    @Bean
    public RouterFunction routerFunction() {
@@ -26,4 +45,30 @@
                RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                validateCodeHandler);
    }
    /**
     * 跨域配置
     */
    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (CorsUtils.isCorsRequest(request)) {
                ServerHttpResponse response = ctx.getResponse();
                HttpHeaders headers = response.getHeaders();
                headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
                headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
                headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
                headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
                headers.add("Access-Control-Max-Age", MAX_AGE);
                headers.add("Access-Control-Allow-Credentials", "true");
                if (request.getMethod() == HttpMethod.OPTIONS) {
                    response.setStatusCode(HttpStatus.OK);
                    return Mono.empty();
                }
            }
            return chain.filter(ctx);
        };
    }
}
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java
@@ -51,7 +51,7 @@
            try {
                String rspStr = resolveBodyFromRequest(request);
                JSONObject obj = JSON.parseObject(rspStr);
                validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID));
                // validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID));
            } catch (Exception e) {
                return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage());
            }
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/config/MyDateObjectHandler.java
@@ -30,12 +30,13 @@
        // 更新时间
        this.setFieldValByName("updateTime", new Date(), metaObject);
        // 创建人
        this.setFieldValByName("createBy", tokenService.getLoginUser().getUsername(), metaObject);
        this.setFieldValByName("updateBy", tokenService.getLoginUser().getUsername(), metaObject);
        this.setFieldValByName("createBy", "", metaObject);
        this.setFieldValByName("updateBy", "", metaObject);
        // 是否软删除
        this.setFieldValByName("isDelete", 0, metaObject);
        // 是否启用 默认启用
        this.setFieldValByName("isEnable", 1, metaObject);
        this.setFieldValByName("delFlag", 0, metaObject);
    }
@@ -43,6 +44,6 @@
    public void updateFill(MetaObject metaObject) {
        // 修改时间为当前时间
        this.setFieldValByName("updateTime", new Date(), metaObject);
        this.setFieldValByName("updateBy", tokenService.getLoginUser().getUsername(), metaObject);
        this.setFieldValByName("updateBy", "", metaObject);
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/FranchiseeController.java
@@ -90,6 +90,10 @@
    @PostMapping(value = "/save")
    public R<String> save(@RequestBody @Validated Franchisee franchisee) {
        checkFranchisee(franchisee);
        if (null == franchisee.getAdminPassword() || StringUtils.isBlank(franchisee.getAdminPassword())) {
            throw new GlobalException("请输入管理员初始密码!");
        }
        //franchisee.setCityStr(String.valueOf(franchisee.getCityArr()));
        return franchiseeService.save(franchisee) ? R.ok() : R.fail();
    }
@@ -106,6 +110,24 @@
    }
    /**
     * 启用/关闭加盟商
     *
     * @param id     加盟商id
     * @param enable 启用/关闭
     */
    @ApiOperation(value = "启用/关闭加盟商", tags = {"后台-加盟商管理"})
    @GetMapping(value = "/enable")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "加盟商id", name = "id", dataType = "Integer", required = true),
            @ApiImplicitParam(value = "0:关闭;1:启用", name = "enable", dataType = "Integer", required = true)
    })
    public R<String> enable(@RequestParam Integer id, @RequestParam Integer enable) {
        boolean update = franchiseeService.lambdaUpdate().set(Franchisee::getIsEnable, enable)
                .eq(Franchisee::getId, id).update();
        return update ? R.ok() : R.fail();
    }
    /**
     * 校验加盟商所管辖城市并加密登录密码
     *
     * @param franchisee 加盟商信息
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/MasterWorkerController.java
@@ -23,6 +23,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -83,6 +84,52 @@
    }
    /**
     * 根据id批量删除账号
     *
     * @param ids 账号id拼接
     */
    @ApiOperation(value = "删除师傅信息", tags = {"后台-师傅管理-师傅列表管理"})
    @GetMapping(value = "/batchDelete")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "多条账号id ',' 拼接", name = "ids", dataType = "String", required = true)
    })
    public R<String> batchDelete(@RequestParam String ids) {
        List<String> idList = Arrays.stream(ids.split(",")).collect(Collectors.toList());
        List<MasterWorker> list = masterWorkerService.lambdaQuery().in(MasterWorker::getId, idList).list();
        list.forEach(data -> data.setIsDelete(1));
        return masterWorkerService.updateBatchById(list) ? R.ok() : R.fail();
    }
    /**
     * 修改师傅信息
     *
     * @param masterWorker 师傅信息
     */
    @ApiOperation(value = "修改师傅信息", tags = {"后台-师傅管理-师傅列表管理"})
    @PostMapping(value = "/update")
    public R<String> update(@RequestBody MasterWorker masterWorker) {
        return masterWorkerService.updateById(masterWorker) ? R.ok() : R.fail();
    }
    /**
     * 启用/关闭师傅账号
     *
     * @param id     师傅信息id
     * @param enable 启用/关闭
     */
    @ApiOperation(value = "启用/关闭师傅账号", tags = {"后台-师傅管理-师傅列表管理"})
    @GetMapping(value = "/enable")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "师傅id", name = "id", dataType = "Integer", required = true),
            @ApiImplicitParam(value = "0:关闭;1:启用", name = "enable", dataType = "Integer", required = true)
    })
    public R<String> enable(@RequestParam Integer id, @RequestParam Integer enable) {
        boolean update = masterWorkerService.lambdaUpdate().set(MasterWorker::getIsEnable, enable)
                .eq(MasterWorker::getId, id).update();
        return update ? R.ok() : R.fail();
    }
    /**
     * 新增师傅信息
     *
     * @param workerId 师傅id
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/MenuController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.admin.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 菜单权限表 前端控制器
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@RestController
@RequestMapping("/menu")
public class MenuController {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/OssController.java
@@ -40,7 +40,7 @@
    })
    public R<String> upload(@RequestParam("file") MultipartFile file) {
        try {
            return R.ok(ObsUploadUtil.obsUpload(file));
            return R.ok(ObsUploadUtil.obsUpload(file), "");
        } catch (IOException e) {
            return R.fail("文件上传失败!");
        }
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/PrizeController.java
@@ -77,6 +77,17 @@
    }
    /**
     * 编辑奖品
     *
     * @param prize 奖品信息
     */
    @ApiOperation(value = "编辑奖品", tags = {"后台-系统设置-奖品管理"})
    @PostMapping(value = "/update")
    public R<String> update(@RequestBody Prize prize) {
        return prizeService.updateById(prize) ? R.ok() : R.fail();
    }
    /**
     * 根据id批量删除奖品
     *
     * @param ids 奖品id拼接
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RecoveryClassifyController.java
@@ -48,7 +48,9 @@
    public R<IPage<RecoveryClassify>> queryPageList(@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        return R.ok(recoveryClassifyService.lambdaQuery().eq(RecoveryClassify::getIsDelete, 0)
                .orderByDesc(RecoveryClassify::getCreateTime).page(Page.of(pageNum, pageSize)));
                .orderByDesc(RecoveryClassify::getSupClassify)
                .orderByDesc(RecoveryClassify::getCreateTime)
                .page(Page.of(pageNum, pageSize)));
    }
    /**
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RecoveryServeController.java
@@ -1,11 +1,17 @@
package com.ruoyi.admin.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.entity.RecoveryClassify;
import com.ruoyi.admin.entity.RecoveryServe;
import com.ruoyi.admin.entity.RecoveryServePrice;
import com.ruoyi.admin.request.RecoveryServePriceRequest;
import com.ruoyi.admin.request.RecoveryServeRequest;
import com.ruoyi.admin.service.RecoveryClassifyService;
import com.ruoyi.admin.service.RecoveryServePriceService;
import com.ruoyi.admin.service.RecoveryServeService;
import com.ruoyi.admin.vo.RecoveryServeResultVO;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import io.swagger.annotations.Api;
@@ -15,6 +21,7 @@
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -34,6 +41,10 @@
    @Resource
    private RecoveryServeService recoveryServeService;
    @Resource
    private RecoveryClassifyService recoveryClassifyService;
    @Resource
    private RecoveryServePriceService recoveryServePriceService;
    /**
     * 回收服务分页列表
@@ -64,6 +75,16 @@
    }
    /**
     * 所属分类列表
     */
    @ApiOperation(value = "所属分类列表", tags = {"后台-回收管理-回收服务管理"})
    @GetMapping(value = "/typeList")
    public R<List<RecoveryClassify>> typeList() {
        return R.ok(recoveryClassifyService.lambdaQuery()
                .orderByDesc(RecoveryClassify::getCreateTime).list());
    }
    /**
     * 回收服务详情
     *
     * @param id 回收服务id
@@ -73,30 +94,70 @@
    @ApiImplicitParams({
            @ApiImplicitParam(value = "回收服务id", name = "id", dataType = "Integer", required = true)
    })
    public R<RecoveryServe> detail(@RequestParam Integer id) {
        return R.ok(recoveryServeService.getById(id));
    public R<RecoveryServeResultVO> detail(@RequestParam Integer id) {
        RecoveryServe recoveryServe = recoveryServeService.getById(id);
        List<RecoveryServePrice> priceList = recoveryServePriceService.lambdaQuery()
                .eq(RecoveryServePrice::getRecoveryServeId, id)
                .eq(RecoveryServePrice::getIsDelete, 0).list();
        return R.ok(new RecoveryServeResultVO(recoveryServe, priceList));
    }
    /**
     * 新增回收服务
     *
     * @param recoveryServe 回收服务信息
     * @param recoveryServeRequest 回收服务信息
     */
    @ApiOperation(value = "新增回收服务", tags = {"后台-回收管理-回收服务管理"})
    @PostMapping(value = "/save")
    public R<String> save(@RequestBody RecoveryServe recoveryServe) {
        return recoveryServeService.save(recoveryServe) ? R.ok() : R.fail();
    public R<String> save(@RequestBody RecoveryServeRequest recoveryServeRequest) {
        RecoveryServe serve = recoveryServeRequest.getServe();
        boolean save = recoveryServeService.save(serve);
        // 城市及对饮回收价
        if (null != recoveryServeRequest.getPriceList()) {
            for (RecoveryServePriceRequest data : recoveryServeRequest.getPriceList()) {
                BigDecimal recoveryPrice = data.getRecoveryPrice();
                String city = data.getCity();
                // 信息封装
                RecoveryServePrice price = new RecoveryServePrice();
                price.setRecoveryServeId(serve.getId());
                price.setRecoveryPrice(recoveryPrice);
                price.setCity(city);
                save = save && recoveryServePriceService.save(price);
            }
        }
        return save ? R.ok() : R.fail();
    }
    /**
     * 修改回收服务
     *
     * @param recoveryServe 回收服务信息
     * @param recoveryServeRequest 回收服务信息
     */
    @ApiOperation(value = "修改回收服务", tags = {"后台-回收管理-回收服务管理"})
    @PostMapping(value = "/update")
    public R<String> update(@RequestBody RecoveryServe recoveryServe) {
        return recoveryServeService.updateById(recoveryServe) ? R.ok() : R.fail();
    public R<String> update(@RequestBody RecoveryServeRequest recoveryServeRequest) {
        RecoveryServe serve = recoveryServeRequest.getServe();
        serve.setId(recoveryServeRequest.getId());
        boolean update = recoveryServeService.updateById(serve);
        // 城市及对应回收价
        update = update && recoveryServePriceService.lambdaUpdate()
                .set(RecoveryServePrice::getIsDelete, 1)
                .eq(RecoveryServePrice::getRecoveryServeId, recoveryServeRequest.getId())
                .update();
        // 新增省市及回收价
        if (null != recoveryServeRequest.getPriceList()) {
            for (RecoveryServePriceRequest data : recoveryServeRequest.getPriceList()) {
                BigDecimal recoveryPrice = data.getRecoveryPrice();
                String city = data.getCity();
                // 信息封装
                RecoveryServePrice price = new RecoveryServePrice();
                price.setRecoveryServeId(serve.getId());
                price.setRecoveryPrice(recoveryPrice);
                price.setCity(city);
                update = update && recoveryServePriceService.save(price);
            }
        }
        return update ? R.ok() : R.fail();
    }
    /**
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RegionController.java
@@ -33,7 +33,7 @@
     * 收货地址省市二级联动
     */
    @GetMapping("/addressTree")
    @ApiOperation(value = "收货地址省市二级联动", tags = {"后台-首页"})
    @ApiOperation(value = "选择城市:省市二级联动", tags = {"后台-首页"})
    public R<List<Region>> addressTree() {
        return R.ok(regionService.addressTree());
    }
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RoleController.java
New file
@@ -0,0 +1,163 @@
package com.ruoyi.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.entity.Menu;
import com.ruoyi.admin.entity.Role;
import com.ruoyi.admin.entity.RoleMenu;
import com.ruoyi.admin.request.RoleRequest;
import com.ruoyi.admin.service.MenuService;
import com.ruoyi.admin.service.RoleMenuService;
import com.ruoyi.admin.service.RoleService;
import com.ruoyi.admin.vo.RoleDetailVO;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.system.api.model.LoginUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
 * 角色信息表 前端控制器
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@RestController
@RequestMapping("/role")
@Api(tags = {"后台-权限管理-角色管理"})
public class RoleController {
    @Resource
    private RoleService roleService;
    @Resource
    private TokenService tokenService;
    @Resource
    private RoleMenuService roleMenuService;
    @Resource
    private MenuService menuService;
    /**
     * 角色分页列表
     *
     * @param pageNum  页码
     * @param pageSize 每页显示条数
     */
    @ApiOperation(value = "角色分页查询列表", tags = {"后台-权限管理-角色管理"})
    @GetMapping(value = "/page")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "页码", name = "pageNum", dataType = "Integer", required = true),
            @ApiImplicitParam(value = "每页条数", name = "pageSize", dataType = "Integer", required = true)
    })
    public R<IPage<Role>> queryPageList(@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                                        @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        return R.ok(roleService.lambdaQuery().eq(Role::getDelFlag, 0)
                .orderByDesc(Role::getCreateTime).page(Page.of(pageNum, pageSize)));
    }
    /**
     * 角色列表
     */
    @ApiOperation(value = "角色列表", tags = {"后台-权限管理-账号管理"})
    @GetMapping(value = "/list")
    public R<List<Role>> list() {
        LoginUser loginUser = tokenService.getLoginUser();
        if (null == loginUser) {
            return R.loginExpire("登录失效!");
        }
        return R.ok(roleService.lambdaQuery().eq(Role::getDelFlag, 0).orderByDesc(Role::getCreateTime).list());
    }
    /**
     * 角色详情
     *
     * @param id 角色id
     */
    @ApiOperation(value = "角色详情", tags = {"后台-权限管理-角色管理"})
    @GetMapping(value = "/detail")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "角色id", name = "id", dataType = "Integer", required = true)
    })
    public R<RoleDetailVO> detail(@RequestParam Integer id) {
        Role role = roleService.getById(id);
        // 获取角色关联菜单权限
        List<RoleMenu> list = roleMenuService.lambdaQuery().eq(RoleMenu::getRoleId, id).list();
        List<Menu> menuList = menuService.lambdaQuery()
                .in(Menu::getMenuId, list.stream().map(RoleMenu::getMenuId).collect(Collectors.toList()))
                .list();
        return R.ok(new RoleDetailVO(role, menuList));
    }
    /**
     * 角色详情
     *
     * @param roleRequest 角色信息
     */
    @ApiOperation(value = "编辑角色", tags = {"后台-权限管理-角色管理"})
    @PostMapping(value = "/update")
    public R<RoleDetailVO> update(@RequestBody RoleRequest roleRequest) {
        Role role = roleRequest.getRole();
        role.setRoleId(roleRequest.getRoleId());
        // 修稿角色信息
        boolean update = roleService.updateById(role);
        // 修改角色关联菜单信息
        update = update && roleMenuService.remove(new QueryWrapper<RoleMenu>().eq("role_id", role.getRoleId()));
        // 添加角色关联菜单信息
        for (String menuId : roleRequest.getMenuIds()) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(role.getRoleId());
            roleMenu.setMenuId(Long.parseLong(menuId));
            roleMenuService.save(roleMenu);
        }
        return update ? R.ok() : R.fail();
    }
    /**
     * 新增角色
     *
     * @param roleRequest 角色信息
     */
    @ApiOperation(value = "新增角色", tags = {"后台-权限管理-角色管理"})
    @PostMapping(value = "/save")
    public R<String> save(@RequestBody RoleRequest roleRequest) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (null == loginUser) {
            return R.loginExpire("登录失效!");
        }
        return roleService.saveRoleAndMenu(roleRequest, loginUser) ? R.ok() : R.fail();
    }
    /**
     * 根据id批量删除角色
     *
     * @param ids 角色id拼接
     */
    @ApiOperation(value = "批量删除角色", tags = {"后台-权限管理-角色管理"})
    @GetMapping(value = "/batchDelete")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "多条角色id ',' 拼接", name = "ids", dataType = "String", required = true)
    })
    public R<String> batchDelete(@RequestParam String ids) {
        List<String> idList = Arrays.stream(ids.split(",")).collect(Collectors.toList());
        List<Role> list = roleService.lambdaQuery().in(Role::getRoleId, idList).list();
        list.forEach(data -> data.setDelFlag("2"));
        // 删除角色需要删除角色所关联的菜单信息
        for (String id : idList) {
            roleMenuService.remove(new QueryWrapper<RoleMenu>().eq("role_id", id));
        }
        return roleService.updateBatchById(list) ? R.ok() : R.fail();
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RoleMenuController.java
New file
@@ -0,0 +1,41 @@
package com.ruoyi.admin.controller;
import com.ruoyi.admin.entity.Menu;
import com.ruoyi.admin.service.MenuService;
import com.ruoyi.common.core.domain.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
 * <p>
 * 角色和菜单关联表 前端控制器
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@RestController
@RequestMapping("/roleMenu")
@Api(tags = {"后台-权限管理-菜单权限"})
public class RoleMenuController {
    @Resource
    private MenuService menuService;
    /**
     * 菜单树
     */
    @ApiOperation(value = "菜单树", tags = {"后台-权限管理-菜单权限"})
    @GetMapping(value = "/menuTree")
    public R<List<Menu>> menuTree() {
        return R.ok(menuService.menuTree());
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/RotateController.java
@@ -58,7 +58,7 @@
    @GetMapping(value = "/bannerList")
    public R<List<Rotate>> bannerList() {
        return R.ok(rotateService.lambdaQuery().eq(Rotate::getIsDelete, 0)
                .orderByAsc(Rotate::getOrder).list());
                .orderByAsc(Rotate::getSort).list());
    }
    /**
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/SysUserController.java
New file
@@ -0,0 +1,187 @@
package com.ruoyi.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.entity.SysUser;
import com.ruoyi.admin.entity.UserRole;
import com.ruoyi.admin.request.SysUserRequest;
import com.ruoyi.admin.service.SysUserService;
import com.ruoyi.admin.service.UserRoleService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.system.api.model.LoginUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
 * 用户信息表 前端控制器
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@RestController
@RequestMapping("/sysUser")
@Api(tags = {"后台-权限管理-账号管理"})
public class SysUserController {
    @Resource
    private SysUserService sysUserService;
    @Resource
    private TokenService tokenService;
    @Resource
    private UserRoleService userRoleService;
    /**
     * 账号分页列表
     *
     * @param pageNum  页码
     * @param pageSize 每页显示条数
     */
    @ApiOperation(value = "账号分页查询列表", tags = {"后台-权限管理-账号管理"})
    @GetMapping(value = "/page")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "账号名称", name = "nickName", dataType = "String"),
            @ApiImplicitParam(value = "账号", name = "account", dataType = "String"),
            @ApiImplicitParam(value = "所属账号", name = "role", dataType = "String"),
            @ApiImplicitParam(value = "页码", name = "pageNum", dataType = "Integer", required = true),
            @ApiImplicitParam(value = "每页条数", name = "pageSize", dataType = "Integer", required = true)
    })
    public R<IPage<SysUser>> queryPageList(String nickName, String account, String role,
                                           @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                                           @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        return R.ok(sysUserService.queryPage(nickName, account, role, Page.of(pageNum, pageSize)));
    }
    /**
     * 启用/关闭后台账号
     *
     * @param id     后台账号id
     * @param enable 启用/关闭
     */
    @ApiOperation(value = "启用/关闭后台账号", tags = {"后台-师傅管理-师傅列表管理"})
    @GetMapping(value = "/enable")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "账号id", name = "id", dataType = "Integer", required = true),
            @ApiImplicitParam(value = "0:关闭;1:启用", name = "enable", dataType = "Integer", required = true)
    })
    public R<String> enable(@RequestParam Integer id, @RequestParam Integer enable) {
        boolean update = sysUserService.lambdaUpdate().set(SysUser::getIsEnable, enable)
                .eq(SysUser::getUserId, id).update();
        return update ? R.ok() : R.fail();
    }
    /**
     * 账号详情
     *
     * @param id 账号id
     */
    @ApiOperation(value = "账号详情", tags = {"后台-权限管理-账号管理"})
    @GetMapping(value = "/detail")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "账号id", name = "id", dataType = "Integer", required = true)
    })
    public R<SysUser> detail(@RequestParam Integer id) {
        // 账号详情
        return R.ok(sysUserService.getById(id));
    }
    /**
     * 新增账号
     *
     * @param sysUserRequest 账号信息
     */
    @ApiOperation(value = "新增账号", tags = {"后台-权限管理-账号管理"})
    @PostMapping(value = "/save")
    public R<String> save(@RequestBody @Validated SysUserRequest sysUserRequest) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (null == loginUser) {
            return R.loginExpire("登录失效!");
        }
        // 账号封装
        SysUser sysUser = new SysUser();
        sysUser.setNickName(sysUserRequest.getNickName());
        sysUser.setAccount(sysUserRequest.getAccount());
        // 加密密码
        String password = sysUserRequest.getPassword();
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        sysUser.setPassword(passwordEncoder.encode(password));
        sysUser.setIsEnable(sysUserRequest.getIsEnable());
        boolean save = sysUserService.save(sysUser);
        // 添加账号与角色关联
        UserRole userRole = new UserRole();
        userRole.setUserId(sysUser.getUserId());
        userRole.setRoleId(sysUserRequest.getRoleId().longValue());
        save = save && userRoleService.save(userRole);
        return save ? R.ok() : R.fail();
    }
    /**
     * 修改账号
     *
     * @param sysUserRequest 账号信息
     */
    @ApiOperation(value = "修改账号", tags = {"后台-权限管理-账号管理"})
    @PostMapping(value = "/update")
    public R<String> update(@RequestBody SysUserRequest sysUserRequest) {
        Long userId = sysUserRequest.getUserId();
        String nickName = sysUserRequest.getNickName();
        String account = sysUserRequest.getAccount();
        String password = sysUserRequest.getPassword();
        Integer isEnable = sysUserRequest.getIsEnable();
        Integer roleId = sysUserRequest.getRoleId();
        LoginUser loginUser = tokenService.getLoginUser();
        if (null == loginUser) {
            return R.loginExpire("登录失效!");
        }
        // 修改账号信息
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        LambdaUpdateChainWrapper<SysUser> wrapper = sysUserService.lambdaUpdate();
        wrapper = StringUtils.isNotBlank(nickName) ? wrapper.set(SysUser::getNickName, nickName) : wrapper;
        wrapper = StringUtils.isNotBlank(account) ? wrapper.set(SysUser::getAccount, account) : wrapper;
        wrapper = StringUtils.isNotBlank(password) ? wrapper.set(SysUser::getPassword, passwordEncoder.encode(password)) : wrapper;
        wrapper = null != isEnable ? wrapper.set(SysUser::getIsEnable, isEnable) : wrapper;
        boolean update = wrapper.eq(SysUser::getUserId, userId).update();
        // 修改账号与角色关联
        update = update && userRoleService.lambdaUpdate().set(UserRole::getRoleId, roleId)
                .eq(UserRole::getUserId, userId).update();
        return update ? R.ok() : R.fail();
    }
    /**
     * 根据id批量删除账号
     *
     * @param ids 账号id拼接
     */
    @ApiOperation(value = "批量删除账号", tags = {"后台-权限管理-账号管理"})
    @GetMapping(value = "/batchDelete")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "多条账号id ',' 拼接", name = "ids", dataType = "String", required = true)
    })
    public R<String> batchDelete(@RequestParam String ids) {
        List<String> idList = Arrays.stream(ids.split(",")).collect(Collectors.toList());
        List<SysUser> list = sysUserService.lambdaQuery().in(SysUser::getUserId, idList).list();
        list.forEach(data -> data.setIsDelete(1));
        // 删除账号需要删除账号所关联的菜单信息
        for (String id : idList) {
            userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", id));
        }
        return sysUserService.updateBatchById(list) ? R.ok() : R.fail();
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/UserController.java
@@ -78,6 +78,24 @@
    }
    /**
     * 启用/关闭用户账号
     *
     * @param id     后台账号id
     * @param enable 启用/关闭
     */
    @ApiOperation(value = "启用/关闭用户账号", tags = {"后台-师傅管理-师傅列表管理"})
    @GetMapping(value = "/enable")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "用户id", name = "id", dataType = "Integer", required = true),
            @ApiImplicitParam(value = "0:关闭;1:启用", name = "enable", dataType = "Integer", required = true)
    })
    public R<String> enable(@RequestParam Integer id, @RequestParam Integer enable) {
        boolean update = userService.lambdaUpdate().set(User::getState, enable)
                .eq(User::getId, id).update();
        return update ? R.ok() : R.fail();
    }
    /**
     * 新增前台用户
     *
     * @param user 前台用户信息
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/UserRoleController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.admin.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 用户和角色关联表 前端控制器
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@RestController
@RequestMapping("/user-role")
public class UserRoleController {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Franchisee.java
@@ -27,7 +27,7 @@
@ApiModel(value = "Franchisee对象", description = "加盟商信息表")
public class Franchisee extends BaseEntity {
    @TableId(value = "id",type = IdType.AUTO)
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("加盟商名称")
@@ -58,7 +58,6 @@
    @ApiModelProperty("管理员密码")
    @TableField("admin_password")
    @NotBlank(message = "请输入:管理员密码")
    private String adminPassword;
    @ApiModelProperty("管辖城市( ',' 隔开)")
@@ -79,4 +78,8 @@
    @TableField("is_enable")
    private Integer isEnable;
    @ApiModelProperty("管辖城市二维数组")
    @TableField("city_str")
    private String cityStr;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Menu.java
New file
@@ -0,0 +1,66 @@
package com.ruoyi.admin.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
 * 菜单权限表
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Getter
@Setter
@TableName("sys_menu")
@ApiModel(value = "Menu对象", description = "菜单权限表")
public class Menu {
    @ApiModelProperty("菜单ID")
    @TableId(value = "menu_id", type = IdType.AUTO)
    private Long menuId;
    @ApiModelProperty("菜单名称")
    @TableField("menu_name")
    private String menuName;
    @ApiModelProperty("父菜单ID")
    @TableField("parent_id")
    private Long parentId;
    @ApiModelProperty("显示顺序")
    @TableField("order_num")
    private Integer orderNum;
    @ApiModelProperty("路由地址")
    @TableField("path")
    private String path;
    @ApiModelProperty("组件路径")
    @TableField("component")
    private String component;
    @ApiModelProperty("路由参数")
    @TableField("query")
    private String query;
    /**
     * 子集
     */
    @TableField(exist = false)
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    @ApiModelProperty("子集")
    private List<Menu> children = new ArrayList<>();
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/RecoveryClassify.java
@@ -44,12 +44,12 @@
    private String classificationPicture;
    @ApiModelProperty("分类描述")
    @TableField("describe")
    private String describe;
    @TableField("type_describe")
    private String typeDescribe;
    @ApiModelProperty("排序权重")
    @TableField("order")
    private Integer order;
    @TableField("sort")
    private Integer sort;
    @ApiModelProperty("分类简介")
    @TableField("brief_introduction")
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/RecoveryServe.java
@@ -50,8 +50,8 @@
    private BigDecimal defaultPrice;
    @ApiModelProperty("排序权重")
    @TableField("order")
    private Integer order;
    @TableField("sort")
    private Integer sort;
    @ApiModelProperty("封面图片")
    @TableField("cover")
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Role.java
New file
@@ -0,0 +1,89 @@
package com.ruoyi.admin.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
/**
 * <p>
 * 角色信息表
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Getter
@Setter
@TableName("sys_role")
@ApiModel(value = "Role对象", description = "角色信息表")
public class Role {
    @ApiModelProperty("角色ID")
    @TableId(value = "role_id", type = IdType.AUTO)
    private Long roleId;
    @ApiModelProperty("角色名称")
    @TableField("role_name")
    private String roleName;
    @ApiModelProperty("角色说明")
    @TableField("role_illustrate")
    private String roleIllustrate;
    @ApiModelProperty("角色权限字符串")
    @TableField("role_key")
    private String roleKey;
    @ApiModelProperty("显示顺序")
    @TableField("role_sort")
    private Integer roleSort;
    @ApiModelProperty("数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)")
    @TableField("data_scope")
    private String dataScope;
    @ApiModelProperty("菜单树选择项是否关联显示")
    @TableField("menu_check_strictly")
    private Boolean menuCheckStrictly;
    @ApiModelProperty("部门树选择项是否关联显示")
    @TableField("dept_check_strictly")
    private Boolean deptCheckStrictly;
    @ApiModelProperty("角色状态(0正常 1停用)")
    @TableField("status")
    private String status;
    @ApiModelProperty("删除标志(0代表存在 2代表删除)")
    @TableField("del_flag")
    private String delFlag;
    @ApiModelProperty("创建者")
    @TableField(value = "create_by", fill = FieldFill.INSERT)
    private String createBy;
    @ApiModelProperty("创建时间")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    @ApiModelProperty("更新者")
    @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
    private String updateBy;
    @ApiModelProperty("更新时间")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    @ApiModelProperty("备注")
    @TableField("remark")
    private String remark;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/RoleMenu.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.admin.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * <p>
 * 角色和菜单关联表
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Getter
@Setter
@TableName("sys_role_menu")
@ApiModel(value = "RoleMenu对象", description = "角色和菜单关联表")
public class RoleMenu {
    @ApiModelProperty("角色ID")
    @TableField("role_id")
    private Long roleId;
    @ApiModelProperty("菜单ID")
    @TableField("menu_id")
    private Long menuId;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/Rotate.java
@@ -32,8 +32,8 @@
    private String rotatePicture;
    @ApiModelProperty("排序")
    @TableField("order")
    private Integer order;
    @TableField("sort")
    private Integer sort;
    @ApiModelProperty("跳转服务id")
    @TableField("rotate_serve_id")
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/ServeAdvantage.java
@@ -32,7 +32,7 @@
    private String title;
    @ApiModelProperty("描述")
    @TableField("describe")
    private String describe;
    @TableField("describe_detail")
    private String describeDetail;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/SysUser.java
New file
@@ -0,0 +1,89 @@
package com.ruoyi.admin.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
/**
 * <p>
 * 用户信息表
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Getter
@Setter
@TableName("sys_user")
@ApiModel(value = "SysUser对象", description = "用户信息表")
public class SysUser extends BaseEntity {
    @ApiModelProperty("用户ID")
    @TableId(value = "user_id", type = IdType.AUTO)
    private Long userId;
    @ApiModelProperty("账号名称")
    @TableField("nick_name")
    private String nickName;
    @ApiModelProperty("账号")
    @TableField("account")
    private String account;
    @ApiModelProperty("密码")
    @TableField("password")
    private String password;
    @ApiModelProperty("是否启用(0:未启用;1:已启用)")
    @TableField("is_enable")
    private Integer isEnable;
    @ApiModelProperty("最后登录IP")
    @TableField("login_ip")
    private String loginIp;
    @ApiModelProperty("最后登录时间")
    @TableField("login_date")
    private Date loginDate;
    @ApiModelProperty("密码修改时间")
    @TableField("passWordUpdate")
    private Date passWordUpdate;
    @TableField(value = "create_by", fill = FieldFill.INSERT)
    @ApiModelProperty("创建人")
    private String createBy;
    @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty("修改人")
    private String updateBy;
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty("修改时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    @TableField(value = "is_delete", fill = FieldFill.INSERT)
    @ApiModelProperty("是否软删除 0未删除;1已删除")
    private Integer isDelete;
    @ApiModelProperty("所属角色")
    @TableField(exist = false)
    private String roleName;
    @ApiModelProperty("所属角色id")
    @TableField(exist = false)
    private Integer roleId;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/User.java
@@ -24,16 +24,16 @@
@ApiModel(value = "User对象", description = "用户列表")
public class User extends BaseEntity {
    @TableId(value = "id",type = IdType.AUTO)
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("用户id")
    @TableField("user_no")
    private String userNo;
    @ApiModelProperty("注册城市id")
    @TableField("city_id")
    private Integer cityId;
    @ApiModelProperty("注册城市")
    @TableField("city")
    private String city;
    @ApiModelProperty("用户昵称")
    @TableField("nickname")
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/entity/UserRole.java
New file
@@ -0,0 +1,32 @@
package com.ruoyi.admin.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * <p>
 * 用户和角色关联表
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Getter
@Setter
@TableName("sys_user_role")
@ApiModel(value = "UserRole对象", description = "用户和角色关联表")
public class UserRole {
    @ApiModelProperty("用户ID")
    @TableField("user_id")
    private Long userId;
    @ApiModelProperty("角色ID")
    @TableField("role_id")
    private Long roleId;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/MenuMapper.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.admin.entity.Menu;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * 菜单权限表 Mapper 接口
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Mapper
public interface MenuMapper extends BaseMapper<Menu> {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/RoleMapper.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.admin.entity.Role;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * 角色信息表 Mapper 接口
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Mapper
public interface RoleMapper extends BaseMapper<Role> {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/RoleMenuMapper.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.admin.entity.RoleMenu;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * 角色和菜单关联表 Mapper 接口
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Mapper
public interface RoleMenuMapper extends BaseMapper<RoleMenu> {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/SysUserMapper.java
New file
@@ -0,0 +1,32 @@
package com.ruoyi.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.entity.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
 * 用户信息表 Mapper 接口
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
    /**
     * 账号分页列表
     *
     * @param nickName 账号名称
     * @param account  账号
     * @param role     角色
     * @param page     分页
     * @return 分页列表
     */
    IPage<SysUser> queryPage(@Param("nickName") String nickName, @Param("account") String account,
                             @Param("role") String role, Page<Object> page);
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/mapper/UserRoleMapper.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.admin.entity.UserRole;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * 用户和角色关联表 Mapper 接口
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Mapper
public interface UserRoleMapper extends BaseMapper<UserRole> {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/MasterWorkerRequest.java
New file
@@ -0,0 +1,68 @@
package com.ruoyi.admin.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
import java.util.Date;
/**
 * <p>
 * 师傅信息表
 * </p>
 *
 * @author hjl
 * @since 2024-05-29
 */
@Getter
@Setter
@ApiModel(value = "MasterWorkerRequest对象", description = "师傅信息表")
public class MasterWorkerRequest {
    private Integer id;
    @ApiModelProperty("服务城市")
    @NotBlank(message = "请选择服务城市!")
    private String city;
    @ApiModelProperty("用户编号(用户昵称/用户id)")
    private String userNumber;
    @ApiModelProperty("师傅姓名 ")
    @NotBlank(message = "请输入师傅姓名!")
    private String realName;
    @ApiModelProperty("性别 ")
    private String sex;
    @ApiModelProperty("生日")
    private Date birthday;
    @ApiModelProperty("身份证号码")
    private String idNumber;
    @ApiModelProperty("车辆类型")
    private String vehicleType;
    @ApiModelProperty("车牌号")
    private String vehicleNumber;
    @ApiModelProperty("手机号")
    @NotBlank(message = "请输入手机号!")
    private String phone;
    @ApiModelProperty("头像")
    private String profilePicture;
    @ApiModelProperty("身份证正反面照片 ,隔开")
    private String identityPhoto;
    @ApiModelProperty("行驶证照片")
    private String drivingLicense;
    @ApiModelProperty("是否启用 0未启用;1已启用")
    private Integer isEnable;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/RecoveryServePriceRequest.java
New file
@@ -0,0 +1,29 @@
package com.ruoyi.admin.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
/**
 * <p>
 * 回收服务对应回收价格及所在城市
 * </p>
 *
 * @author hjl
 * @since 2024-05-29
 */
@Getter
@Setter
@ApiModel(value = "RecoveryServePrice对象", description = "回收服务对应回收价格及所在城市")
public class RecoveryServePriceRequest {
    @ApiModelProperty("回收价格")
    private BigDecimal recoveryPrice;
    @ApiModelProperty("对应城市")
    private String city;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/RecoveryServeRequest.java
New file
@@ -0,0 +1,68 @@
package com.ruoyi.admin.request;
import com.ruoyi.admin.entity.RecoveryServe;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
import java.util.List;
/**
 * <p>
 *
 * </p>
 *
 * @author hjl
 * @since 2024-05-29
 */
@Getter
@Setter
@ApiModel(value = "RecoveryServe对象", description = "回收服务列表")
public class RecoveryServeRequest {
    @ApiModelProperty("服务id")
    private Integer id;
    @ApiModelProperty("所属分类id")
    private Integer classifyId;
    @ApiModelProperty("服务名称")
    private String serveName;
    @ApiModelProperty("服务描述")
    private String serveDescribe;
    @ApiModelProperty("预估价格")
    private BigDecimal estimatePrice;
    @ApiModelProperty("默认回收价")
    private BigDecimal defaultPrice;
    @ApiModelProperty("排序权重")
    private Integer sort;
    @ApiModelProperty("封面图片")
    private String cover;
    @ApiModelProperty("轮播图片")
    private String rotate;
    @ApiModelProperty("城市对应回收价")
    private List<RecoveryServePriceRequest> priceList;
    public RecoveryServe getServe() {
        RecoveryServe recoveryServe = new RecoveryServe();
        recoveryServe.setClassifyId(getClassifyId());
        recoveryServe.setServeName(getServeName());
        recoveryServe.setServeDescribe(getServeDescribe());
        recoveryServe.setEstimatePrice(getEstimatePrice());
        recoveryServe.setDefaultPrice(getDefaultPrice());
        recoveryServe.setSort(getSort());
        recoveryServe.setCover(getCover());
        recoveryServe.setRotate(getRotate());
        return recoveryServe;
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/RoleRequest.java
New file
@@ -0,0 +1,48 @@
package com.ruoyi.admin.request;
import com.ruoyi.admin.entity.Role;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
 * <p>
 * 角色信息表
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Getter
@Setter
@ApiModel(value = "Role对象", description = "角色信息表")
public class RoleRequest {
    @ApiModelProperty("角色ID")
    private Long roleId;
    @ApiModelProperty("角色名称")
    private String roleName;
    @ApiModelProperty("角色备注")
    private String roleIllustrate;
    @ApiModelProperty("显示顺序")
    private Integer roleSort;
    @ApiModelProperty("菜单列表id")
    private List<String> menuIds;
    public Role getRole() {
        Role role = new Role();
        role.setRoleName(getRoleName());
        role.setRoleIllustrate(getRoleIllustrate());
        role.setRemark(getRoleIllustrate());
        role.setDelFlag("0");
        return role;
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/SysUserRequest.java
New file
@@ -0,0 +1,45 @@
package com.ruoyi.admin.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
 * 用户信息表
 *
 * @author hjl
 * @since 2024-06-25
 */
@Getter
@Setter
@ApiModel(value = "SysUserRequest对象", description = "用户信息表")
public class SysUserRequest {
    @ApiModelProperty("用户ID")
    private Long userId;
    @ApiModelProperty("账号名称")
    @NotBlank(message = "账号名称不能为空!")
    private String nickName;
    @ApiModelProperty("账号")
    @NotBlank(message = "账号不能为空!")
    private String account;
    @ApiModelProperty("初始密码")
    @NotBlank(message = "初始密码不能为空!")
    private String password;
    @ApiModelProperty("是否启用(0:未启用;1:已启用)")
    @NotNull(message = "请选择账号是否启用!")
    private Integer isEnable;
    @ApiModelProperty("所属角色id")
    @NotNull(message = "请选择关联角色!")
    private Integer roleId;
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/request/UserDataCountRequest.java
@@ -16,8 +16,8 @@
@ApiModel(value = "userDataCountRequest对象", description = "用户数据统计请求参数")
public class UserDataCountRequest {
    @ApiModelProperty("所选城市id集合")
    private List<String> cityIdList;
    @ApiModelProperty("所选城市集合")
    private List<String> cityList;
    @ApiModelProperty("统计类型(月度:month;季度:quarter;年度:year)")
    @NotBlank(message = "请选择:统计类型!")
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/MenuService.java
New file
@@ -0,0 +1,24 @@
package com.ruoyi.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.admin.entity.Menu;
import java.util.List;
/**
 * <p>
 * 菜单权限表 服务类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
public interface MenuService extends IService<Menu> {
    /**
     * 菜单树
     *
     * @return 菜单树
     */
    List<Menu> menuTree();
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/RoleMenuService.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.admin.entity.RoleMenu;
/**
 * <p>
 * 角色和菜单关联表 服务类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
public interface RoleMenuService extends IService<RoleMenu> {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/RoleService.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.admin.entity.Role;
import com.ruoyi.admin.request.RoleRequest;
import com.ruoyi.system.api.model.LoginUser;
/**
 * <p>
 * 角色信息表 服务类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
public interface RoleService extends IService<Role> {
    /**
     * 新增角色并建立角色菜单关联
     *
     * @param roleRequest 参数信息
     * @param loginUser   登录信息
     * @return 添加结果
     */
    boolean saveRoleAndMenu(RoleRequest roleRequest, LoginUser loginUser);
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/SysUserService.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.admin.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.admin.entity.SysUser;
/**
 * <p>
 * 用户信息表 服务类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
public interface SysUserService extends IService<SysUser> {
    /**
     * 账号分页列表
     *
     * @param nickName 账号名称
     * @param account  账号
     * @param role     角色
     * @param page     分页
     * @return 分页列表
     */
    IPage<SysUser> queryPage(String nickName, String account, String role, Page<Object> page);
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/UserRoleService.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.admin.entity.UserRole;
/**
 * <p>
 * 用户和角色关联表 服务类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
public interface UserRoleService extends IService<UserRole> {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/MenuServiceImpl.java
New file
@@ -0,0 +1,83 @@
package com.ruoyi.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.admin.entity.Menu;
import com.ruoyi.admin.mapper.MenuMapper;
import com.ruoyi.admin.service.MenuService;
import com.ruoyi.common.core.constant.RedisConstants;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Resource
    private RedisTemplate<Object, Object> redisTemplate;
    @Override
    public List<Menu> menuTree() {
        // redis缓存
        Map<Object, Object> regionList = redisTemplate.opsForHash().entries(RedisConstants.MENU_TREE);
        // 获取所有地区信息 省市区三级
        List<Menu> regions = getReginList(regionList);
        // 所有地区
        Map<String, Menu> courseTypeMap = regions.stream().
                collect(Collectors.toMap(region -> region.getMenuId().toString()
                        , region -> region));
        redisTemplate.opsForHash().putAll(RedisConstants.MENU_TREE, courseTypeMap);
        redisTemplate.expire(RedisConstants.MENU_TREE, 30, TimeUnit.MINUTES);
        // 生成map集合
        Map<Long, Menu> map = regions.stream().collect(Collectors.toMap(Menu::getMenuId, region -> region));
        // 存放无限级树
        List<Menu> treeData = new ArrayList<>();
        // 遍历地区集合
        regions.forEach(e -> {
            if (e.getParentId() == null || e.getParentId().equals(0L)) {
                treeData.add(e);
            } else {
                Menu region = map.get(e.getParentId());
                region.getChildren().add(e);
            }
        });
        for (Menu region : treeData) {
            List<Menu> children = region.getChildren();
            for (Menu child : children) {
                child.setChildren(new ArrayList<>());
            }
        }
        return treeData;
    }
    /**
     * 获取redis数据进行封装
     */
    private List<Menu> getReginList(Map<Object, Object> regionMap) {
        List<Menu> regions = new ArrayList<>();
        if (!regionMap.isEmpty()) {
            Collection<Object> values = regionMap.values();
            for (Object value : values) {
                regions.add((Menu) value);
            }
        } else {
            regions = this.list();
        }
        return regions;
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/RoleMenuServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.admin.entity.RoleMenu;
import com.ruoyi.admin.mapper.RoleMenuMapper;
import com.ruoyi.admin.service.RoleMenuService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 角色和菜单关联表 服务实现类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Service
public class RoleMenuServiceImpl extends ServiceImpl<RoleMenuMapper, RoleMenu> implements RoleMenuService {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/RoleServiceImpl.java
New file
@@ -0,0 +1,44 @@
package com.ruoyi.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.admin.entity.Role;
import com.ruoyi.admin.entity.RoleMenu;
import com.ruoyi.admin.mapper.RoleMapper;
import com.ruoyi.admin.request.RoleRequest;
import com.ruoyi.admin.service.RoleMenuService;
import com.ruoyi.admin.service.RoleService;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Resource
    private RoleMenuService roleMenuService;
    @Override
    public boolean saveRoleAndMenu(RoleRequest roleRequest, LoginUser loginUser) {
        Role role = roleRequest.getRole();
        role.setCreateBy(loginUser.getUsername());
        boolean save = this.save(role);
        List<String> menuIds = roleRequest.getMenuIds();
        for (String menuId : menuIds) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(role.getRoleId());
            roleMenu.setMenuId(Long.parseLong(menuId));
            save = save && roleMenuService.save(roleMenu);
        }
        return save;
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/SendSmsServiceImpl.java
@@ -40,8 +40,6 @@
    private String sendPhoneCode(String phone, String redisKey, Integer timeout, TimeUnit timeUnit) {
        // 生成随机 6位数字 验证码
        String phoneCode = RandomUtil.randomNumbers(6);
        // todo 手机验证码暂时 123456
        phoneCode = "123456";
        // 判断redis中是否存在手机验证码
        Object phoneCodeRedis = redisTemplate.opsForValue().get(redisKey + phone);
        if (phoneCodeRedis == null) {
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/SysUserServiceImpl.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.admin.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.admin.entity.SysUser;
import com.ruoyi.admin.mapper.SysUserMapper;
import com.ruoyi.admin.service.SysUserService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Override
    public IPage<SysUser> queryPage(String nickName, String account, String role, Page<Object> page) {
        return baseMapper.queryPage(nickName, account, role, page);
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/UserRoleServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.admin.entity.UserRole;
import com.ruoyi.admin.mapper.UserRoleMapper;
import com.ruoyi.admin.service.UserRoleService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 用户和角色关联表 服务实现类
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Service
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService {
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/service/impl/UserServiceImpl.java
@@ -48,7 +48,7 @@
    @Override
    public Object userDataCount(UserDataCountRequest userDataCountRequest) {
        List<String> cityIdList = userDataCountRequest.getCityIdList();
        List<String> cityList = userDataCountRequest.getCityList();
        List<User> userList = lambdaQuery().eq(User::getIsDelete, 0).list();
        // 用户总量
        Integer userNumber = null == userList ? 0 : userList.size();
@@ -68,25 +68,25 @@
        if (OrderConstants.QUARTER.equals(userDataCountRequest.getCountType())) {
            // 用户增长数
            increaseNumber = lambdaQuery().ge(User::getCreateTime, startDateStr).le(User::getCreateTime, endDateStr)
                    .in(User::getCityId, cityIdList).eq(User::getIsDelete, 0).count();
                    .in(User::getCity, cityList).eq(User::getIsDelete, 0).count();
            // 用户总交易额
            totalMoney = orderService.totalMoneyByQuarter(startDateStr, endDateStr, cityIdList);
            totalMoney = orderService.totalMoneyByQuarter(startDateStr, endDateStr, cityList);
            // 用户提现总额
            withdrawalTotalMoney = withdrawService.withdrawalTotalMoney(cityIdList);
            withdrawalTotalMoney = withdrawService.withdrawalTotalMoney(cityList);
        } else if (OrderConstants.YEAR.equals(userDataCountRequest.getCountType())) {
            // 用户增长数
            increaseNumber = baseMapper.increaseNumberByYear(cityIdList);
            increaseNumber = baseMapper.increaseNumberByYear(cityList);
            // 用户总交易额
            totalMoney = orderService.totalMoneyByYear(cityIdList);
            totalMoney = orderService.totalMoneyByYear(cityList);
            // 用户提现总额
            withdrawalTotalMoney = withdrawService.withdrawalTotalMoneyByYear(cityIdList);
            withdrawalTotalMoney = withdrawService.withdrawalTotalMoneyByYear(cityList);
        } else if (OrderConstants.MONTH.equals(userDataCountRequest.getCountType())) {
            // 用户增长数
            increaseNumber = baseMapper.increaseNumberByMonth(cityIdList);
            increaseNumber = baseMapper.increaseNumberByMonth(cityList);
            // 用户总交易额
            totalMoney = orderService.totalMoneyByMonth(cityIdList);
            totalMoney = orderService.totalMoneyByMonth(cityList);
            // 用户提现总额
            withdrawalTotalMoney = withdrawService.withdrawalTotalMoneyByMonth(cityIdList);
            withdrawalTotalMoney = withdrawService.withdrawalTotalMoneyByMonth(cityList);
        } else {
            // 数量初始化
            increaseNumber = 0L;
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/utils/GeneratorCodeConfig.java
@@ -91,7 +91,7 @@
                            // 开启跳过视图
                            // .enableSkipView()
                            // 增加过滤表前缀
                            .addTablePrefix("ot_", "b_", "iot_", "sys_", "t_")
                            .addTablePrefix("ot_", "b_", "iot_", "t_")
                            // 增加过滤表后缀
                            .addTableSuffix("_n")
                            // 增加过滤字段前缀
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/vo/RecoveryServeResultVO.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.admin.vo;
import com.ruoyi.admin.entity.RecoveryServe;
import com.ruoyi.admin.entity.RecoveryServePrice;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author HJL
 * @version 1.0
 * @since 2024-06-25 16:45
 */
@Data
public class RecoveryServeResultVO {
    @ApiModelProperty("回收服务信息")
    private RecoveryServe recoveryServe;
    @ApiModelProperty("城市及对应回收价")
    private List<RecoveryServePrice> priceList;
    public RecoveryServeResultVO(RecoveryServe recoveryServe, List<RecoveryServePrice> priceList) {
        this.recoveryServe = recoveryServe;
        this.priceList = priceList;
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/vo/RoleDetailVO.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.admin.vo;
import com.ruoyi.admin.entity.Menu;
import com.ruoyi.admin.entity.Role;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author HJL
 * @version 1.0
 * @since 2024-06-25 14:19
 */
@Data
public class RoleDetailVO {
    @ApiModelProperty("角色信息")
    private Role role;
    @ApiModelProperty("角色关联菜单信息")
    private List<Menu> menuList;
    public RoleDetailVO(Role role, List<Menu> menuList) {
        this.role = role;
        this.menuList = menuList;
    }
}
ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/vo/SysUserDetailVO.java
New file
@@ -0,0 +1,32 @@
package com.ruoyi.admin.vo;
import com.ruoyi.admin.entity.Menu;
import com.ruoyi.admin.entity.SysUser;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * <p>
 * 用户信息表
 * </p>
 *
 * @author hjl
 * @since 2024-06-25
 */
@Data
@ApiModel(value = "SysUser对象", description = "用户信息表")
public class SysUserDetailVO {
    @ApiModelProperty("用户ID")
    private SysUser sysUser;
    private List<Menu> menuList;
    public SysUserDetailVO(SysUser sysUser, List<Menu> menuList) {
        this.sysUser = sysUser;
        this.menuList = menuList;
    }
}
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/MenuMapper.xml
New file
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.admin.mapper.MenuMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.admin.entity.Menu">
        <id column="menu_id" property="menuId"/>
        <result column="menu_name" property="menuName"/>
        <result column="parent_id" property="parentId"/>
        <result column="order_num" property="orderNum"/>
        <result column="path" property="path"/>
        <result column="component" property="component"/>
        <result column="query" property="query"/>
        <result column="is_frame" property="isFrame"/>
        <result column="is_cache" property="isCache"/>
        <result column="menu_type" property="menuType"/>
        <result column="visible" property="visible"/>
        <result column="status" property="status"/>
        <result column="perms" property="perms"/>
        <result column="icon" property="icon"/>
        <result column="create_by" property="createBy"/>
        <result column="create_time" property="createTime"/>
        <result column="update_by" property="updateBy"/>
        <result column="update_time" property="updateTime"/>
        <result column="remark" property="remark"/>
    </resultMap>
</mapper>
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RecoveryClassifyMapper.xml
@@ -9,8 +9,8 @@
        <result column="sub_classify" property="subClassify" />
        <result column="home_page_name" property="homePageName" />
        <result column="classification_picture" property="classificationPicture" />
        <result column="describe" property="describe" />
        <result column="order" property="order" />
        <result column="type_describe" property="typeDescribe" />
        <result column="sort" property="sort" />
        <result column="brief_introduction" property="briefIntroduction" />
        <result column="is_recommend" property="isRecommend" />
        <result column="createBy" property="createBy" />
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RecoveryServeMapper.xml
@@ -9,7 +9,7 @@
        <result column="serve_name" property="serveName" />
        <result column="serve_describe" property="serveDescribe" />
        <result column="estimate_price" property="estimatePrice" />
        <result column="order" property="order" />
        <result column="sort" property="sort" />
        <result column="cover" property="cover" />
        <result column="rotate" property="rotate" />
        <result column="createBy" property="createBy" />
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RoleMapper.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.ruoyi.admin.mapper.RoleMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.admin.entity.Role">
        <id column="role_id" property="roleId"/>
        <result column="role_name" property="roleName"/>
        <result column="role_illustrate" property="roleIllustrate"/>
        <result column="role_key" property="roleKey"/>
        <result column="role_sort" property="roleSort"/>
        <result column="data_scope" property="dataScope"/>
        <result column="menu_check_strictly" property="menuCheckStrictly"/>
        <result column="dept_check_strictly" property="deptCheckStrictly"/>
        <result column="status" property="status"/>
        <result column="del_flag" property="delFlag"/>
        <result column="create_by" property="createBy"/>
        <result column="create_time" property="createTime"/>
        <result column="update_by" property="updateBy"/>
        <result column="update_time" property="updateTime"/>
        <result column="remark" property="remark"/>
    </resultMap>
</mapper>
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RoleMenuMapper.xml
New file
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.admin.mapper.RoleMenuMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.admin.entity.RoleMenu">
        <id column="role_id" property="roleId" />
        <id column="menu_id" property="menuId" />
    </resultMap>
</mapper>
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/RotateMapper.xml
@@ -5,7 +5,7 @@
    <resultMap id="BaseResultMap" type="com.ruoyi.admin.entity.Rotate">
        <id column="id" property="id"/>
        <result column="rotate_pricture" property="rotatePicture"/>
        <result column="order" property="order"/>
        <result column="sort" property="sort"/>
        <result column="rotate_serve_id" property="rotateServeId"/>
        <result column="is_rotate" property="isRotate"/>
        <result column="createBy" property="createBy"/>
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/ServeAdvantageMapper.xml
@@ -5,7 +5,7 @@
    <resultMap id="BaseResultMap" type="com.ruoyi.admin.entity.ServeAdvantage">
        <id column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="describe" property="describe"/>
        <result column="describe_detail" property="describeDetail"/>
        <result column="createBy" property="createBy"/>
        <result column="updateBy" property="updateBy"/>
        <result column="createTime" property="createTime"/>
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/SysUserMapper.xml
New file
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.admin.mapper.SysUserMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.admin.entity.SysUser">
        <id column="user_id" property="userId"/>
        <result column="nick_name" property="nickName"/>
        <result column="account" property="account"/>
        <result column="password" property="password"/>
        <result column="is_enable" property="isEnable"/>
        <result column="login_ip" property="loginIp"/>
        <result column="login_date" property="loginDate"/>
        <result column="passWordUpdate" property="passWordUpdate"/>
        <result column="create_by" property="createBy"/>
        <result column="create_time" property="createTime"/>
        <result column="update_by" property="updateBy"/>
        <result column="update_time" property="updateTime"/>
        <result column="is_delete" property="isDelete"/>
        <result column="role_name" property="roleName"/>
        <result column="role_id" property="roleId"/>
    </resultMap>
    <select id="queryPage" resultMap="BaseResultMap">
        select u.*, r.role_name,r.role_id
        from sys_user u
                 left join sys_user_role ur on u.user_id = ur.user_id
                 left join sys_role r on ur.role_id = r.role_id
        <where>
            u.is_delete = 0
            <if test="nickName != null and nickName != ''">
                and u.nick_name like CONCAT('%', #{nickName}, '%')
            </if>
            <if test="account != null and account != ''">
                and u.account like CONCAT('%', #{account}, '%')
            </if>
            <if test="role != null and role != ''">
                and r.role_name like CONCAT('%', #{role}, '%')
            </if>
        </where>
        order by u.create_time desc
    </select>
</mapper>
ruoyi-service/ruoyi-admin/src/main/resources/mapper/admin/UserRoleMapper.xml
New file
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.admin.mapper.UserRoleMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.admin.entity.UserRole">
        <id column="user_id" property="userId"/>
        <id column="role_id" property="roleId"/>
    </resultMap>
</mapper>
ruoyi-service/ruoyi-admin/src/main/resources/template/订单记录.xlsx
Binary files differ
ruoyi-service/ruoyi-user/pom.xml
@@ -21,6 +21,12 @@
    <dependencies>
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-apache-httpclient</artifactId>
            <version>0.4.7</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.3.0</version>
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/entity/RecoveryClassify.java
@@ -44,8 +44,8 @@
    private String classificationPicture;
    @ApiModelProperty("分类描述")
    @TableField("describe")
    private String describe;
    @TableField("type_describe")
    private String typeDescribe;
    @ApiModelProperty("排序权重")
    @TableField("order")
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/service/impl/WithdrawServiceImpl.java
@@ -1,11 +1,14 @@
package com.ruoyi.user.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.admin.api.entity.WithdrawalSetting;
import com.ruoyi.admin.api.feignClient.AdminClient;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.WechatConstants;
import com.ruoyi.common.core.exception.GlobalException;
import com.ruoyi.common.core.utils.SnowflakeIdWorker;
import com.ruoyi.user.entity.Order;
import com.ruoyi.user.entity.RecoveryServe;
import com.ruoyi.user.entity.User;
@@ -18,27 +21,30 @@
import com.ruoyi.user.vo.WithdrawListVO;
import com.ruoyi.user.vo.WithdrawMoneyVO;
import com.ruoyi.user.vo.WithdrawOrderVO;
import com.ruoyi.user.vx.HttpUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
 * <p>
 * 用户提现申请记录表 服务实现类
 * </p>
 *
 * @author hjl
 * @since 2024-06-07
 */
@Service
public class WithdrawServiceImpl extends ServiceImpl<WithdrawMapper, Withdraw> implements WithdrawService {
    /**
     * 雪花算法类
     */
    private static final SnowflakeIdWorker SNOW_FLAKE_ID_WORKER = new SnowflakeIdWorker(5, 5);
    @Resource
    private OrderService orderService;
@@ -48,6 +54,31 @@
    private UserService userService;
    @Resource
    private AdminClient adminClient;
    /**
     * 小程序id
     */
    @Value("wx.appid")
    private String appId;
    /**
     * 转账名称
     */
    @Value("wx.batchName")
    private String batchName;
    /**
     * 商户号
     */
    @Value("wx.mchId")
    private String mchId;
    /**
     * 支付证书序列号
     */
    @Value("wx.wechatPayserialNo")
    private String wechatPayserialNo;
    /**
     * 转账备注
     */
    @Value("wx.transferRemark")
    private String transferRemark;
    @Override
    public WithdrawListVO withdrawList(Integer userid) {
@@ -99,6 +130,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean confirmWithdraw(Integer orderId, Integer userid) {
        User user = userService.lambdaQuery().eq(User::getId, userid).eq(User::getIsDelete, 0).one();
        Order order = orderService.lambdaQuery().eq(Order::getId, orderId).eq(Order::getIsDelete, 0).one();
        if (null == order) {
            throw new GlobalException("订单信息异常!");
@@ -112,13 +144,21 @@
        } else if (stateList.contains(Constants.ONE)) {
            throw new GlobalException("当前订单已提现通过!");
        }
        User user = userService.lambdaQuery().eq(User::getId, userid).eq(User::getIsDelete, 0).one();
        // 系统审核设置
        WithdrawalSetting setting = adminClient.withdrawProcess().getData();
        Withdraw withdraw = new Withdraw();
        // 未开启全局 提现审核,则用户提现不需要后台审核
        if (Constants.ZERO.equals(setting.getEnableProcess())) {
            // 已通过
            withdraw.setState(Constants.ONE);
            // 商家微信打款至微信零钱
            boolean update = weChatPay(order.getOrderMoney(), user.getOpenId());
            if (!update) {
                throw new GlobalException("交易提现失败,请检查是否绑定微信!");
            }
        } else {
            // 待审核
            withdraw.setState(Constants.ZERO);
            // todo 商家微信打款至微信零钱
        }
        withdraw.setUserId(user.getId());
        withdraw.setUserPhone(user.getPhone());
@@ -127,4 +167,66 @@
        withdraw.setOrderId(orderId);
        return this.save(withdraw);
    }
    private boolean weChatPay(BigDecimal orderMoney, String openId) {
        Map<String, Object> postMap = new HashMap<>(8);
        // 小程序 id
        postMap.put(WechatConstants.APP_ID, appId);
        postMap.put(WechatConstants.OUT_BATCH_NO, String.valueOf(UUID.randomUUID()).replaceAll("-", ""));
        // 该笔批量转账的名称
        postMap.put(WechatConstants.BATCH_NAME, batchName);
        // 转账说明,UTF8编码,最多允许32个字符
        postMap.put(WechatConstants.BATCH_REMARK, batchName);
        // 转账金额单位为“分”。 总金额
        postMap.put(WechatConstants.TOTAL_AMOUNT, orderMoney.multiply(new BigDecimal(Constants.ONE_HUNDRED)));
        // 转账总笔数
        postMap.put(WechatConstants.TOTAL_NUM, Constants.ONE);
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> subMap = new HashMap<>(4);
        // 商家明细单号 该商家下唯一
        // subMap.put("out_detail_no", RandomUtil.randomString(32))
        subMap.put(WechatConstants.OUT_DETAIL_NO, SNOW_FLAKE_ID_WORKER.nextId());
        // 转账金额
        subMap.put(WechatConstants.TRANSFER_AMOUNT, orderMoney);
        // 转账备注
        subMap.put(WechatConstants.TRANSFER_REMARK, transferRemark);
        // 用户在直连商户应用下的用户标示
        subMap.put(WechatConstants.OPEN_ID, openId);
        // 大金额需要传入真实姓名
        /*subMap.put("user_name",
        RsaCryptoUtil.encryptOAEP(userName,WechatPayV3Util.getSaveCertificates(privatekeypath)))*/
        list.add(subMap);
        postMap.put(WechatConstants.TRANSFER_DETAIL_LIST, list);
        // 使用类加载器获取资源 URL
        ClassPathResource classPathResource = new ClassPathResource("vx/apiclient_key.pem");
        /*// 获取 resources 目录下的文件路径,假设文件路径为 "resources/data/example.txt"
        String filePath = "resources/data/vx/apiclient_key.pem";
        File file = new File(filePath);
        // 输出文件的绝对路径
        String absolutePath = file.getAbsolutePath();*/
        String result = HttpUtil.postTransBatRequest(
                WechatConstants.WE_CHAT_URL_PRE,
                JSONObject.toJSONString(postMap),
                // 支付证书序列号
                wechatPayserialNo,
                // 商户号
                mchId,
                classPathResource.getPath(), WechatConstants.WE_CHAT_URL_SUF);
        JSONObject jsonObject = JSONObject.parseObject(result);
        /*
         * 成功示例
         * {
         *   "out_batch_no": "plfk2020042013",
         *   "batch_id": "1030000071100999991182020050700019480001",
         *   "create_time": "2015-05-20T13:29:35.120+08:00"
         * }
         */
        if (null == jsonObject || null != jsonObject.get(WechatConstants.CREATE_TIME)) {
            //转账成功
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }
}
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/vo/WechatEntPayForm.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.user.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author HJL
 * @version 1.0
 * @since 2024-06-24 10:11
 */
@Data
public class WechatEntPayForm {
    /**
     * 提现单号
     */
    private String partnerTradeNo;
    /**
     * 用户openId
     */
    private String openId;
    /**
     * 退款金额
     */
    private BigDecimal totalAmount;
    /**
     * 用户名
     */
    private String userName;
    /**
     * app,xcx,gzh
     */
    private String wxType;
}
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/vx/HttpUtil.java
New file
@@ -0,0 +1,195 @@
package com.ruoyi.user.vx;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.WECHAT_PAY_SERIAL;
import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpHeaders.CONTENT_TYPE;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;
/**
 * 微信支付专用类 请求操作方法
 *
 * @author hjl
 */
@Slf4j
public class HttpUtil {
    /**
     * 发起批量转账API 批量转账到零钱
     *
     * @param requestUrl        请求路径
     * @param requestJson       组合参数
     * @param wechatPayserialNo 商户证书序列号
     * @param privatekeypath    商户私钥证书路径
     */
    public static String postTransBatRequest(
            String requestUrl,
            String requestJson,
            String wechatPayserialNo,
            String mchId,
            String privatekeypath, String url) {
        CloseableHttpResponse response;
        HttpEntity entity;
        CloseableHttpClient httpClient = null;
        try {
            HttpPost httpPost = createHttpPost(requestUrl, requestJson, wechatPayserialNo, mchId, privatekeypath, url);
            httpClient = HttpClients.createDefault();
            //发起转账请求
            response = httpClient.execute(httpPost);
            log.info("response:{}", response);
            //获取返回的数据
            entity = response.getEntity();
            log.info("-----getHeaders.Request-ID:" + response.getHeaders("Request-ID"));
            return EntityUtils.toString(entity);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    /**
     * 账单查询
     *
     * @param requestUrl        请求完整地址
     * @param wechatPayserialNo 商户证书序列号
     * @param privatekeypath    商户私钥证书路径
     */
    public static String getTransBatRequest(
            String requestUrl,
            String wechatPayserialNo,
            String mchId,
            String privatekeypath, String url) {
        CloseableHttpResponse response;
        HttpEntity entity;
        CloseableHttpClient httpClient = null;
        try {
            HttpGet httpPost = createHttpGet(requestUrl, wechatPayserialNo, mchId, privatekeypath, url);
            httpClient = HttpClients.createDefault();
            //发起转账请求
            response = httpClient.execute(httpPost);
            log.info("response:{}", response);
            //获取返回的数据
            entity = response.getEntity();
            log.info("-----getHeaders.Request-ID:" + response.getHeaders("Request-ID"));
            return EntityUtils.toString(entity);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    /**
     * @param requestUrl        请求完整地址
     * @param requestJson       请求参数
     * @param wechatPayserialNo 支付证书序列号
     * @param mchId             商户号
     * @param privatekeypath    私钥路径
     * @param servletPath       相对路径
     */
    private static HttpPost createHttpPost(String requestUrl,
                                           String requestJson,
                                           String wechatPayserialNo,
                                           String mchId,
                                           String privatekeypath, String servletPath) {
        //商户私钥证书
        HttpPost httpPost = new HttpPost(requestUrl);
        // NOTE: 建议指定charset=utf-8。低于4.4.6版本的HttpCore,不能正确的设置字符集,可能导致签名错误
        httpPost.addHeader(ACCEPT, APPLICATION_JSON.toString());
        httpPost.addHeader(CONTENT_TYPE, APPLICATION_JSON.toString());
        //"55E551E614BAA5A3EA38AE03849A76D8C7DA735A");
        httpPost.addHeader(WECHAT_PAY_SERIAL, wechatPayserialNo);
        //-------------------------核心认证 start-----------------------------------------------------------------
        String strToken = null;
        try {
            log.info("requestJson:{}", requestJson);
            strToken = WechatPayV3Util.getToken("POST",
                    servletPath,
                    requestJson, mchId, wechatPayserialNo, privatekeypath);
        } catch (Exception e) {
            log.error("createHttpPost error:", e);
            e.printStackTrace();
        }
        StringEntity reqEntity = new StringEntity(requestJson, APPLICATION_JSON);
        log.info("token " + strToken);
        // 添加认证信息
        httpPost.addHeader("Authorization",
                "WECHATPAY2-SHA256-RSA2048" + " "
                        + strToken);
        //---------------------------核心认证 end---------------------------------------------------------------
        httpPost.setEntity(reqEntity);
        return httpPost;
    }
    /**
     * 创建get 请求
     *
     * @param requestUrl        请求完整地址
     * @param wechatPayserialNo 支付证书序列号
     * @param mchId             商户号
     * @param privatekeypath    私钥路径
     * @param servletPath       相对路径  请求地址上如果有参数 则此处需要带上参数
     * @return HttpGet
     */
    private static HttpGet createHttpGet(String requestUrl,
                                         String wechatPayserialNo,
                                         String mchId,
                                         String privatekeypath, String servletPath) {
        //商户私钥证书
        HttpGet httpGet = new HttpGet(requestUrl);
        // NOTE: 建议指定charset=utf-8。低于4.4.6版本的HttpCore,不能正确的设置字符集,可能导致签名错误
        httpGet.addHeader("Content-Type", "application/json");
        httpGet.addHeader("Accept", "application/json");
        //"55E551E614BAA5A3EA38AE03849A76D8C7DA735A");
        httpGet.addHeader("Wechatpay-Serial", wechatPayserialNo);
        //-------------------------核心认证 start-----------------------------------------------------------------
        String strToken = null;
        try {
            strToken = WechatPayV3Util.getToken("GET",
                    servletPath,
                    "", mchId, wechatPayserialNo, privatekeypath);
        } catch (Exception e) {
            log.error("createHttpGet error:", e);
            e.printStackTrace();
        }
        log.info("token " + strToken);
        // 添加认证信息
        httpGet.addHeader("Authorization",
                "WECHATPAY2-SHA256-RSA2048" + " "
                        + strToken);
        //---------------------------核心认证 end---------------------------------------------------------------
        return httpGet;
    }
}
ruoyi-service/ruoyi-user/src/main/java/com/ruoyi/user/vx/WechatPayV3Util.java
New file
@@ -0,0 +1,113 @@
package com.ruoyi.user.vx;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Random;
/**
 * @author HJL
 */
@Slf4j
public class WechatPayV3Util {
    /**
     * @param method       请求方法 post
     * @param canonicalUrl 请求地址
     * @param body         请求参数   GET请求传空字符
     * @param merchantId   这里用的商户号
     * @param certSerialNo 商户证书序列号
     * @param keyPath      私钥商户证书地址
     */
    public static String getToken(
            String method,
            String canonicalUrl,
            String body,
            String merchantId,
            String certSerialNo,
            String keyPath) throws Exception {
        String signStr;
        //获取32位随机字符串
        String nonceStr = getRandomString(32);
        //当前系统运行时间
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, canonicalUrl, timestamp, nonceStr, body);
        //签名操作
        //签名操作
        String signature = sign(message.getBytes(StandardCharsets.UTF_8), keyPath);
        //组装参数
        signStr = "mchid=\"" + merchantId + "\"," +
                "timestamp=\"" + timestamp + "\"," +
                "nonce_str=\"" + nonceStr + "\"," +
                "serial_no=\"" + certSerialNo + "\"," +
                "signature=\"" + signature + "\"";
        return signStr;
    }
    public static String buildMessage(String method, String canonicalUrl, long timestamp, String nonceStr, String body) {
//        String canonicalUrl = url.encodedPath();
//        if (url.encodedQuery() != null) {
//            canonicalUrl += "?" + url.encodedQuery();
//        }
        return method + "\n" + canonicalUrl + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
    }
    public static String sign(byte[] message, String keyPath) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(getPrivateKey(keyPath));
        sign.update(message);
        return Base64.encodeBase64String(sign.sign());
    }
    /**
     * 微信支付-前端唤起支付参数-获取商户私钥
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {
        log.info("签名 证书地址是 " + filename);
        String content = new String(Files.readAllBytes(Paths.get(filename)), StandardCharsets.UTF_8);
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }
    /**
     * 获取随机位数的字符串
     *
     * @param length 需要的长度
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}
ruoyi-service/ruoyi-user/src/main/resources/mapper/user/RecoveryClassifyMapper.xml
@@ -9,7 +9,7 @@
        <result column="sub_classify" property="subClassify" />
        <result column="home_page_name" property="homePageName" />
        <result column="classification_picture" property="classificationPicture" />
        <result column="describe" property="describe" />
        <result column="type_describe" property="typeDescribe" />
        <result column="order" property="order" />
        <result column="brief_introduction" property="briefIntroduction" />
        <result column="is_recommend" property="isRecommend" />
ruoyi-service/ruoyi-user/src/main/resources/vx/apiclient_cert.p12
Binary files differ
ruoyi-service/ruoyi-user/src/main/resources/vx/apiclient_cert.pem
New file
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEMTCCAxmgAwIBAgIUfuoEQpsAbhKqpCHAAuxIu+7VvpQwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjQwNjIwMDY1MzMyWhcNMjkwNjE5MDY1MzMyWjCBijETMBEGA1UEAwwK
MTY2NTMzMDQxNzEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTYwNAYDVQQL
DC3mrabmsYnluILlpb3ov5DlkIjnm5vmkKzov4Hlt6XnqIvmnInpmZDlhazlj7gx
CzAJBgNVBAYTAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMLqFYQnJ7S2ReDfU7FqeYnh3LDQq1F0K00aUYLR0uy3
sc83rAUanlJHd48odNKgDc6k7oKuUzgs8y9v5i52ZZCg6LSWrZLnRtPV2qjqRvqY
ZhasFjqsH/ZCbsHuEvJw34gIUXl3FDPkTW7wThCe8BEqz9rywlKOSGMHZKR5pHTQ
AtjA4JG3SgV7qCiMtsdpCn8hzsUIflIjg16Qw8j4lav149oHMIp9ZWk6Vuz5oYZf
X/yqD8OsWz6CG1KmU0n8W7ObfYRNUKhBbZq3msLFscr9a2cxO008h4SzSRwleEQT
EL711OZyQgy9moBpkyLIEoQp3Wy6NaEvZ9LOBj0wQT8CAwEAAaOBuTCBtjAJBgNV
HRMEAjAAMAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0
cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIw
RTUwREJDMDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0
MjJFMTJCMjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUA
A4IBAQBTHQhhakcZyah8zTsODzmHS2xq4AiMiSpYyfEe4rTuLZPFj17vZQ4CMjnM
LXT30uyjPqGCrY8IRajRVCG9DATXX8vKpYk3/LRlM8o0ApBxwpf/g1H2VbO17l0E
V4CJBbOoi9QA7itMQnJa5PXzrOHlq2G65Q6LAQQTbIzF9TmkxkSIqVbzrKtnbQmL
dejQxS0ZfKCxA5nuyxmelmidu6VNFzFwV4W/4ToyuXy7gxpBYekhK4SmxQiAa6lU
49UamtQDHz8WJFwjmvnmVc0h44TjCTl8EsUI2j+pWzDwvcNNz2kYg+chqUYHHmvn
3s+QkMmYLq/LeNi7GF4M2CFpZu1T
-----END CERTIFICATE-----
ruoyi-service/ruoyi-user/src/main/resources/vx/apiclient_key.pem
New file
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDC6hWEJye0tkXg
31OxanmJ4dyw0KtRdCtNGlGC0dLst7HPN6wFGp5SR3ePKHTSoA3OpO6CrlM4LPMv
b+YudmWQoOi0lq2S50bT1dqo6kb6mGYWrBY6rB/2Qm7B7hLycN+ICFF5dxQz5E1u
8E4QnvARKs/a8sJSjkhjB2SkeaR00ALYwOCRt0oFe6gojLbHaQp/Ic7FCH5SI4Ne
kMPI+JWr9ePaBzCKfWVpOlbs+aGGX1/8qg/DrFs+ghtSplNJ/Fuzm32ETVCoQW2a
t5rCxbHK/WtnMTtNPIeEs0kcJXhEExC+9dTmckIMvZqAaZMiyBKEKd1sujWhL2fS
zgY9MEE/AgMBAAECggEARQazEfbv186JFqbgM79aRVsoVbHASftS7l44qZR3Fv/C
x3iWwcP4d3j5vUf9fy3RVfIQyVTFAerhQFZndOLW+w4Q+ws1cwXWjmR4qEM3Wb2o
wbS1tpeIRiSmpqUSLquMbddMSzDBhdL/HR+a9cXjjKDVtVstOCFNP0y59olhlUAK
czDmuhDTTD0lVCcqI/+xc+xeY2rrbYpWVJYTtjH3g5R8oELjvJYARgRb6SAjz58a
q/4iL5g3B903d3p8XPDdGgyd4xhR0Aaf/rTUYpehUjdoEHkovUVefbrB+xKsIxll
xax3IdQJq6UvAiskflHTwLsu2Now/xXPEM6TRJC+aQKBgQDv8tvDhECqhcsEcj9/
PyyJtfeSEbNTGs3dZqzz3ZN5BKt2FNuCkfQm8UYddVdkODSP7OU0pkVL5A/flNP/
KTmrHl/81riYdqujwV3UYhKbIBFfgumy8lFHy6u5rrYdaCdGciKNg6xKbiD6wexd
G2gWAx+Id2QmYPArVwYhu9TFAwKBgQDP9AJ/tQRhFAIdBN1EpTFE84A5ovA7rd4j
Me/21MDlwAgOyrlidr8gzBA4TcYIfs+2B3zIWC2YxEc+uRcU5exDG++2/nO9ftMm
Nlkn/YmxcfcQAd75mPZvqLDpAXEsLogI1FyhDBAg/ICk6dM6cmLuPGDHvP5Ttl8i
SoB4oNwIFQKBgDkelgQgCojNWrvPOqBe+Io7wBiMkCS7X8BRveA7oeyQGQT+CBc4
CWfvzaIbmdcorhKI8TMsVZiwTLsLob+/H5RFodH9h2n77fYIhP6W7hjxdFFJR7qq
hoDR0ipclcvATIEvkFwhuTTqrH0lBtBPQuLikXIaAcRFFUcr6zDClu7jAoGBAInj
gsSrgvvcCIq1bwLVhpXx4FRXdnQcFe/AbR1+dWniq3Ujd0mS86kLprWu3GFFtPU+
gb9WuOVTQOqWUHfK/Z6CJ7Fvh89fCSONZhDeTS8cIna6xt86Ti477RKTojdpo0o3
hjRDi25T//laEnXu4yqVXpcS+pEHnI1gWU+jWkMBAoGBAMVzBi/05H8+zusudGMR
UWZaVQ0bLtH1ePF7dgDxiEXeAg7Xp2LWxH4jABSwIhyAMApucZKOXPILwPNQBW47
zUFB21xK39mFvZOe8UKxLtGKnrNlGtVFWvnJrKPQd+c4r2eCpXUk0QHr1SoNekVq
VNSUH+BwA3mGKhUqbJquhQZn
-----END PRIVATE KEY-----
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/controller/MasterWorkerController.java
@@ -113,15 +113,11 @@
    @PostMapping(value = "/phoneCodeLogin")
    public R<Object> phoneCodeLogin(@RequestBody @Validated LoginPhoneRequest loginPhoneRequest) {
        String phone = loginPhoneRequest.getPhone();
        MasterWorker worker = masterWorkerService.lambdaQuery().eq(MasterWorker::getPhone, phone)
                .eq(MasterWorker::getIsDelete, 0).one();
        if (null != worker) {
            if (!Constants.ONE.equals(worker.getIsEnable())) {
                return R.notEnabled("登录失败,当前账号未启用!");
            }
            String phoneCode = loginPhoneRequest.getPhoneCode();
            // 获取缓存验证码
            Object phoneCodeRedis = redisService.getCacheObject(RedisConstants.USER_LOGIN_PHONE_CODE + phone);
        String phoneCode = loginPhoneRequest.getPhoneCode();
        // 默认验证码 123456
        if (!"123456".equals(phoneCode)) {
            // 手机验证码校验获取缓存验证码
            Object phoneCodeRedis = redisService.getCacheObject(RedisConstants.WORKER_APPLY_KEY + phone);
            if (null == phoneCodeRedis) {
                return R.errorCode("登录失败,验证码已过期!");
            } else {
@@ -132,8 +128,15 @@
                    return R.errorCode("登录失败,验证码无效!");
                }
            }
        }
        MasterWorker worker = masterWorkerService.lambdaQuery().eq(MasterWorker::getPhone, phone)
                .eq(MasterWorker::getIsDelete, 0).one();
        if (null != worker) {
            if (!Constants.ONE.equals(worker.getIsEnable())) {
                return R.notEnabled("登录失败,当前账号未启用!");
            }
        } else {
            return R.unregistered("当前手机号未注册!");
            return R.unregistered("当前手机号通过入驻申请认证!");
        }
        // 校验通过,生成token及过期时间
        return R.ok(generateLoginToken(worker));
@@ -277,7 +280,8 @@
        OrderCountVO orderCount = masterWorkerService.orderCount(masterWorker.getId());
        // 操作指导详情
        Agreement agreement = adminClient.dataInfo(Constants.TWO).getData();
        return R.ok(new HomePageInfoVO(masterWorker, orderCount, agreement.getContent()));
        return R.ok(new HomePageInfoVO(masterWorker, orderCount,
                null == agreement ? null : agreement.getContent()));
    }
    /**
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/controller/OrderController.java
@@ -8,7 +8,6 @@
import com.ruoyi.common.core.exception.GlobalException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.api.model.LoginUserInfo;
import com.ruoyi.worker.entity.Evaluate;
import com.ruoyi.worker.entity.MasterWorker;
@@ -116,6 +115,38 @@
     *
     * @param orderId 订单id
     */
    @ApiOperation(value = "订单路线导航", tags = {"师傅端-首页"})
    @GetMapping(value = "/orderNavigation")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "订单id", name = "orderId", dataType = "Integer", required = true),
            @ApiImplicitParam(value = "师傅所在经度", name = "longitude", dataType = "String", required = true),
            @ApiImplicitParam(value = "师傅所在纬度", name = "latitude", dataType = "String", required = true)
    })
    public R<Object> orderNavigation(@RequestParam Integer orderId, @RequestParam String longitude,
                                     @RequestParam String latitude) {
        LoginUserInfo loginWorker = tokenService.getLoginUserByWorker();
        if (null == loginWorker) {
            return R.loginExpire("登录失效!");
        }
        Order order = orderService.lambdaQuery().eq(Order::getId, orderId).eq(Order::getServerId, loginWorker.getUserid())
                .eq(Order::getIsDelete, 0).one();
        if (null == order) {
            throw new GlobalException("请确认当前订单所派单师傅是否是您!");
        }
        // 用户下单经纬度
        Double userLongitude = order.getLongitude();
        Double userLatitude = order.getLatitude();
        String userPosition = userLongitude + "," + userLatitude;
        // 师傅当前位置 经纬度
        String workerPosition = longitude + "," + latitude;
        return R.ok(orderService.orderNavigation(userPosition, workerPosition));
    }
    /**
     * 师傅端-已到达预约地点
     *
     * @param orderId 订单id
     */
    @ApiOperation(value = "已到达预约地点", tags = {"师傅端-订单列表"})
    @GetMapping(value = "/reachPosition")
    @ApiImplicitParams({
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/entity/RecoveryClassify.java
@@ -24,7 +24,7 @@
@ApiModel(value = "RecoveryClassify对象", description = "回收分类表")
public class RecoveryClassify extends BaseEntity {
    @TableId(value = "id",type = IdType.AUTO)
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("上级分类名称")
@@ -44,12 +44,12 @@
    private String classificationPicture;
    @ApiModelProperty("分类描述")
    @TableField("describe")
    private String describe;
    @TableField("type_describe")
    private String typeDescribe;
    @ApiModelProperty("排序权重")
    @TableField("order")
    private Integer order;
    @TableField("sort")
    private Integer sort;
    @ApiModelProperty("分类简介")
    @TableField("brief_introduction")
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/MasterWorkerService.java
@@ -35,4 +35,5 @@
     * @return 代办列表
     */
    List<OrderListVO> orderNotHandle(Integer userid, String longitude, String latitude);
}
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/OrderService.java
@@ -24,4 +24,12 @@
     */
    List<Order> orderList(Integer userid, Integer state);
    /**
     * 到订单去,路线规划
     *
     * @param userPosition   用户下单经纬度信息
     * @param workerPosition 师傅所在经纬度信息
     * @return 路线规划
     */
    Object orderNavigation(String userPosition, String workerPosition);
}
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/impl/MasterWorkerServiceImpl.java
@@ -4,7 +4,6 @@
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.common.core.utils.GaoDeMapUtil;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.worker.entity.MasterWorker;
import com.ruoyi.worker.entity.Order;
import com.ruoyi.worker.entity.RecoveryServe;
@@ -58,9 +57,35 @@
            // 根据经纬度计算与师傅的距离
            Result<Long> result = GaoDeMapUtil.getDistance(orderPosition, longitude + "," + latitude);
            Long distance = result.getDatas();
            // 回收服务信息
            RecoveryServe recoveryServe = recoveryServeService.lambdaQuery().eq(RecoveryServe::getId, order.getServeId())
                    .eq(RecoveryServe::getIsDelete, 0).one();
            // vo类信息封装
            OrderListVO orderListVO = new OrderListVO(order.getServeId());
            BeanUtils.copyProperties(orderListVO, orderListVO);
            orderListVO.setOrderId(order.getId());
            orderListVO.setOrderNumber(order.getOrderNumber());
            orderListVO.setSiteId(order.getSiteId());
            orderListVO.setSiteName(order.getSiteName());
            orderListVO.setServeId(order.getServeId());
            orderListVO.setServeName(order.getServeName());
            orderListVO.setServePicture(recoveryServe.getCover());
            orderListVO.setServePrice(recoveryServe.getDefaultPrice());
            orderListVO.setUserId(userid);
            orderListVO.setReservationName(order.getReservationName());
            orderListVO.setReservationPhone(order.getReservationPhone());
            orderListVO.setReservationAddress(order.getReservationAddress());
            orderListVO.setTime(order.getTime());
            orderListVO.setServerId(order.getServerId());
            orderListVO.setServerName(order.getServerName());
            orderListVO.setServerPhone(order.getServerPhone());
            orderListVO.setReservationRemark(order.getReservationRemark());
            orderListVO.setOrderMoney(order.getOrderMoney());
            orderListVO.setState(order.getState());
            orderListVO.setAcceptTime(order.getAcceptTime());
            orderListVO.setArriveTime(order.getArriveTime());
            orderListVO.setType(order.getType());
            orderListVO.setLongitude(order.getLongitude());
            orderListVO.setLatitude(order.getLatitude());
            OrderNotHandleVO vo = new OrderNotHandleVO(distance, orderListVO);
            list.add(vo);
        }
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/service/impl/OrderServiceImpl.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.utils.GaoDeMapUtil;
import com.ruoyi.worker.entity.Order;
import com.ruoyi.worker.mapper.OrderMapper;
import com.ruoyi.worker.service.OrderService;
@@ -37,4 +38,9 @@
        }
        return wrapper.list();
    }
    @Override
    public Object orderNavigation(String userPosition, String workerPosition) {
        return GaoDeMapUtil.routing(userPosition, workerPosition);
    }
}
ruoyi-service/ruoyi-worker/src/main/java/com/ruoyi/worker/vo/OrderListVO.java
@@ -81,10 +81,10 @@
    private Integer type;
    @ApiModelProperty("下单用户经度")
    private Integer longitude;
    private Double longitude;
    @ApiModelProperty("下单用户纬度")
    private Integer latitude;
    private Double latitude;
    public OrderListVO(Integer orderId) {
        this.orderId = orderId;
ruoyi-service/ruoyi-worker/src/main/resources/mapper/worker/RecoveryClassifyMapper.xml
@@ -9,8 +9,8 @@
        <result column="sub_classify" property="subClassify" />
        <result column="home_page_name" property="homePageName" />
        <result column="classification_picture" property="classificationPicture" />
        <result column="describe" property="describe" />
        <result column="order" property="order" />
        <result column="type_describe" property="typeDescribe" />
        <result column="sort" property="sort" />
        <result column="brief_introduction" property="briefIntroduction" />
        <result column="is_recommend" property="isRecommend" />
        <result column="createBy" property="createBy" />