rk
12 小时以前 095210f9149c73e6e00d997b39fd6c44a65e4d38
代码生成
已添加10个文件
已修改31个文件
1303 ■■■■ 文件已修改
server/.claude/settings.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/java/com/doumee/api/business/DriverInfoController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/java/com/doumee/api/business/MemberController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/java/com/doumee/api/business/PrinterInfoController.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/java/com/doumee/api/business/ShopInfoController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/db/db_change.sql 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/config/alipay/AlipayFundTransUniTransfer.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/config/jwt/WebMvcConfig.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/constants/Constants.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/utils/aliyun/AliSmsService.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/utils/xpyun/XpyunPrintService.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/utils/xpyun/XpyunResponse.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/PrinterInfoMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/AppVersion.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/Category.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/DriverInfo.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/Orders.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/PrinterInfo.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/ShopInfo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/dto/ChangePasswordDTO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/dto/PrinterBindDTO.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/dto/WithdrawalDTO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/DriverCenterVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/AreasService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/PrinterInfoService.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/ShopInfoService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/AppVersionServiceImpl.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/AreasServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java 152 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/PrinterInfoServiceImpl.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java 94 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/SmsrecordServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/ConfigApi.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/DriverInfoApi.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/PaymentCallback.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/ShopInfoApi.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/.claude/settings.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
{
  "permissions": {
    "allow": [
      "WebSearch"
    ],
    "additionalDirectories": [
      "d:\\DouMee\\javaCodeGit\\gtzxinglijicun\\server\\services\\src\\main\\java\\com\\doumee\\core\\utils"
    ]
  }
}
server/admin/src/main/java/com/doumee/api/business/DriverInfoController.java
@@ -109,9 +109,9 @@
    }
    @ApiOperation("修改司机状态")
    @PostMapping("/changeStatus")
    @PostMapping("/updateStatus")
    @RequiresPermissions("business:driverInfo:update")
    public ApiResponse changeStatus(@RequestBody ChangeStatusDTO dto) {
    public ApiResponse updateStatus(@RequestBody ChangeStatusDTO dto) {
        driverInfoService.changeStatus(dto);
        return ApiResponse.success("操作成功");
    }
server/admin/src/main/java/com/doumee/api/business/MemberController.java
@@ -8,6 +8,7 @@
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.dto.ChangeStatusDTO;
import com.doumee.dao.dto.MemberListQueryDTO;
import com.doumee.dao.vo.MemberDetailVO;
import com.doumee.dao.vo.MemberListVO;
@@ -118,4 +119,18 @@
    public ApiResponse<MemberDetailVO> findMemberDetail(@PathVariable Integer id) {
        return ApiResponse.success(memberService.findMemberDetail(id));
    }
    @ApiOperation("修改会员状态")
    @PostMapping("/updateStatus")
    @RequiresPermissions("business:member:update")
    public ApiResponse updateStatus(@RequestBody ChangeStatusDTO dto) {
        if (dto.getId() == null || dto.getStatus() == null || (dto.getStatus() != 0 && dto.getStatus() != 1)) {
            return ApiResponse.failed("参数错误,状态:0=启用;1=禁用");
        }
        Member member = new Member();
        member.setId(dto.getId());
        member.setStatus(dto.getStatus());
        memberService.updateById(member);
        return ApiResponse.success("操作成功");
    }
}
server/admin/src/main/java/com/doumee/api/business/PrinterInfoController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.doumee.api.business;
import com.doumee.api.BaseController;
import com.doumee.core.annotation.pr.PreventRepeat;
import com.doumee.core.model.ApiResponse;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.PrinterInfo;
import com.doumee.service.business.PrinterInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
 * æ‰“印机信息
 * @author rk
 * @date 2026/04/28
 */
