Преглед изворни кода

添加内部地址功能和超市商品分页功能

liu пре 9 месеци
родитељ
комит
811789bbea
43 измењених фајлова са 1745 додато и 179 уклоњено
  1. 36 0
      db/update_250913.sql
  2. 103 0
      src/main/java/com/sqx/modules/address/controller/AdminInsideAddressController.java
  3. 11 6
      src/main/java/com/sqx/modules/address/controller/app/AddressController.java
  4. 47 0
      src/main/java/com/sqx/modules/address/controller/app/InsideAddressController.java
  5. 10 1
      src/main/java/com/sqx/modules/address/dao/AddressDao.java
  6. 25 0
      src/main/java/com/sqx/modules/address/dao/InsideAddressDao.java
  7. 37 0
      src/main/java/com/sqx/modules/address/dto/AddressAddDTO.java
  8. 78 0
      src/main/java/com/sqx/modules/address/dto/InsideAddressDTO.java
  9. 19 0
      src/main/java/com/sqx/modules/address/dto/InsideAddressUpdateStatusDto.java
  10. 29 9
      src/main/java/com/sqx/modules/address/entity/Address.java
  11. 69 0
      src/main/java/com/sqx/modules/address/entity/InsideAddress.java
  12. 69 0
      src/main/java/com/sqx/modules/address/query/InsideAddressQuery.java
  13. 68 0
      src/main/java/com/sqx/modules/address/service/InsideAddressService.java
  14. 73 5
      src/main/java/com/sqx/modules/address/service/impl/AddressServiceImpl.java
  15. 317 0
      src/main/java/com/sqx/modules/address/service/impl/InsideAddressServiceImpl.java
  16. 8 0
      src/main/java/com/sqx/modules/address/validator/FullAddressGroup.java
  17. 8 0
      src/main/java/com/sqx/modules/address/validator/InsideAddressGroup.java
  18. 34 0
      src/main/java/com/sqx/modules/address/vo/InsideAddressShortVO.java
  19. 78 0
      src/main/java/com/sqx/modules/address/vo/InsideAddressVO.java
  20. 3 0
      src/main/java/com/sqx/modules/errand/entity/TbIndent.java
  21. 8 1
      src/main/java/com/sqx/modules/errand/service/impl/TbIndentServiceImpl.java
  22. 27 1
      src/main/java/com/sqx/modules/exportExecl/controller/ExportExeclController.java
  23. 1 1
      src/main/java/com/sqx/modules/goods/controller/GoodsShopController.java
  24. 14 0
      src/main/java/com/sqx/modules/goods/controller/app/AppGoodsController.java
  25. 5 0
      src/main/java/com/sqx/modules/goods/dao/GoodsDao.java
  26. 4 0
      src/main/java/com/sqx/modules/goods/service/GoodsService.java
  27. 32 0
      src/main/java/com/sqx/modules/goods/service/impl/GoodsServiceImpl.java
  28. 28 0
      src/main/java/com/sqx/modules/goods/vo/GoodsListVo.java
  29. 5 0
      src/main/java/com/sqx/modules/invite/controller/InviteController.java
  30. 3 18
      src/main/java/com/sqx/modules/order/entity/TbOrder.java
  31. 33 133
      src/main/java/com/sqx/modules/order/service/impl/AppAppOrderServiceImpl.java
  32. 25 0
      src/main/java/com/sqx/modules/riderStation/controller/app/RiderStationController.java
  33. 2 0
      src/main/java/com/sqx/modules/riderStation/service/RiderStationService.java
  34. 8 0
      src/main/java/com/sqx/modules/riderStation/service/impl/RiderStationServiceImpl.java
  35. 29 0
      src/main/java/com/sqx/modules/utils/SenInfoCheckUtil.java
  36. 96 0
      src/main/java/com/sqx/modules/utils/excel/EasyExcelUtil.java
  37. 56 0
      src/main/java/com/sqx/modules/utils/excel/ExcelDataListener.java
  38. 22 0
      src/main/java/com/sqx/modules/utils/excel/ExcelFinishCallBack.java
  39. 88 0
      src/main/java/com/sqx/scheduler/export/ExportScheduler.java
  40. 0 1
      src/main/resources/application-dev.yml
  41. 11 3
      src/main/resources/mapper/address/AddressDao.xml
  42. 86 0
      src/main/resources/mapper/address/InsideAddressDao.xml
  43. 40 0
      src/main/resources/mapper/goods/GoodsMapper.xml

+ 36 - 0
db/update_250913.sql

