当前位置: 首页 > news >正文

二刷 苍穹外卖day09

查询历史订单

service

public PageResult pageQuery4User(int pageNum, int pageSize, Integer status) {// 设置分页PageHelper.startPage(pageNum, pageSize);OrdersPageQueryDTO ordersPageQueryDTO = new OrdersPageQueryDTO();ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());ordersPageQueryDTO.setStatus(status);// 分页条件查询Page<Orders> page = orderMapper.pageQuery(ordersPageQueryDTO);List<OrderVO> list = new ArrayList();// 查询出订单明细,并封装入OrderVO进行响应if (page != null && page.getTotal() > 0) {for (Orders orders : page) {Long orderId = orders.getId();// 订单id// 查询订单明细List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(orderId);OrderVO orderVO = new OrderVO();BeanUtils.copyProperties(orders, orderVO);orderVO.setOrderDetailList(orderDetails);list.add(orderVO);}}return new PageResult(page.getTotal(), list);}

先创建了一个OrdersPageQueryDTO对象,用于封装查询条件

通过BaseContent.getCurrentId()获取当前用户id
在设置好状态后
用条件查询功能查询符合要求的订单数据,返回一个Page对象

创建OrderVO类型的list列表用于存储封装后的订单数据

将page对象中的每一个订单Orders,查询订单id,并通过订单id查询订单明细,通过BeanUtils工具将Orders对象的属性复制到orderVO中,并将查询到的订单明细列表也赋值到orderVO中

取消订单

 public void userCancelById(Long id) throws Exception {// 根据id查询订单Orders ordersDB = orderMapper.getById(id);// 校验订单是否存在if (ordersDB == null) {throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);}//订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消if (ordersDB.getStatus() > 2) {throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);}Orders orders = new Orders();orders.setId(ordersDB.getId());// 更新订单状态、取消原因、取消时间orders.setStatus(Orders.CANCELLED);orders.setCancelReason("用户取消");orders.setCancelTime(LocalDateTime.now());orderMapper.update(orders);}

先检查订单是否存在,再检查订单状态是否能够取消(这里省略了退款情况,因为没做支付功能)
然后创建一个orders对象,将部分信息修改,这里是Update,只会修改有的,而没提到的菜品信息等仍然会保留

再来一单

service

    /*** 再来一单** @param id*/public void repetition(Long id) {// 查询当前用户idLong userId = BaseContext.getCurrentId();// 根据订单id查询当前订单详情List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);// 将订单详情对象转换为购物车对象List<ShoppingCart> shoppingCartList = orderDetailList.stream().map(x -> {ShoppingCart shoppingCart = new ShoppingCart();// 将原订单详情里面的菜品信息重新复制到购物车对象中BeanUtils.copyProperties(x, shoppingCart, "id");shoppingCart.setUserId(userId);shoppingCart.setCreateTime(LocalDateTime.now());return shoppingCart;}).collect(Collectors.toList());// 将购物车对象批量添加到数据库shoppingCartMapper.insertBatch(shoppingCartList);}

使用Stream(流)操作,对orderDetailList中的每个元素进行映射操作,map会对OrderDetailList中的每个元素执行括号内的逻辑,再将其转换为ShoppingCart类型的对象
最后通过collect(Collectors.toList())将转换后的对象收集到一个List类型的shoppingCartList中

流操作

流操作 = 流水线工厂

想象你是一个工厂老板,有一批订单详情(比如汉堡、薯条、可乐的订单)需要变成购物车商品(给顾客结账用)。流操作就像是一条流水线,每个订单在流水线上走一遍,出来就变成了购物车商品。

  1. stream()

    • 把一个列表(订单详情)变成 “可以逐个处理的东西”,就像把一堆零件放到传送带上。
  2. map()

    • 对流水线上的每个东西做转换(比如把订单→购物车商品)。x -> {...} 是一个箭头函数,表示 “对每个 x 做这些操作”。
  3. collect(Collectors.toList())

    • 流水线的终点,把处理好的东西重新收集回一个列表。

订单搜索

    /*** 订单搜索** @param ordersPageQueryDTO* @return*/public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());Page<Orders> page = orderMapper.pageQuery(ordersPageQueryDTO);// 部分订单状态,需要额外返回订单菜品信息,将Orders转化为OrderVOList<OrderVO> orderVOList = getOrderVOList(page);return new PageResult(page.getTotal(), orderVOList);}private List<OrderVO> getOrderVOList(Page<Orders> page) {// 需要返回订单菜品信息,自定义OrderVO响应结果List<OrderVO> orderVOList = new ArrayList<>();List<Orders> ordersList = page.getResult();if (!CollectionUtils.isEmpty(ordersList)) {for (Orders orders : ordersList) {// 将共同字段复制到OrderVOOrderVO orderVO = new OrderVO();BeanUtils.copyProperties(orders, orderVO);String orderDishes = getOrderDishesStr(orders);// 将订单菜品信息封装到orderVO中,并添加到orderVOListorderVO.setOrderDishes(orderDishes);orderVOList.add(orderVO);}}return orderVOList;}/*** 根据订单id获取菜品信息字符串** @param orders* @return*/private String getOrderDishesStr(Orders orders) {// 查询订单菜品详情信息(订单中的菜品和数量)List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orders.getId());// 将每一条订单菜品信息拼接为字符串(格式:宫保鸡丁*3;)List<String> orderDishList = orderDetailList.stream().map(x -> {String orderDish = x.getName() + "*" + x.getNumber() + ";";return orderDish;}).collect(Collectors.toList());// 将该订单对应的所有菜品信息拼接在一起return String.join("", orderDishList);}

conditionSearch是对外暴露的订单搜索接口,负责分页查询并返回订单列表
调用getOrderVOList将Orders对象转换为OrderVO对象,其中包含更多展示字段
在gerOrderVOList方法中通过调用page.getResult就能拿到List
先判断是否为空,然后将所有值都复制到OrderVO中,再调用getOrderDishesStr方法将所有菜品信息拼接成特定格式的字符串

而getOrderDishesStr方法使用了Stream流,将所有菜品详情都转换成了字符串的格式,最后通过Stream.join拼接

检验收货地址是否超出配送范围

/*** 检查客户的收货地址是否超出配送范围* @param address*/private void checkOutOfRange(String address) {Map map = new HashMap();map.put("address",shopAddress);map.put("output","json");map.put("ak",ak);//获取店铺的经纬度坐标String shopCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", map);JSONObject jsonObject = JSON.parseObject(shopCoordinate);if(!jsonObject.getString("status").equals("0")){throw new OrderBusinessException("店铺地址解析失败");}//数据解析JSONObject location = jsonObject.getJSONObject("result").getJSONObject("location");String lat = location.getString("lat");String lng = location.getString("lng");//店铺经纬度坐标String shopLngLat = lat + "," + lng;map.put("address",address);//获取用户收货地址的经纬度坐标String userCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", map);jsonObject = JSON.parseObject(userCoordinate);if(!jsonObject.getString("status").equals("0")){throw new OrderBusinessException("收货地址解析失败");}//数据解析location = jsonObject.getJSONObject("result").getJSONObject("location");lat = location.getString("lat");lng = location.getString("lng");//用户收货地址经纬度坐标String userLngLat = lat + "," + lng;map.put("origin",shopLngLat);map.put("destination",userLngLat);map.put("steps_info","0");//路线规划String json = HttpClientUtil.doGet("https://api.map.baidu.com/directionlite/v1/driving", map);jsonObject = JSON.parseObject(json);if(!jsonObject.getString("status").equals("0")){throw new OrderBusinessException("配送路线规划失败");}//数据解析JSONObject result = jsonObject.getJSONObject("result");JSONArray jsonArray = (JSONArray) result.get("routes");Integer distance = (Integer) ((JSONObject) jsonArray.get(0)).get("distance");if(distance > 5000){//配送距离超过5000米throw new OrderBusinessException("超出配送范围");}}

先通过调用百度地图api获取店铺的经纬度坐标
然后解析json数据得到店铺的经纬度坐标
然后同理获取用户的经纬度坐标
然后解析json数据得到用户收货地址的经纬度坐标
解析json数据后得到店铺的经纬度坐标
然后把两地的经纬度坐标放到map中让百度地图进行路径规划
把规划好后的距离解析查看距离是否大于5000米,大于回复超出配送范围

记得修改submitOrder方法,在其中调用这个函数

总结

1.为什么在订单查询中使用PageResult和OrderVO对象

PageResult用于封装分页查询结果(包括总记录数和当前页数据),便于前端展示分页信息
OrderVO是专为前端展示设计的对象,在Orders实体的基础上扩展了额外字段,避免返回数据,提升接口性能。

2.Stream流在订单处理中主要是什么应用场景

对象转换:将OrderDetail转换为ShoppingCart对象
数据拼接:将订单菜品信息拼接成字符串

3.取消订单时为什么要校验订单状态?

订单状态决定了业务流程的合法性:
仅当状态为代付款和代接单才能被允许取消,比较已配送或已完成的订单被误操作.

4.”再来一单“功能如何实现从订单到购物车的转换?

通过Stream.map()遍历整个订单详情,将每个OrderDetail转换为ShoppingCart对象
利用BeanUtils.copyProperties复制基础属性
最终通过collect(Collectors.toList())收集为购物车列表,批量存入数据库
5.## 配送范围校验中,百度地图 API 的核心调用流程是什么?
地址解析:将店铺和用户地址转换为经纬度坐标。
路线规划:调用 driving 接口计算两地驾车距离。
距离判断:若距离超过 5000 米,抛出 “超出配送范围” 异常。
关键是确保 API 请求参数正确,并正确解析 JSON 响应中的 distance 字段。

http://www.lryc.cn/news/577175.html

相关文章:

  • 【硬核数学 · LLM篇】3.1 Transformer之心:自注意力机制的线性代数解构《从零构建机器学习、深度学习到LLM的数学认知》
  • 借助 Wisdom SSH,实现 Linux 用户组与权限的精细化智能管控
  • DataGrip测试连接时出现报错解决方案
  • 谷歌高调宣布,Gemini 2.5 Pro正式版,绘制常见图表(折线图、柱状图、PPT等),国内直接使用
  • 将 h264+g711a存为 mp4文件,记录
  • uniapp+vue2 ba-tree-picker下拉项多选 树形层级选择器(支持单选、多选、父级选择、映射)
  • SAP月结问题9-FAGLL03H与损益表中研发费用金额不一致(FAGLL03H Bug)
  • 【数据结构中的位运算】
  • 堆排序实现及复杂度分析
  • AWS WebRTC:通过shell分析并发启动master后产生的日志文件
  • 腾讯云空间,高性能显卡云,安装xinference报错,pip install 空间不够用了
  • 大语言模型(LLM)笔记
  • JavaEE-MyBatis-Plus
  • datax-web报错:连接数据库失败. 请检查您的 账号、密码、数据库名称、IP、Port或者向 DBA 寻求帮助(注意网络环境)
  • Flutter插件ios_pod
  • 跨时间潜运动迁移以实现操作中的多帧预测
  • 云效DevOps vs Gitee vs 自建GitLab的技术选型
  • 临床试验审计问题分类与整改策略
  • 高效数据采集:Python与Rust完美结合
  • 将本地仓库推送到GitHub
  • 【Pandas】pandas DataFrame attrs
  • 2025年光学工程、精密仪器与光电子技术国际会议(OEPIOT 2025)
  • 【MCP服务】蓝耘元生代 | 蓝耘MCP平台来袭!DeepSeek MCP服务器玩转大模型集成
  • Python-Word文档、PPT、PDF以及Pillow处理图像详解
  • 车载ECU刷写文件格式汇总详解
  • 博图SCL编程:结构体(STRUCT)使用详解与实战案例
  • .net实现内容推荐算法代码
  • C++ --- list
  • ES6笔记1
  • ES6从入门到精通:箭头函数