@Api(tags = "打印机信息")
@RestController
@RequestMapping("/business/printerInfo")
public class PrinterInfoController extends BaseController {
    @Autowired
    private PrinterInfoService printerInfoService;
    @PreventRepeat
    @ApiOperation("新建")
    @PostMapping("/create")
    @RequiresPermissions("business:printerInfo:create")
    public ApiResponse create(@RequestBody PrinterInfo printerInfo) {
        printerInfo.setCreateUser(this.getLoginUser().getId());
        return ApiResponse.success(printerInfoService.create(printerInfo));
    }
    @ApiOperation("删除")
    @GetMapping("/delete/{id}")
    @RequiresPermissions("business:printerInfo:delete")
    public ApiResponse deleteById(@PathVariable Integer id) {
        printerInfoService.deleteById(id);
        return ApiResponse.success(null);
    }
    @ApiOperation("批量删除")
    @GetMapping("/delete/batch")
    @RequiresPermissions("business:printerInfo:delete")
    public ApiResponse deleteByIdInBatch(@RequestParam String ids) {
        String[] idArray = ids.split(",");
        List<Integer> idList = new ArrayList<>();
        for (String id : idArray) {
            idList.add(Integer.valueOf(id));
        }
        printerInfoService.deleteByIdInBatch(idList);
        return ApiResponse.success(null);
    }
    @ApiOperation("修改")
    @PostMapping("/updateById")
    @RequiresPermissions("business:printerInfo:update")
    public ApiResponse updateById(@RequestBody PrinterInfo printerInfo) {
        printerInfo.setUpdateUser(this.getLoginUser().getId());
        printerInfoService.updateById(printerInfo);
        return ApiResponse.success(null);
    }
    @ApiOperation("分页查询")
    @PostMapping("/page")
    @RequiresPermissions("business:printerInfo:query")
    public ApiResponse<PageData<PrinterInfo>> findPage(@RequestBody PageWrap<PrinterInfo> pageWrap) {
        return ApiResponse.success(printerInfoService.findPage(pageWrap));
    }
    @ApiOperation("根据ID查询")
    @GetMapping("/{id}")
    @RequiresPermissions("business:printerInfo:query")
    public ApiResponse findById(@PathVariable Integer id) {
        return ApiResponse.success(printerInfoService.findById(id));
    }
}
server/admin/src/main/java/com/doumee/api/business/ShopInfoController.java
@@ -9,6 +9,7 @@
import com.doumee.dao.business.model.ShopInfo;
import com.doumee.dao.dto.AuditDTO;
import com.doumee.dao.dto.ChangeStatusDTO;
import com.doumee.dao.dto.PrinterBindDTO;
import com.doumee.dao.dto.ResetPasswordDTO;
import com.doumee.dao.dto.ShopUpdateDTO;
import com.doumee.dao.vo.ShopDetailVO;
@@ -135,4 +136,27 @@
        return ApiResponse.success("修改成功");
    }
    @ApiOperation("绑定打印机")
    @PostMapping("/bindPrinter")
    @RequiresPermissions("business:shopInfo:update")
    public ApiResponse bindPrinter(@RequestBody @javax.validation.Valid PrinterBindDTO dto) {
        shopInfoService.bindPrinter(dto);
        return ApiResponse.success("绑定成功");
    }
    @ApiOperation("解绑打印机")
    @PostMapping("/unbindPrinter/{shopId}")
    @RequiresPermissions("business:shopInfo:update")
    public ApiResponse unbindPrinter(@PathVariable Integer shopId) {
        shopInfoService.unbindPrinter(shopId);
        return ApiResponse.success("解绑成功");
    }
    @ApiOperation("查询打印机状态")
    @GetMapping("/printerStatus/{shopId}")
    @RequiresPermissions("business:shopInfo:query")
    public ApiResponse queryPrinterStatus(@PathVariable Integer shopId) {
        return ApiResponse.success(shopInfoService.queryPrinterStatus(shopId));
    }
}
server/services/db/db_change.sql
@@ -5,6 +5,37 @@
-- ============================================================
-- 2026/04/28 APP版本文件路径字典
-- ============================================================
INSERT INTO `system_dict_data` (`DICT_ID`, `CODE`, `LABEL`, `REMARK`, `SORT`, `DISABLED`, `CREATE_USER`, `CREATE_TIME`, `DELETED`) VALUES ((SELECT `id` FROM `system_dict` WHERE `code` = 'OSS'), '', 'APP_FILES', 'APP版本文件路径', 0, 0, 1, NOW(), 0);
-- ============================================================
-- 2026/04/28 æ‰“印机信息表 + æƒé™
-- ============================================================
INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:printerInfo:create', '新建打印机', '打印机信息', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0);
INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:printerInfo:delete', '删除打印机', '打印机信息', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0);
INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:printerInfo:update', '修改打印机', '打印机信息', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0);
INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:printerInfo:query', '查询打印机', '打印机信息', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0);
-- ============================================================
-- 2026/04/28 èŠ¯çƒ¨äº‘æ‰“å°æœºé›†æˆï¼šé—¨åº—è¡¨å¢žåŠ æ‰“å°æœºSN字段
-- ============================================================
ALTER TABLE `shop_info` ADD COLUMN `PRINTER_SN` VARCHAR(64) DEFAULT NULL COMMENT '芯烨云打印机SN编号' AFTER `BUSINESS_TYPE`;
-- ============================================================
-- 2026/04/28 èŠ¯çƒ¨äº‘æ‰“å°æœºé…ç½®å­—å…¸ï¼ˆè´¦å·ä¿¡æ¯åŽç»­æ‰‹åŠ¨ç»´æŠ¤CODE值)
-- ============================================================
INSERT INTO `system_dict` (`id`, `code`, `name`, `disabled`, `deleted`) VALUES (106, 'XPYUN_CONFIG', '芯烨云配置', 0, 0);
INSERT INTO `system_dict_data` (`DICT_ID`, `CODE`, `LABEL`, `REMARK`, `SORT`, `DISABLED`, `CREATE_USER`, `CREATE_TIME`, `DELETED`) VALUES (106, '', 'XPYUN_USER', '芯烨云开发者ID', 0, 0, 1, NOW(), 0);
INSERT INTO `system_dict_data` (`DICT_ID`, `CODE`, `LABEL`, `REMARK`, `SORT`, `DISABLED`, `CREATE_USER`, `CREATE_TIME`, `DELETED`) VALUES (106, '', 'XPYUN_USER_KEY', '芯烨云开发者密钥', 1, 0, 1, NOW(), 0);
-- ============================================================
-- 2026/04/22 è®¢å•退款表新增退款前订单状态字段
-- ============================================================
ALTER TABLE `orders_refund` ADD COLUMN `BEFORE_STATUS` INT NULL DEFAULT NULL COMMENT '退款前订单状态' AFTER `STATUS`;
server/services/src/main/java/com/doumee/config/alipay/AlipayFundTransUniTransfer.java
@@ -75,10 +75,10 @@
        // è®¾ç½®å•†å®¶ä¾§å”¯ä¸€è®¢å•号
        data.setOutBizNo(dto.getOutBizNo());
        // è®¾ç½®è®¢å•总金额
        data.setTransAmount("1");
        data.setTransAmount("0.1");
        // è®¾ç½®æè¿°ç‰¹å®šçš„业务场景
        data.setOutBizNo(dto.getOutBizNo());
        data.setTransAmount(dto.getTransAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
//        data.setTransAmount(dto.getTransAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
        data.setBizScene("DIRECT_TRANSFER");
        // è®¾ç½®ä¸šåŠ¡äº§å“ç 
        data.setProductCode("TRANS_ACCOUNT_NO_PWD");
server/services/src/main/java/com/doumee/config/jwt/WebMvcConfig.java
@@ -171,10 +171,6 @@
            if(isForbidden == Constants.ONE){
                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"商户已禁用,请联系管理员");
            }
            String dbOpenid = dao.queryForObject(" select ifnull(openid,'')  from shop_info where id  = ?", String.class, shopId);
            if(StringUtils.isBlank(dbOpenid)||!openid.equals(dbOpenid)){
                throw new BusinessException(ResponseStatus.SHOP_TOKEN_EXCEED_TIME);
            }
            Integer count = dao.queryForObject("select count(1) from shop_info where id  = ?", Integer.class, shopId);
            if (count != null && count > 0) {
                request.setAttribute(JwtTokenUtil.SHOP_ID, shop.getId());
server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java
@@ -59,7 +59,7 @@
            com.wechat.pay.java.service.payments.jsapi.model.Amount amount =
                    new com.wechat.pay.java.service.payments.jsapi.model.Amount();
            amount.setTotal(1);//totalCents.intValue());
            amount.setTotal(totalCents.intValue());
            amount.setCurrency("CNY");
            request.setAmount(amount);
@@ -109,8 +109,8 @@
            request.setNotifyUrl(notifyUrl);
            AmountReq amount = new AmountReq();
            amount.setRefund(1L);//refundCents);
            amount.setTotal(1L);//totalCents);
            amount.setRefund(refundCents);
            amount.setTotal(totalCents);
            amount.setCurrency("CNY");
            request.setAmount(amount);
server/services/src/main/java/com/doumee/core/constants/Constants.java
@@ -88,6 +88,7 @@
    public static final String DRIVER_FILES = "DRIVER_FILES";
    public static final String BANNER_FILES = "BANNER_FILES";
    public static final String ORDERS_FILES = "ORDERS_FILES";
    public static final String APP_FILES = "APP_FILES";
    // è¿è¥é…ç½®
    public static final String OPERATION_CONFIG = "OPERATION_CONFIG";
@@ -102,6 +103,12 @@
    public static final String OP_NO_GRAB_NOTIFY_TIME = "NO_GRAB_NOTIFY_TIME";
    public static final String OP_NO_GRAB_NOTIFY_USERS = "NO_GRAB_NOTIFY_USERS";
    public static final String OP_DEFAULT_DELIVERY_RANGE = "DEFAULT_DELIVERY_RANGE";
    // èŠ¯çƒ¨äº‘æ‰“å°æœºé…ç½®
    public static final String XPYUN_CONFIG = "XPYUN_CONFIG";
    public static final String XPYUN_USER = "XPYUN_USER";
    public static final String XPYUN_USER_KEY = "XPYUN_USER_KEY";
    public static boolean WORKORDER_SHE_EMAIL_SENDING = false;
    public static  boolean DEALING_COMPANY_SYNC = false ;
    public static  boolean DEALING_MEMBER_SYNC = false ;
@@ -431,7 +438,7 @@
        waitPay(0, "待支付", new int[]{OrderStatus.waitPay.status}),
        waitDeposit(1, "待核验", new int[]{OrderStatus.waitDeposit.status}),
        waitDeliver(2, "待配送", new int[]{OrderStatus.accepted.status}),
        waitReceive(3, "待收货", new int[]{ OrderStatus.delivering.status, OrderStatus.arrived.status}),
        waitReceive(3, "待收货", new int[]{  OrderStatus.arrived.status}),
        finished(4, "已完成", new int[]{OrderStatus.finished.status}),
        refund(5, "取消", new int[]{OrderStatus.cancelled.status}),
        home(6, "首页查询", new int[]{OrderStatus.waitPay.status, OrderStatus.waitDeposit.status, OrderStatus.deposited.status
@@ -603,22 +610,22 @@
    @Getter
    @AllArgsConstructor
    public enum SmsNotify {
        PLATFORM_WAIT_GRAB("SMS_505790009", "平台端-待抢单", "您好,订单:{orderNo}已超过{time}分钟无司机抢单,请尽快加急派单,避免客户过久等待。"),
        SHOP_REFUNDING("SMS_505900008", "门店端-退款中", "行李订单:{orderNo}客户已提交退款申请,请尽快处理。"),
        SHOP_WAIT_VERIFY("SMS_505925004", "门店端-待核验", "新行李订单:{orderNo}客户已支付,请尽快核验用户物品信息。"),
        DRIVER_REFUNDING("SMS_505795005", "司机端-退款中", "行李订单:{orderNo}用户已提交退款申请,该订单任务已取消,请勿前往。"),
        DRIVER_WAIT_PICKUP("SMS_505650038", "司机端-待取件", "您已抢单成功,订单{orderNo},请按时到{address}取件。"),
        MEMBER_CANCELLED("SMS_505605028", "会员端-已取消", "您的行李订单:{orderNo}已取消,感谢您的支持,欢迎下次再会。"),
        MEMBER_REFUNDED("SMS_505920002", "会员端-已退款", "您的行李订单:{orderNo}退款已完成,金额{money}元将原路退回,请注意查收。"),
        MEMBER_ARRIVED("SMS_505875004", "会员端-已送达", "您的行李订单:{orderNo}已送到{address},请及时取件,取件码:{code}。"),
        MEMBER_DELIVERING("SMS_505935002", "会员端-配送中", "您的行李订单:{orderNo}已由司机{name}取件,正运往目的地。"),
        PLATFORM_WAIT_GRAB("SMS_505865290", "平台端-待抢单", "您好,订单:{orderNo}已超过{time}分钟无司机抢单,请尽快加急派单,避免客户过久等待。"),
        SHOP_REFUNDING("SMS_505905263", "门店端-退款中", "行李订单:{orderNo}客户已提交退款申请,请尽快处理。"),
        SHOP_WAIT_VERIFY("SMS_505915292", "门店端-待核验", "新行李订单:{orderNo}客户已支付,请尽快核验用户物品信息。"),
        DRIVER_REFUNDING("SMS_505905264", "司机端-退款中", "行李订单:{orderNo}用户已提交退款申请,该订单任务已取消,请勿前往。"),
        DRIVER_WAIT_PICKUP("SMS_505960277", "司机端-待取件", "您已抢单成功,订单{orderNo},请按时到{address}取件。"),
        MEMBER_CANCELLED("SMS_505615328", "会员端-已取消", "您的行李订单:{orderNo}已取消,感谢您的支持,欢迎下次再会。"),
        MEMBER_REFUNDED("SMS_505850299", "会员端-已退款", "您的行李订单:{orderNo}退款已完成,金额{money}元将原路退回,请注意查收。"),
        MEMBER_ARRIVED("SMS_505645328", "会员端-已送达", "您的行李订单:{orderNo}已送到{address},请及时取件,取件码:{code}。"),
        MEMBER_DELIVERING("SMS_505715321", "会员端-配送中", "您的行李订单:{orderNo}已由司机{name}取件,正运往目的地。"),
        VERIFY_CODE("SMS_333770877", "验证码短信", "您的验证码为:{code},请勿泄露于他人!"),
        DRIVER_AUTH_REJECTED("SMS_505790115", "司机端-司机认证被拒绝", "尊敬的{driver},很遗憾,您的司机认证未通过审核。原因:{reason}。您可修改资料后重新提交。"),
        DRIVER_AUTH_APPROVED("SMS_505885083", "司机端-司机认证通过", "尊敬的{driver},恭喜您已通过平台司机认证审核。您可登录司机端APP开始接单,配送过程中请注意安全,祝您接单顺利!"),
        DRIVER_URGENT_DISPATCH("SMS_505885082", "司机端-加急派单", "您好,您有一个新的行李订单(编号:{orderNo})。起点:{address1},终点:{address2},配送费{money1}元(含加急费{money2}元)。请尽快确认订单任务。"),
        DRIVER_URGENT_DISPATCH("SMS_505940293", "司机端-加急派单", "您好,您有一个新的行李订单(编号:{orderNo})。起点:{address1},终点:{address2},配送费{money1}元(含加急费{money2}元)。请尽快确认订单任务。"),
        SHOP_AUTH_REJECTED("SMS_505925106", "门店端-资料审核被拒绝", "很遗憾,您的门店\"{storeName}\"未通过审核,原因:{reason},您可修改资料后重新提交。"),
        SHOP_AUTH_APPROVED_DEPOSIT("SMS_505705111", "门店端-审核通过需缴纳押金", "恭喜您!您的门店\"{storeName}\"已通过初步审核。请支付押金{money}元以完成入驻,支付后即可登录门店后台正式接单。"),
        SHOP_AUTH_SUCCESS("SMS_505810110", "门店端-成功入驻通知", "恭喜您!您的门店\"{storeName}\"已通过平台审核,正式入驻成功。您可登录商家后台开始接单,账号:{phone},初始密码:{password}(建议首次登录后修改)。"),
        SHOP_AUTH_SUCCESS("SMS_505915289", "门店端-成功入驻通知", "恭喜您!您的门店\"{storeName}\"已通过平台审核,正式入驻成功。 æ‚¨å¯ç™»å½•商家后台开始接单,账号:注册手机号,初始密码::{password}(建议首次登录后修改)。"),
        ;
        private final String templateCode;
server/services/src/main/java/com/doumee/core/utils/aliyun/AliSmsService.java
@@ -44,49 +44,33 @@
     * @param templateParam æ¨¡æ¿å˜é‡json字符串
     * @return å¤„理结果
     */
    public static Boolean sendSms(String phone, String templateCode, String templateParam) {
    public static String sendSms(String phone, String templateCode, String templateParam) {
        try {
            //设置超时时间-可自行调整
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
            //初始化ascClient需要的几个参数
            //短信API产品名称(短信产品名固定,无需修改)
            final String product = "Dysmsapi";
            //短信API产品域名(接口地址固定,无需修改)
            final String domain = "dysmsapi.aliyuncs.com";
            //初始化ascClient,暂时不支持多region(请勿修改)
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);
            //组装请求对象
            SendSmsRequest request = new SendSmsRequest();
            //使用post提交
            request.setMethod(MethodType.POST);
            //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
            request.setPhoneNumbers(phone);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName(SING_NAME);
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(templateCode);
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\n,否则会导致JSON在服务端解析失败
            request.setTemplateParam(templateParam);
            //可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
            //dto.setSmsUpExtendCode("90997");
            //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
            //dto.setOutId("yourOutId");
            //请求失败这里会抛ClientException异常
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
            if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
                log.info("短信发送内容:"+phone + "-" + templateCode + "-" + templateParam + " >>> " + JSON.toJSONString(sendSmsResponse));
                return true;
                log.info("短信发送成功:phone={}, template={}", phone, templateCode);
                return null;
            } else {
                log.error("短信发送内容:"+phone + "-" + templateCode + "-" + templateParam + " >>> " + JSON.toJSONString(sendSmsResponse));
                String error = sendSmsResponse.getCode() + ":" + sendSmsResponse.getMessage();
                log.error("短信发送失败:phone={}, template={}, error={}", phone, templateCode, error);
                return error;
            }
        } catch (Exception e) {
            e.printStackTrace();
//            logger.error(e);
            log.error("短信发送异常:phone={}, template={}, error={}", phone, templateCode, e.getMessage());
            return e.getMessage();
        }
        return false;
    }
}
server/services/src/main/java/com/doumee/core/utils/xpyun/XpyunPrintService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,199 @@
package com.doumee.core.utils.xpyun;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.constants.Constants;
import com.doumee.core.utils.HttpsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
 * èŠ¯çƒ¨äº‘æ‰“å°æœºAPI服务
 */
@Slf4j
@Service
public class XpyunPrintService {
    private static final String BASE_URL = "https://open.xpyun.net/api/openapi/xprinter/";
    @Autowired
    private SystemDictDataBiz systemDictDataBiz;
    /**
     * æ·»åŠ æ‰“å°æœº
     */
    public XpyunResponse addPrinter(String sn, String name) {
        JSONObject body = buildBaseRequest();
        JSONArray printerContent = new JSONArray();
        JSONObject printer = new JSONObject();
        printer.put("sn", sn);
        printer.put("name", name);
        printerContent.add(printer);
        body.put("printerContent", printerContent);
        return callApi("addPrinters", body);
    }
    /**
     * åˆ é™¤æ‰“印机
     */
    public XpyunResponse deletePrinter(String sn) {
        JSONObject body = buildBaseRequest();
        JSONArray snlist = new JSONArray();
        snlist.add(sn);
        body.put("snlist", snlist);
        return callApi("delPrinters", body);
    }
    /**
     * æŸ¥è¯¢æ‰“印机状态
     */
    public XpyunResponse queryPrinterStatus(String sn) {
        JSONObject body = buildBaseRequest();
        body.put("sn", sn);
        return callApi("queryPrinterStatus", body);
    }
    /**
     * æ‰“印标签
     */
    public XpyunResponse printLabel(String sn, String content) {
        JSONObject body = buildBaseRequest();
        body.put("sn", sn);
        body.put("content", content);
        return callApi("printLabel", body);
    }
    /**
     * æž„建订单标签内容 (60mm Ã— 60mm = 480 Ã— 480 dots)
     *
     * å¸ƒå±€:
     * shopName                   sn/countSn
     * è®¢å•编号:code              ä¸‹å•时间:xxx
     * æ”¶ä»¶ä¿¡æ¯ï¼šå¼ ä¸‰ï¼ˆæ‰‹æœºå°¾å·1234)
     * è®¢å•行李:
     *   è¡ŒæŽç®±Ã—1 åŒè‚©åŒ…×2
     * è®¢å•备注
     *   xxxxxxx
     */
    public String buildOrderLabel(String shopName, String orderCode, String createTime,
                                  String takeUser, String takePhone,
                                  String goodsInfo, String remark,
                                  String snLabel) {
        StringBuilder sb = new StringBuilder();
        sb.append("<PAGE>");
        sb.append("<WIDTH>480</WIDTH>");
        sb.append("<HEIGHT>480</HEIGHT>");
        // ç¬¬1行: shopName å·¦ä¾§, snLabel å³ä¾§
        sb.append("<TEXT X=\"8\" Y=\"8\" W=\"320\" H=\"28\" T=\"16\">")
                .append(escapeXml(shopName)).append("</TEXT>");
        sb.append("<TEXT X=\"340\" Y=\"8\" W=\"140\" H=\"28\" T=\"14\">")
                .append(escapeXml(snLabel)).append("</TEXT>");
        // ç¬¬2行: è®¢å•编号 + ä¸‹å•æ—¶é—´
        sb.append("<TEXT X=\"8\" Y=\"44\" W=\"340\" H=\"24\" T=\"13\">")
                .append("订单编号:").append(escapeXml(orderCode)).append("</TEXT>");
        sb.append("<TEXT X=\"356\" Y=\"44\" W=\"124\" H=\"24\" T=\"13\">")
                .append(escapeXml(createTime)).append("</TEXT>");
        // è®¢å•编号条形码
        sb.append("<C128 X=\"8\" Y=\"72\" W=\"464\" H=\"56\" T=\"")
                .append(escapeXml(orderCode)).append("\"/>");
        // ç¬¬4行: æ”¶ä»¶ä¿¡æ¯
        String contactInfo = takeUser != null ? takeUser : "";
        if (takePhone != null && takePhone.length() >= 4) {
            contactInfo += "(手机尾号" + takePhone.substring(takePhone.length() - 4) + ")";
        }
        sb.append("<TEXT X=\"8\" Y=\"140\" W=\"464\" H=\"24\" T=\"13\">")
                .append("收件信息:").append(escapeXml(contactInfo)).append("</TEXT>");
        // ç¬¬5行: è®¢å•行李
        sb.append("<TEXT X=\"8\" Y=\"172\" W=\"464\" H=\"24\" T=\"13\">")
                .append("订单行李:</TEXT>");
        if (StringUtils.isNotBlank(goodsInfo)) {
            sb.append("<TEXT X=\"8\" Y=\"200\" W=\"464\" H=\"24\" T=\"12\">")
                    .append(escapeXml(goodsInfo)).append("</TEXT>");
        }
        // è®¢å•备注
        if (StringUtils.isNotBlank(remark)) {
            sb.append("<TEXT X=\"8\" Y=\"240\" W=\"464\" H=\"24\" T=\"13\">")
                    .append("订单备注:</TEXT>");
            sb.append("<TEXT X=\"8\" Y=\"268\" W=\"464\" H=\"48\" T=\"12\">")
                    .append(escapeXml(remark)).append("</TEXT>");
        }
        sb.append("</PAGE>");
        return sb.toString();
    }
    // ========== ç§æœ‰æ–¹æ³• ==========
    private JSONObject buildBaseRequest() {
        String user = systemDictDataBiz.queryByCode(Constants.XPYUN_CONFIG, Constants.XPYUN_USER).getCode();
        String userKey = systemDictDataBiz.queryByCode(Constants.XPYUN_CONFIG, Constants.XPYUN_USER_KEY).getCode();
        long timestamp = System.currentTimeMillis() / 1000;
        String sign = sha1(user + userKey + timestamp);
        JSONObject body = new JSONObject();
        body.put("user", user);
        body.put("timestamp", timestamp);
        body.put("sign", sign);
        return body;
    }
    private XpyunResponse callApi(String endpoint, JSONObject body) {
        try {
            String url = BASE_URL + endpoint;
            String result = HttpsUtil.postJson(url, body.toJSONString());
            if (result == null) {
                log.error("芯烨云API调用失败: endpoint={}, å“åº”为空", endpoint);
                XpyunResponse resp = new XpyunResponse();
                resp.setCode(-1);
                resp.setMsg("响应为空");
                return resp;
            }
            return JSON.parseObject(result, XpyunResponse.class);
        } catch (Exception e) {
            log.error("芯烨云API调用异常: endpoint={}, error={}", endpoint, e.getMessage(), e);
            XpyunResponse resp = new XpyunResponse();
            resp.setCode(-1);
            resp.setMsg(e.getMessage());
            return resp;
        }
    }
    private static String sha1(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException("SHA-1计算失败", e);
        }
    }
    private static String escapeXml(String text) {
        if (text == null) return "";
        return text.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&apos;");
    }
}
server/services/src/main/java/com/doumee/core/utils/xpyun/XpyunResponse.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.doumee.core.utils.xpyun;
import lombok.Data;
/**
 * èŠ¯çƒ¨äº‘API响应
 */
@Data
public class XpyunResponse {
    private Integer code;
    private String msg;
    private Object data;
    private Long serverExecutedTime;
}
server/services/src/main/java/com/doumee/dao/business/PrinterInfoMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.doumee.dao.business;
import com.doumee.dao.business.model.PrinterInfo;
import com.github.yulichang.base.MPJBaseMapper;
/**
 * æ‰“印机信息Mapper
 * @author rk
 * @date 2026/04/28
 */
public interface PrinterInfoMapper extends MPJBaseMapper<PrinterInfo> {
}
server/services/src/main/java/com/doumee/dao/business/model/AppVersion.java
@@ -1,6 +1,7 @@
package com.doumee.dao.business.model;
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.doumee.core.annotation.excel.ExcelColumn;
@@ -91,4 +92,8 @@
    @ExcelColumn(name = "版本号")
    private Integer versionNum;
    @ApiModelProperty(value = "创建人名称")
    @TableField(exist = false)
    private String createUserName;
}
server/services/src/main/java/com/doumee/dao/business/model/Category.java
@@ -102,4 +102,12 @@
    @ApiModelProperty(value = "自关联对象名称")
    @TableField(exist = false)
    private String relationName;
    @ApiModelProperty(value = "自关联对象otherField")
    @TableField(exist = false)
    private String relationOtherField;
    @ApiModelProperty(value = "自关联对象备注")
    @TableField(exist = false)
    private String relationRemark;
}
server/services/src/main/java/com/doumee/dao/business/model/DriverInfo.java
@@ -111,7 +111,7 @@
    private String unionid;
    @ApiModelProperty(value = "审批时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date auditTime;
    @ApiModelProperty(value = "审批人", example = "1")
@@ -229,4 +229,8 @@
    @ApiModelProperty(value = "区县名称")
    private String districtName;
    @TableField(exist = false)
    @ApiModelProperty(value = "审批人名称")
    private String auditUserName;
}
server/services/src/main/java/com/doumee/dao/business/model/Orders.java
@@ -370,13 +370,13 @@
    private Date platformSmsNotifiedTime;
    @TableField(exist = false)
    @ApiModelProperty(value = "创建开始时间(查询用)", example = "2026-01-01")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @ApiModelProperty(value = "创建开始时间(查询用)", example = "2026-01-01 00:00:00")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createStartTime;
    @TableField(exist = false)
    @ApiModelProperty(value = "创建结束时间(查询用)", example = "2026-12-31")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @ApiModelProperty(value = "创建结束时间(查询用)", example = "2026-12-31 23:59:59")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createEndTime;
    @TableField(exist = false)
