咖啡商城|基于Springboot+Vue前后端分离咖啡商城系统

Posted 编程指南针

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了咖啡商城|基于Springboot+Vue前后端分离咖啡商城系统相关的知识,希望对你有一定的参考价值。

作者主页:编程指南针

作者简介:Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师

主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助

收藏点赞不迷路  关注作者有好处

文末获取源码 

项目编号:BS-SC-042

前言:

在目前电商为王的中国社会上,种类繁多的电子商务网站如雨后春笋般纷纷建立,百花齐鸣的发展态势可以在很大程度上,十分有效的解决原来时代的信息资源闭塞和地域上的限制[1]。网上交易代替了很多传统的线下消费,这种势头发展的越来越火热,而这一却都是伴随着用户的购买能力的提高,和IT信息化产业的发展以及新型互联网技术的应用。

互联网以及移动互联网的普及应用,也使得消费者的消费路径更加快捷短暂,足不出户可一缆天下,一机在手可买遍全球。所以消费者基本上已经被新的消费模式所吸引,也具备了网络消费的应用水平。而对于广大的电商平台来讲,大而全的电商有之,小而美的电商也有自己的存活空间。而最近这些年比较流行的垂直电商平台的崛起和应用,也让我们的用户可以直接找到自己所喜欢咖啡的平台,进行点对点的消费,这就是我们进行咖啡电商研究的一个基础背景。

一,项目简介

本项目基于Spring Boot搭建的咖啡商城系统主要有用户管理功能、商品管理功能、购物车管理功能、订单管理功能、角色管理功能等,一共分为七个大的核心模块:

前台管理系统:

(1)用户功能模块:用户可以进行登录注册与注销操作,并且可以对个人信息进行响应的修改。

(2)手办功能模块:用户可以搜索查看自己想要的手办,也可以点击手办进行查看手办的详细信息。

(3)购物车管理模块:用户可以把自己感兴趣的商品加入购物车,点击购物车查看购物车信息,可以的对购物车内的商品进行修改,用账号余额对购物车进行结算。

(4)订单功能模块:用户点击订单查看自己的所有订单信息,看到当前订单状态,对已完成的订单进行评价。

后台管理系统:

(5)用户管理模块:管理员可以对普通用户信息进行相应的增删改查操作。

(6)手办资讯管理:管理员可以对商品资讯进行相应的增删改查操作,向用户进行商品推荐。

(7)商品管理模块:管理员可以对商品的信息进行修改,增加新的商品,删除掉不用的商品。

(8)轮播图管理模块:管理员可以对轮播图的信息进行修改,增加新的轮播图,根据优惠在首页显示推荐商品轮播图,实时修改轮播图信息。

1.1.2  性能需求

本系统的主要使用对象为手办系统管理员以及消费者,由于消费者主要为年轻人群体,所以对时间的要求不高,没有限制使用的时间。本系统在浏览器运行,需要保证隐私性要强。

时间性:新品手办上架时,可能登录系统的用户较多,需要保证用户操作时服务器反应时间在5秒以内。

运行环境约束:系统可以在IE8以上浏览器平稳运行,可以在不同浏览器运行,对运行的环境要求较低。

易用性需求:本系统页面简介明了易操作,对于众多用户来说可用性较强,不需要进行培训等流程都可以操作。

本系统采用B/S架构进行设计,主要针对PC端用户使用的,不需要专门的客户端,只需要浏览器就能使用,所以对于其他架构来说方便就是它的优势。它是跨平台的,是基于网页语言的、操作系统对其没有太大的影响。系统架构设计图如下图4-1所示:

图2-1 系统架构设计图

2.2  主要功能设计

2.2.1  用户管理功能

用户管理功能主要有前台用户注册、用户账号登录、查看用户信息、修改用户的详细信息以及搜索用户。用户需要登录账号才可以对个人用户信息进行查看和修改,在输入账号密码时会进行信息的判断,数据传到服务器进行信息的验证,如果用户未注册,系统会提示用户账号或密码不正确;如果用户已注册输入的信息有误会提示用户输入正确的账号密码信息,如果信息无误则直接登录成功。用户登录流程图如图2-2所示,用户注册流程图如图2-3所示,用户管理流程图如图2-4所示。

图2-2 用户登录流程图

