瑞吉外卖-移动端菜品展示功能,购物车添加菜品及修改等功能,用户下单功能及历史订单派送功能

整理记录下学习整个瑞吉外卖项目,详细代码可在我的Gitee仓库瑞吉外卖实战克隆下载学习使用!

12.菜品展示

12.1 需求分析

![[Pasted image 20230304211220.png]]

12.2 更改前台页面使其正常显示

由于购物车功能还未进行开发,所以修改main.js中的cartListJson函数中访问固定数据,如图
![[Pasted image 20230305102615.png]]
重启清除缓存后如图![[Pasted image 20230305103748.png]]

12.3 修改查询菜品方法

12.3.1 代码开发

前台访问的是查询菜品接口方法list,但移动端还需要菜品的口味信息,所以必须得修改DishController中原有的方法,修改如下:

    @GetMapping("/list")  public Result<List<DishDto>> list(Dish dish) {  List<DishDto> dishDtoList;  //构造查询条件  LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());  //添加条件,查询状态为1(起售状态)的菜品  queryWrapper.eq(Dish::getStatus, 1);  //添加排序条件  queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);  List<Dish> list = dishService.list(queryWrapper);  dishDtoList = list.stream().map((item) -> {  DishDto dishDto = new DishDto();  BeanUtils.copyProperties(item, dishDto);  Long categoryId = item.getCategoryId();//分类id  //当前菜品的id  Long dishId = item.getId();  LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();  lambdaQueryWrapper.eq(DishFlavor::getDishId, dishId);  //SQL:select * from dish_flavor where dish_id = ?  List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);  dishDto.setFlavors(dishFlavorList);  return dishDto;  }).collect(Collectors.toList());  return Result.success(dishDtoList);  }

12.3.2 测试

  • 测试后如图,点击添加规格有口味信息来选择,![[Pasted image 20230305104045.png]]

12.4 查询套餐

12.4.1 代码开发

SetmealController编写查询套餐代码,如下:

@GetMapping("/list")  public Result<List<Setmeal>> list(Setmeal setmeal) {  LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId());  queryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());  queryWrapper.orderByDesc(Setmeal::getUpdateTime);  List<Setmeal> list = setmealService.list(queryWrapper);  return Result.success(list);  }

12.4.2 测试

如图所示,不再报错
![[Pasted image 20230305110950.png]]

13. 购物车模块

13.1需求分析

![[Pasted image 20230305110759.png]]

13.2 数据模型

购物车对应表为shopping_cart表,结构如下:
![[Pasted image 20230305111150.png]]

13.3 代码开发

13.3.1 导入实体类或编写实体类

@Data  
public class ShoppingCart implements Serializable {  private static final long serialVersionUID = 1L;  private Long id;  //名称  private String name;  //用户id  private Long userId;  //菜品id  private Long dishId;  //套餐id  private Long setmealId;  //口味  private String dishFlavor;  //数量  private Integer number;  //金额  private BigDecimal amount;  //图片  private String image;  private LocalDateTime createTime;  
}

13.3.2 新建对应的Mapper、Service及实现类和controller类

这里自行建立就行,和之前一样

13.3.3 购物车添加功能

  • controller编写添加功能,如下:
@Slf4j  
@RestController  
@RequestMapping("/shoppingCart")  
@RequiredArgsConstructor  
public class ShoppingCartController {  private final ShoppingCartService shoppingCartService;  /**  * 添加购物车  * @param shoppingCart  * @return  */  @PostMapping("/add")  public Result<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart){  log.info("购物车数据:{}",shoppingCart);  //设置用户id,指定当前是哪个用户的购物车数据  Long currentId = BaseContext.getCurrentId();  shoppingCart.setUserId(currentId);  Long dishId = shoppingCart.getDishId();  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(ShoppingCart::getUserId,currentId);  if(dishId != null){  //添加到购物车的是菜品  queryWrapper.eq(ShoppingCart::getDishId,dishId);  }else{  //添加到购物车的是套餐  queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());  }  //查询当前菜品或者套餐是否在购物车中  //SQL:select * from shopping_cart where user_id = ? and dish_id/setmeal_id = ?  ShoppingCart cartServiceOne = shoppingCartService.getOne(queryWrapper);  if(cartServiceOne != null){  //如果已经存在,就在原来数量基础上加一  Integer number = cartServiceOne.getNumber();  cartServiceOne.setNumber(number + 1);  shoppingCartService.updateById(cartServiceOne);  }else{  //如果不存在,则添加到购物车,数量默认就是一  shoppingCart.setNumber(1);  shoppingCart.setCreateTime(LocalDateTime.now());  shoppingCartService.save(shoppingCart);  cartServiceOne = shoppingCart;  }  return Result.success(cartServiceOne);  }}

13.3.4 测试

测试添加功能,如图操作![[Pasted image 20230305140219.png]]
数据库查看结果![[Pasted image 20230305140240.png]]

13.3.5 购物车查看