@@ -443,4 +443,8 @@
    @ApiModelProperty(value = "司机电话(关联查询)")
    private String driverPhone;
    @TableField(exist = false)
    @ApiModelProperty(value = "门店主键(同时查询存件/取件门店)")
    private Integer shopId;
}
server/services/src/main/java/com/doumee/dao/business/model/PrinterInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.doumee.dao.business.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * æ‰“印机信息
 * @author rk
 * @date 2026/04/28
 */
@Data
@ApiModel("打印机信息")
@TableName("`printer_info`")
public class PrinterInfo {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty(value = "主键", example = "1")
    private Integer id;
    @ApiModelProperty(value = "是否已删除 0未删除 1已删除")
    private Integer deleted;
    @ApiModelProperty(value = "创建人编码")
    private Integer createUser;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "创建时间")
    private Date createTime;
    @ApiModelProperty(value = "更新人编码")
    private Integer updateUser;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "更新时间")
    private Date updateTime;
    @ApiModelProperty(value = "备注")
    private String remark;
    @ApiModelProperty(value = "打印机名称")
    private String name;
    @ApiModelProperty(value = "SN")
    private String sn;
    @ApiModelProperty(value = "门店主键")
    private Integer shopId;
}
server/services/src/main/java/com/doumee/dao/business/model/ShopInfo.java
@@ -186,6 +186,9 @@
    @ApiModelProperty(value = "门店营业类型:0=非全天;1=全天", example = "0")
    private Integer businessType;
    @ApiModelProperty(value = "芯烨云打印机SN编号")
    private String printerSn;
    // éžæŒä¹…化:附件列表
    @TableField(exist = false)
server/services/src/main/java/com/doumee/dao/dto/ChangePasswordDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.doumee.dao.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
 * ä¿®æ”¹å¯†ç è¯·æ±‚
 *
 * @author rk
 * @date 2026/04/28
 */