图2-3 用户注册流程图

图2-4 用户管理流程图

2.2.2  商品管理功能

商品管理功能主要包括了添加商品、修改商品信息、查看商品信息以及下架商品等操作。管理员只有在登录后才可以对商品信息进行操作,可以添加需要新增的商品信息,如果商品信息有误或商品促销时会降价,管理员可以手动修改商品的价格或商品的其他信息,管理员还可以对需要下架的商品进行删除操作。商品管理顺序图如图4-5所示。

图2-5 商品管理流程图

2.2.3  购物车管理功能

用户在登录账号后可以看到自己的购物车页面,用户可以选择将心仪的商品添加至购物车,在购物车页面进行商品的购买与结算,不再需要一单一结操作简单,为用户带来了便利。在购物车页面,用户也可以修改购物车内添加的商品数量。购物车管理顺序图如图2-6所示。

图2-6 购物车管理顺序图

2.2.4  订单管理功能

订单管理模块主要是用户点击订单查看自己的所有订单信息,看到当前订单状态,对已完成的订单进行评价。订单管理流程图如图4-7所示。

图2-7 订单管理流程图

2.2.5  轮播图管理功能

轮播图管理功能属于管理员登录后可以进行的操作,管理员可以按照需求添加新的轮播图信息,可以在原本设置好的轮播图信息上进行修改。轮播图管理功能流程图如图2-8所示。

图2-8 轮播图管理流程图

2.2.6  商品资讯管理功能

商品资讯管理功能属于管理员登录后可以进行的操作,管理员可以按照需求添加新的资讯信息,也可以对老旧的资讯进行删除和更新。商品资讯管理功能流程图如图2-9所示。

图2-9 商品资讯管理流程图

二,环境介绍

语言环境:Java:  jdk1.8

数据库:mysql: mysql5.7

应用服务器:Tomcat:  tomcat8.5.31

开发工具:IDEA或eclipse

后台开发技术:Springboot+Mybatis

前台开发技术:Vue+nodejs+ElementUI

特色:支付宝沙箱支付、前后端分离开发

三,系统展示

系统首页

分类展示

 商品详情

前端用户注册登陆

 购物车

下单支付:点支付从充值卡里扣除,如不够则进入支付宝沙箱支付平台

 商品资讯

 个人中心:可以实现在线充值

 我的订单

用户管理

商品分类管理

商品管理

 评价管理

轮播图管理

商品资讯

四,核心代码展示

package com.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PathVariable;
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 com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.ConfigEntity;
import com.entity.EIException;
import com.service.ConfigService;
import com.utils.R;

/**
 * 上传文件映射表
 */
@RestController
@RequestMapping("file")
@SuppressWarnings("unchecked","rawtypes")
public class FileController
	@Autowired
    private ConfigService configService;
	/**
	 * 上传文件
	 */
	@RequestMapping("/upload")
	public R upload(@RequestParam("file") MultipartFile file,String type) throws Exception 
		if (file.isEmpty()) 
			throw new EIException("上传文件不能为空");
		
		String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
		//File path = new File(ResourceUtils.getURL("classpath:static").getPath());
		String path2 = ResourceUtils.getFile("classpath:static").getAbsolutePath();
		/*if(!path.exists()) 
		    path = new File("");
		*/
		File upload = new File(path2,"/upload/");
		if(!upload.exists()) 
		    upload.mkdirs();
		
		String fileName = new Date().getTime()+"."+fileExt;
		File dest = new File(upload.getAbsolutePath()+"/"+fileName);
		file.transferTo(dest);
		if(StringUtils.isNotBlank(type) && type.equals("1")) 
			ConfigEntity configEntity = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "faceFile"));
			if(configEntity==null) 
				configEntity = new ConfigEntity();
				configEntity.setName("faceFile");
				configEntity.setValue(fileName);
			 else 
				configEntity.setValue(fileName);
			
			configService.insertOrUpdate(configEntity);
		
		return R.ok().put("file", fileName);
	

	/**
	 * 下载文件
	 */
	@IgnoreAuth
	@RequestMapping("/download")
	public ResponseEntity<byte[]> download(@RequestParam String fileName) 
		try 
			File path = new File(ResourceUtils.getURL("classpath:static").getPath());
			if(!path.exists()) 
			    path = new File("");
			
			File upload = new File(path.getAbsolutePath(),"/upload/");
			if(!upload.exists()) 
			    upload.mkdirs();
			
			File file = new File(upload.getAbsolutePath()+"/"+fileName);
			if(file.exists())
				/*if(!fileService.canRead(file, SessionManager.getSessionUser()))
					getResponse().sendError(403);
				*/
				HttpHeaders headers = new HttpHeaders();
			    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
			    headers.setContentDispositionFormData("attachment", fileName);
			    return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
			
		 catch (IOException e) 
			e.printStackTrace();
		
		return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);
	