  • 更改main.js为原来,如图![[Pasted image 20230305141021.png]]
  • 编写查看方法,如下:
@GetMapping("/list")  
public Result<List<ShoppingCart>> list(){  log.info("查看购物车...");  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());  queryWrapper.orderByAsc(ShoppingCart::getCreateTime);  List<ShoppingCart> list = shoppingCartService.list(queryWrapper);  return Result.success(list);  
}

13.3.6 测试

测试,登录之前账号查看,如图![[Pasted image 20230305141403.png]]

13.3.7 购物车套餐或菜品数量减少

  • 编写减少方法,如下:
@PostMapping("/sub")  
public Result<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart) {  Long dishId = shoppingCart.getDishId();  Long setmealId = shoppingCart.getSetmealId();  //条件构造器  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  //只查询当前用户ID的购物车  queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());  //代表数量减少的是菜品数量  if (dishId != null) {  //通过dishId查出购物车菜品数据  queryWrapper.eq(ShoppingCart::getDishId, dishId);  ShoppingCart dishCart = shoppingCartService.getOne(queryWrapper);  //将查出来的数据的数量-1  dishCart.setNumber(dishCart.getNumber() - 1);  Integer currentNum = dishCart.getNumber();  //然后判断  if (currentNum > 0) {  //大于0则更新  shoppingCartService.updateById(dishCart);  } else if (currentNum == 0) {  //小于0则删除  shoppingCartService.removeById(dishCart.getId());  }  return Result.success(dishCart);  }  if (setmealId != null) {  //通过setmealId查询购物车套餐数据  queryWrapper.eq(ShoppingCart::getSetmealId, setmealId);  ShoppingCart setmealCart = shoppingCartService.getOne(queryWrapper);  //将查出来的数据的数量-1  setmealCart.setNumber(setmealCart.getNumber() - 1);  Integer currentNum = setmealCart.getNumber();  //然后判断  if (currentNum > 0) {  //大于0则更新  shoppingCartService.updateById(setmealCart);  } else if (currentNum == 0) {  //等于0则删除  shoppingCartService.removeById(setmealCart.getId());  }  return Result.success(setmealCart);  }  return Result.error("系统繁忙,请稍后再试");  
}
  • 测试,再次登录之前账号,点击+号结果如图,添加成功
    ![[Pasted image 20230305141510.png]]
    点击-号,如图![[Pasted image 20230305141540.png]]
    数据库结果正确![[Pasted image 20230305141557.png]]

13.3.8 购物车清空

@DeleteMapping("/clean")  
public Result<String> clean(){  //SQL:delete from shopping_cart where user_id = ?  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());  shoppingCartService.remove(queryWrapper);  return Result.success("清空购物车成功");  
}

13.3.9 测试

再次登录之前账号,点击清空,结果如图![[Pasted image 20230305141630.png]]

14. 用户下单

14.1 需求分析

![[Pasted image 20230305141803.png]]

14.2 数据模型

涉及到两张表orders表和order-detials表,结构如图
- 订单表orders,如图![[Pasted image 20230305141933.png]]
- 订单详情表order_details,如图![[Pasted image 20230305141959.png]]

14.3 代码开发

14.3.1 编写导入实体类