@Data
@ApiModel("修改密码请求")
public class ChangePasswordDTO {
    @NotBlank(message = "旧密码不能为空")
    @ApiModelProperty(value = "旧密码", required = true)
    private String oldPassword;
    @NotBlank(message = "新密码不能为空")
    @ApiModelProperty(value = "新密码", required = true)
    private String newPassword;
}
server/services/src/main/java/com/doumee/dao/dto/PrinterBindDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
package com.doumee.dao.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ApiModel("打印机绑定请求")
public class PrinterBindDTO {
    @ApiModelProperty(value = "门店ID", required = true)
    @NotNull(message = "门店ID不能为空")
    private Integer shopId;
    @ApiModelProperty(value = "打印机SN编号", required = true)
    @NotBlank(message = "打印机SN不能为空")
    private String printerSn;
    @ApiModelProperty(value = "打印机KEY", required = true)
    @NotBlank(message = "打印机KEY不能为空")
    private String printerKey;
}
server/services/src/main/java/com/doumee/dao/dto/WithdrawalDTO.java
@@ -28,4 +28,8 @@
    @NotBlank(message = "支付宝提现账户不能为空")
    private String aliAccount;
    @ApiModelProperty(value = "支付宝实名姓名", required = true)
    @NotBlank(message = "支付宝实名姓名不能为空")
    private String aliName;
}
server/services/src/main/java/com/doumee/dao/vo/DriverCenterVO.java
@@ -31,6 +31,9 @@
    @ApiModelProperty(value = "司机定级:5=S 4=A 3=B 2=C 1=D")
    private Integer driverLevel;
    @ApiModelProperty(value = "司机定级名称:S/A/B/C/D")
    private String driverLevelName;
    @ApiModelProperty(value = "审核状态:0=待审批 1=审批通过 2=审批驳回")
    private Integer auditStatus;
server/services/src/main/java/com/doumee/service/business/AreasService.java
@@ -64,6 +64,8 @@
     */
    Areas findById(Integer id);
    Areas getById(Integer id);
    /**
     * æ ¹æ®id和type查询对象信息
     * @param id
server/services/src/main/java/com/doumee/service/business/PrinterInfoService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
package com.doumee.service.business;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.PrinterInfo;
import java.util.List;
/**
 * æ‰“印机信息Service定义
 * @author rk
 * @date 2026/04/28
 */