@@ -0,0 +1,36 @@
+-- address 新增内部地址id
+alter table address add inside_address_id bigint comment '内部地址id' after lat;
+
+-- address 新增备注字段
+ALTER TABLE address ADD remark varchar(900) comment '备注';
+
+-- 新增系统配置 是否开启校内地址 1是,0否
+INSERT INTO common_info (id, create_at, max, min, type, value, condition_from) VALUES (442, '2025-09-14 11:34:00', null, '是否开启校内地址', 442, '1', 'xitong');
+
+-- 修改表:tb_indent[跑腿订单]
+-- 添加字段:
+ALTER TABLE tb_indent ADD COLUMN `inside_delivery_fee` DECIMAL(24,6) NOT NULL DEFAULT 0 COMMENT '校内跑腿费;' AFTER indent_money;
+/* --------------- 修改表 --------------- */
+-- 修改表:tb_order[订单主表]
+-- 添加字段:
+ALTER TABLE tb_order ADD COLUMN `inside_delivery_fee` DECIMAL(24,6) NOT NULL DEFAULT 0 COMMENT '校内配送费;' AFTER errand_money;
+
+-- 新增内部地址表
+DROP TABLE IF EXISTS inside_address;
+CREATE TABLE inside_address(
+       `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+       `del_flag` VARCHAR(1) NOT NULL   COMMENT '删除标识;0未删除、1已删除' ,
+       `create_time` DATETIME NOT NULL   COMMENT '创建时间' ,
+       `update_time` DATETIME NOT NULL   COMMENT '更新时间' ,
+       `station_id` bigint NOT NULL   COMMENT '站点id' ,
+       `delivery_fee` DECIMAL(24,6) NOT NULL   COMMENT '配送费用' ,
+       `province` VARCHAR(32) NOT NULL   COMMENT '省份' ,
+       `city` VARCHAR(32) NOT NULL   COMMENT '城市' ,
+       `district` VARCHAR(32) NOT NULL   COMMENT '区县' ,
+       `address_detail` VARCHAR(90) NOT NULL   COMMENT '地址详情' ,
+       `lng` DECIMAL(24,6) NOT NULL   COMMENT '经度' ,
+       `lat` DECIMAL(24,6) NOT NULL   COMMENT '维度' ,
+       `status` VARCHAR(1) NOT NULL  DEFAULT 1 COMMENT '启用状态;1启用、0禁用' ,
+       `sort` INT NOT NULL  DEFAULT 1 COMMENT '排序' ,
+       PRIMARY KEY (id)
+)  COMMENT = '内部地址';

+ 103 - 0
src/main/java/com/sqx/modules/address/controller/AdminInsideAddressController.java

@@ -0,0 +1,103 @@
+package com.sqx.modules.address.controller;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.common.utils.Result;
+import com.sqx.modules.address.dto.InsideAddressDTO;
+import com.sqx.modules.address.dto.InsideAddressUpdateStatusDto;
+import com.sqx.modules.address.entity.InsideAddress;
+import com.sqx.modules.address.query.InsideAddressQuery;
+import com.sqx.modules.address.service.InsideAddressService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.Valid;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.List;
+
+
+@RestController
+@Api(value = "管理端-内部地址", tags = {"管理端-内部地址"})
+@RequestMapping(value = "admin/inside-address")
+@RequiredArgsConstructor
+public class AdminInsideAddressController {
+
+    private final InsideAddressService insideAddressService;
+
+    @GetMapping("pages")
+    @ApiOperation("分页查询内部地址列表")
+    public Result pages(@Valid InsideAddressQuery query) {
+        PageUtils pageUtils = insideAddressService.pages(query);
+        return Result.success().put("data", pageUtils);
+    }
+
+    @PostMapping("add")
+    @ApiOperation("新增内部地址")
+    public Result add(@Valid @RequestBody InsideAddressDTO insideAddressDTO) {
+        insideAddressService.addInsideAddress(insideAddressDTO);
+        return Result.success();
+    }
+
+    @PostMapping("update")
+    @ApiOperation("更新内部地址")
+    public Result update(@Valid @RequestBody InsideAddressDTO insideAddressDTO) {
+        if (ObjectUtil.isNull(insideAddressDTO.getId())) {
+            throw new SqxException("id不能为空");
+        }
+        insideAddressService.updateInsideAddress(insideAddressDTO);
+        return Result.success();
+    }
+
+    @PostMapping("delete")
+    @ApiOperation("删除内部地址")
+    public Result delete(@RequestBody List<Long> ids) {
+        insideAddressService.deleteByIds(ids);
+        return Result.success();
+    }
+
+    @PostMapping("updateStatus")
+    @ApiOperation("更改状态")
+    public Result updateStatus(@Valid @RequestBody InsideAddressUpdateStatusDto dto) {
+        if (ObjectUtil.isNull(dto.getId())) {
+            throw new SqxException("id不能为空");
+        }
+        InsideAddress insideAddress = new InsideAddress();
+        BeanUtil.copyProperties(dto,insideAddress);
+        insideAddressService.updateById(insideAddress);
+        return Result.success();
+    }
+
+    @GetMapping("export")
+    @ApiOperation("导出内部地址列表")
+    public void export(@Valid InsideAddressQuery query) {
+        insideAddressService.exportData(query);
+    }
+
+    @PostMapping("import")
+    @ApiOperation("导入内部地址列表")
+    public Result importData(@RequestParam("file") MultipartFile file) throws IOException, ParseException {
+        if (file.isEmpty()) {
+            throw new SqxException("请选择需要上传的文件");
+        }
+
+        insideAddressService.importData(file);
+        return Result.success();
+    }
+
+    @GetMapping( "/downloadInsideAddressExcel")
+    @ApiOperation(value = "内部地址导出模板", notes = "内部地址导出模板", httpMethod = "GET")
+    public Result downloadInsideAddressExcel() {
+        return Result.success().put("data", "https://mxys.chuanghai-tech.com/wmfile/file/收货地址管理导出模板.xlsx");
+    }
+}

+ 11 - 6
src/main/java/com/sqx/modules/address/controller/app/AddressController.java

@@ -2,6 +2,7 @@ package com.sqx.modules.address.controller.app;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.sqx.common.exception.SqxException;
 import com.sqx.common.utils.Result;
 import com.sqx.modules.address.entity.Address;
 import com.sqx.modules.address.service.AddressService;
@@ -13,7 +14,12 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -21,7 +27,6 @@ import java.util.Map;
 @RestController
 @Api(value = "用户端-地址", tags = {"用户端-地址"})
 @RequestMapping(value = "/app/address")
-@Slf4j
 public class AddressController {
 
     @Autowired
@@ -93,10 +98,9 @@ public class AddressController {
                 JSONObject result = jsonObject.getJSONObject("result");
                 JSONObject adInfo = result.getJSONObject("ad_info");
                 return Result.success().put("data", adInfo);
-            } else {
-                log.error("转换失败!!!原因:" + jsonObject.getString("message"));
             }
-            return Result.error("获取定位失败!");
+
+            throw new SqxException(jsonObject.getString("message"));
         }else{
             String value = commonInfoService.findOne(417).getValue();
             String url="http://api.tianditu.gov.cn/geocoder";
@@ -123,7 +127,8 @@ public class AddressController {
                 jsonObject1.put("district",county);
                 return Result.success().put("data", jsonObject1);
             }
-            return Result.error("获取定位失败!");
+
+            throw new SqxException("获取定位失败!");
         }
     }
 

+ 47 - 0
src/main/java/com/sqx/modules/address/controller/app/InsideAddressController.java

@@ -0,0 +1,47 @@
+package com.sqx.modules.address.controller.app;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.Result;
+import com.sqx.modules.address.entity.InsideAddress;
+import com.sqx.modules.address.service.InsideAddressService;
+import com.sqx.modules.address.vo.InsideAddressShortVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@Api(value = "用户端-内部地址", tags = {"用户端-内部地址"})
+@RequestMapping(value = "app/inside-address")
+@RequiredArgsConstructor
+public class InsideAddressController {
+
+    private final InsideAddressService insideAddressService;
+
+    @ApiOperation("根据站点id查询内部地址列表")
+    @GetMapping("list/{stationId}")
+    public Result listByStationId(@PathVariable("stationId") Long stationId) {
+        List<InsideAddress> list = insideAddressService.listByStationId(stationId);
+        return Result.success().put("data", list);
+    }
+
+    @ApiOperation("根据id查询内部地址")
+    @GetMapping("{id}")
+    public Result info(@PathVariable("id") Long id) {
+        InsideAddress address = insideAddressService.getById(id);
+        if(ObjectUtil.isNull(address)){
+            throw new SqxException("无效的内部地址id");
+        }
+
+        InsideAddressShortVO insideAddressShortVO = new InsideAddressShortVO();
+        BeanUtil.copyProperties(address, insideAddressShortVO);
+        return Result.success().put("data", insideAddressShortVO);
+    }
+}

+ 10 - 1
src/main/java/com/sqx/modules/address/dao/AddressDao.java

@@ -5,10 +5,19 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.sqx.modules.address.entity.Address;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 @Mapper
 public interface AddressDao extends BaseMapper<Address> {
 
-    IPage<Address> selectAddressList(Page<Address> pages, Long userId);
+    /**
+     * 分页查询用户地址列表
+     *
+     * @param pages             分页信息
+     * @param userId            用户id
+     * @param insideAddressFlag 是否查询内部地址标识
+     * @return 用户地址列表
+     */
+    IPage<Address> selectAddressList(@Param("pages") Page<Address> pages, @Param("userId") Long userId, @Param("insideAddressFlag") Boolean insideAddressFlag);
 
 }

+ 25 - 0
src/main/java/com/sqx/modules/address/dao/InsideAddressDao.java

@@ -0,0 +1,25 @@
+package com.sqx.modules.address.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.sqx.modules.address.entity.InsideAddress;
+import com.sqx.modules.address.query.InsideAddressQuery;
+import com.sqx.modules.address.vo.InsideAddressVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 内部地址 dao
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Mapper
+public interface InsideAddressDao extends BaseMapper<InsideAddress> {
+
+    IPage<InsideAddressVO> selectPages(@Param("page") Page<InsideAddress> page, @Param("query") InsideAddressQuery query);
+
+    List<InsideAddressVO> exportShippingAddress(@Param("query") InsideAddressQuery query);
+}

+ 37 - 0
src/main/java/com/sqx/modules/address/dto/AddressAddDTO.java

@@ -0,0 +1,37 @@
+package com.sqx.modules.address.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+/**
+ * 用户根据内部地址新增地址DTO
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Data
+public class AddressAddDTO {
+
+    @ApiModelProperty(value = "用户名称")
+    @NotBlank(message = "用户名称不能为空")
+    private String userName;
+
+    @ApiModelProperty(value = "手机号")
+    @NotBlank(message = "手机号不能为空")
+    private String phone;
+
+    @ApiModelProperty(value = "内部地址id")
+    @NotNull(message = "内部地址id不能为空")
+    private Long insideAddressId;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty("默认地址 0:非默认  1:默认")
+    @NotNull(message = "默认地址不能为空")
+    @Pattern(regexp = "0|1", message = "默认地址格式错误")
+    private Integer addressDefault;
+}

+ 78 - 0
src/main/java/com/sqx/modules/address/dto/InsideAddressDTO.java

@@ -0,0 +1,78 @@
+package com.sqx.modules.address.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+/**
+ * 内部地址
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Data
+@ApiModel(value = "内部地址")
+public class InsideAddressDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(name = "id,修改时不能为空")
+    private Long id;
+
+    @ApiModelProperty(name = "站点id")
+    @NotNull(message = "站点id不能为空")
+    @ExcelProperty(value = "站点id")
+    private Long stationId;
+
+    @ApiModelProperty(name = "配送费用")
+    @NotNull(message = "配送费用不能为空")
+    @Min(value = 0, message = "配送费用不能小于0")
+    @ExcelProperty(value = "配送费用")
+    private Double deliveryFee;
+
+    @ApiModelProperty(name = "省份")
+    @NotBlank(message = "省份不能为空")
+    @ExcelProperty(value = "省份")
+    private String province;
+
+    @ApiModelProperty(name = "城市")
+    @NotBlank(message = "城市不能为空")
+    @ExcelProperty(value = "城市")
+    private String city;
+
+    @ApiModelProperty(name = "区县")
+    @NotBlank(message = "区县不能为空")
+    @ExcelProperty(value = "区县")
+    private String district;
+
+    @ApiModelProperty(name = "地址详情")
+    @NotBlank(message = "地址详情不能为空")
+    @ExcelProperty(value = "地址详情")
+    private String addressDetail;
+
+    @ApiModelProperty(name = "经度")
+    @NotNull(message = "经度不能为空")
+    @ExcelProperty(value = "经度")
+    private Double lng;
+
+    @ApiModelProperty(name = "纬度")
+    @NotNull(message = "纬度不能为空")
+    @ExcelProperty(value = "纬度")
+    private Double lat;
+
+    @ApiModelProperty(name = "启用状态;1启用、0禁用")
+    @NotBlank(message = "启用状态不能为空")
+    @Pattern(regexp = "0|1", message = "启用状态只能为0或1")
+    @ExcelProperty(value = "启用状态")
+    private String status;
+
+    @ApiModelProperty(name = "排序")
+    @NotNull(message = "排序不能为空")
+    @ExcelProperty(value = "排序")
+    private Integer sort;
+}

+ 19 - 0
src/main/java/com/sqx/modules/address/dto/InsideAddressUpdateStatusDto.java

@@ -0,0 +1,19 @@
+package com.sqx.modules.address.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+@Data
+public class InsideAddressUpdateStatusDto {
+    @ApiModelProperty(name = "id,修改时不能为空")
+    private Long id;
+
+    @ApiModelProperty(name = "启用状态;1启用、0禁用")
+    @NotBlank(message = "启用状态不能为空")
+    @Pattern(regexp = "0|1", message = "启用状态只能为0或1")
+    private String status;
+}

+ 29 - 9
src/main/java/com/sqx/modules/address/entity/Address.java

@@ -1,11 +1,18 @@
 package com.sqx.modules.address.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.sqx.modules.address.validator.FullAddressGroup;
+import com.sqx.modules.address.validator.InsideAddressGroup;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 @Data
 public class Address implements Serializable {
@@ -13,57 +20,70 @@ public class Address implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @TableId(type = IdType.AUTO)
-
     @ApiModelProperty("主键id")
     private Long addressId;
 
-
     @ApiModelProperty("用户id")
     private Long userId;
 
-
     @ApiModelProperty("用户姓名")
+    @NotBlank(message = "用户姓名不能为空", groups = {FullAddressGroup.class, InsideAddressGroup.class})
     private String userName;
 
-
     @ApiModelProperty("用户电话")
+    @NotBlank(message = "用户电话不能为空", groups = {FullAddressGroup.class, InsideAddressGroup.class})
     private String userPhone;
 
-
     @ApiModelProperty("用户地址")
+    @NotBlank(message = "省份不能为空", groups = {FullAddressGroup.class})
     private String province;
 
     @ApiModelProperty("用户地址")
+    @NotBlank(message = "城市不能为空", groups = {FullAddressGroup.class})
     private String city;
 
     @ApiModelProperty("用户地址")
+    @NotBlank(message = "区县不能为空", groups = {FullAddressGroup.class})
     private String district;
 
-
     @ApiModelProperty("用户详细地址(用户手动输入的地址)")
+    @NotBlank(message = "详细地址不能为空", groups = {FullAddressGroup.class})
     private String addressDetail;
 
     @ApiModelProperty("经度")
+    @NotNull(message = "经度不能为空", groups = {FullAddressGroup.class})
     private Double lng;
 
     @ApiModelProperty("维度")
+    @NotNull(message = "纬度不能为空", groups = {FullAddressGroup.class})
     private Double lat;
 
+    @ApiModelProperty("内部地址id,当用户选择使用内部地址时,该字段不能为空")
+    @NotNull(message = "内部地址id不能为空", groups = {InsideAddressGroup.class})
+    private Long insideAddressId;
 
     @ApiModelProperty("创建时间")
     private String createTime;
 
-
     @ApiModelProperty("是否删除(0:未删除;1:删除)")
     private Integer deleteFlag;
 
+    @ApiModelProperty("备注")
+    private String remark;
 
     @ApiModelProperty("默认地址 0:非默认  1:默认")
+    @NotNull(message = "默认地址不能为空", groups = {FullAddressGroup.class, InsideAddressGroup.class})
+    @Pattern(regexp = "0|1", message = "默认地址只能为0或1")
     private Integer addressDefault;
 
-
     @ApiModelProperty("修改时间")
     private String updateTime;
 
-    public Address() {}
+    @ApiModelProperty("校内地址配送费")
+    @TableField(exist = false)
+    private BigDecimal insideDeliveryFee;
+
+    @ApiModelProperty(name = "站点id")
+    @TableField(exist = false)
+    private Long stationId;
 }

+ 69 - 0
src/main/java/com/sqx/modules/address/entity/InsideAddress.java

@@ -0,0 +1,69 @@
+package com.sqx.modules.address.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 内部地址
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Data
+@ApiModel(value = "内部地址")
+@TableName("inside_address")
+public class InsideAddress implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(name = "id")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(name = "删除标识;0未删除、1已删除")
+    @TableLogic(value = "0", delval = "1")
+    private String delFlag;
+
+    @ApiModelProperty(name = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(name = "更新时间")
+    private Date updateTime;
+
+    @ApiModelProperty(name = "站点id")
+    private Long stationId;
+
+    @ApiModelProperty(name = "配送费用")
+    private BigDecimal deliveryFee;
+
+    @ApiModelProperty(name = "省份")
+    private String province;
+
+    @ApiModelProperty(name = "城市")
+    private String city;
+
+    @ApiModelProperty(name = "区县")
+    private String district;
+
+    @ApiModelProperty(name = "地址详情")
+    private String addressDetail;
+
+    @ApiModelProperty(name = "经度")
+    private Double lng;
+
+    @ApiModelProperty(name = "维度")
+    private Double lat;
+
+    @ApiModelProperty(name = "启用状态;1启用、0禁用")
+    private String status;
+
+    @ApiModelProperty(name = "排序")
+    private Integer sort;
+}

+ 69 - 0
src/main/java/com/sqx/modules/address/query/InsideAddressQuery.java

@@ -0,0 +1,69 @@
+package com.sqx.modules.address.query;
+
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.sqx.common.query.PageQuery;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+
+/**
+ * 内部地址查询
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Data
+public class InsideAddressQuery extends PageQuery {
+
+    @ApiModelProperty("地址详情")
+    private String addressDetail;
+
+    @ApiModelProperty("状态")
+    private String status;
+
+    @ApiModelProperty("站点id")
+    private Long stationId;
+
+    @ApiModelProperty("查询开始时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date startTime;
+
+    @ApiModelProperty("查询结束时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date endTime;
+
+    @ApiModelProperty(value = "登录人id")
+    private String userId;
+
+    public String toStrMessage() {
+        DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        StringBuilder stringBuilder=new StringBuilder();
+        stringBuilder
+                .append(StringUtils.hasText(addressDetail)?"地址详情:"+addressDetail+";":"")
+                .append(ObjectUtils.isNotEmpty(startTime) ?"查询开始时间:"+ LocalDateTime.ofInstant(startTime.toInstant(), ZoneId.systemDefault()).format(dateTimeFormatter1)+";":"")
+                .append(ObjectUtils.isNotEmpty(endTime)?"查询结束时间:"+LocalDateTime.ofInstant(endTime.toInstant(), ZoneId.systemDefault()).format(dateTimeFormatter1)+";":"");
+        if(StringUtils.hasText(status)){
+            switch (status){
+                case "1": stringBuilder.append("状态:启用;");break;
+                case "0": stringBuilder.append("状态:禁用;");break;
+            }
+        }
+        return stringBuilder.toString();
+    }
+
+    public String toStrCode() {
+        DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        return
+                ","+(addressDetail==null?"":addressDetail)
+                        +","+(status==null?"":status)
+                        +","+(stationId==null?"":stationId)
+                        +","+(startTime==null?"":LocalDateTime.ofInstant(startTime.toInstant(), ZoneId.systemDefault()).format(dateTimeFormatter1))
+                        +","+(endTime==null?"":LocalDateTime.ofInstant(endTime.toInstant(), ZoneId.systemDefault()).format(dateTimeFormatter1))
+                        +",";
+    }
+}

+ 68 - 0
src/main/java/com/sqx/modules/address/service/InsideAddressService.java

@@ -0,0 +1,68 @@
+package com.sqx.modules.address.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.address.dto.AddressAddDTO;
+import com.sqx.modules.address.dto.InsideAddressDTO;
+import com.sqx.modules.address.entity.InsideAddress;
+import com.sqx.modules.address.query.InsideAddressQuery;
+import com.sqx.modules.address.vo.InsideAddressShortVO;
+import com.sqx.modules.address.vo.InsideAddressVO;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * @author codingliang
+ * @date 2025-09-13
+ */
+public interface InsideAddressService extends IService<InsideAddress> {
+
+    /**
+     * 分页查询
+     * @param query 分页查询参数
+     * @return 分页数据
+     */
+    PageUtils pages(InsideAddressQuery query);
+
+    /**
+     * 新增内部地址
+     * @param insideAddressDTO 内部地址
+     */
+    void addInsideAddress(InsideAddressDTO insideAddressDTO);
+
+    /**
+     * 更新内部地址
+     * @param insideAddressDTO 内部地址
+     */
+    void updateInsideAddress(InsideAddressDTO insideAddressDTO);
+
+    /**
+     * 删除内部地址
+     * @param ids 内部地址id列表
+     */
+    void deleteByIds(List<Long> ids);
+
+    /**
+     * 根据站点id查询内部地址列表 (精简信息)
+     * @param stationId 站点id
+     * @return 内部地址列表(精简信息)
+     */
+    List<InsideAddress> listByStationId(Long stationId);
+
+    /**
+     * 导出内部地址列表
+     * @param query 导出查询参数
+     */
+    void exportData(InsideAddressQuery query);
+
+    List<InsideAddressVO> exportShippingAddress(InsideAddressQuery query);
+    /**
+     * 导入内部地址列表
+     * @param file 导入文件
+     */
+    void importData(MultipartFile file)throws IOException, ParseException;
+
+}

+ 73 - 5
src/main/java/com/sqx/modules/address/service/impl/AddressServiceImpl.java

@@ -1,14 +1,26 @@
 package com.sqx.modules.address.service.impl;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.Constant;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.Result;
+import com.sqx.common.validator.ValidatorUtils;
 import com.sqx.modules.address.dao.AddressDao;
 import com.sqx.modules.address.entity.Address;
+import com.sqx.modules.address.entity.InsideAddress;
 import com.sqx.modules.address.service.AddressService;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.sqx.modules.address.service.InsideAddressService;
+import com.sqx.modules.address.validator.FullAddressGroup;
+import com.sqx.modules.address.validator.InsideAddressGroup;
+import com.sqx.modules.common.entity.CommonInfo;
+import com.sqx.modules.common.service.CommonInfoService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -16,26 +28,38 @@ import java.text.SimpleDateFormat;
 import java.util.Date;
 
 @Service
+@RequiredArgsConstructor
 public class AddressServiceImpl extends ServiceImpl<AddressDao, Address> implements AddressService {
 
-    @Autowired
-    private AddressDao addressDao;
+    private final InsideAddressService insideAddressService;
+    private final CommonInfoService commonInfoService;
 
     @Override
     public Result selectAddressList(Long userId, Integer page, Integer limit) {
+        CommonInfo insideAddressSetting = commonInfoService.findOne(442);
+
+        boolean insideAddressFlag = false;
+        if (ObjectUtil.isNotNull(insideAddressSetting) && StrUtil.equals(insideAddressSetting.getValue(), Constant.YES)) {
+            insideAddressFlag = true;
+        }
+
         Page<Address> pages=new Page<>(page,limit);
-        PageUtils pageUtils = new PageUtils(addressDao.selectAddressList(pages, userId));
+        PageUtils pageUtils = new PageUtils(baseMapper.selectAddressList(pages, userId, insideAddressFlag));
         return Result.success().put("data", pageUtils);
     }
 
     @Transactional
     @Override
     public Result insertAddress(Address address) {
+        // 校验地址参数
+        validateAddress(address);
+
         String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
         address.setCreateTime(format);
         address.setUpdateTime(format);
         address.setDeleteFlag(0);
-        //如果该条地址不是默认地址,则直接添加
+
+        // 如果该条地址不是默认地址,则直接添加
         if(address.getAddressDefault()==0){
             baseMapper.insert(address);
             return Result.success();
@@ -54,6 +78,9 @@ public class AddressServiceImpl extends ServiceImpl<AddressDao, Address> impleme
     @Transactional
     @Override
     public Result updateAddress(Address address) {
+        // 校验地址参数
+        validateAddress(address);
+
         String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
         address.setUpdateTime(format);
         //如果该条地址不是默认地址,则直接修改
@@ -73,6 +100,16 @@ public class AddressServiceImpl extends ServiceImpl<AddressDao, Address> impleme
     @Override
     public Result selectAddressById(Long addressId) {
         Address address = baseMapper.selectById(addressId);
+        if(ObjectUtil.isNull(address)){
+            throw new SqxException("地址不存在");
+        }
+        Long insideAddressId = address.getInsideAddressId();
+        if (ObjectUtils.isNotEmpty(insideAddressId)) {
+            InsideAddress insideAddress = insideAddressService.getById(insideAddressId);
+            if (ObjectUtils.isNotEmpty(insideAddress)) {
+                address.setStationId(insideAddress.getStationId());
+            }
+        }
         return Result.success().put("data", address);
     }
 
@@ -84,11 +121,42 @@ public class AddressServiceImpl extends ServiceImpl<AddressDao, Address> impleme
 
     @Override
     public Result searchAddress(Long userId, Integer page, Integer limit, String impotr) {
+        CommonInfo insideAddressSe = commonInfoService.findOne(442);
+
         Page<Address> pages = new Page<>(page, limit);
         PageUtils pageUtils = new PageUtils(baseMapper.selectPage(pages, new QueryWrapper<Address>()
                 .like("address_detail", impotr)
                 .eq("user_id", userId)
+                // 开启校内地址,则只查询校内的地址
+                .isNotNull(
+                    ObjectUtil.isNotNull(insideAddressSe) && StrUtil.equals(Constant.YES, insideAddressSe.getValue()),
+                    "inside_address_id"
+                )
                 .orderByDesc("create_time")));
         return Result.success().put("data", pageUtils);
     }
+
+    /**
+     * 校验地址参数
+     * @param address 地址参数
+     */
+    private void validateAddress(Address address) {
+        CommonInfo insideAddressSetting = commonInfoService.findOne(442);
+        if (ObjectUtil.isNotNull(insideAddressSetting) && StrUtil.equals(insideAddressSetting.getValue(), Constant.YES)) {
+            ValidatorUtils.validateEntity(address, InsideAddressGroup.class);
+            InsideAddress insideAddress = insideAddressService.getById(address.getInsideAddressId());
+            if (ObjectUtil.isNull(insideAddress)) {
+                throw new SqxException("无效的内部地址id");
+            }
+
+            address.setProvince(insideAddress.getProvince());
+            address.setCity(insideAddress.getCity());
+            address.setDistrict(insideAddress.getDistrict());
+            address.setAddressDetail(insideAddress.getAddressDetail());
+            address.setLng(insideAddress.getLng());
+            address.setLat(insideAddress.getLat());
+        } else {
+            ValidatorUtils.validateEntity(address, FullAddressGroup.class);
+        }
+    }
 }

+ 317 - 0
src/main/java/com/sqx/modules/address/service/impl/InsideAddressServiceImpl.java

@@ -0,0 +1,317 @@
+package com.sqx.modules.address.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.Constant;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.common.validator.ValidatorUtils;
+import com.sqx.modules.address.dao.InsideAddressDao;
+import com.sqx.modules.address.dto.InsideAddressDTO;
+import com.sqx.modules.address.entity.InsideAddress;
+import com.sqx.modules.address.query.InsideAddressQuery;
+import com.sqx.modules.address.service.InsideAddressService;
+import com.sqx.modules.address.vo.InsideAddressVO;
+import com.sqx.modules.riderStation.entity.RiderStation;
+import com.sqx.modules.riderStation.service.RiderStationService;
+import com.sqx.modules.utils.excel.EasyExcelUtil;
+import com.sqx.modules.utils.excel.ExcelFinishCallBack;
+import com.sqx.modules.utils.excel.ExcelUtils;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.checkerframework.checker.units.qual.A;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Service
+public class InsideAddressServiceImpl extends ServiceImpl<InsideAddressDao, InsideAddress> implements InsideAddressService {
+
+    @Autowired
+    RiderStationService riderStationService;
+
+    @Override
+    public PageUtils pages(InsideAddressQuery query) {
+        Page<InsideAddress> page = new Page<>(query.getPage(), query.getLimit());
+        IPage<InsideAddressVO> data = baseMapper.selectPages(page, query);
+        return new PageUtils(data);
+    }
+
+    @Override
+    public void addInsideAddress(InsideAddressDTO insideAddressDTO) {
+        // 地址详情不能重复
+        checkAddressUnique(insideAddressDTO);
+
+        // 新增内部地址
+        InsideAddress insideAddress = new InsideAddress();
+        BeanUtil.copyProperties(insideAddressDTO, insideAddress);
+        insideAddress.setDelFlag(Constant.NO);
+        insideAddress.setCreateTime(new Date());
+        insideAddress.setUpdateTime(new Date());
+        baseMapper.insert(insideAddress);
+    }
+
+    @Override
+    public void updateInsideAddress(InsideAddressDTO insideAddressDTO) {
+        // 地址详情不能重复
+        checkAddressUnique(insideAddressDTO);
+
+        // 更新内部地址
+        InsideAddress insideAddress = new InsideAddress();
+        BeanUtil.copyProperties(insideAddressDTO, insideAddress);
+        insideAddress.setUpdateTime(new Date());
+        baseMapper.updateById(insideAddress);
+    }
+
+    @Override
+    @Transactional
+    public void deleteByIds(List<Long> ids) {
+        removeByIds(ids);
+    }
+
+    @Override
+    public List<InsideAddress> listByStationId(Long stationId) {
+        List<InsideAddress> list = baseMapper.selectList(new LambdaQueryWrapper<InsideAddress>()
+                .eq(InsideAddress::getStationId, stationId)
+                .eq(InsideAddress::getStatus, Constant.YES)
+                .orderByAsc(InsideAddress::getSort));
+
+//        精简数据缺少
+//        List<InsideAddressShortVO> vos = list.stream().map(item -> {
+//            InsideAddressShortVO vo = new InsideAddressShortVO();
+//            BeanUtil.copyProperties(item, vo);
+//            return vo;
+//        }).collect(Collectors.toList());
+
+        return list;
+    }
+
+    @Override
+    public void exportData(InsideAddressQuery query) {
+        Page<InsideAddress> page = new Page<>(query.getPage(), query.getLimit());
+        IPage<InsideAddressVO> data = baseMapper.selectPages(page, query);
+
+        // 导出数据
+        List<InsideAddressVO> list = data.getRecords();
+
+        list.forEach(item -> {
+            item.setStatus(item.getStatus() == Constant.YES ? "正常" : "停用");
+        });
+
+        EasyExcelUtil.exportExcel(list, InsideAddressVO.class, "内部地址", "sheet1");
+    }
+
+    @Override
+    public List<InsideAddressVO> exportShippingAddress(InsideAddressQuery query) {
+        return baseMapper.exportShippingAddress(query);
+    }
+
+    @Override
+    public void importData(MultipartFile file) throws IOException, ParseException {
+        InputStream inputStream = file.getInputStream();
+        XSSFWorkbook sheets = new XSSFWorkbook(inputStream);
+        //读取第一张sheet
+        XSSFSheet sheetAt = sheets.getSheetAt(0);
+        DataFormatter dataFormatter = new DataFormatter();
+        ArrayList<InsideAddress> insideAddresses = new ArrayList<>();
+        for (int rowNum = 0; rowNum < sheetAt.getLastRowNum() + 1; rowNum++) {
+            XSSFRow row = sheetAt.getRow(rowNum);
+            if (row != null) {
+                if (rowNum == 0) {
+                    String stationName = dataFormatter.formatCellValue(row.getCell(0));//骑手站点
+                    if (!stationName.equals("骑手站点")) {
+                        throw new SqxException("导入数据第一列为骑手站点");
+                    }
+                    String province = dataFormatter.formatCellValue(row.getCell(1));//省
+                    if (!province.equals("省")) {
+                        throw new SqxException("导入数据第二列为省");
+                    }
+                    String city = dataFormatter.formatCellValue(row.getCell(2));//市
+                    if (!city.equals("市")) {
+                        throw new SqxException("导入数据第三列为市");
+                    }
+                    String district = dataFormatter.formatCellValue(row.getCell(3));//区/县
+                    if (!district.equals("区/县")) {
+                        throw new SqxException("导入数据第四列为区/县");
+                    }
+                    String addressDetail = dataFormatter.formatCellValue(row.getCell(4));//地址名
+                    if (!addressDetail.equals("地址名")) {
+                        throw new SqxException("导入数据第五列为地址名");
+                    }
+                    String lng = dataFormatter.formatCellValue(row.getCell(5));//经度
+                    if (!lng.equals("经度")) {
+                        throw new SqxException("导入数据第六列为经度");
+                    }
+                    String lat = dataFormatter.formatCellValue(row.getCell(6));//纬度
+                    if (!lat.equals("纬度")) {
+                        throw new SqxException("导入数据第列七为纬度");
+                    }
+                    String deliveryFee = dataFormatter.formatCellValue(row.getCell(7));//地址配送费
+                    if (!deliveryFee.equals("地址配送费")) {
+                        throw new SqxException("导入数据第列七为地址配送费");
+                    }
+                    String sort = dataFormatter.formatCellValue(row.getCell(8));//排序
+                    if (!sort.equals("排序")) {
+                        throw new SqxException("导入数据第列七为排序");
+                    }
+                    String status = dataFormatter.formatCellValue(row.getCell(9));//是否启用
+                    if (!status.equals("是否启用")) {
+                        throw new SqxException("导入数据第列七为是否启用");
+                    }
+
+                }else {
+                    InsideAddress insideAddress = new InsideAddress();
+                    String stationName = dataFormatter.formatCellValue(row.getCell(0));//骑手站点
+                    if (ObjectUtils.isNotEmpty(stationName)) {
+                        RiderStation riderStation=riderStationService.getName(stationName);
+                        if (ObjectUtils.isNotEmpty(riderStation)) {
+                            insideAddress.setStationId(riderStation.getId());
+                        }else {
+                            int h = rowNum + 1;
+                            throw new SqxException("第" + h + "行,骑手站点不存在");
+                        }
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,骑手站点为空");
+                    }
+                    String province = dataFormatter.formatCellValue(row.getCell(1));//省
+                    if (ObjectUtils.isNotEmpty(province)) {
+                        insideAddress.setProvince(province);
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,省为空");
+                    }
+
+                    String city = dataFormatter.formatCellValue(row.getCell(2));//市
+                    if (ObjectUtils.isNotEmpty(city)) {
+                        insideAddress.setCity(city);
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,市为空");
+                    }
+
+                    String district = dataFormatter.formatCellValue(row.getCell(3));//区/县
+                    if (ObjectUtils.isNotEmpty(district)) {
+                        insideAddress.setDistrict(district);
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,市为空");
+                    }
+
+                    String addressDetail = dataFormatter.formatCellValue(row.getCell(4));//地址名
+                    if (ObjectUtils.isNotEmpty(addressDetail)) {
+//                        判断地址是否重复
+                        long count = baseMapper.selectCount(new LambdaQueryWrapper<InsideAddress>()
+                                .eq(InsideAddress::getAddressDetail, addressDetail));
+                        if (count > 0) {
+                            throw new SqxException("地址详情不能重复");
+                        }
+                        insideAddress.setAddressDetail(addressDetail);
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,地址名为空");
+                    }
+
+                    String lng = dataFormatter.formatCellValue(row.getCell(5));//经度
+                    if (ObjectUtils.isNotEmpty(lng)) {
+                        insideAddress.setLng(Double.valueOf(lng));
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,经度为空");
+                    }
+
+                    String lat = dataFormatter.formatCellValue(row.getCell(6));//纬度
+                    if (ObjectUtils.isNotEmpty(lat)) {
+                        insideAddress.setLat(Double.valueOf(lat));
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,纬度为空");
+                    }
+
+                    String deliveryFee = dataFormatter.formatCellValue(row.getCell(7));//地址配送费
+                    if (ObjectUtils.isNotEmpty(deliveryFee)) {
+                        insideAddress.setDeliveryFee(new BigDecimal(deliveryFee));
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,地址配送费为空");
+                    }
+
+                    String sort = dataFormatter.formatCellValue(row.getCell(8));//排序
+                    if (ObjectUtils.isNotEmpty(sort)) {
+                        insideAddress.setSort(Integer.valueOf(sort));
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,排序为空");
+                    }
+
+                    String status = dataFormatter.formatCellValue(row.getCell(9));//是否启用
+                    if (ObjectUtils.isNotEmpty(status)) {
+                        if (status.equals("启用")) {
+                            insideAddress.setStatus("1");
+                        }else {
+                            insideAddress.setStatus("0");
+                        }
+                    }else {
+                        int h = rowNum + 1;
+                        throw new SqxException("第" + h + "行,是否启用为空");
+                    }
+
+                    insideAddress.setDelFlag(Constant.NO);
+                    insideAddress.setCreateTime(new Date());
+                    insideAddress.setUpdateTime(new Date());
+
+                    insideAddresses.add(insideAddress);
+                }
+            }
+
+        }
+//        去掉导入表的重复数据,并且重复地址只取第一条
+        ArrayList<InsideAddress> list = new ArrayList<>();
+        ArrayList<String> addressDetailList = new ArrayList<>();
+        for (int i = 0; i < insideAddresses.size(); i++) {
+            InsideAddress insideAddress = insideAddresses.get(i);
+            String addressDetail = insideAddress.getAddressDetail();
+            if (!list.contains(insideAddress)&&!addressDetailList.contains(addressDetail)) {
+                list.add(insideAddress);
+                addressDetailList.add(addressDetail);
+            }
+        }
+
+        this.saveBatch(list);
+
+    }
+
+    private void checkAddressUnique(InsideAddressDTO insideAddressDTO) {
+        long count = baseMapper.selectCount(new LambdaQueryWrapper<InsideAddress>()
+                .eq(InsideAddress::getAddressDetail, insideAddressDTO.getAddressDetail())
+                .ne(ObjectUtil.isNotNull(insideAddressDTO.getId()), InsideAddress::getId, insideAddressDTO.getId()));
+        if (count > 0) {
+            throw new SqxException("地址详情不能重复");
+        }
+    }
+}

+ 8 - 0
src/main/java/com/sqx/modules/address/validator/FullAddressGroup.java

@@ -0,0 +1,8 @@
+package com.sqx.modules.address.validator;
+
+/**
+ * 完整地址校验组
+ * 包含:userName、userPhone、province、city、district、addressDetail、lng、lat、addressDefault
+ */
+public interface FullAddressGroup {
+}

+ 8 - 0
src/main/java/com/sqx/modules/address/validator/InsideAddressGroup.java

@@ -0,0 +1,8 @@
+package com.sqx.modules.address.validator;
+
+/**
+ * 内部地址校验组
+ * 包含:userName、userPhone、insideAddressId、addressDefault
+ */
+public interface InsideAddressGroup {
+}

+ 34 - 0
src/main/java/com/sqx/modules/address/vo/InsideAddressShortVO.java

@@ -0,0 +1,34 @@
+package com.sqx.modules.address.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 内部地址
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Data
+@ApiModel(value = "内部地址")
+public class InsideAddressShortVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(name = "id")
+    private Long id;
+
+    @ApiModelProperty(name = "站点id")
+    private Long stationId;
+
+    @ApiModelProperty(name = "配送费用")
+    private Double deliveryFee;
+
+    @ApiModelProperty(name = "地址详情")
+    private String addressDetail;
+
+    @ApiModelProperty(name = "排序")
+    private Integer sort;
+}

+ 78 - 0
src/main/java/com/sqx/modules/address/vo/InsideAddressVO.java

@@ -0,0 +1,78 @@
+package com.sqx.modules.address.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 内部地址
+ * @author codingliang
+ * @date 2025-09-13
+ */
+@Data
+@ApiModel(value = "内部地址")
+public class InsideAddressVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(name = "id")
+    private Long id;
+
+    @ExcelProperty("创建时间")
+    @ApiModelProperty(name = "创建时间")
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ExcelProperty("更新时间")
+    @ApiModelProperty(name = "更新时间")
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    @ApiModelProperty(name = "站点id")
+    @ExcelProperty("站点id")
+    private Long stationId;
+
+    @ApiModelProperty(name = "站点名称")
+    @ExcelProperty("站点名称")
+    private String stationName;
+
+    @ApiModelProperty(name = "配送费用")
+    @ExcelProperty("配送费用")
+    private Double deliveryFee;
+
+    @ApiModelProperty(name = "省份")
+    @ExcelProperty("省份")
+    private String province;
+
+    @ApiModelProperty(name = "城市")
+    @ExcelProperty("城市")
+    private String city;
+
+    @ApiModelProperty(name = "区县")
+    @ExcelProperty("区县")
+    private String district;
+
+    @ApiModelProperty(name = "地址详情")
+    @ExcelProperty("地址详情")
+    private String addressDetail;
+
+    @ApiModelProperty(name = "经度")
+    @ExcelProperty("经度")
+    private Double lng;
+
+    @ApiModelProperty(name = "维度")
+    @ExcelProperty("维度")
+    private Double lat;
+
+    @ApiModelProperty(name = "启用状态;1启用、0禁用")
+    @ExcelProperty("启用状态;1启用、0禁用")
+    private String status;
+
+    @ApiModelProperty(name = "排序")
+    @ExcelProperty("排序")
+    private Integer sort;
+}

+ 3 - 0
src/main/java/com/sqx/modules/errand/entity/TbIndent.java

@@ -108,6 +108,9 @@ public class TbIndent implements Serializable {
     @ApiModelProperty("跑腿费")
     private BigDecimal errandMoney;
 
+    @ApiModelProperty("校内跑腿费")
+    private BigDecimal insideDeliveryFee;
+
     @ApiModelProperty("商品详情")
     private String productDetails;
 

+ 8 - 1
src/main/java/com/sqx/modules/errand/service/impl/TbIndentServiceImpl.java

@@ -329,9 +329,16 @@ public class TbIndentServiceImpl extends ServiceImpl<TbIndentDao, TbIndent> impl
             //骑手最终可得金额
             errandMoney = errandMoney.subtract(platformMoney);
         }
+
+        // 校内跑腿费
+        tbIndent.setInsideDeliveryFee(order.getInsideDeliveryFee());
         tbIndent.setErrandMoney(errandMoney);
-        tbIndent.setRiderMoney(errandMoney);
+
+        // 骑手收入 = 跑腿费 + 校内跑腿费
+        tbIndent.setRiderMoney(errandMoney.add(tbIndent.getInsideDeliveryFee()));
+
         tbIndent.setPlatformMoney(platformMoney);
+
         // 配送订单,直接改为2
         if (goodsShop.getAutoSendOrder() == 0) {
             tbIndent.setIndentState("2");

+ 27 - 1
src/main/java/com/sqx/modules/exportExecl/controller/ExportExeclController.java

@@ -8,6 +8,7 @@ import com.jcraft.jsch.SftpException;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.SftpUtil;
+import com.sqx.modules.address.query.InsideAddressQuery;
 import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.datacentre.query.RankListQuery;
 import com.sqx.modules.datacentre.query.ShopCenterQuery;
@@ -34,6 +35,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -274,7 +276,7 @@ public class ExportExeclController {
         return getBill(queryDTO,"平台对账.xlsx","platformBill");
     }
 
-    private @NotNull Result getBill(PlatformBillDto queryDTO,String excelName,String fileType) {
+    private Result getBill(PlatformBillDto queryDTO,String excelName,String fileType) {
         if(!StringUtils.hasText(queryDTO.getUserId())){
             return Result.error("用户id不能为空");
         }
@@ -293,4 +295,28 @@ public class ExportExeclController {
             return Result.error("新增对账导出计划失败");
         }
     }
+
+    @GetMapping("exportShippingAddress")
+    @ApiOperation("导出内部地址列表")
+    public Result exportShippingAddress(InsideAddressQuery queryDTO) {
+        queryDTO.setUserId("1");
+        if(!StringUtils.hasText(queryDTO.getUserId())){
+            return Result.error("用户id不能为空");
+        }
+        String strMessage=queryDTO.toStrMessage();
+        if(StringUtils.hasText(queryDTO.getStationId()+"")){
+            RiderStation riderStation=riderStationService.getById(queryDTO.getStationId());
+            if(riderStation!=null){
+                strMessage=strMessage+"站点:"+riderStation.getStationName()+";";
+            }
+        }
+        ExportJob exportJob =this.buildExportJob("收货地址管理.xlsx","shippingAddress",queryDTO.getUserId(),strMessage,queryDTO.toStrCode());
+        boolean a=exportJobService.save(exportJob);
+        if (a){
+            return Result.success("收货地址管理导出成功");
+        }else{
+            return Result.error("收货地址管理导出失败");
+        }
+    }
+
 }

+ 1 - 1
src/main/java/com/sqx/modules/goods/controller/GoodsShopController.java

@@ -122,7 +122,7 @@ public class GoodsShopController {
         return goodsShopService.selectGoodsShop(phone,msg);
     }
 
-        @ApiOperation("修改商户信息")
+    @ApiOperation("修改商户信息")
     @PostMapping("/updateGoodsShop")
     public Result updateGoodsShop(@RequestBody GoodsShop goodsShop){
         if (ObjectUtils.isEmpty(goodsShop.getShopTypeId())) {

+ 14 - 0
src/main/java/com/sqx/modules/goods/controller/app/AppGoodsController.java

@@ -134,4 +134,18 @@ public class AppGoodsController {
         return goodsService.goodsParticularsPictureList(page,limit,name);
     }
 
+    @ApiOperation("根据商铺id查看超市商品类型列表")
+    @GetMapping(value = "/selectGoodsClassifyList")
+    public Result selectGoodsClassifyList(Long shopId, Double lng, Double lat){
+
+        return goodsService.selectGoodsClassifyList(shopId, lng, lat);
+    }
+
+    @ApiOperation("根据商铺id和商品类型id查看商品列表")
+    @GetMapping(value = "/selectSupermarketGoodsList")
+    public Result selectSupermarketGoodsList(Long shopId, Integer classifyId, Integer page, Integer limit){
+
+        return goodsService.selectSupermarketGoodsList(shopId, classifyId, page,limit);
+    }
+
 }

+ 5 - 0
src/main/java/com/sqx/modules/goods/dao/GoodsDao.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.sqx.modules.goods.entity.Goods;
 import com.sqx.modules.goods.entity.GoodsClassify;
 import com.sqx.modules.goods.entity.GoodsShop;
+import com.sqx.modules.goods.vo.GoodsListVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -43,4 +44,8 @@ public interface GoodsDao extends BaseMapper<Goods> {
     IPage<Goods> goodsPictureList(Page<Goods> pages,@Param("name") String name,@Param("total") Integer total);
 
     IPage<Goods> goodsParticularsPictureList(Page<Goods> pages,@Param("name") String name,@Param("total") Integer total);
+
+    List<GoodsListVo> selectGoodsVoByClassify(@Param("classifyId") Integer classifyId, @Param("shopId") Long shopId);
+
+    IPage<Goods> selectSupermarketGoodsList(Page<Goods> pages,@Param("shopId") Long shopId,@Param("classifyId") Integer classifyId);
 }

+ 4 - 0
src/main/java/com/sqx/modules/goods/service/GoodsService.java

@@ -75,4 +75,8 @@ public interface GoodsService extends IService<Goods> {
     Result goodsPictureList(Integer page, Integer limit, String name);
 
     Result goodsParticularsPictureList(Integer page, Integer limit, String name);
+
+    Result selectGoodsClassifyList(Long shopId, Double lng, Double lat);
+
+    Result selectSupermarketGoodsList(Long shopId, Integer classifyId, Integer page, Integer limit);
 }

+ 32 - 0
src/main/java/com/sqx/modules/goods/service/impl/GoodsServiceImpl.java

@@ -38,6 +38,7 @@ import com.sqx.modules.goods.service.GoodsAttrValueService;
 import com.sqx.modules.goods.service.GoodsService;
 import com.sqx.modules.goods.service.GoodsSkuService;
 import com.sqx.modules.goods.utils.SkuUtil;
+import com.sqx.modules.goods.vo.GoodsListVo;
 import com.sqx.modules.goods.vo.GoodsVo;
 import com.sqx.modules.order.entity.Evaluate;
 import com.sqx.modules.shop.dao.ShopMessageDao;
@@ -174,11 +175,13 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsDao, Goods> implements Go
         GoodsShop goodsShop = goodsShopDao.selectGoodsList(shopId, lng, lat);
         //List<Goods> goodsList = goodsDao.selectGoodsClassifyList(shopId);
         List<GoodsClassify> goodsClassifies = goodsDao.selectAllClassifyList(null, shopId);
+
         List<Map<String, Object>> list = new ArrayList<>();
         for (int i = 0; i < goodsClassifies.size(); i++) {
             Map<String, Object> hashMap = new HashMap<>();
             GoodsClassify goodsClassify = goodsClassifies.get(i);
             List<Goods> goodsList1 = goodsDao.selectGoodsByClassify(goodsClassify.getClassifyId(), shopId);
+//            List<GoodsListVo> goodsList1 = goodsDao.selectGoodsVoByClassify(goodsClassify.getClassifyId(), shopId);
             hashMap.put("classifyId", goodsClassifies.get(i).getClassifyId());
             hashMap.put("classifyName", goodsClassify.getClassifyName());
             hashMap.put("goodsList", goodsList1);
@@ -873,4 +876,33 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsDao, Goods> implements Go
         return Result.success().put("data", pageUtils);
     }
 
+    @Override
+    public Result selectGoodsClassifyList(Long shopId, Double lng, Double lat) {
+        GoodsShop goodsShop = goodsShopDao.selectGoodsList(shopId, lng, lat);
+        //List<Goods> goodsList = goodsDao.selectGoodsClassifyList(shopId);
+        List<GoodsClassify> goodsClassifies = goodsDao.selectAllClassifyList(null, shopId);
+
+        CommonInfo one = commonInfoService.findOne(292);
+        CommonInfo one1 = commonInfoService.findOne(293);
+        if (goodsShop.getDistance() == null) {
+            goodsShop.setDistance(0.00);
+        }
+        BigDecimal a = BigDecimal.valueOf(goodsShop.getDistance()).divide(new BigDecimal(one.getValue()), 2, BigDecimal.ROUND_HALF_DOWN);
+        if (a.doubleValue() < Double.parseDouble(one1.getValue())) {
+            a = new BigDecimal(one1.getValue());
+        }
+        goodsShop.setErrandTime(a.doubleValue());
+        Map<String, Object> result = new HashMap<>();
+        result.put("goodsShop", goodsShop);
+        result.put("list", goodsClassifies);
+        return Result.success().put("data", result);
+    }
+
+    @Override
+    public Result selectSupermarketGoodsList(Long shopId, Integer classifyId, Integer page, Integer limit) {
+        Page<Goods> pages = new Page<>(page, limit);
+        IPage<Goods> goodsIPage = goodsDao.selectSupermarketGoodsList(pages,shopId, classifyId);
+        return Result.success().put("data", goodsIPage);
+    }
+
 }

+ 28 - 0
src/main/java/com/sqx/modules/goods/vo/GoodsListVo.java

@@ -0,0 +1,28 @@
+package com.sqx.modules.goods.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GoodsListVo {
+    @ApiModelProperty("goods_id")
+    private Long goodsId;
+
+    @ApiModelProperty("商品封面图")
+    private String goodsCover;
+
+    @ApiModelProperty("商品名称")
+    private String goodsName;
+
+    @ApiModelProperty("商品销量")
+    private Integer sales;
+
+    @ApiModelProperty("商品描述")
+    private String goodsDescribe;
+
+    @ApiModelProperty("商品实际价格")
+    private BigDecimal goodsMoney;
+}

+ 5 - 0
src/main/java/com/sqx/modules/invite/controller/InviteController.java

@@ -64,6 +64,11 @@ public class InviteController {
         SenInfoCheckUtil.getShopQr(shopId,response);
     }
 
+    @GetMapping("/shopQr2")
+    @ApiOperation("门店二维码")
+    public void shopQr2(String shopId, HttpServletResponse response) {
+        SenInfoCheckUtil.getShopQr2(shopId,response);
+    }
 
 
 

+ 3 - 18
src/main/java/com/sqx/modules/order/entity/TbOrder.java

@@ -23,88 +23,73 @@ public class TbOrder implements Serializable {
     @ApiModelProperty("order_id")
     private Long orderId;
 
-
     @ApiModelProperty("优惠券id")
     @TableField(value = "coupon_id")
     private Long couponId;
 
-
     @ApiModelProperty("用户id")
     private Long userId;
 
-
     @ApiModelProperty("用户名")
     private String userName;
 
-
     @ApiModelProperty("手机号")
     private String phone;
 
-
     @ApiModelProperty("地址id")
     private Long addressId;
 
-
     @ApiModelProperty("地址信息")
     private String address;
 
-
     @ApiModelProperty("订单号")
     private String orderNumber;
 
-
     @ApiModelProperty("是否支付 0未支付 1已支付")
     private Integer isPay;
 
-
     @ApiModelProperty("下单时间")
     private String createTime;
 
     @ApiModelProperty("最后一次修改订单状态时间")
     private String updateTime;
 
-
     @ApiModelProperty("支付时间")
     private String payTime;
 
-
     @ApiModelProperty("支付方式  1微信支付  2余额支付  3支付宝支付")
     private Integer payType;
 
-
     @ApiModelProperty("取餐号码")
     private String orderCode;
 
-
     @ApiModelProperty("订单类型 1上门 2外卖")
     private Integer orderType;
 
     @ApiModelProperty("订单类型拓展 1上门 2骑手配送 3商家配送")
     private Integer orderTypeExtra;
 
-
     @ApiModelProperty("订单父id")
     private Long parentId;
 
-
     @ApiModelProperty("打包费")
     private BigDecimal packMoney;
 
-
     @ApiModelProperty("跑腿费")
     private BigDecimal errandMoney;
 
     @ApiModelProperty("跑腿费达到商家满减要求 商家承担配送费")
     private String errandMoneyIsShop;
 
+    @ApiModelProperty("内部配送费")
+    private BigDecimal insideDeliveryFee;
+
     @ApiModelProperty("订单状态 0待结算 1待支付 2直接购买(未支付) 7商家待接单 8商家拒绝接单 6制作中  3待取餐/派送中 4已完成 5已取消 13外卖待接单")
     private Integer status;
 
-
     @ApiModelProperty("是否开启自动派单 0开启 1关闭")
     private Integer autoSendOrder;
 
-
     @ApiModelProperty("是否删除该订单 0未删除 1删除")
     private Integer deleteFlag;
 

+ 33 - 133
src/main/java/com/sqx/modules/order/service/impl/AppAppOrderServiceImpl.java

@@ -1,12 +1,8 @@
 package com.sqx.modules.order.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.core.util.URLUtil;
-import com.alibaba.excel.EasyExcel;
-import com.alibaba.excel.converters.longconverter.LongStringConverter;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -24,14 +20,20 @@ import com.github.wxpay.sdk.WXPay;
 import com.sqx.common.constant.RedisKey;
 import com.sqx.common.exception.SqxException;
 import com.sqx.common.sms.SmsSendResult;
-import com.sqx.common.utils.*;
+import com.sqx.common.utils.Constant;
+import com.sqx.common.utils.DateUtils;
+import com.sqx.common.utils.DistanceUtil;
+import com.sqx.common.utils.MyGlobalThreadPool;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.common.utils.Result;
 import com.sqx.modules.activity.entity.ActivityPartRecord;
 import com.sqx.modules.activity.service.ActivityPartRecordService;
 import com.sqx.modules.activity.service.ActivityService;
 import com.sqx.modules.activity.vo.OrderSuitActivityVO;
-import com.sqx.modules.address.dao.AddressDao;
 import com.sqx.modules.address.entity.Address;
+import com.sqx.modules.address.entity.InsideAddress;
 import com.sqx.modules.address.service.AddressService;
+import com.sqx.modules.address.service.InsideAddressService;
 import com.sqx.modules.app.dao.UserBrowseDao;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.dao.UserMoneyDao;
@@ -47,7 +49,6 @@ import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.coupon.dao.TbCouponUserDao;
 import com.sqx.modules.coupon.entity.TbCouponUser;
 import com.sqx.modules.datacentre.entity.SysUserShop;
-import com.sqx.modules.errand.dao.TbIndentDao;
 import com.sqx.modules.errand.entity.TbIndent;
 import com.sqx.modules.errand.entity.TbIndentSmsSendLog;
 import com.sqx.modules.errand.service.TbIndentService;
@@ -101,15 +102,11 @@ import com.sqx.modules.shop.service.ShopTypeService;
 import com.sqx.modules.sys.entity.SysUserEntity;
 import com.sqx.modules.sys.service.SysUserService;
 import com.sqx.modules.utils.SenInfoCheckUtil;
+import com.sqx.modules.utils.excel.EasyExcelUtil;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.fieYun.FeiYunUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
 import org.apache.shiro.SecurityUtils;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
@@ -121,16 +118,10 @@ import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.support.DefaultTransactionDefinition;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
 
 import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -186,8 +177,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
     @Autowired
     private UserMoneyService userMoneyService;
     @Autowired
-    private TbIndentDao tbIndentDao;
-    @Autowired
     private UserBrowseDao userBrowseDao;
     @Autowired
     private PayDetailsDao payDetailsDao;
@@ -216,16 +205,16 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
     private UserIntegralDao userIntegralDao;
     @Autowired
     private UserIntegralDetailsDao userIntegralDetailsDao;
-
     @Autowired
     private EvaluateRiderService evaluateRiderService;
     @Autowired
     private ShopTypeService shopTypeService;
-
     @Autowired
     private GoodsShopService goodsShopService;
 
     @Resource
+    private InsideAddressService insideAddressService;
+    @Resource
     private RedissonClient redissonClient;
 
     private final static String RHT_PAY_BASE_URL = "https://api.ekbuyclub.com";
@@ -1020,7 +1009,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
     }
 
     /**
-     * 计算店铺收益 店铺订单收益=订单应付金额+订单使用的优惠券金额-跑腿费用
+     * 计算店铺收益 店铺订单收益=订单应付金额+订单使用的优惠券金额-跑腿费用-校内配送费用
      *
      * @param order     订单信息
      * @param goodsShop 店铺信息
@@ -1034,6 +1023,8 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             sumMoney = sumMoney.subtract(goodsShop.getErrandMoney());
         }
 
+        sumMoney = sumMoney.subtract(order.getInsideDeliveryFee());
+
         BigDecimal shopMoney = sumMoney.multiply(shopRate);
         order.setShopIncomeMoney(shopMoney.setScale(2, BigDecimal.ROUND_DOWN));
 
@@ -1110,6 +1101,12 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                 throw new SqxException("超出商家配送范围,无法点餐!");
             }
 
+            Long insideAddressId = address.getInsideAddressId();
+            if (ObjectUtil.isNotNull(insideAddressId)) {
+                InsideAddress insideAddress = insideAddressService.getById(insideAddressId);
+                order.setInsideDeliveryFee(insideAddress.getDeliveryFee());
+            }
+
             // 店铺是否开启配送费满减 0是 1否
             Integer enableFullReductionFlag = goodsShop.getEnableFullReductionFlag() != null ? goodsShop.getEnableFullReductionFlag() : 1;
             // 店铺跑腿费
@@ -1143,6 +1140,9 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
 
             order.setErrandMoney(shopErrandMoney);
 
+            // 支付金额加入内部配送费
+            order.setPayMoney(order.getPayMoney().add(order.getInsideDeliveryFee()));
+
             // 判断订单金额是否大于最低起送金额
             if (goodsShop.getMinimumDelivery() == null) {
                 goodsShop.setMinimumDelivery(BigDecimal.valueOf(0));
@@ -1167,8 +1167,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             order.setErrandMoney(BigDecimal.ZERO);
         }
 
-        log.info("preOrder==>[{}],订单跑腿费计算结束,跑腿费[{}],当前订单应付总价[{}]",
-                order.getOrderId(), order.getErrandMoney(), order.getPayMoney());
+        log.info("preOrder==>[{}],订单跑腿费计算结束,跑腿费[{}],校内配送费[{}],当前订单应付总价[{}]", order.getOrderId(), order.getErrandMoney(), order.getInsideDeliveryFee(), order.getPayMoney());
     }
 
     /**
@@ -1361,49 +1360,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
         return Result.success().put("data", orderGoodsList);
     }
 
-
-
-
-    /*public Result insertOrder1(Long userId, Long shopId, Long goodsId, Integer num, Long skuId, String skuMessage, Integer orderType) {
-        //判断该用户在该商店有没有订单,没有的话创建订单,有的话加入订单
-        List<TbOrder> tbOrder1 = appOrderDao.selectList(new QueryWrapper<TbOrder>()
-                .eq("user_id", userId).eq("shop_id", shopId).eq("status", 1));
-
-        if(tbOrder1==null) {
-            Goods goods = goodsDao.selectById(goodsId);
-            UserEntity userEntity = userDao.selectById(userId);
-            net.sf.json.JSONObject goodsJson = net.sf.json.JSONObject.fromObject(goods);
-
-            TbOrder order = new TbOrder();
-            order.setUserId(userId);
-            order.setUserName(userEntity.getUserName());
-            order.setPhone(userEntity.getPhone());
-            order.setOrderNumber(getGeneralOrder());
-            order.setIsPay(0);
-            order.setDeleteFlag(0);
-            order.setStatus(1);
-        //    order.setNum(num);
-            order.setShopId(shopId);
-            //创建订单,订单发起人就是该登录用户
-            order.setParentUserId(userId);
-            order.setPackMoney(goods.getPackMoney());
-            order.setOrderType(orderType);
-            order.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
-            if (orderType == 2) {
-                CommonInfo one = commonInfoService.findOne(121);
-                Double value = Double.valueOf(one.getValue());
-                order.setErrandMoney(BigDecimal.valueOf(value));
-            }
-            appOrderDao.insertOrder(order);
-            TbOrder tbOrder = new TbOrder();
-            tbOrder.setOrderId(order.getOrderId());
-            tbOrder.setParentId(order.getOrderId());
-            appOrderDao.updateById(tbOrder);
-        }
-        return Result.success();
-    }*/
-
-
     @Override
     public TbOrder selectOrderByNum(String orderNum) {
         TbOrder tbOrder = appOrderDao.selectOne(new QueryWrapper<TbOrder>().eq("order_number", orderNum));
@@ -1438,22 +1394,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
     @Override
     public Result selectAllOrderAdmin(OrderQueryDto queryDto) {
         Page<TbOrder> pages = new Page<>(queryDto.getPage(), queryDto.getLimit());
-//        pages.setOptimizeCountSql(false);
-//        pages.setSearchCount(false);
-//        pages.setTotal()
-
-//        if (org.springframework.util.StringUtils.hasText(queryDto.getEndTime())) {
-//            queryDto.setEndTime(queryDto.getEndTime() + " 23:59:59");
-//        }
-//         if (org.springframework.util.StringUtils.hasText(queryDto.getPayEndTime())) {
-//             queryDto.setPayEndTime(queryDto.getPayEndTime() + " 23:59:59");
-//         }
-//        if (org.springframework.util.StringUtils.hasText(queryDto.getStartTime())) {
-//            queryDto.setStartTime(queryDto.getStartTime() + " 00:00:00");
-//        }
-//         if (org.springframework.util.StringUtils.hasText(queryDto.getPayStartTime())) {
-//             queryDto.setPayStartTime(queryDto.getPayStartTime() + " 00:00:00");
-//         }
         IPage<TbOrder> tbOrderIPage = appOrderDao.selectAllOrderAdmin(pages, queryDto);
         for (int i = 0; i < tbOrderIPage.getRecords().size(); i++) {
             List<OrderGoods> orderGoodsList = orderGoodsDao.selectList(new QueryWrapper<OrderGoods>()
@@ -1469,21 +1409,11 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
         if (org.springframework.util.StringUtils.hasText(queryDto.getEndTime())) {
             queryDto.setEndTime(queryDto.getEndTime() + " 23:59:59");
         }
-        // if (org.springframework.util.StringUtils.hasText(queryDto.getPayEndTime())) {
-        //     queryDto.setPayEndTime(queryDto.getPayEndTime() + " 23:59:59");
-        // }
         if (org.springframework.util.StringUtils.hasText(queryDto.getStartTime())) {
             queryDto.setStartTime(queryDto.getStartTime() + " 00:00:00");
         }
-        // if (org.springframework.util.StringUtils.hasText(queryDto.getPayStartTime())) {
-        //     queryDto.setPayStartTime(queryDto.getPayStartTime() + " 00:00:00");
-        // }
+
         List<TbOrder> tbOrderIPage = appOrderDao.excelAllOrderAdmin(queryDto);
-//        for (int i = 0; i < tbOrderIPage.size(); i++) {
-//            List<OrderGoods> orderGoodsList = orderGoodsDao.selectList(new QueryWrapper<OrderGoods>()
-//                    .eq("order_id", tbOrderIPage.get(i).getOrderId()));
-//            tbOrderIPage.get(i).setOrderGoodsList(orderGoodsList);
-//        }
         ExcelData data = new ExcelData();
         data.setName("订单列表");
         List<String> titles = new ArrayList();
@@ -1556,17 +1486,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             row.add(order.getRiderPhone());
             row.add(order.getReceivingTime());
             row.add(order.getOrderNumber());
-//            stringBuffer=new StringBuffer();
-//            BigDecimal sumGoodsPrice=BigDecimal.ZERO;
-//            List<OrderGoods> orderGoodsList = order.getOrderGoodsList();
-//            for(int i=0;i<orderGoodsList.size();i++){
-//                OrderGoods orderGoods = orderGoodsList.get(i);
-//                stringBuffer.append(i + 1).append(". 商品名:").append(orderGoods.getGoodsName()).append(",数量:").append(orderGoods.getGoodsNum()).append(",规格:").append(orderGoods.getSkuMessage());
-//                if(orderGoods.getGoodsPrice()!=null && orderGoods.getGoodsNum()!=null){
-//                    BigDecimal goodsPrice = orderGoods.getGoodsPrice().multiply(BigDecimal.valueOf(orderGoods.getGoodsNum()));
-//                    sumGoodsPrice=sumGoodsPrice.add(goodsPrice);
-//                }
-//            }
             row.add(order.getDetail());
             row.add(order.getSumPrice());
             row.add(order.getCouponMoney());
@@ -1697,9 +1616,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             tbOrder.setShopName(goodsShop.getShopName());
             tbOrder.setShopPhone(goodsShop.getPhone());
         }
-//        if (tbOrder.getOrderTypeExtra() == 2 && "2".equals(tbOrder.getIndentState())) {
-//            tbOrder.setStatus(13);
-//        }
         List<OrderGoods> orderGoodsList = orderGoodsDao.selectList(new QueryWrapper<OrderGoods>().eq("order_id", tbOrder.getOrderId()));
         tbOrder.setOrderGoodsList(orderGoodsList);
         TbIndent tbIndent = tbIndentService.getOne(new QueryWrapper<TbIndent>().eq("order_id", tbOrder.getOrderId()));
@@ -1834,7 +1750,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             // 生成跑腿订单
             tbIndentService.insertIndent(tbOrder);
 
-
             //设置小程序消息推送
             CommonInfo one = commonInfoService.findOne(269);
             List<String> msgList = new ArrayList<>();
@@ -1861,6 +1776,9 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                 sumMoney = sumMoney.subtract(goodsShop.getErrandMoney());
             }
 
+            // 再减去校内配送费
+            sumMoney = sumMoney.subtract(tbOrder.getInsideDeliveryFee());
+
             BigDecimal shopMoney = sumMoney.multiply(shopRate);
             shopMoney = (shopMoney.setScale(2, BigDecimal.ROUND_DOWN));
             tbOrder.setShopIncomeMoney(shopMoney);
@@ -2172,6 +2090,9 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             }
         }
 
+        // 再减去校内配送费
+        sumMoney = sumMoney.subtract(tbOrder.getInsideDeliveryFee());
+
         // 店铺收入
         BigDecimal shopMoney = sumMoney.multiply(shopRate);
         shopMoney = shopMoney.setScale(2, BigDecimal.ROUND_DOWN);
@@ -2244,6 +2165,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             contentBuffer.append("跑腿费:").append(errandMoney.setScale(2, BigDecimal.ROUND_DOWN)).append("(").append(tbOrder.getErrandMoneyIsShop()).append(")").append(",");
         }
 
+        contentBuffer.append("特殊地址跑腿费:").append(tbOrder.getInsideDeliveryFee().setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         contentBuffer.append("平台服务费:").append(pingRate.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         contentBuffer.append("短信服务费:").append(smsSendMoney.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         contentBuffer.append("到账金额:").append(shopMoney.setScale(2, BigDecimal.ROUND_DOWN));
@@ -2552,7 +2474,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
 
     @Override
     public Result selectBuyGoods(Long userId, Long orderId) {
-        //   TbOrder tbOrder = appOrderDao.selectOne(new QueryWrapper<TbOrder>().eq("order_id", orderId).eq("user_id", userId));
         TbOrder tbOrder = appOrderDao.selectBuyGoods(orderId, userId);
         List<OrderGoods> orderGoodsList = orderGoodsDao.selectList(new QueryWrapper<OrderGoods>().eq("order_id", tbOrder.getOrderId()));
         tbOrder.setOrderGoodsList(orderGoodsList);
@@ -2969,26 +2890,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
         IPage<GoodsSkuSalesCountVO> page = baseMapper.getGoodsSkuSalesCount(pages, query);
         List<GoodsSkuSalesCountVO> records = page.getRecords();
 
-        try {
-            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
-            HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse();
-            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
-            response.setCharacterEncoding("UTF-8");
-
-            String excelName = "sku销售记录_";
-            excelName += DateUtil.format(new Date(), "yyyyMMddHHmmss");
-            String fileName = URLUtil.encode(excelName, "UTF-8");
-            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
-
-            EasyExcel.write(response.getOutputStream(), GoodsSkuSalesCountVO.class)
-                    .sheet("sheet1")
-                    .registerConverter(new LongStringConverter())
-                    .doWrite(records);
-        } catch (IOException e) {
-            log.error("sku销售记录导出失败:{}", e.getMessage());
-            throw new SqxException("sku销售记录导出失败");
-        }
+        EasyExcelUtil.exportExcel(records, GoodsSkuSalesCountVO.class, "sku销售记录", "sheet1");
     }
 
     /**
@@ -3009,6 +2911,4 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             lock.unlock();
         }
     }
-
-
 }

+ 25 - 0
src/main/java/com/sqx/modules/riderStation/controller/app/RiderStationController.java

@@ -0,0 +1,25 @@
+package com.sqx.modules.riderStation.controller.app;
+
+import com.sqx.common.utils.Result;
+import com.sqx.modules.riderStation.service.RiderStationService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Api(value = "用户端-骑手站点", tags = {"用户端-骑手站点"})
+@RequestMapping(value = "/app/riderStation")
+public class RiderStationController {
+
+    @Autowired
+    private RiderStationService riderStationService;
+
+    @ApiOperation("站点下拉框")
+    @GetMapping(value = "/stationList")
+    public Result stationList(){
+        return riderStationService.stationList();
+    }
+}

+ 2 - 0
src/main/java/com/sqx/modules/riderStation/service/RiderStationService.java

@@ -21,4 +21,6 @@ public interface RiderStationService extends IService<RiderStation> {
     Result updateStation(RiderStation riderStation);
 
     Result removeStation(Integer id);
+
+    RiderStation getName(String stationName);
 }

+ 8 - 0
src/main/java/com/sqx/modules/riderStation/service/impl/RiderStationServiceImpl.java

@@ -101,4 +101,12 @@ public class RiderStationServiceImpl extends ServiceImpl<RiderStationDao, RiderS
         return Result.success();
     }
 
+    @Override
+    public RiderStation getName(String stationName) {
+        LambdaQueryWrapper<RiderStation> wrapper=new LambdaQueryWrapper<>();
+        wrapper.eq(RiderStation::getStationName,stationName);
+        RiderStation station = this.getOne(wrapper);
+        return station;
+    }
+
 }

+ 29 - 0
src/main/java/com/sqx/modules/utils/SenInfoCheckUtil.java

@@ -198,6 +198,35 @@ public class SenInfoCheckUtil {
         }
     }
 
+    /**
+     * 获取二维码图片
+     */
+    public static void getShopQr2(String shopId, HttpServletResponse response){
+        String mpToken = getMpToken();
+        //获取二维码数据
+        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+mpToken;
+        Map<String,Object> map = Maps.newHashMap();
+        map.put("scene",shopId);
+        CommonInfo one = commonInfoService.findOne(261);
+        if("是".equals(one.getValue())){
+            map.put("page","my/index/shop/index2");
+        }
+        map.put("check_path",false);
+        map.put("env_version","trial");
+        map.put("width", 280);
+        String jsonString = JSON.toJSONString(map);
+        InputStream inputStream = sendPostBackStream(url, jsonString);
+        //生成二维码图片
+        response.setContentType("image/png");
+        try{
+            BufferedImage bi = ImageIO.read(inputStream);
+            ImageIO.write(bi, "JPG", response.getOutputStream());
+            inputStream.close();
+        }catch (Exception e){
+            logger.error(e.getMessage());
+        }
+    }
+
     /*public static void getShopQr(String shopId, HttpServletResponse response){
         String mpToken = getMpToken();
         //获取二维码数据

+ 96 - 0
src/main/java/com/sqx/modules/utils/excel/EasyExcelUtil.java

@@ -0,0 +1,96 @@
+package com.sqx.modules.utils.excel;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.converters.longconverter.LongStringConverter;
+import com.alibaba.excel.write.builder.ExcelWriterBuilder;
+import com.sqx.common.exception.SqxException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * easyexcel工具类
+ * @author codingliang
+ * @date 2025-09-16
+ */
+@Slf4j
+public class EasyExcelUtil {
+
+    /**
+     * 读取excel文件
+     *
+     * @param <T>      数据类型
+     * @param file     excel文件
+     * @param head     列名
+     * @param callBack 回调 导入时传入定义好的回调接口,excel数据解析完毕之后监听器将数据传入回调函数
+     *                 这样调用工具类时可以通过回调函数获取导入的数据,如果数据量过大可根据实际情况进行分配入库
+     */
+    public static <T> void readAnalysis(MultipartFile file, Class<T> head, ExcelFinishCallBack<T> callBack) {
+        try {
+            EasyExcel.read(file.getInputStream(), head, new ExcelDataListener<>(callBack)).sheet().doRead();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 导出Excel文件
+     * @param dataList 数据列表
+     * @param clazz 数据类的Class对象
+     * @param fileName 文件名(不含后缀)
+     * @param sheetName 工作表名称
+     * @throws IOException IO异常
+     */
+    public static <T> void exportExcel(List<T> dataList, Class<T> clazz, String fileName, String sheetName) {
+        try {
+            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+            if (requestAttributes == null) {
+                throw new SqxException("无法获取响应对象");
+            }
+            HttpServletResponse response = requestAttributes.getResponse();
+
+            // 设置响应头
+            setResponseHeader(response, fileName);
+
+            ExcelWriterBuilder writerBuilder = EasyExcel.write(response.getOutputStream(), clazz);
+            writerBuilder.sheet(sheetName);
+
+
+            EasyExcel.write(response.getOutputStream(), clazz)
+                    .sheet(sheetName)
+                    .registerConverter(new LongStringConverter())
+                    .doWrite(dataList);
+        } catch (IOException e) {
+            log.error("Excel导出失败:{}", e.getMessage());
+            throw new SqxException("Excel导出失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 设置响应头,包括内容类型和文件名
+     */
+    private static void setResponseHeader(HttpServletResponse response, String fileName) throws IOException {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+        response.setCharacterEncoding("UTF-8");
+
+        // 如果文件名为空,使用默认名称
+        if (StrUtil.isBlank(fileName)) {
+            fileName = "导出数据";
+        }
+        // 添加时间戳,避免文件名重复
+        fileName += "_" + DateUtil.format(new Date(), "yyyyMMddHHmmss");
+        // URL编码,避免中文乱码
+        String encodedFileName = URLEncoder.encode(fileName, "UTF-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx");
+    }
+}

+ 56 - 0
src/main/java/com/sqx/modules/utils/excel/ExcelDataListener.java

@@ -0,0 +1,56 @@
+package com.sqx.modules.utils.excel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * excel读取监听器
+ */
+public class ExcelDataListener<T> extends AnalysisEventListener<T> {
+    /**
+     * 定义一个保存Excel所有记录的集合
+     */
+    private final List<T> list = new LinkedList<>();
+    /**
+     * 回调接口
+     */
+    private final ExcelFinishCallBack<T> callBack;
+
+    /**
+     * 构造 ExcelFinishCallBack
+     *
+     * @param callBack ExcelFinishCallBack
+     */
+    public ExcelDataListener(ExcelFinishCallBack<T> callBack) {
+        this.callBack = callBack;
+    }
+
+
+    /**
+     * 这个每一条数据解析都会来调用
+     *
+     * @param data    one row value. is same as {@link AnalysisContext#readRowHolder()}
+     * @param context context
+     */
+    @Override
+    public void invoke(T data, AnalysisContext context) {
+        list.add(data);
+        if (list.size() == 500) {
+            this.callBack.doSaveBatch(list);
+            list.clear();
+        }
+    }
+
+    /**
+     * 解析完成之后将所有数据存入回调接口中
+     *
+     * @param context context
+     */
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        this.callBack.doAfterAllAnalysed(this.list);
+    }
+}

+ 22 - 0
src/main/java/com/sqx/modules/utils/excel/ExcelFinishCallBack.java

@@ -0,0 +1,22 @@
+package com.sqx.modules.utils.excel;
+
+import java.util.List;
+
+public interface ExcelFinishCallBack<T> {
+
+    /**
+     * 导出后置处理数据
+     * Do after all analysed.
+     *
+     * @param result the result
+     */
+    void doAfterAllAnalysed(List<T> result);
+
+    /**
+     * Do save batch.
+     *
+     * @param result the result
+     */
+    default void doSaveBatch(List<T> result) {
+    }
+}

+ 88 - 0
src/main/java/com/sqx/scheduler/export/ExportScheduler.java

@@ -1,7 +1,13 @@
 package com.sqx.scheduler.export;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.sqx.common.utils.Constant;
+import com.sqx.common.utils.Result;
 import com.sqx.common.utils.SftpUtil;
+import com.sqx.modules.address.query.InsideAddressQuery;
+import com.sqx.modules.address.service.InsideAddressService;
+import com.sqx.modules.address.vo.InsideAddressVO;
 import com.sqx.modules.app.entity.RechargeRecord;
 import com.sqx.modules.app.service.RechargeRecordService;
 import com.sqx.modules.app.service.UserMoneyDetailsService;
@@ -22,6 +28,7 @@ import com.sqx.modules.reconciliation.service.PlatformBillService;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.excel.ExportExcelUtils;
 import com.sqx.scheduler.config.SchedulerLock;
+import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
@@ -32,12 +39,17 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -67,6 +79,8 @@ public class ExportScheduler {
     private final DataCentreService dataCentreService;
     private final PlatformBillService platformBillService;
 
+    private final InsideAddressService insideAddressService;
+
 
     /**
      * 将所有超过失效时间的优惠券改为失效状态
@@ -130,6 +144,8 @@ public class ExportScheduler {
                         excelData=getShopBillExcelData(exportJob);
                     }else if("platformBill".equals(fileType)){
                         excelData=getPlatformBillExcelData(exportJob);
+                    }else if ("shippingAddress".equals(fileType)){
+                        excelData=getShippingAddressExcelData(exportJob);
                     }else{
                         continue;
                     }
@@ -174,6 +190,77 @@ public class ExportScheduler {
         }
     }
 
+    private ExcelData getShippingAddressExcelData(ExportJob exportJob) {
+        DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String[] conditions=exportJob.getConditions().split(",",-1);
+        InsideAddressQuery query = new InsideAddressQuery();
+        query.setAddressDetail(conditions[1]);
+        query.setStatus(conditions[2]);
+        if(!"".equals(conditions[3])){
+            query.setStationId(Long.valueOf(conditions[3]));
+        }
+        if(!"".equals(conditions[4])){
+            Date start = Date.from(LocalDateTime.parse(conditions[4], dateTimeFormatter1).atZone(ZoneId.systemDefault()).toInstant());
+            log.info("start:"+start);
+            query.setStartTime(start);
+        }
+        if(!"".equals(conditions[5])){
+            Date end = Date.from(LocalDateTime.parse(conditions[5], dateTimeFormatter1).atZone(ZoneId.systemDefault()).toInstant());
+            query.setEndTime(end);
+            log.info("end:"+end);
+        }
+
+        ExcelData data = new ExcelData();
+        data.setName("内部地址表");
+        List<String> titles = new ArrayList();
+        titles.add("编号");
+        titles.add("骑手站点");
+        titles.add("省");
+        titles.add("市");
+        titles.add("区/县");
+        titles.add("地址名");
+        titles.add("经度");
+        titles.add("纬度");
+        titles.add("地址配送费");
+        titles.add("排序");
+        titles.add("是否启用");
+        titles.add("创建时间");
+        data.setTitles(titles);
+
+        List<InsideAddressVO> recordList=insideAddressService.exportShippingAddress(query);
+        List<List<Object>> rows = new ArrayList<>();
+        for (int i = 0; i < recordList.size(); i++) {
+            InsideAddressVO record = recordList.get(i);
+            List<Object> row = new ArrayList<>();
+            row.add(i+1);
+            row.add(record.getStationName());
+            row.add(record.getProvince());
+            row.add(record.getCity());
+            row.add(record.getDistrict());
+            row.add(record.getAddressDetail());
+            row.add(record.getLng());
+            row.add(record.getLat());
+            row.add(record.getDeliveryFee());
+            row.add(record.getSort());
+            String status="禁用";
+            if (ObjectUtils.isNotEmpty(record.getStatus())) {
+                if ("1".equals(record.getStatus())) {
+                    status="启用";
+                }
+            }
+            row.add(status);
+            Date createTime = record.getCreateTime();
+            String start="";
+            if (ObjectUtils.isNotEmpty(createTime)) {
+                LocalDateTime localDateTime = LocalDateTime.ofInstant(createTime.toInstant(), ZoneId.systemDefault());
+                start = localDateTime.format(dateTimeFormatter1);
+            }
+            row.add(start);
+            rows.add(row);
+        }
+        data.setRows(rows);
+        return data;
+    }
 
 
     //订单导出
@@ -348,4 +435,5 @@ public class ExportScheduler {
         PlatformBillDto query = getPlatformBillDto(exportJob);
         return platformBillService.excelPlatformBillList(query);
     }
+
 }

+ 0 - 1
src/main/resources/application-dev.yml

@@ -96,7 +96,6 @@ secure-api:
             - /app/wxPay/notify
             - /app/wxPay/notifyJsApi
             - /app/wxPay/notifyShop
-            - 、
             - /app/wxPay/notifyJsApiShop
             - /app/wxPay/notifyMpShop
             - /pay/open/notify

+ 11 - 3
src/main/resources/mapper/address/AddressDao.xml

@@ -3,8 +3,16 @@
 <mapper namespace="com.sqx.modules.address.dao.AddressDao">
 
     <select id="selectAddressList" resultType="com.sqx.modules.address.entity.Address">
-        select * from address where user_id = #{userId}
-        order by address_default desc, update_time desc
+        select
+            *
+        from
+            address
+        where
+            user_id = #{userId}
+            <if test="insideAddressFlag">
+                and inside_address_id is not null
+            </if>
+        order by
+            address_default desc, update_time desc
     </select>
-
 </mapper>

+ 86 - 0
src/main/resources/mapper/address/InsideAddressDao.xml

@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.sqx.modules.address.dao.InsideAddressDao">
+
+    <select id="selectPages" resultType="com.sqx.modules.address.vo.InsideAddressVO">
+        SELECT
+            a.id,
+            a.create_time AS createTime,
+            a.update_time AS updateTime,
+            a.station_id AS stationId,
+            rs.station_name AS stationName,
+            a.delivery_fee AS deliveryFee,
+            a.province,
+            a.city,
+            a.district,
+            a.address_detail AS addressDetail,
+            a.lng,
+            a.lat,
+            a.status,
+            a.sort
+        FROM
+            inside_address a
+        LEFT JOIN
+            rider_station rs ON a.station_id = rs.id
+        WHERE
+            a.del_flag = '0'
+        <if test="query.addressDetail != null and query.addressDetail != ''">
+            AND a.address_detail LIKE CONCAT('%', #{query.addressDetail}, '%')
+        </if>
+        <if test="query.status != null and query.status != ''">
+            AND a.status = #{query.status}
+        </if>
+        <if test="query.stationId != null">
+            AND a.station_id = #{query.stationId}
+        </if>
+        <if test="query.startTime != null">
+            AND a.create_time &gt;= #{query.startTime}
+        </if>
+        <if test="query.endTime != null">
+            AND a.create_time &lt;= #{query.endTime}
+        </if>
+        ORDER BY
+            a.sort
+    </select>
+
+    <select id="exportShippingAddress" resultType="com.sqx.modules.address.vo.InsideAddressVO">
+        SELECT
+        a.id,
+        a.create_time AS createTime,
+        a.update_time AS updateTime,
+        a.station_id AS stationId,
+        rs.station_name AS stationName,
+        a.delivery_fee AS deliveryFee,
+        a.province,
+        a.city,
+        a.district,
+        a.address_detail AS addressDetail,
+        a.lng,
+        a.lat,
+        a.status,
+        a.sort
+        FROM
+        inside_address a
+        LEFT JOIN
+        rider_station rs ON a.station_id = rs.id
+        WHERE
+        a.del_flag = '0'
+        <if test="query.addressDetail != null and query.addressDetail != ''">
+            AND a.address_detail LIKE CONCAT('%', #{query.addressDetail}, '%')
+        </if>
+        <if test="query.status != null and query.status != ''">
+            AND a.status = #{query.status}
+        </if>
+        <if test="query.stationId != null">
+            AND a.station_id = #{query.stationId}
+        </if>
+        <if test="query.startTime != null">
+            AND a.create_time &gt;= #{query.startTime}
+        </if>
+        <if test="query.endTime != null">
+            AND a.create_time &lt;= #{query.endTime}
+        </if>
+        ORDER BY
+        a.sort
+    </select>
+</mapper>

+ 40 - 0
src/main/resources/mapper/goods/GoodsMapper.xml

@@ -199,4 +199,44 @@
         GROUP BY a.goods_particulars_picture
     </select>
 
+    <select id="selectGoodsVoByClassify" resultType="com.sqx.modules.goods.vo.GoodsListVo">
+        select g.goods_id as goodsId,
+               g.goods_cover as goodsCover,
+               g.goods_name as goodsName,
+               g.goods_describe as goodsDescribe,
+               g.goods_money as goodsMoney,
+               gsr.sales as sales
+        from goods_shop_relevancy gsr
+                 left join goods g on gsr.goods_id = g.goods_id
+        where gsr.shop_id = #{shopId}
+          and g.classify_id = #{classifyId}
+          and g.status = 0
+        order by g.sort asc
+    </select>
+    <select id="selectSupermarketGoodsList" resultType="com.sqx.modules.goods.entity.Goods">
+        select g.*, gsr.sales as sales, gsr.inventory as inventory, ga.activityList
+        from goods_shop_relevancy gsr
+                 left join goods g on gsr.goods_id = g.goods_id
+                 left join (
+            select
+                tmp.goods_id, group_concat(a.title) as activityList
+            from
+                (
+                    select t.activity_shop_id, substring_index(substring_index(t.goods_ids, ',', n.n), ',', -1) goods_id
+                    from
+                            (select 1 as n union select 2 union select 3 union select 4) n
+                                inner join activity_goods t on char_length(t.goods_ids)-char_length(replace(t.goods_ids, ',', ''))>=n.n-1
+                    order by n.n
+                ) tmp
+                    left join activity_shop ach on ach.id = tmp.activity_shop_id
+                    left join activity a on ach.activity_id = a.id
+            where a.del_flag = '0'
+            group by tmp.goods_id
+        ) ga on ga.goods_id = g.goods_id
+        where gsr.shop_id = #{shopId}
+          and g.classify_id = #{classifyId}
+          and g.status = 0
+        order by g.sort asc
+    </select>
+
 </mapper>