package com.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

import com.utils.ValidatorUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PathVariable;
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 com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.annotation.IgnoreAuth;

import com.entity.OrdersEntity;
import com.entity.view.OrdersView;

import com.service.OrdersService;
import com.service.TokenService;
import com.utils.PageUtils;
import com.utils.R;
import com.utils.MD5Util;
import com.utils.MPUtil;
import com.utils.CommonUtil;


/**
 * 订单
 * 后端接口
 * @author 
 * @email 
 * @date 2021-03-13 12:49:52
 */
@RestController
@RequestMapping("/orders")
public class OrdersController 
    @Autowired
    private OrdersService ordersService;
    


    /**
     * 后端列表
     */
    @RequestMapping("/page")
    public R page(@RequestParam Map<String, Object> params,OrdersEntity orders,
		HttpServletRequest request)
    	if(!request.getSession().getAttribute("role").toString().equals("管理员")) 
    		orders.setUserid((Long)request.getSession().getAttribute("userId"));
    	
        EntityWrapper<OrdersEntity> ew = new EntityWrapper<OrdersEntity>();
		PageUtils page = ordersService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, orders), params), params));

        return R.ok().put("data", page);
    
    
    /**
     * 前端列表
     */
    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params,OrdersEntity orders, HttpServletRequest request)
        EntityWrapper<OrdersEntity> ew = new EntityWrapper<OrdersEntity>();
		PageUtils page = ordersService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, orders), params), params));
        return R.ok().put("data", page);
    

	/**
     * 列表
     */
    @RequestMapping("/lists")
    public R list( OrdersEntity orders)
       	EntityWrapper<OrdersEntity> ew = new EntityWrapper<OrdersEntity>();
      	ew.allEq(MPUtil.allEQMapPre( orders, "orders")); 
        return R.ok().put("data", ordersService.selectListView(ew));
    

	 /**
     * 查询
     */
    @RequestMapping("/query")
    public R query(OrdersEntity orders)
        EntityWrapper< OrdersEntity> ew = new EntityWrapper< OrdersEntity>();
 		ew.allEq(MPUtil.allEQMapPre( orders, "orders")); 
		OrdersView ordersView =  ordersService.selectView(ew);
		return R.ok("查询订单成功").put("data", ordersView);
    
	
    /**
     * 后端详情
     */
    @RequestMapping("/info/id")
    public R info(@PathVariable("id") Long id)
        OrdersEntity orders = ordersService.selectById(id);
        return R.ok().put("data", orders);
    

    /**
     * 前端详情
     */
    @RequestMapping("/detail/id")
    public R detail(@PathVariable("id") Long id)
        OrdersEntity orders = ordersService.selectById(id);
        return R.ok().put("data", orders);
    
    



    /**
     * 后端保存
     */
    @RequestMapping("/save")
    public R save(@RequestBody OrdersEntity orders, HttpServletRequest request)
    	orders.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
    	//ValidatorUtils.validateEntity(orders);
    	orders.setUserid((Long)request.getSession().getAttribute("userId"));
        ordersService.insert(orders);
        return R.ok();
    
    
    /**
     * 前端保存
     */
    @RequestMapping("/add")
    public R add(@RequestBody OrdersEntity orders, HttpServletRequest request)
    	orders.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
    	//ValidatorUtils.validateEntity(orders);
        ordersService.insert(orders);
        return R.ok();
    

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody OrdersEntity orders, HttpServletRequest request)
        //ValidatorUtils.validateEntity(orders);
        ordersService.updateById(orders);//全部更新
        return R.ok();
    
    

    /**
     * 删除
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Long[] ids)
        ordersService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    
    
    /**
     * 提醒接口
     */
	@RequestMapping("/remind/columnName/type")
	public R remindCount(@PathVariable("columnName") String columnName, HttpServletRequest request, 
						 @PathVariable("type") String type,@RequestParam Map<String, Object> map) 
		map.put("column", columnName);
		map.put("type", type);
		
		if(type.equals("2")) 
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Calendar c = Calendar.getInstance();
			Date remindStartDate = null;
			Date remindEndDate = null;
			if(map.get("remindstart")!=null) 
				Integer remindStart = Integer.parseInt(map.get("remindstart").toString());
				c.setTime(new Date()); 
				c.add(Calendar.DAY_OF_MONTH,remindStart);
				remindStartDate = c.getTime();
				map.put("remindstart", sdf.format(remindStartDate));
			
			if(map.get("remindend")!=null) 
				Integer remindEnd = Integer.parseInt(map.get("remindend").toString());
				c.setTime(new Date());
				c.add(Calendar.DAY_OF_MONTH,remindEnd);
				remindEndDate = c.getTime();
				map.put("remindend", sdf.format(remindEndDate));
			
		
		
		Wrapper<OrdersEntity> wrapper = new EntityWrapper<OrdersEntity>();
		if(map.get("remindstart")!=null) 
			wrapper.ge(columnName, map.get("remindstart"));
		
		if(map.get("remindend")!=null) 
			wrapper.le(columnName, map.get("remindend"));
		
		if(!request.getSession().getAttribute("role").toString().equals("管理员")) 
    		wrapper.eq("userid", (Long)request.getSession().getAttribute("userId"));
    	


		int count = ordersService.selectCount(wrapper);
		return R.ok().put("count", count);
	
	