public interface PrinterInfoService {
    Integer create(PrinterInfo printerInfo);
    void deleteById(Integer id);
    void delete(PrinterInfo printerInfo);
    void deleteByIdInBatch(List<Integer> ids);
    void updateById(PrinterInfo printerInfo);
    void updateByIdInBatch(List<PrinterInfo> printerInfos);
    PrinterInfo findById(Integer id);
    PrinterInfo findOne(PrinterInfo printerInfo);
    List<PrinterInfo> findList(PrinterInfo printerInfo);
    PageData<PrinterInfo> findPage(PageWrap<PrinterInfo> pageWrap);
    long count(PrinterInfo printerInfo);
}
server/services/src/main/java/com/doumee/service/business/ShopInfoService.java
@@ -219,4 +219,19 @@
     */
    void changePassword(Integer shopId, String oldPassword, String newPassword, String token);
    /**
     * ç»‘定打印机
     */
    void bindPrinter(com.doumee.dao.dto.PrinterBindDTO dto);
    /**
     * è§£ç»‘打印机
     */
    void unbindPrinter(Integer shopId);
    /**
     * æŸ¥è¯¢æ‰“印机状态
     */
    Object queryPrinterStatus(Integer shopId);
}
server/services/src/main/java/com/doumee/service/business/impl/AppVersionServiceImpl.java
@@ -13,6 +13,7 @@
import com.doumee.dao.business.AppVersionMapper;
import com.doumee.dao.business.model.AppVersion;
import com.doumee.service.business.AppVersionService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -108,55 +109,30 @@
    @Override
    public PageData<AppVersion> findPage(PageWrap<AppVersion> pageWrap) {
        IPage<AppVersion> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        QueryWrapper<AppVersion> queryWrapper = new QueryWrapper<>();
        Utils.MP.blankToNull(pageWrap.getModel());
        pageWrap.getModel().setDeleted(Constants.ZERO);
        if (pageWrap.getModel().getId() != null) {
            queryWrapper.lambda().eq(AppVersion::getId, pageWrap.getModel().getId());
        MPJLambdaWrapper<AppVersion> wrapper = new MPJLambdaWrapper<>();
        wrapper.selectAll(AppVersion.class)
                .select("su.REALNAME as createUserName")
                .leftJoin("system_user su on su.ID = t.CREATE_USER")
                .eq(AppVersion::getDeleted, Constants.ZERO);
        AppVersion model = pageWrap.getModel();
        Utils.MP.blankToNull(model);
        if (model.getVersionInfo() != null) {
            wrapper.like(AppVersion::getVersionInfo, model.getVersionInfo());
        }
        if (pageWrap.getModel().getDeleted() != null) {
            queryWrapper.lambda().eq(AppVersion::getDeleted, pageWrap.getModel().getDeleted());
        if (model.getName() != null) {
            wrapper.like(AppVersion::getName, model.getName());
        }
        if (pageWrap.getModel().getCreateUser() != null) {
            queryWrapper.lambda().eq(AppVersion::getCreateUser, pageWrap.getModel().getCreateUser());
        if (model.getTitle() != null) {
            wrapper.like(AppVersion::getTitle, model.getTitle());
        }
        if (pageWrap.getModel().getCreateTime() != null) {
            queryWrapper.lambda().ge(AppVersion::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateTime()));
            queryWrapper.lambda().le(AppVersion::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateTime()));
        if (model.getIsForce() != null) {
            wrapper.eq(AppVersion::getIsForce, model.getIsForce());
        }
        if (pageWrap.getModel().getUpdateUser() != null) {
            queryWrapper.lambda().eq(AppVersion::getUpdateUser, pageWrap.getModel().getUpdateUser());
        if (model.getType() != null) {
            wrapper.eq(AppVersion::getType, model.getType());
        }
        if (pageWrap.getModel().getUpdateTime() != null) {
            queryWrapper.lambda().ge(AppVersion::getUpdateTime, Utils.Date.getStart(pageWrap.getModel().getUpdateTime()));
            queryWrapper.lambda().le(AppVersion::getUpdateTime, Utils.Date.getEnd(pageWrap.getModel().getUpdateTime()));
        }
        if (pageWrap.getModel().getRemark() != null) {
            queryWrapper.lambda().eq(AppVersion::getRemark, pageWrap.getModel().getRemark());
        }
        if (pageWrap.getModel().getVersionInfo() != null) {
            queryWrapper.lambda().like(AppVersion::getVersionInfo, pageWrap.getModel().getVersionInfo());
        }
        if (pageWrap.getModel().getName() != null) {
            queryWrapper.lambda().like(AppVersion::getName, pageWrap.getModel().getName());
        }
        if (pageWrap.getModel().getTitle() != null) {
            queryWrapper.lambda().like(AppVersion::getTitle, pageWrap.getModel().getTitle());
        }
        if (pageWrap.getModel().getIsForce() != null) {
            queryWrapper.lambda().eq(AppVersion::getIsForce, pageWrap.getModel().getIsForce());
        }
        if (pageWrap.getModel().getType() != null) {
            queryWrapper.lambda().eq(AppVersion::getType, pageWrap.getModel().getType());
        }
        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        return PageData.from(appVersionMapper.selectPage(page, queryWrapper));
        wrapper.orderByDesc(AppVersion::getId);
        return PageData.from(appVersionMapper.selectJoinPage(page, AppVersion.class, wrapper));
    }
    @Override
server/services/src/main/java/com/doumee/service/business/impl/AreasServiceImpl.java
@@ -133,6 +133,11 @@
    }
    @Override
    public Areas getById(Integer id) {
       return areasMapper.selectById(id);
    }
    @Override
    public Areas findById(Integer id) {
        if(ALL_AREA_LIST!=null){
            for(Areas a : ALL_AREA_LIST){
server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
@@ -252,11 +252,17 @@
                }
            }
            java.util.Map<Integer, String> relationNameMap = new java.util.HashMap<>();
            java.util.Map<Integer, String> relationOtherFieldMap = new java.util.HashMap<>();
            java.util.Map<Integer, String> relationRemarkMap = new java.util.HashMap<>();
            if (!relationIds.isEmpty()) {
                categoryMapper.selectList(new QueryWrapper<Category>().lambda()
                        .in(Category::getId, relationIds)
                        .eq(Category::getDeleted, Constants.ZERO))
                        .forEach(c -> relationNameMap.put(c.getId(), c.getName()));
                        .forEach(c -> {
                            relationNameMap.put(c.getId(), c.getName());
                            relationOtherFieldMap.put(c.getId(), c.getOtherField());
                            relationRemarkMap.put(c.getId(), c.getRemark());
                        });
            }
            for (Category category:categoryList) {
                if(StringUtils.isNotBlank(category.getIcon())){
@@ -264,6 +270,8 @@
                }
                if (category.getRelationId() != null) {
                    category.setRelationName(relationNameMap.get(category.getRelationId()));
                    category.setRelationOtherField(relationOtherFieldMap.get(category.getRelationId()));
                    category.setRelationRemark(relationRemarkMap.get(category.getRelationId()));
                }
            }
        }
server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java
@@ -34,6 +34,8 @@
import com.doumee.dao.vo.DriverCancelLimitVO;
import com.doumee.dao.vo.DriverCenterVO;
import com.doumee.dao.vo.DriverGrabOrderVO;
import com.doumee.dao.system.model.SystemUser;
import com.doumee.service.system.SystemUserService;
import com.doumee.dao.vo.DriverOrderDetailVO;
import com.doumee.core.utils.aliyun.AliSmsService;
import com.doumee.service.business.DriverInfoService;
@@ -115,6 +117,9 @@
    @Autowired
    private AreasBizImpl areasBiz;
    @Autowired
    private SystemUserService systemUserService;
    /**
     * å‘送订单站内信通知
@@ -270,13 +275,7 @@
                .select(" ( select ifnull(sum(r.OPT_TYPE * r.AMOUNT),0) from revenue r where r.MEMBER_TYPE = 1 and r.MEMBER_ID= t.id and r.VAILD_STATUS = 1 ) as memberAmount ")
                .selectAs(Category::getName,DriverInfo::getCarTypeName)
                .leftJoin(Category.class, Category::getId,DriverInfo::getCarType);
        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        queryWrapper.orderByDesc(DriverInfo::getId);
        PageData<DriverInfo> pageData = PageData.from(driverInfoMapper.selectPage(page, queryWrapper));
        for (DriverInfo d : pageData.getRecords()) {
            d.setGender(Constants.getGenderByIdCard(d.getIdcard()));
@@ -301,7 +300,7 @@
        String code = RandomStringUtils.randomNumeric(6);
        // å‘送短信
        String templateParam = "{\"code\":\"" + code + "\"}";
        AliSmsService.sendSms(telephone, "SMS_491325122", templateParam);
        AliSmsService.sendSms(telephone, Constants.SmsNotify.VERIFY_CODE.getTemplateCode(), templateParam);
        // ä¿å­˜çŸ­ä¿¡è®°å½•
        Smsrecord smsrecord = new Smsrecord();
        smsrecord.setDeleted(Constants.ZERO);
@@ -716,6 +715,17 @@
                }
            }
        }
        // æŸ¥è¯¢å®¡æ‰¹äººåç§°
        if (driverInfo.getAuditUser() != null) {
            try {
                SystemUser auditUser = systemUserService.findById(driverInfo.getAuditUser());
                if (auditUser != null) {
                    driverInfo.setAuditUserName(auditUser.getRealname());
                }
            } catch (Exception e) {
                // å®¡æ‰¹äººå·²åˆ é™¤ç­‰å¼‚常忽略
            }
        }
        return driverInfo;
    }
@@ -812,6 +822,7 @@
        vo.setCarCode(driver.getCarCode());
        vo.setScore(driver.getScore() != null ? driver.getScore().toPlainString() : "0");
        vo.setDriverLevel(driver.getDriverLevel());
        vo.setDriverLevelName(Constants.getDriverLevelName(driver.getDriverLevel()));
        vo.setAuditStatus(driver.getAuditStatus());
        vo.setAuditRemark(driver.getAuditRemark());
        vo.setBalance(driver.getBalance() != null ? driver.getBalance() : 0L);
@@ -823,7 +834,7 @@
            vo.setFullImgUrl(imgPrefix + driver.getImgurl());
        }
        // ä»Šæ—¥é¢„计佣金:revenue表中今天的收入记录金额之和
        // ä»Šæ—¥é¢„计佣金:今日接单的司机佣金 + å¹³å°å¥–励金
        Date now = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(now);
@@ -833,16 +844,16 @@
        cal.set(Calendar.MILLISECOND, 0);
        Date todayStart = cal.getTime();
        QueryWrapper<Revenue> revenueWrapper = new QueryWrapper<>();
        revenueWrapper.lambda()
                .eq(Revenue::getMemberId, memberId)
                .eq(Revenue::getMemberType, Constants.ONE)
                .eq(Revenue::getOptType, Constants.ONE)
                .eq(Revenue::getDeleted, Constants.ZERO)
                .ge(Revenue::getCreateTime, todayStart);
        revenueWrapper.select("IFNULL(SUM(AMOUNT),0) as amount");
        Revenue sumResult = revenueMapper.selectOne(revenueWrapper);
        vo.setTodayCommission(sumResult != null && sumResult.getAmount() != null ? sumResult.getAmount() : 0L);
        QueryWrapper<Orders> commissionWrapper = new QueryWrapper<>();
        commissionWrapper.lambda()
                .eq(Orders::getAcceptDriver, driver.getId())
                .eq(Orders::getDeleted, Constants.ZERO)
                .ge(Orders::getAcceptTime, todayStart);
        commissionWrapper.select("IFNULL(SUM(DRIVER_FEE),0) as driverFee", "IFNULL(SUM(PLATFORM_REWARD_AMOUNT),0) as platformRewardAmount");
        Orders commissionResult = ordersMapper.selectOne(commissionWrapper);
        long driverFee = commissionResult != null && commissionResult.getDriverFee() != null ? commissionResult.getDriverFee() : 0L;
        long rewardAmount = commissionResult != null && commissionResult.getPlatformRewardAmount() != null ? commissionResult.getPlatformRewardAmount() : 0L;
        vo.setTodayCommission(driverFee + rewardAmount);
        // ä»Šæ—¥æŽ¥å•数:今天完成的订单数(acceptDriver=司机主键,状态=已完成)
        Long todayOrderCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
@@ -966,7 +977,7 @@
                .select("c2.other_field as c2OtherField")
                .select("c2.name as goodLevelName")
                // æ˜¯å¦å­˜åœ¨ç‰¹å¤§å°ºå¯¸
                .select("IF(EXISTS(SELECT 1 FROM orders_detail od JOIN category c3 ON c3.id = od.LUGGAGE_ID AND c3.TYPE = 4 AND c3.OTHER_FIELD = '1' WHERE od.ORDER_ID = t.ID AND od.DELETED = 0), 1, 0) as hasOversized")
                .select("IF(EXISTS(SELECT 1 FROM orders_detail od JOIN category c3 ON c3.id = od.LUGGAGE_ID AND c3.TYPE = 4 AND c3.detail = '1' WHERE od.ORDER_ID = t.ID AND od.DELETED = 0), 1, 0) as hasOversized")
                // JOIN
                .leftJoin("shop_info s1 on s1.id = t.DEPOSIT_SHOP_ID and s1.DELETED = 0")
                .leftJoin("shop_info s2 on s2.id = t.TAKE_SHOP_ID and s2.DELETED = 0")
@@ -1418,6 +1429,7 @@
        // 7. é€šçŸ¥ä¼šå‘˜ï¼šå¸æœºå·²æŠ¢å•
        sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_PICKUP_GRABBED, orderId,
                "orderNo", order.getCode(),
                "driverName", driver.getName());
        // é€šçŸ¥å­˜ä»¶é—¨åº—:订单已抢单待取件
@@ -1804,19 +1816,16 @@
            for (int i = 0; i < paramPairs.length - 1; i += 2) {
                templateParam.put(paramPairs[i], paramPairs[i + 1]);
            }
            boolean result = AliSmsService.sendSms(phone, smsNotify.getTemplateCode(),
            String error = AliSmsService.sendSms(phone, smsNotify.getTemplateCode(),
                    templateParam.toJSONString());
            if (result) {
                log.info("短信发送成功: phone={}, template={}", phone, smsNotify.name());
            } else {
                log.warn("短信发送失败: phone={}, template={}", phone, smsNotify.name());
            }
            // å­˜å‚¨çŸ­ä¿¡è®°å½•
            Smsrecord record = new Smsrecord();
            record.setPhone(phone);
            record.setContent(content);
            record.setType(Constants.ONE); // 1=订单通知
            record.setStatus(result ? Constants.ONE : Constants.ZERO);
            record.setType(Constants.ONE);
            record.setStatus(error == null ? Constants.ONE : Constants.ZERO);
            if (error != null) {
                record.setRemark(error);
            }
            record.setCreateTime(new Date());
            record.setDeleted(Constants.ZERO);
            smsrecordMapper.insert(record);
@@ -1828,6 +1837,7 @@
                record.setContent(content);
                record.setType(Constants.ONE);
                record.setStatus(Constants.ZERO);
                record.setRemark(e.getMessage());
                record.setCreateTime(new Date());
                record.setDeleted(Constants.ZERO);
                smsrecordMapper.insert(record);
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -519,13 +519,7 @@
                queryWrapper.lambda().le(Member::getCreateTime, Utils.Date.getEnd(query.getEndTime()));
            }
        }
        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        queryWrapper.lambda().orderByDesc(Member::getId);
        IPage<Member> memberPage = memberMapper.selectPage(page, queryWrapper);
        IPage<MemberListVO> voPage = memberPage.convert(this::toListVO);
        return PageData.from(voPage);
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -222,8 +222,8 @@
        queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getDepositShopName()), "s1.name", pageWrap.getModel().getDepositShopName());
        queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getTakeShopName()),  "s2.name",  pageWrap.getModel().getTakeShopName());
        queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getGoodsInfo()), Orders::getGoodsInfo, pageWrap.getModel().getGoodsInfo());
        queryWrapper.ge(pageWrap.getModel().getCreateStartTime() != null, Orders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime()));
        queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime()));
        queryWrapper.ge(pageWrap.getModel().getCreateStartTime() != null, Orders::getCreateTime, pageWrap.getModel().getCreateStartTime());
        queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, pageWrap.getModel().getCreateEndTime());
        queryWrapper.eq(pageWrap.getModel().getDepositShopId() != null, Orders::getDepositShopId, pageWrap.getModel().getDepositShopId());
        queryWrapper.eq(pageWrap.getModel().getType() != null, Orders::getType, pageWrap.getModel().getType());
        queryWrapper.eq(pageWrap.getModel().getStatus() != null, Orders::getStatus, pageWrap.getModel().getStatus());
@@ -231,6 +231,9 @@
        queryWrapper.and(pageWrap.getModel().getDriverKeyword() != null, i->i.like(DriverInfo::getName, pageWrap.getModel().getDriverKeyword())
                .or().like(DriverInfo::getTelephone, pageWrap.getModel().getDriverKeyword()));
        queryWrapper.eq(pageWrap.getModel().getSettlementStatus() != null, Orders::getSettlementStatus, pageWrap.getModel().getSettlementStatus());
        queryWrapper.eq(pageWrap.getModel().getAcceptDriver() != null, Orders::getAcceptDriver, pageWrap.getModel().getAcceptDriver());
        queryWrapper.and(pageWrap.getModel().getShopId() != null, i -> i.eq(Orders::getDepositShopId, pageWrap.getModel().getShopId())
                .or().eq(Orders::getTakeShopId, pageWrap.getModel().getShopId()));
        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
@@ -263,8 +266,8 @@
        queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getDepositShopName()), "s1.name", pageWrap.getModel().getDepositShopName());
        queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getTakeShopName()),  "s2.name",  pageWrap.getModel().getTakeShopName());
        queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getGoodsInfo()), Orders::getGoodsInfo, pageWrap.getModel().getGoodsInfo());
        queryWrapper.ge(pageWrap.getModel().getCreateStartTime() != null, Orders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime()));
        queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime()));
        queryWrapper.ge(pageWrap.getModel().getCreateStartTime() != null, Orders::getCreateTime, pageWrap.getModel().getCreateStartTime());
        queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, pageWrap.getModel().getCreateEndTime());
        queryWrapper.eq(pageWrap.getModel().getDepositShopId() != null, Orders::getDepositShopId, pageWrap.getModel().getDepositShopId());
        queryWrapper.eq(pageWrap.getModel().getType() != null, Orders::getType, pageWrap.getModel().getType());
        queryWrapper.eq(pageWrap.getModel().getStatus() != null, Orders::getStatus, pageWrap.getModel().getStatus());
@@ -272,6 +275,9 @@
        queryWrapper.and(pageWrap.getModel().getDriverKeyword() != null, i->i.like(DriverInfo::getName, pageWrap.getModel().getDriverKeyword())
                .or().like(DriverInfo::getTelephone, pageWrap.getModel().getDriverKeyword()));
        queryWrapper.eq(pageWrap.getModel().getSettlementStatus() != null, Orders::getSettlementStatus, pageWrap.getModel().getSettlementStatus());
        queryWrapper.eq(pageWrap.getModel().getAcceptDriver() != null, Orders::getAcceptDriver, pageWrap.getModel().getAcceptDriver());
        queryWrapper.and(pageWrap.getModel().getShopId() != null, i -> i.eq(Orders::getDepositShopId, pageWrap.getModel().getShopId())
                .or().eq(Orders::getTakeShopId, pageWrap.getModel().getShopId()));
        queryWrapper.select(
                "IFNULL(SUM(t.total_amount), 0) as total_amount_sum",
@@ -544,18 +550,26 @@
            insuranceFeeFen = insuranceFeeYuan.multiply(new BigDecimal(100)).longValue();
        }
        // 5. åŠ æ€¥è´¹ç”¨ï¼šç‰©å“ä»·æ ¼ Ã— åŠ æ€¥ç³»æ•°(字典 URGENT_COEFFICIENT)
        // 5. åŠ æ€¥è´¹ç”¨ï¼šç‰©å“ä»·æ ¼ Ã— (加急系数-1),如150%表示增加50%
        long urgentFeeFen = 0L;
        String urgentRateStr = systemDictDataBiz.queryByCode(
                Constants.OPERATION_CONFIG, Constants.OP_URGENT_COEFFICIENT).getCode();
        BigDecimal urgentRate = new BigDecimal(urgentRateStr);
        urgentFeeFen = new BigDecimal(itemPriceTotal).multiply(urgentRate)
        BigDecimal urgentIncreaseRate = urgentRate.subtract(BigDecimal.ONE);
        urgentFeeFen = new BigDecimal(itemPriceTotal).multiply(urgentIncreaseRate)
                .setScale(0, RoundingMode.HALF_UP).longValue();
        // 6. æ€»ä»·æ ¼ = ç‰©å“ä»·æ ¼ + ä¿ä»·è´¹ç”¨ + åŠ æ€¥è´¹ç”¨ï¼ˆåŠ æ€¥æ—¶æ‰åŒ…å«åŠ æ€¥è´¹ï¼‰
        long totalPrice = itemPriceTotal + insuranceFeeFen;
        if (Boolean.TRUE.equals(dto.getUrgent())) {
            totalPrice += urgentFeeFen;
            // åŠ æ€¥æ—¶æ›´æ–°ç‰©å“æ˜Žç»†å•ä»·å’Œå°è®¡
            for (ItemPriceVO vo : itemList) {
                long adjustedUnitPrice = new BigDecimal(vo.getUnitPrice()).multiply(urgentRate)
                        .setScale(0, RoundingMode.HALF_UP).longValue();
                vo.setUnitPrice(adjustedUnitPrice);
                vo.setSubtotal(adjustedUnitPrice * vo.getQuantity());
            }
        }
        PriceCalculateVO result = new PriceCalculateVO();
@@ -830,6 +844,12 @@
        orders.setEstimatedAmount(priceResult.getTotalPrice());
        orders.setTotalAmount(priceResult.getTotalPrice());
        orders.setUrgentAmount(priceResult.getUrgentFee());
        // å­˜å‚¨åŠ æ€¥ç³»æ•°
        if (Constants.ONE.equals(dto.getType()) && Constants.ONE.equals(dto.getIsUrgent())) {
            String urgentRateStr = systemDictDataBiz.queryByCode(
                    Constants.OPERATION_CONFIG, Constants.OP_URGENT_COEFFICIENT).getCode();
            orders.setUrgentRata(new BigDecimal(urgentRateStr));
        }
        if (dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0) {
            orders.setDeclaredAmount(dto.getDeclaredAmount().multiply(new BigDecimal(100)).longValue());
        } else {
@@ -861,6 +881,13 @@
        orderLogService.create(createLog);
        // ========== 7. åˆ›å»ºè®¢å•明细 ==========
        // å¼‚地寄存极速达时,按加急比例计算明细行单价
        BigDecimal urgentIncreaseRate = null;
        if (Constants.ONE.equals(dto.getType()) && Constants.ONE.equals(dto.getIsUrgent())) {
            String urgentRateStr = systemDictDataBiz.queryByCode(
                    Constants.OPERATION_CONFIG, Constants.OP_URGENT_COEFFICIENT).getCode();
            urgentIncreaseRate = new BigDecimal(urgentRateStr).subtract(BigDecimal.ONE);
        }
        for (ItemPriceVO itemVO : priceResult.getItemList()) {
            OrdersDetail detail = new OrdersDetail();
            detail.setOrderId(orderId);
@@ -868,11 +895,29 @@
            detail.setLuggageName(itemVO.getCategoryName());
            detail.setLuggageDetail(itemVO.getDetail());
            detail.setNum(itemVO.getQuantity());
            detail.setUnitPrice(itemVO.getUnitPrice());
            long detailUnitPrice = itemVO.getUnitPrice();
            if (urgentIncreaseRate != null) {
                detailUnitPrice = new BigDecimal(detailUnitPrice)
                        .multiply(BigDecimal.ONE.add(urgentIncreaseRate))
                        .setScale(0, RoundingMode.HALF_UP).longValue();
            }
            detail.setUnitPrice(detailUnitPrice);
            detail.setStartDistance(itemVO.getStartDistance());
            detail.setStartPrice(itemVO.getStartPrice());
            if (urgentIncreaseRate != null && itemVO.getStartPrice() != null) {
                detail.setStartPrice(new BigDecimal(itemVO.getStartPrice())
                        .multiply(BigDecimal.ONE.add(urgentIncreaseRate))
                        .setScale(0, RoundingMode.HALF_UP).longValue());
            } else {
                detail.setStartPrice(itemVO.getStartPrice());
            }
            detail.setExtraDistance(itemVO.getExtraDistance());
            detail.setExtraPrice(itemVO.getExtraPrice());
            if (urgentIncreaseRate != null && itemVO.getExtraPrice() != null) {
                detail.setExtraPrice(new BigDecimal(itemVO.getExtraPrice())
                        .multiply(BigDecimal.ONE.add(urgentIncreaseRate))
                        .setScale(0, RoundingMode.HALF_UP).longValue());
            } else {
                detail.setExtraPrice(itemVO.getExtraPrice());
            }
            detail.setLocallyPrice(itemVO.getLocallyPrice());
            detail.setDeleted(Constants.ZERO);
            detail.setCreateTime(now);
@@ -1816,46 +1861,17 @@
            vo.setMemberVerifyCode(order.getMemberVerifyCode());
        }
        // å¼‚地寄存经纬度(就地寄存不返回)
        if (Constants.ONE.equals(order.getType())) {
            // status=3(已接单):返回存件门店经纬度 + å¸æœºç»çº¬åº¦
            if (Constants.equalsInteger(status, Constants.OrderStatus.accepted.getStatus())) {
                ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId());
                if (depositShop != null) {
                    vo.setDepositShopLng(depositShop.getLongitude());
                    vo.setDepositShopLat(depositShop.getLatitude());
                }
                if (order.getAcceptDriver() != null) {
                    DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver());
                    if (driver != null) {
                        vo.setDriverLng(driver.getLongitude());
                        vo.setDriverLat(driver.getLatitude());
                    }
                }
            }
            // status=4(配送中):返回取件点经纬度 + å¸æœºç»çº¬åº¦
            if (Constants.equalsInteger(status, Constants.OrderStatus.delivering.getStatus())) {
                // å–件点经纬度(优先取件门店,否则订单上的取件坐标)
                if (order.getTakeShopId() != null) {
                    ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId());
                    if (takeShop != null) {
                        vo.setTakeLng(takeShop.getLongitude());
                        vo.setTakeLat(takeShop.getLatitude());
                    }
                } else if (order.getTakeLgt() != null && order.getTakeLat() != null) {
                    vo.setTakeLng(order.getTakeLgt().doubleValue());
                    vo.setTakeLat(order.getTakeLat().doubleValue());
                }
                if (order.getAcceptDriver() != null) {
                    DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver());
                    if (driver != null) {
                        vo.setDriverLng(driver.getLongitude());
                        vo.setDriverLat(driver.getLatitude());
                    }
                }
            }
        vo.setDepositShopLng(order.getDepositLgt().doubleValue());
        vo.setDepositShopLat(order.getDepositLat().doubleValue());
        // å–件点经纬度
        vo.setTakeLng(order.getTakeLgt().doubleValue());
        vo.setTakeLat(order.getTakeLat().doubleValue());
        //司机经纬度
        DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver());
        if (driver != null) {
            vo.setDriverLng(driver.getLongitude());
            vo.setDriverLat(driver.getLatitude());
        }
        // è¯„价信息
        vo.setCommentStatus(order.getCommentStatus());
        if (Constants.equalsInteger(order.getCommentStatus(), Constants.ONE)) {
@@ -2308,6 +2324,7 @@
    public PayResponse payShopDeposit(Integer memberId) {
        // 1. æŸ¥è¯¢é—¨åº—信息
        ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
                .eq(ShopInfo::getDeleted,Constants.ZERO)
                .eq(ShopInfo::getRegionMemberId,memberId));
        if (shopInfo == null) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "门店不存在");
@@ -2393,14 +2410,13 @@
        sendSmsNotify(shopInfo.getTelephone(),
                Constants.SmsNotify.SHOP_AUTH_SUCCESS,
                "storeName", shopInfo.getName(),
                "phone", shopInfo.getTelephone() != null ? shopInfo.getTelephone() : "",
                "password", rawPassword);
        // 6. æŠ¼é‡‘支付完成后,若城市未开通则自动开通
        if (shopInfo.getAreaId() != null) {
            Areas shopArea = areasBiz.resolveArea(shopInfo.getAreaId());
            Areas shopArea = areasService.getById(shopInfo.getAreaId());
            if (shopArea != null && shopArea.getParentId() != null) {
                Areas cityArea = areasBiz.resolveArea(shopArea.getParentId());
                Areas cityArea = areasService.getById(shopArea.getParentId());
                if (cityArea != null && !Constants.equalsInteger(cityArea.getStatus(), Constants.ONE)) {
                    cityArea.setStatus(Constants.ONE);
                    cityArea.setEditDate(now);
@@ -2430,7 +2446,8 @@
                .eq(Orders::getDeleted, Constants.ZERO)
                .eq(Orders::getStatus, Constants.OrderStatus.finished.getStatus())
                .eq(Orders::getSettlementStatus, Constants.ZERO)
                .le(Orders::getFinishTime, deadline));
                .le(Orders::getFinishTime, deadline)
        );
        if (ordersList == null || ordersList.isEmpty()) {
            return;
        }
@@ -2475,7 +2492,7 @@
                } else if (Constants.equalsInteger(revenue.getMemberType(), Constants.TWO)) {
                    // é—¨åº—:通过 memberId æŸ¥ ShopInfo(regionMemberId),更新 balance / totalBalance
                    ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
                            .eq(ShopInfo::getRegionMemberId, revenue.getMemberId())
                            .eq(ShopInfo::getId, revenue.getMemberId())
                            .eq(ShopInfo::getDeleted, Constants.ZERO)
                            .last("limit 1"));
                    if (shop != null) {
@@ -3182,8 +3199,8 @@
        // å­˜ä»¶é—¨åº—收益
        if (depositShopFee > 0 && order.getDepositShopId() != null) {
            ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId());
            if (depositShop != null && depositShop.getRegionMemberId() != null) {
                revenueMapper.insert(buildRevenue(depositShop.getRegionMemberId(), Constants.TWO,
            if (depositShop != null && depositShop.getId() != null) {
                revenueMapper.insert(buildRevenue(depositShop.getId(), Constants.TWO,
                        depositShopFee, orderId, order.getCode()));
            }
        }
@@ -3191,8 +3208,8 @@
        // å–件门店收益(异地寄存且有取件门店)
        if (takeShopFee > 0 && order.getTakeShopId() != null) {
            ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId());
            if (takeShop != null && takeShop.getRegionMemberId() != null) {
                revenueMapper.insert(buildRevenue(takeShop.getRegionMemberId(), Constants.TWO,
            if (takeShop != null && takeShop.getId() != null) {
                revenueMapper.insert(buildRevenue(takeShop.getId(), Constants.TWO,
                        takeShopFee, orderId, order.getCode()));
            }
        }
@@ -3729,7 +3746,7 @@
        QueryWrapper<Orders> wrapper = new QueryWrapper<>();
        wrapper.eq("MEMBER_ID", memberId)
                .in("STATUS", 0, 1, 2, 3, 4, 5)
                .orderByDesc("CREATE_TIME")
                .orderByAsc("CREATE_TIME")
                .last("LIMIT 1");
        Orders order = ordersMapper.selectOne(wrapper);
        if (order == null) {
@@ -4061,31 +4078,28 @@
            for (int i = 0; i < paramPairs.length - 1; i += 2) {
                templateParam.put(paramPairs[i], paramPairs[i + 1]);
            }
            boolean result = AliSmsService.sendSms(phone, smsNotify.getTemplateCode(),
            String error = AliSmsService.sendSms(phone, smsNotify.getTemplateCode(),
                    templateParam.toJSONString());
            if (result) {
                log.info("短信发送成功: phone={}, template={}", phone, smsNotify.name());
            } else {
                log.warn("短信发送失败: phone={}, template={}", phone, smsNotify.name());
            }
            // å­˜å‚¨çŸ­ä¿¡è®°å½•
            Smsrecord record = new Smsrecord();
            record.setPhone(phone);
            record.setContent(content);
            record.setType(Constants.ONE); // 1=订单通知
            record.setStatus(result ? Constants.ONE : Constants.ZERO); // 1=已发送, 0=发送失败
            record.setType(Constants.ONE);
            record.setStatus(error == null ? Constants.ONE : Constants.ZERO);
            if (error != null) {
                record.setRemark(error);
            }
            record.setCreateTime(new Date());
            record.setDeleted(Constants.ZERO);
            smsrecordMapper.insert(record);
        } catch (Exception e) {
            log.error("短信发送异常: phone={}, template={}, error={}", phone, smsNotify.name(), e.getMessage());
            // å¼‚常也记录
            try {
                Smsrecord record = new Smsrecord();
                record.setPhone(phone);
                record.setContent(content);
                record.setType(Constants.ONE);
                record.setStatus(Constants.ZERO); // å‘送失败
                record.setStatus(Constants.ZERO);
                record.setRemark(e.getMessage());
                record.setCreateTime(new Date());
                record.setDeleted(Constants.ZERO);
                smsrecordMapper.insert(record);
server/services/src/main/java/com/doumee/service/business/impl/PrinterInfoServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,118 @@
package com.doumee.service.business.impl;
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.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.xpyun.XpyunPrintService;
import com.doumee.core.utils.xpyun.XpyunResponse;
import com.doumee.dao.business.PrinterInfoMapper;
import com.doumee.dao.business.model.PrinterInfo;
import com.doumee.service.business.PrinterInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
 * æ‰“印机信息Service实现
 * @author rk
 * @date 2026/04/28
 */
@Service
public class PrinterInfoServiceImpl implements PrinterInfoService {
    @Autowired
    private PrinterInfoMapper printerInfoMapper;
    @Autowired
    private XpyunPrintService xpyunPrintService;
    @Override
    public Integer create(PrinterInfo printerInfo) {
        if (StringUtils.isBlank(printerInfo.getSn())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "打印机SN不能为空");
        }
        if (StringUtils.isBlank(printerInfo.getName())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "打印机名称不能为空");
        }
        XpyunResponse response = xpyunPrintService.addPrinter(printerInfo.getSn(), printerInfo.getName());
        if (response.getCode() != 0) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "芯烨云添加打印机失败:" + response.getMsg());
        }
        printerInfoMapper.insert(printerInfo);
        return printerInfo.getId();
    }
    @Override
    public void deleteById(Integer id) {
        printerInfoMapper.deleteById(id);
    }
    @Override
    public void delete(PrinterInfo printerInfo) {
        printerInfoMapper.delete(new QueryWrapper<>(printerInfo));
    }
    @Override
    public void deleteByIdInBatch(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        printerInfoMapper.deleteBatchIds(ids);
    }
    @Override
    public void updateById(PrinterInfo printerInfo) {
        printerInfoMapper.updateById(printerInfo);
    }
    @Override
    public void updateByIdInBatch(List<PrinterInfo> printerInfos) {
        if (CollectionUtils.isEmpty(printerInfos)) {
            return;
        }
        for (PrinterInfo printerInfo : printerInfos) {
            this.updateById(printerInfo);
        }
    }
    @Override
    public PrinterInfo findById(Integer id) {
        return printerInfoMapper.selectById(id);
    }
    @Override
    public PrinterInfo findOne(PrinterInfo printerInfo) {
        return printerInfoMapper.selectOne(new QueryWrapper<>(printerInfo));
    }
    @Override
    public List<PrinterInfo> findList(PrinterInfo printerInfo) {
        return printerInfoMapper.selectList(new QueryWrapper<>(printerInfo));
    }
    @Override
    public PageData<PrinterInfo> findPage(PageWrap<PrinterInfo> pageWrap) {
        IPage<PrinterInfo> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        QueryWrapper<PrinterInfo> wrapper = new QueryWrapper<>(pageWrap.getModel());
        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                wrapper.orderByDesc(sortData.getProperty());
            } else {
                wrapper.orderByAsc(sortData.getProperty());
            }
        }
        return PageData.from(printerInfoMapper.selectPage(page, wrapper));
    }
    @Override
    public long count(PrinterInfo printerInfo) {
        return printerInfoMapper.selectCount(new QueryWrapper<>(printerInfo));
    }
}
server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java
@@ -229,13 +229,7 @@
        if (pageWrap.getModel().getOpenid() != null) {
            queryWrapper.lambda().like(ShopInfo::getOpenid, pageWrap.getModel().getOpenid());
        }
        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        queryWrapper.lambda().orderByDesc(ShopInfo::getId);
        return PageData.from(shopInfoMapper.selectPage(page, queryWrapper));
    }