@Data  
public class Orders implements Serializable {  private static final long serialVersionUID = 1L;  private Long id;  //订单号  private String number;  //订单状态 1待付款,2待派送,3已派送,4已完成,5已取消  private Integer status;  //下单用户id  private Long userId;  //地址id  private Long addressBookId;  //下单时间  private LocalDateTime orderTime;  //结账时间  private LocalDateTime checkoutTime;  //支付方式 1微信,2支付宝  private Integer payMethod;  //实收金额  private BigDecimal amount;  //备注  private String remark;  //用户名  private String userName;  //手机号  private String phone;  //地址  private String address;  //收货人  private String consignee;  
}//订单详情类
@Data  
public class OrderDetail implements Serializable {  private static final long serialVersionUID = 1L;  private Long id;  //名称  private String name;  //订单id  private Long orderId;  //菜品id  private Long dishId;  //套餐id  private Long setmealId;  //口味  private String dishFlavor;  //数量  private Integer number;  //金额  private BigDecimal amount;  //图片  private String image;  
}

14.3.2 新建对应的Mapper、Service及实现类

和之前一样

14.3.3 添加数据传输对象OrdersDto

用于将订单和对应的订单详情结合在一个类里,代码如下:

@Data  
public class OrdersDto extends Orders {  private List<OrderDetail> orderDetails;  
}

14.3.4 编写提交订单业务

OrderService加入submit方法并进行实现。代码如下:

@Service  
@Slf4j  
@RequiredArgsConstructor  
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {  private final ShoppingCartService shoppingCartService;  private final UserService userService;  private final AddressBookService addressBookService;  private final OrderDetailService orderDetailService;  /**  * 用户下单  * @param orders  */  @Transactional  public void submit(Orders orders) {  //获得当前用户id  Long userId = BaseContext.getCurrentId();  //查询当前用户的购物车数据  LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();  wrapper.eq(ShoppingCart::getUserId,userId);  List<ShoppingCart> shoppingCarts = shoppingCartService.list(wrapper);  if(shoppingCarts == null || shoppingCarts.size() == 0){  throw new CustomException("购物车为空,不能下单");  }  //查询用户数据  User user = userService.getById(userId);  //查询地址数据  Long addressBookId = orders.getAddressBookId();  AddressBook addressBook = addressBookService.getById(addressBookId);  if(addressBook == null){  throw new CustomException("用户地址信息有误,不能下单");  }  long orderId = IdWorker.getId();//订单号  AtomicInteger amount = new AtomicInteger(0);  List<OrderDetail> orderDetails = shoppingCarts.stream().map((item) -> {  OrderDetail orderDetail = new OrderDetail();  orderDetail.setOrderId(orderId);  orderDetail.setNumber(item.getNumber());  orderDetail.setDishFlavor(item.getDishFlavor());  orderDetail.setDishId(item.getDishId());  orderDetail.setSetmealId(item.getSetmealId());  orderDetail.setName(item.getName());  orderDetail.setImage(item.getImage());  orderDetail.setAmount(item.getAmount());  amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());  return orderDetail;  }).collect(Collectors.toList());  orders.setId(orderId);  orders.setOrderTime(LocalDateTime.now());  orders.setCheckoutTime(LocalDateTime.now());  orders.setStatus(2);  orders.setAmount(new BigDecimal(amount.get()));//总金额  orders.setUserId(userId);  orders.setNumber(String.valueOf(orderId));  orders.setUserName(user.getName());  orders.setConsignee(addressBook.getConsignee());  orders.setPhone(addressBook.getPhone());  orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())  + (addressBook.getCityName() == null ? "" : addressBook.getCityName())  + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())  + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));  //向订单表插入数据,一条数据  this.save(orders);  //向订单明细表插入数据,多条数据  orderDetailService.saveBatch(orderDetails);  //清空购物车数据  shoppingCartService.remove(wrapper);  }  
}

14.3.5 编写Controller类

controller层调用提交订单方法即可,如图
![[Pasted image 20230305154720.png]]

14.4 测试

启动项目后,登录之前的账号,点击结算后填写地址并设置为默认地址,如图![[Pasted image 20230305154934.png]]
再次点击结算后跳转到支付页面,如图![[Pasted image 20230305155032.png]]
支付成功后如图
![[Pasted image 20230305155233.png]]

15. 历史订单

15.1需求分析

  • 当用户想再次点购上次吃的菜品或套餐时可以通过查看历史订单来知道
  • 当用户下单后管理员必须进行相应的操作,派送或者查看订单详情

15.2 代码开发

  • 直接在OrdesController类中编写查找历史订单,修改订单状态及查看订单方法,如下:
@GetMapping("/userPage")  
public Result<Page> page(int page, int pageSize) {  //获取当前id  Long userId = BaseContext.getCurrentId();  Page<Orders> pageInfo = new Page<>(page, pageSize);  Page<OrdersDto> ordersDtoPage = new Page<>(page, pageSize);  //条件构造器  LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();  //查询当前用户id订单数据  queryWrapper.eq(userId != null, Orders::getUserId, userId);  //按时间降序排序  queryWrapper.orderByDesc(Orders::getOrderTime);  orderService.page(pageInfo, queryWrapper);  List<OrdersDto> list = pageInfo.getRecords().stream().map((item) -> {  OrdersDto ordersDto = new OrdersDto();  //获取orderId,然后根据这个id,去orderDetail表中查数据  Long orderId = item.getId();  LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();  wrapper.eq(OrderDetail::getOrderId, orderId);  List<OrderDetail> details = orderDetailService.list(wrapper);  BeanUtils.copyProperties(item, ordersDto);  //之后set一下属性  ordersDto.setOrderDetails(details);  return ordersDto;  }).collect(Collectors.toList());  BeanUtils.copyProperties(pageInfo, ordersDtoPage, "records");  ordersDtoPage.setRecords(list);  //日志输出看一下  log.info("list:{}", list);  return Result.success(ordersDtoPage);  
}
@PostMapping("/again")  
public Result<String> again(@RequestBody Map<String,String> map){  //获取order_id  Long orderId = Long.valueOf(map.get("id"));  //条件构造器  LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();  //查询订单的口味细节数据  queryWrapper.eq(OrderDetail::getOrderId,orderId);  List<OrderDetail> details = orderDetailService.list(queryWrapper);  //获取用户id,待会需要set操作  Long userId = BaseContext.getCurrentId();  List<ShoppingCart> shoppingCarts = details.stream().map((item) ->{  ShoppingCart shoppingCart = new ShoppingCart();  //Copy对应属性值  BeanUtils.copyProperties(item,shoppingCart);  //设置一下userId  shoppingCart.setUserId(userId);  //设置一下创建时间为当前时间  shoppingCart.setCreateTime(LocalDateTime.now());  return shoppingCart;  }).collect(Collectors.toList());  //加入购物车  shoppingCartService.saveBatch(shoppingCarts);  return Result.success("喜欢吃就再来一单吖~");  
}  
/**  * 订单明细  * @param page  * @param pageSize  * @param number  * @param beginTime  * @param endTime  * @return  */  
@GetMapping("/page")  
public Result<Page> page(int page, int pageSize, Long number, String beginTime, String endTime) {  //获取当前id  Page<Orders> pageInfo = new Page<>(page, pageSize);  Page<OrdersDto> ordersDtoPage = new Page<>(page, pageSize);  //条件构造器  LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();  //按时间降序排序  queryWrapper.orderByDesc(Orders::getOrderTime);  //订单号  queryWrapper.eq(number != null, Orders::getId, number);  //时间段,大于开始,小于结束  queryWrapper.gt(!StringUtils.isEmpty(beginTime), Orders::getOrderTime, beginTime)  .lt(!StringUtils.isEmpty(endTime), Orders::getOrderTime, endTime);  orderService.page(pageInfo, queryWrapper);  List<OrdersDto> list = pageInfo.getRecords().stream().map((item) -> {  OrdersDto ordersDto = new OrdersDto();  //获取orderId,然后根据这个id,去orderDetail表中查数据  Long orderId = item.getId();  LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();  wrapper.eq(OrderDetail::getOrderId, orderId);  List<OrderDetail> details = orderDetailService.list(wrapper);  BeanUtils.copyProperties(item, ordersDto);  //之后set一下属性  ordersDto.setOrderDetails(details);  return ordersDto;  }).collect(Collectors.toList());  BeanUtils.copyProperties(pageInfo, ordersDtoPage, "records");  ordersDtoPage.setRecords(list);  //日志输出看一下  log.info("list:{}", list);  return Result.success(ordersDtoPage);  
}  @PutMapping  
public Result<String> changeStatus(@RequestBody Map<String, String> map) {  int status = Integer.parseInt(map.get("status"));  Long orderId = Long.valueOf(map.get("id"));  log.info("修改订单状态:status={status},id={id}", status, orderId);  LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<>();  updateWrapper.eq(Orders::getId, orderId);  updateWrapper.set(Orders::getStatus, status);  orderService.update(updateWrapper);  return Result.success("订单状态修改成功");  
}

15.3 测试

  • 还是登录之前账号,点击头像后选择历史订单,结果如图
    ![[Pasted image 20230305160342.png]]
  • 后台登录管理员进行点击派送,如图
    ![[Pasted image 20230305222308.png]]
    显示订单派送完成,如图
    ![[Pasted image 20230305222333.png]]
  • 点击完成订单,如图![[Pasted image 20230305222401.png]]
    显示![[Pasted image 20230305222413.png]]
  • 点击查看订单详情后如图![[Pasted image 20230305222438.png]]
  • 输入订单号进行查询后,如图
    ![[Pasted image 20230305222546.png]]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34123.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外卖点餐APP-04(后台--菜品管理)

&#xff08;一&#xff09;新增 controller层思路&#xff1a; 调用service处理响应处理结果 PostMapping public R<String> save(RequestBody DishDto dishDto){dishService.saveWithFlavors(dishDto);return R.success("新增成功&#xff01;"); } servi…

瑞吉外卖:后台系统登录和退出功能

文章目录 需求分析代码开发创建实体类导入返回结果类Rcontroller、service与mapperlogin.html防止非法访问 需求分析 点击登录按钮后&#xff0c;浏览器以POST方式向employee/login提交username和password&#xff0c;服务器经过处理后向浏览器返回某种格式的数据&#xff0c;…

服装销售数据分析

目录&#xff1a; 一、项目背景介绍 二、数据源 三、分析流程 四、分析框架 五、知识点总结 一、项目背景介绍&#xff1a; 某服装经销商经营多个女装品牌&#xff0c;每个品牌设有线下店铺。该公司老板及销售总监需在每日营业结束后查看当日销售数据。以往主要由业务员手动整…

创建报价单或销售凭证,提示无定价确定过程能被确定,消息号V1212

创建报价单&#xff0c;提示无定价确定过程能被确定&#xff0c;消息号V1212。 解决方案&#xff1a; spro 》销售和分销——》基本功能——》定价——》定价控制——》定价并分配定价过程 1&#xff09;将凭证定价程序分配给订单类型 2&#xff09;设置定价程序确定&#xff0…

ChatGPT工作提效之layedit上传多附件的解决方案(layedit赋值、layui.js底层修改、追加模式多附件上传)

ChatGPT工作提效系列文章目录 ChatGPT工作提效之初探路径独孤九剑遇强则强ChatGPT工作提效之在程序开发中的巧劲和指令(创建MySQL语句、PHP语句、Javascript用法、python的交互)ChatGPT工作提效之生成开发需求和报价单并转为Excel格式ChatGPT工作提效之小鹅通二次开发批量API对…

Zia和ChatGPT如何协同工作?

有没有集成ChatGPT的CRM系统推荐&#xff1f;Zoho CRM已经正式与ChatGPT集成。下面我们将从使用场景、使用价值和使用范围等方面切入讲述CRMAI的应用和作用。 Zia和ChatGPT如何协同工作&#xff1f; Zia和ChatGPT是不同的人工智能模型&#xff0c;在CRM中呈现出共生的关系。 …

AIGC持续火爆大模型争相推出,庞大市场造就算力供应模式演变

本图由AI生成 文/王吉伟 近期的AIGC领域仍旧火爆异常。 但火的不只是AIGC应用&#xff0c;还有巨头之间的AI竞赛&#xff0c;以及接连不断上新的AI大模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;。 面对ChatGPT带来的技术冲击&#xff0c;为了研发谷歌多…

ChatGPT实现命名实体识别(NER, named entity recognization)和词性归类

语义分析词格分类 命名实体识别(NER, named entity recognization)和词性归类是 NLP 技术中的关键一环。过去 NLP 领域有不少流行的开源项目专注在这个领域&#xff0c;如 Spacy、NLTK 等等。我们来试试 ChatGPT 在这方面的表现情况如何。我们从"四渡赤水"的百度百科…

突发!两所知名大学,曝合并!校方紧急回应:校长将亲自说明!

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 来源丨联合新闻网 编辑丨3D视觉工坊 点击进入—>3D视觉工坊学习交流群 我国台湾又有“国立”大学传出合并的消息&#xff0c;台湾中山大学与台湾高雄大学传将重启合并协商&#xff0c;有网友曝光中山大学发…

从 Uber 数据泄露事件我们可以学到什么?

Uber 数据泄露始于一名黑客从暗网市场购买属于一名 Uber 员工的被盗凭证。最初尝试使用这些凭据连接到 Uber 的网络失败&#xff0c;因为该帐户受 MFA 保护。为了克服这一安全障碍&#xff0c;黑客通过 What’s App 联系了 Uber 员工&#xff0c;并假装是 Uber 的安全人员&…

点击率预估

点击率预估是广告技术的核心算法之一&#xff0c;它是很多广告算法工程师喜爱的战场。一直想介绍一下点击率预估&#xff0c;但是涉及公式和模型理论太多&#xff0c;怕说不清楚&#xff0c;读者也不明白。所以&#xff0c;这段时间花了一些时间整理点击率预估的知识&#xff0…

老鸟教你如何精确评估开发时间

一个程序员能否精确评估开发时间&#xff0c;是一件非常重要的事情。如果你掌握了这项技能&#xff0c;你在别人的眼里就会是这样&#xff1a; 靠谱经验十足对需求很了解延期风险小合格的软件工程师正规军&#xff0c;不是野路子 评估开发时间的重要性 首先&#xff0c;在一…

从FM推演各深度CTR预估模型(附代码)

作者&#xff1a; 龙心尘 && 寒小阳 时间&#xff1a;2018年7月 出处&#xff1a;https://blog.csdn.net/longxinchen_ml/article/details/81031736 https://blog.csdn.net/han_xiaoyang/article/details/81031961 声明&#xff1a;版权所有&#xff0c;转载请联系作者…

[项目管理] 如何评估工作量

1.1. 工作量估算的定义 工作量估算 即对开发软件产品所需的人力和时间的估算——人力成本是一个项目的主要成本。 我们可以根据预估的工作量决定具体由几个人、哪几个人参与该项目。 工作量通常以 人/天、人/月、人/年 的形式来衡量。 1.2. 为什么要进行工作量估算 做好工…

机器学习实战 | 综合项目-电商销量预估

作者&#xff1a;韩信子ShowMeAI 教程地址&#xff1a;https://www.showmeai.tech/tutorials/41 本文地址&#xff1a;https://www.showmeai.tech/article-detail/206 声明&#xff1a;版权所有&#xff0c;转载请联系平台与作者并注明出处 收藏ShowMeAI查看更多精彩内容 1.案例…

Python:实现进度条和时间预估

一、前言 在python当中可以用进度条来显示工作的进度&#xff0c;比如for循环的进度或者一些模型训练的进度。 在这里可以使用progressbar包以及tqdm包来实现。 使用pip install progressbar 安装progressbar包。 使用pip install tqdm安装tqdm包。 二、代码 1. progress…

如何科学预估开发时间

0. 我是前言 一个开发人员能否精确评估开发时间&#xff0c;是一件非常重要的事情。如果你掌握了这项技能&#xff0c;你在别人的眼里就会是这样&#xff1a; 1. 评估开发时间的重要性 首先&#xff0c;在一个项目中&#xff0c;所有的环节都是承上启下的&#xff0c;不管你是…

编译原理之代码生成

前面提到了经过了词法分析->语法分析->语义分析->中间代码优化&#xff0c;最后的阶段便是在目标机器上运行的目标代码的生成了。目标代码生成阶段的任务是&#xff1a;将此前的中间代码转换成特定机器上的机器语言或汇编语言&#xff0c;这种转换程序便被称为代码生成…

前端案例-跟随鼠标移动的天使

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域新星创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

前端代码在线编辑器:codepen、codesandbox

文章目录 单文件在线编辑器项目级在线编辑器 推荐两个前端代码在线编辑器 单文件在线编辑器&#xff1a;https://codepen.io/pen/ 项目级在线编辑器&#xff1a;https://codesandbox.io/ 单文件在线编辑器 codepen 相信使用 element-ui组件库的小伙伴应该知道 codepen在线编…