package com.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

import com.utils.ValidatorUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PathVariable;
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 com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.annotation.IgnoreAuth;

import com.entity.StoreupEntity;
import com.entity.view.StoreupView;

import com.service.StoreupService;
import com.service.TokenService;
import com.utils.PageUtils;
import com.utils.R;
import com.utils.MD5Util;
import com.utils.MPUtil;
import com.utils.CommonUtil;


/**
 * 收藏表
 * 后端接口
 * @author 
 * @email 
 * @date 2021-03-13 12:49:52
 */
@RestController
@RequestMapping("/storeup")
public class StoreupController 
    @Autowired
    private StoreupService storeupService;
    


    /**
     * 后端列表
     */
    @RequestMapping("/page")
    public R page(@RequestParam Map<String, Object> params,StoreupEntity storeup,
		HttpServletRequest request)
    	if(!request.getSession().getAttribute("role").toString().equals("管理员")) 
    		storeup.setUserid((Long)request.getSession().getAttribute("userId"));
    	
        EntityWrapper<StoreupEntity> ew = new EntityWrapper<StoreupEntity>();
		PageUtils page = storeupService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, storeup), params), params));

        return R.ok().put("data", page);
    
    
    /**
     * 前端列表
     */
    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params,StoreupEntity storeup, HttpServletRequest request)
    	if(!request.getSession().getAttribute("role").toString().equals("管理员")) 
    		storeup.setUserid((Long)request.getSession().getAttribute("userId"));
    	
        EntityWrapper<StoreupEntity> ew = new EntityWrapper<StoreupEntity>();
		PageUtils page = storeupService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, storeup), params), params));
        return R.ok().put("data", page);
    

	/**
     * 列表
     */
    @RequestMapping("/lists")
    public R list( StoreupEntity storeup)
       	EntityWrapper<StoreupEntity> ew = new EntityWrapper<StoreupEntity>();
      	ew.allEq(MPUtil.allEQMapPre( storeup, "storeup")); 
        return R.ok().put("data", storeupService.selectListView(ew));
    

	 /**
     * 查询
     */
    @RequestMapping("/query")
    public R query(StoreupEntity storeup)
        EntityWrapper< StoreupEntity> ew = new EntityWrapper< StoreupEntity>();
 		ew.allEq(MPUtil.allEQMapPre( storeup, "storeup")); 
		StoreupView storeupView =  storeupService.selectView(ew);
		return R.ok("查询收藏表成功").put("data", storeupView);
    
	
    /**
     * 后端详情
     */
    @RequestMapping("/info/id")
    public R info(@PathVariable("id") Long id)
        StoreupEntity storeup = storeupService.selectById(id);
        return R.ok().put("data", storeup);
    

    /**
     * 前端详情
     */
    @RequestMapping("/detail/id")
    public R detail(@PathVariable("id") Long id)
        StoreupEntity storeup = storeupService.selectById(id);
        return R.ok().put("data", storeup);
    
    



    /**
     * 后端保存
     */
    @RequestMapping("/save")
    public R save(@RequestBody StoreupEntity storeup, HttpServletRequest request)
    	storeup.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
    	//ValidatorUtils.validateEntity(storeup);
    	storeup.setUserid((Long)request.getSession().getAttribute("userId"));
        storeupService.insert(storeup);
        return R.ok();
    
    
    /**
     * 前端保存
     */
    @RequestMapping("/add")
    public R add(@RequestBody StoreupEntity storeup, HttpServletRequest request)
    	storeup.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
    	//ValidatorUtils.validateEntity(storeup);
    	storeup.setUserid((Long)request.getSession().getAttribute("userId"));
        storeupService.insert(storeup);
        return R.ok();
    

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody StoreupEntity storeup, HttpServletRequest request)
        //ValidatorUtils.validateEntity(storeup);
        storeupService.updateById(storeup);//全部更新
        return R.ok();
    
    

    /**
     * 删除
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Long[] ids)
        storeupService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    
    
    /**
     * 提醒接口
     */
	@RequestMapping("/remind/columnName/type")
	public R remindCount(@PathVariable("columnName") String columnName, HttpServletRequest request, 
						 @PathVariable("type") String type,@RequestParam Map<String, Object> map) 
		map.put("column", columnName);
		map.put("type", type);
		
		if(type.equals("2")) 
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Calendar c = Calendar.getInstance();
			Date remindStartDate = null;
			Date remindEndDate = null;
			if(map.get("remindstart")!=null) 
				Integer remindStart = Integer.parseInt(map.get("remindstart").toString());
				c.setTime(new Date()); 
				c.add(Calendar.DAY_OF_MONTH,remindStart);
				remindStartDate = c.getTime();
				map.put("remindstart", sdf.format(remindStartDate));
			
			if(map.get("remindend")!=null) 
				Integer remindEnd = Integer.parseInt(map.get("remindend").toString());
				c.setTime(new Date());
				c.add(Calendar.DAY_OF_MONTH,remindEnd);
				remindEndDate = c.getTime();
				map.put("remindend", sdf.format(remindEndDate));
			
		
		
		Wrapper<StoreupEntity> wrapper = new EntityWrapper<StoreupEntity>();
		if(map.get("remindstart")!=null) 
			wrapper.ge(columnName, map.get("remindstart"));
		
		if(map.get("remindend")!=null) 
			wrapper.le(columnName, map.get("remindend"));
		
		if(!request.getSession().getAttribute("role").toString().equals("管理员")) 
    		wrapper.eq("userid", (Long)request.getSession().getAttribute("userId"));
    	


		int count = storeupService.selectCount(wrapper);
		return R.ok().put("count", count);
	
	



五,项目总结

基于Springboot实现的咖啡商城网站是一种网络销售模式,将传统的咖啡展示与购买从线上搬到了线上,它解决传统电子产品实体店地域的限制和要求,方便人们足不出户进行产品的购买和消费。具体研究有如下意义:

(1)解决线下单店区域限制的问题,可以实现全域覆盖。

(2)线上销售的总体成本在低于线下实体店,可以有更有竞争力的价格优势。

(3)随着技术的发展,线上的产品浏览体验也越来越好,可以更加方便用户进行对比

(4)疫情当下,线上消费可以实现无接触配送,更加安全高效。

以上是关于咖啡商城|基于Springboot+Vue前后端分离咖啡商城系统的主要内容,如果未能解决你的问题,请参考以下文章

前后端分离第7期的基于Vue+Springboot精简版仿小米商城系统

基于Springboot+Vue实现前后端分离商城管理系统

基于Vue + SpringBoot实现的前后端分离的商城项目,包含秒杀模块(毕设)

基于springboot+vue的宠物商城系统(前后端分离)

基于Java+SpringBoot+vue+element实现前后端分离玩具商城系统

基于Java springboot+vue+redis前后端分离家具商城平台系统设计和实现