@@ -1094,6 +1088,7 @@
        // å–件门店
        List<Orders> takeSalesOrders = ordersMapper.selectList(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getDeleted, Constants.ZERO)
                .eq(Orders::getType,Constants.ONE)
                .ge(Orders::getCreateTime, startTime)
                .lt(Orders::getCreateTime, endTime)
                .eq(Orders::getTakeShopId, shopId));
@@ -1124,19 +1119,27 @@
        vo.setSettlementProfit(depositFee + takeFee);
        // 3. åœ¨åº“订单数
        // 3.1 å­˜ä»¶é—¨åº—=本门店,status in (2已寄存, 5待取件)
        Long depositStorageCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
        // 3.1 å°±åœ°è®¢å•:存件门店=本门店,type=0,status in (2已寄存, 5待取件)
        Long localStorageCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getDeleted, Constants.ZERO)
                .eq(Orders::getDepositShopId, shopId)
                .eq(Orders::getType, Constants.ZERO)
                .in(Orders::getStatus,
                        Constants.OrderStatus.deposited.getStatus(),
                        Constants.OrderStatus.arrived.getStatus()));
        // 3.2 å–件门店=本门店,status = 5待取件
        // 3.2 å¼‚地订单:存件门店=本门店,type=1,status=2已寄存
        Long remoteStorageCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getDeleted, Constants.ZERO)
                .eq(Orders::getDepositShopId, shopId)
                .eq(Orders::getType, Constants.ONE)
                .eq(Orders::getStatus, Constants.OrderStatus.deposited.getStatus()));
        // 3.3 å–件门店=本门店,异地订单,status = 5待取件
        Long takeStorageCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getDeleted, Constants.ZERO)
                .eq(Orders::getType,Constants.ONE)
                .eq(Orders::getTakeShopId, shopId)
                .eq(Orders::getStatus, Constants.OrderStatus.arrived.getStatus()));
        vo.setStorageCount(depositStorageCount.intValue() + takeStorageCount.intValue());
        vo.setStorageCount(localStorageCount.intValue() + remoteStorageCount.intValue() + takeStorageCount.intValue());
        return vo;
    }
@@ -1327,10 +1330,12 @@
        if (shopInfo.getCompanyType() == null) {
            return;
        }
        Areas areas = areasService.findById(shopInfo.getAreaId());
        PricingRule pricingRule = pricingRuleMapper.selectOne(new QueryWrapper<PricingRule>().lambda()
                .eq(PricingRule::getDeleted, Constants.ZERO)
                .eq(PricingRule::getType, Constants.THREE)
                .eq(PricingRule::getFieldA, String.valueOf(shopInfo.getCompanyType()))
                .eq(PricingRule::getFieldA, String.valueOf(Constants.equalsInteger(shopInfo.getCompanyType(),Constants.ZERO)?Constants.ONE:Constants.ZERO))
                .eq(PricingRule::getCityId, areas.getParentId())
                .last("limit 1"));
        if (pricingRule != null && StringUtils.isNotBlank(pricingRule.getFieldB())) {
            shopInfo.setDepositAmount(Long.parseLong(pricingRule.getFieldB()));
@@ -1360,19 +1365,16 @@
            for (int i = 0; i < paramPairs.length - 1; i += 2) {
                templateParam.put(paramPairs[i], paramPairs[i + 1]);
            }
            boolean result = AliSmsService.sendSms(phone, smsNotify.getTemplateCode(),
            String error = AliSmsService.sendSms(phone, smsNotify.getTemplateCode(),
                    templateParam.toJSONString());
            if (result) {
                log.info("短信发送成功: phone={}, template={}", phone, smsNotify.name());
            } else {
                log.warn("短信发送失败: phone={}, template={}", phone, smsNotify.name());
            }
            // å­˜å‚¨çŸ­ä¿¡è®°å½•
            Smsrecord smsRecord = new Smsrecord();
            smsRecord.setPhone(phone);
            smsRecord.setContent(content);
            smsRecord.setType(Constants.ONE);
            smsRecord.setStatus(result ? Constants.ONE : Constants.ZERO);
            smsRecord.setStatus(error == null ? Constants.ONE : Constants.ZERO);
            if (error != null) {
                smsRecord.setRemark(error);
            }
            smsRecord.setCreateTime(new Date());
            smsRecord.setDeleted(Constants.ZERO);
            smsrecordMapper.insert(smsRecord);
@@ -1416,4 +1418,56 @@
        }
    }
    @Autowired
    private com.doumee.core.utils.xpyun.XpyunPrintService xpyunPrintService;
    @Override
    public void bindPrinter(com.doumee.dao.dto.PrinterBindDTO dto) {
        ShopInfo shop = shopInfoMapper.selectById(dto.getShopId());
        if (shop == null || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        // è°ƒç”¨èŠ¯çƒ¨äº‘æ³¨å†Œæ‰“å°æœº
        com.doumee.core.utils.xpyun.XpyunResponse resp = xpyunPrintService.addPrinter(
                dto.getPrinterSn(), shop.getName());
        if (resp.getCode() != null && resp.getCode() == 0) {
            log.info("芯烨云打印机注册成功: sn={}", dto.getPrinterSn());
        } else {
            log.warn("芯烨云打印机注册返回非0: sn={}, code={}, msg={}",
                    dto.getPrinterSn(), resp.getCode(), resp.getMsg());
        }
        // æ— è®ºäº‘端是否成功,都绑定到门店(可后续重试云端注册)
        ShopInfo update = new ShopInfo();
        update.setId(dto.getShopId());
        update.setPrinterSn(dto.getPrinterSn());
        shopInfoMapper.updateById(update);
    }
    @Override
    public void unbindPrinter(Integer shopId) {
        ShopInfo shop = shopInfoMapper.selectById(shopId);
        if (shop == null || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        if (StringUtils.isNotBlank(shop.getPrinterSn())) {
            xpyunPrintService.deletePrinter(shop.getPrinterSn());
        }
        ShopInfo update = new ShopInfo();
        update.setId(shopId);
        update.setPrinterSn(null);
        shopInfoMapper.updateById(update);
    }
    @Override
    public Object queryPrinterStatus(Integer shopId) {
        ShopInfo shop = shopInfoMapper.selectById(shopId);
        if (shop == null || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        if (StringUtils.isBlank(shop.getPrinterSn())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该门店未绑定打印机");
        }
        return xpyunPrintService.queryPrinterStatus(shop.getPrinterSn());
    }
}
server/services/src/main/java/com/doumee/service/business/impl/SmsrecordServiceImpl.java
@@ -178,8 +178,8 @@
        String digits = Strings.randomNumeric(4);
        //发送验证码
        String templateParam = "{\"code\":\"" + digits + "\"}";
        Boolean result = AliSmsService.sendSms(phone, "SMS_491325122", templateParam);
        if (!result) {
        String error = AliSmsService.sendSms(phone, Constants.SmsNotify.VERIFY_CODE.getTemplateCode(), templateParam);
        if (error != null) {
            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "短信发送失败,请稍后重试");
        }
        //存储短信验证码
server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
@@ -191,13 +191,8 @@
        if (StringUtils.isNotBlank(pageWrap.getModel().getMemberName())) {
            queryWrapper.like(DriverInfo::getName, pageWrap.getModel().getMemberName());
        }
        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        queryWrapper.orderByDesc(WithdrawalOrders::getId);
        return PageData.from(withdrawalOrdersMapper.selectJoinPage(page, WithdrawalOrders.class, queryWrapper));
    }
@@ -285,7 +280,7 @@
                    }
                } else if (Constants.equalsInteger(order.getMemberType(), Constants.TWO)) {
                    ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
                            .eq(ShopInfo::getRegionMemberId, order.getMemberId())
                            .eq(ShopInfo::getId, order.getMemberId())
                            .eq(ShopInfo::getDeleted, Constants.ZERO)
                            .last("limit 1"));
                    if (shop != null) {
@@ -305,7 +300,7 @@
                    }
                } else if (Constants.equalsInteger(order.getMemberType(), Constants.TWO)) {
                    ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
                            .eq(ShopInfo::getRegionMemberId, order.getMemberId())
                            .eq(ShopInfo::getId, order.getMemberId())
                            .eq(ShopInfo::getDeleted, Constants.ZERO)
                            .last("limit 1"));
                    if (shop != null) {
@@ -390,7 +385,7 @@
                } else if (Constants.equalsInteger(order.getMemberType(), Constants.TWO)) {
                    // é—¨åº—:通过 memberId æŸ¥ ShopInfo,退回 balance
                    ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
                            .eq(ShopInfo::getRegionMemberId, order.getMemberId())
                            .eq(ShopInfo::getId, order.getMemberId())
                            .eq(ShopInfo::getDeleted, Constants.ZERO)
                            .last("limit 1"));
                    if (shop != null) {
@@ -490,12 +485,22 @@
        order.setType(Constants.ZERO);
        order.setOutBillNo(billNo);
        order.setAliAccount(dto.getAliAccount());
        order.setAliName(driver.getAliName());
        order.setAliName(dto.getAliName());
        order.setDeleted(Constants.ZERO);
        order.setCreateTime(now);
        order.setUpdateTime(now);
        order.setCreateUser(memberId);
        withdrawalOrdersMapper.insert(order);
        // æ”¯ä»˜å®è´¦æˆ·æˆ–姓名有变化时更新司机信息
        boolean aliChanged = !dto.getAliAccount().equals(driver.getAliAccount())
                || (dto.getAliName() != null && !dto.getAliName().equals(driver.getAliName()));
        if (aliChanged) {
            DriverInfo update = new DriverInfo();
            update.setId(driver.getId());
            update.setAliAccount(dto.getAliAccount());
            update.setAliName(dto.getAliName());
            driverInfoMapper.updateById(update);
        }
        // åˆ›å»ºæ”¯å‡º Revenue è®°å½•
        Revenue revenue = new Revenue();
        revenue.setMemberId(memberId);
@@ -535,22 +540,32 @@
                .eq(ShopInfo::getId, shopId));
        // åˆ›å»ºæçŽ°è®°å½•
        WithdrawalOrders order = new WithdrawalOrders();
        order.setMemberId(shop.getRegionMemberId());
        order.setMemberId(shop.getId());
        order.setMemberType(Constants.TWO);
        order.setAmount(amountFen);
        order.setStatus(Constants.ZERO);
        order.setType(Constants.ZERO);
        order.setOutBillNo(billNo);
        order.setAliAccount(dto.getAliAccount());
        order.setAliName(shop.getAliName());
        order.setAliName(dto.getAliName());
        order.setDeleted(Constants.ZERO);
        order.setCreateTime(now);
        order.setUpdateTime(now);
        order.setCreateUser(shop.getRegionMemberId());
        withdrawalOrdersMapper.insert(order);
        // æ”¯ä»˜å®è´¦æˆ·æˆ–姓名有变化时更新门店信息
        boolean aliChanged = !dto.getAliAccount().equals(shop.getAliAccount())
                || (dto.getAliName() != null && !dto.getAliName().equals(shop.getAliName()));
        if (aliChanged) {
            ShopInfo update = new ShopInfo();
            update.setId(shopId);
            update.setAliAccount(dto.getAliAccount());
            update.setAliName(dto.getAliName());
            shopInfoMapper.updateById(update);
        }
        // åˆ›å»ºæ”¯å‡º Revenue è®°å½•
        Revenue revenue = new Revenue();
        revenue.setMemberId(shop.getRegionMemberId());
        revenue.setMemberId(shop.getId());
        revenue.setMemberType(Constants.TWO);
        revenue.setType(Constants.ONE); // 1=提现支出
        revenue.setOptType(-Constants.ONE); // -1=支出
server/web/src/main/java/com/doumee/api/web/ConfigApi.java
@@ -1,5 +1,6 @@
package com.doumee.api.web;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.annotation.LoginDriverRequired;
import com.doumee.core.annotation.LoginRequired;
import com.doumee.core.annotation.LoginShopRequired;
@@ -12,6 +13,7 @@
import com.doumee.dao.business.model.Areas;
import com.doumee.dao.business.model.Banner;
import com.doumee.dao.business.model.Category;
import com.doumee.dao.business.model.AppVersion;
import com.doumee.dao.business.model.Notice;
import com.alibaba.fastjson.JSONObject;
import com.doumee.dao.dto.AreasDto;
@@ -67,6 +69,12 @@
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private AppVersionService appVersionService;
    @Autowired
    private SystemDictDataBiz systemDictDataBiz;
    @ApiOperation("全部区划树形查询")
    @PostMapping("/treeList")
    public ApiResponse<List<Areas>> treeList (@RequestBody AreasDto pageWrap) {
@@ -98,6 +106,15 @@
    })
    public ApiResponse<List<Banner>> getBannerList(@RequestParam Integer position) {
        return ApiResponse.success("操作成功", bannerService.findListByPosition(position));
    }
    @ApiOperation(value = "获取轮播图详情", notes = "根据ID返回轮播图详情,含图片全路径")
    @GetMapping("/getBannerDetail")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "id", value = "轮播图主键", required = true)
    })
    public ApiResponse<Banner> getBannerDetail(@RequestParam Integer id) {
        return ApiResponse.success("查询成功", bannerService.findById(id));
    }
    @ApiOperation(value = "获取城市已开通物品尺寸", notes = "根据城市主键查询已开通的物品尺寸(category type=4)")
@@ -168,7 +185,9 @@
        }
        pageWrap.getModel().setUserId(this.getMemberId());
        pageWrap.getModel().setUserType(Constants.ZERO);
        return ApiResponse.success("查询成功", noticeService.findPage(pageWrap));
        PageData<Notice> pageData = noticeService.findPage(pageWrap);
        noticeService.readAllNotice(0, this.getMemberId());
        return ApiResponse.success("查询成功", pageData);
    }
@@ -184,7 +203,9 @@
        }
        pageWrap.getModel().setUserId(this.getShopId());
        pageWrap.getModel().setUserType(Constants.TWO);
        return ApiResponse.success("查询成功", noticeService.findPage(pageWrap));
        PageData<Notice> pageData = noticeService.findPage(pageWrap);
        noticeService.readAllNotice(Constants.TWO, this.getShopId());
        return ApiResponse.success("查询成功", pageData);
    }
    @LoginShopRequired
@@ -235,7 +256,9 @@
        }
        pageWrap.getModel().setUserId(this.getDriverId());
        pageWrap.getModel().setUserType(Constants.ONE);
        return ApiResponse.success("查询成功", noticeService.findPage(pageWrap));
        PageData<Notice> pageData = noticeService.findPage(pageWrap);
        noticeService.readAllNotice(Constants.ONE, this.getDriverId());
        return ApiResponse.success("查询成功", pageData);
    }
    @LoginDriverRequired
@@ -256,5 +279,16 @@
        return ApiResponse.success("操作成功");
    }
    @ApiOperation(value = "获取最新APP版本")
    @GetMapping("/getApiVersion")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "type", value = "平台类型 0=Android 1=IOS", required = true)
    })
    public ApiResponse<AppVersion> getApiVersion(@RequestParam Integer type) {
        AppVersion appVersion = appVersionService.getLatestVersion(type);
        appVersion.setFileUrl("http://llfc.lmpro.cn/apkversion/gtxljc.apk");
        return ApiResponse.success("查询成功", appVersion);
    }
}
server/web/src/main/java/com/doumee/api/web/DriverInfoApi.java
@@ -18,6 +18,7 @@
import com.doumee.dao.dto.DriverVerifyRequest;
import com.doumee.dao.vo.AccountResponse;
import com.doumee.dao.dto.CancelOrderDTO;
import com.doumee.dao.dto.ChangePasswordDTO;
import com.doumee.dao.vo.DriverActiveOrderCountVO;
import com.doumee.dao.vo.DriverCancelLimitVO;
import com.doumee.dao.vo.DriverCenterVO;
@@ -237,10 +238,9 @@
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true),
    })
    public ApiResponse changePassword(@RequestParam String oldPassword,
                                       @RequestParam String newPassword) {
    public ApiResponse changePassword(@RequestBody @Valid ChangePasswordDTO dto) {
        String token = this.getRequest().getHeader(JwtTokenUtil.HEADER_KEY);
        driverInfoService.changePassword(this.getDriverId(), oldPassword, newPassword, token);
        driverInfoService.changePassword(this.getDriverId(), dto.getOldPassword(), dto.getNewPassword(), token);
        return ApiResponse.success("密码修改成功,请重新登录");
    }
server/web/src/main/java/com/doumee/api/web/PaymentCallback.java
@@ -231,10 +231,10 @@
                                    templateParam.put("orderNo", refundOrder.getCode());
                                    templateParam.put("money", String.valueOf(Constants.getFormatMoney(
                                            refundOrder.getRefundAmount() != null ? refundOrder.getRefundAmount() : 0L)));
                                    boolean smsResult = AliSmsService.sendSms(refundMember.getTelephone(),
                                    String smsError = AliSmsService.sendSms(refundMember.getTelephone(),
                                            Constants.SmsNotify.MEMBER_REFUNDED.getTemplateCode(),
                                            templateParam.toJSONString());
                                    if (smsResult) {
                                    if (smsError == null) {
                                        log.info("退款短信发送成功: phone={}", refundMember.getTelephone());
                                    } else {
                                        log.warn("退款短信发送失败: phone={}", refundMember.getTelephone());
@@ -244,7 +244,10 @@
                                    smsRecord.setPhone(refundMember.getTelephone());
                                    smsRecord.setContent(smsContent);
                                    smsRecord.setType(Constants.ONE);
                                    smsRecord.setStatus(smsResult ? Constants.ONE : Constants.ZERO);
                                    smsRecord.setStatus(smsError == null ? Constants.ONE : Constants.ZERO);
                                    if (smsError != null) {
                                        smsRecord.setRemark(smsError);
                                    }
                                    smsRecord.setCreateTime(new java.util.Date());
                                    smsRecord.setDeleted(Constants.ZERO);
                                    smsrecordMapper.insert(smsRecord);
server/web/src/main/java/com/doumee/api/web/ShopInfoApi.java
@@ -8,6 +8,7 @@
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.dto.ChangePasswordDTO;
import com.doumee.dao.dto.ShopApplyDTO;
import com.doumee.dao.dto.ShopDetailQueryDTO;
import com.doumee.dao.dto.ShopInfoMaintainDTO;
@@ -25,6 +26,7 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.Valid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -136,10 +138,9 @@
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "门店token值", required = true),
    })
    public ApiResponse changePassword(@RequestParam String oldPassword,
                                       @RequestParam String newPassword) {
    public ApiResponse changePassword(@RequestBody @Valid ChangePasswordDTO dto) {
        String token = this.getRequest().getHeader(JwtTokenUtil.HEADER_KEY);
        shopInfoService.changePassword(this.getShopId(), oldPassword, newPassword, token);
        shopInfoService.changePassword(this.getShopId(), dto.getOldPassword(), dto.getNewPassword(), token);
        return ApiResponse.success("密码修改成功,请重新登录");
    }