在首页中随机显示8款奶茶
```java
@GetMapping(“recommend”)
@ApiOperation(value = “ 首页“为你推荐””)
public List recommend() {
随机选择8款奶茶向用户推荐
Integer nums = 8;
Integer start = 1;
Integer end = countMilktea();
//1.创建集合容器对象
List list = new ArrayList();
List ret = new ArrayList();
//2.创建Random对象
Random r = new Random();
//循环将得到的随机数进行判断,如果随机数不存在于集合中,则将随机数放入集合中,如果存在,则将随机数丢弃不做操作,进行下一次循环,直到集合长度等于nums
while (list.size() != nums) {
Integer num = r.nextInt(end - start) + start;
if (!list.contains(num)) {
list.add(num);
}
}
for (Object l : list) {
NumberFormat formatter = NumberFormat.getNumberInstance();
String s = formatter.format(Integer.parseInt(l.toString()));
@PostMapping("addOneOrderByStr")
@ApiOperation(value = "增加一个订单条目")
public boolean addOneOrderByStr(String openid,String drinkStr,String address,String phoneNum,String name)
{
//转对象集合
JSONArray json = JSONArray.fromObject(drinkStr);
List<OrderDrink> drinkList = (List<OrderDrink>) JSONArray.toCollection(json, OrderDrink.class);
//加入时间
Timestamp time = new Timestamp(System.currentTimeMillis());
double totalPrice = 0;
//统计价格
for (OrderDrink d : drinkList) {
totalPrice = totalPrice + d.getDrinkPrice();
}
//先插入orderinfo表
Order order = new Order();
order.setOpenid(openid);
order.setTime(time);
order.setTotal(totalPrice);
order.setStatus(0);
order.setAddress(address);
order.setPhonenum(phoneNum);
order.setName(name);
if (orderMapper.addOneOrderInfo(order) == 0)
return false;
//后插入selectinfo表
SelectInfo selectInfo;
//获取orderinof表最大的orderid
int orderId = orderMapper.findLastOrderId();
//拆分drinklist,组成为单条条目,插入数据库
for (OrderDrink d : drinkList) {
selectInfo = new SelectInfo();
selectInfo.setId(d.getDrinkId());
selectInfo.setDescription(d.getDrinkInfo());
selectInfo.setNumber(d.getDrinkNum());
selectInfo.setPrice(d.getDrinkPrice());
selectInfo.setOrderId(orderId);
totalPrice = totalPrice + d.getDrinkPrice();
if (orderMapper.addOneSelectInfo(selectInfo) == 0)
return false;
}
return true;
}
mapper语句:
<insert id="addOneSelectInfo" parameterType="com.demo01.demo.entity.SelectInfo">
insert into comselectinfo value(#{orderId},#{id},#{number},#{description},#{price})
</insert>
<insert id="addOneOrderInfo" parameterType="com.demo01.demo.entity.Order">
insert into OrderInfo value(null,#{openid},#{time},#{total},#{status},#{address},#{phonenum},#{name})
</insert>
5.查询制作中订单接口
@GetMapping("findMakingMiniOrder")
@ApiOperation(value = "查询用户制作中订单缩略信息")
public List<MiniOrder> findMakingMiniOrder(String openid) {
List<MiniOrderEntry> entryList = orderMapper.findMakingMiniOrder(openid);
List<MiniOrder> orderList = new ArrayList<>();
List<String> drinkIdList = new ArrayList<>();
List<String> imageList = new ArrayList<>();
MiniOrder orderTmp = new MiniOrder();
int drinkId;
int orderId = -1;
double total = 0;
//查询结果为空
if (entryList.size() == 0)
return null;
//根据订单编号合并订单条目,组成一个完整订单
for (MiniOrderEntry e : entryList) {
//当前条目属于一个新订单
if (orderId != e.getOrderId()) {
//不是第一个订单才需要添加到orderList
if (orderId != -1) {
orderTmp.setTotal(total);
orderTmp.setDrinkIdList(drinkIdList);
orderTmp.setImageList(imageList);
orderList.add(orderTmp);
}
//清空上个订单用到的变量
orderTmp = new MiniOrder();
drinkIdList = new ArrayList<>();
imageList = new ArrayList<>();
total = 0;
//不是第一个订单才需要清空drinkList,imageList
if (orderId != -1) {
drinkIdList.clear();
imageList.clear();
}
//
orderId = e.getOrderId();
orderTmp.setOrderId(e.getOrderId());
orderTmp.setOrderTime(e.getTime());
orderTmp.setOpenid(e.getOpenid());
total += e.getPrice();
//加入一种饮品
drinkIdList.add(e.getId());
imageList.add(e.getImage());
}
//当前条目与上条条目属于同一个订单,仅添加饮品
else {
total += e.getPrice();
drinkIdList.add(e.getId());
imageList.add(e.getImage());
}
}
orderTmp.setTotal(total);
orderTmp.setDrinkIdList(drinkIdList);
orderTmp.setImageList(imageList);
orderList.add(orderTmp);
return orderList;
}
mapper语句:
<select id="findMakingMiniOrder" resultType="com.demo01.demo.entity.MiniOrderEntry">
select a.orderId,a.openid,a.total,a.time,b.id,b.number,b.price,c.image
from OrderInfo a, comselectinfo b, milktea c
where openid=#{openid} and a.orderId = b.orderId and b.id = c.id and Status = 0;
</select>
6.查询已完成订单接口
@GetMapping("findCompletedMiniOrder")
@ApiOperation(value = "查询用户已完成订单缩略信息")
public List<MiniOrder> findCompletedMiniOrder(String openid) {
List<MiniOrderEntry> entryList = orderMapper.findCompletedMiniOrder(openid);
List<MiniOrder> orderList = new ArrayList<>();
List<String> drinkIdList = new ArrayList<>();
List<String> imageList = new ArrayList<>();
MiniOrder orderTmp = new MiniOrder();
int drinkId;
int orderId = -1;
double total = 0;
//查询结果为空
if (entryList.size() == 0)
return null;
//根据订单编号合并订单条目,组成一个完整订单
for (MiniOrderEntry e : entryList) {
//当前条目属于一个新订单
if (orderId != e.getOrderId()) {
//不是第一个订单才需要添加到orderList
if (orderId != -1) {
orderTmp.setTotal(total);
orderTmp.setDrinkIdList(drinkIdList);
orderTmp.setImageList(imageList);
orderList.add(orderTmp);
}
//清空上个订单用到的变量
orderTmp = new MiniOrder();
drinkIdList = new ArrayList<>();
imageList = new ArrayList<>();
total = 0;
//不是第一个订单才需要清空drinkList,imageList
if (orderId != -1) {
drinkIdList.clear();
imageList.clear();
}
//
orderId = e.getOrderId();
orderTmp.setOrderId(e.getOrderId());
orderTmp.setOrderTime(e.getTime());
orderTmp.setOpenid(e.getOpenid());
total += e.getPrice();
//加入一种饮品
drinkIdList.add(e.getId());
imageList.add(e.getImage());
}
//当前条目与上条条目属于同一个订单,仅添加饮品
else {
total += e.getPrice();
drinkIdList.add(e.getId());
imageList.add(e.getImage());
}
}
orderTmp.setTotal(total);
orderTmp.setDrinkIdList(drinkIdList);
orderTmp.setImageList(imageList);
orderList.add(orderTmp);
return orderList;
}
mapper语句:
<select id="findCompletedMiniOrder" resultType="com.demo01.demo.entity.MiniOrderEntry">
select a.orderId,a.openid,a.total,a.time,b.id,b.number,b.price,c.image
from OrderInfo a, comselectinfo b, milktea c
where openid=#{openid} and a.orderId = b.orderId and b.id = c.id and Status = 1;
</select>
@RestController
@Api(tags = "管理员控制器")
public class AdminController {
//…………
@PutMapping("/admin/milktea")
@ApiOperation(value = "根据ID修改奶茶")
public Result<?> updateMilkteaInfo(@RequestBody Milktea milktea) {
return ResultUtils.success(milkteaService.updateMilktea(milktea));
}
//…………
}
5.根据ID查询奶茶信息
对应实体类与2.一致 Controller:
@RestController
@Api(tags = "管理员控制器")
public class AdminController {
//…………
@GetMapping("/admin/milktea/{milkteaId}")
@ApiOperation(value = "根据ID查询奶茶")
public Result<?> getMilkteaById(@PathVariable("milkteaId") String milkteaId) {
return ResultUtils.success(milkteaService.selectOneMilktea(milkteaId));
}
//…………
}
6.根据ID删除奶茶信息
略
7.统计近N日每日销售量
给前端返回的是Json以便解析 对应实体类:
public class OrderInfoChart extends BaseRowModel {
@ExcelProperty(value = "时间",index = 0)
String time;
@ExcelProperty(value = "订单数",index = 1)
int orderNum;
//省略Getter and Setter
}
Controller:
@RestController
@Api(tags = "管理员控制器")
public class AdminController {
//…………
@GetMapping("/admin/orders/getOrderInfoAnyTime")
@ApiOperation(value = "统计历史每日订单数")
public Result<?> getOrderInfoAnyTime(int days) {
return ResultUtils.success(orderService.getOrderInfo_anyTime(days));
}
//…………
}
SQL语句:
```mysql
SELECT DATE_FORMAT( Time, '%Y-%m-%d' ) time, count(*) orderNum
FROM orderinfo
where DATE_SUB(CURDATE(), INTERVAL #{days} DAY) <= date(Time)
group by DATE_FORMAT( Time, '%Y-%m-%d' )
东莞理工学院网络空间安全学院
期末大作业:基于微信小程序的新零售移动电商系统设计与实验
基于小程序和Spring Boot的奶茶点单系统
一.项目背景
受新冠疫情影响,消费者闭门不出,线下门店纷纷关闭,实体经济收到重大冲击。除了疫情的挑战,传统
零售与传统电商,一直被效率、场景、管控等问题困扰。
新零售赋能传统零售转型升级。线上商城与线下门店的交易无缝缝合,通过技术改变消费者的习惯,集合
结合高效的物流配送,极大提高消费者的购物体验。基于微信的生态圈用户流量,让平台更快的传播获客,吸引
海量用户资源。
二.需求分析
本项目需要分为两个客户端:
三.技术栈
客户端
微信小程序后台前端
React,Ant组件库后台后端
SpringBoot,Mysql四.具体实现
客户端
客户端采用小程序为客户提供图形界面,方便客户查看商品,下订单,查看订单状态前端
1.登录:
客户可以使用微信一键登录进入小程序,小程序会保存用户的登录信息2.首页(展示推荐信息,公告图片):
3.点单页面
点单页面为客户展示商品列表以供选购4.购物车页面
客户可以在购物车页面查看自己选购了那些商品,并提供下单入口5.订单页面
订单页面向客户展示了客户的历史订单,以及未完成订单6.客户个人信息页面
客户可以在这个页面查看自己的个人信息,退出登录小程序端操作说明
7.下订单
8.在购物车结算
9.支付
10.未取餐订单
支付以后可以在未取餐订单中查看已下订单后端
后端主要提供的功能:1.“为你推荐”接口
在首页中随机显示8款奶茶 ```java @GetMapping(“recommend”) @ApiOperation(value = “ 首页“为你推荐””) public List// System.out.println(s); ret.add(selectOneMilktea(s)); } return ret; }
2.按种类排序返回全部奶茶接口
用于小程序点单页面按照种类显示奶茶。先获取奶茶的种类数,然后根据种类id将全部奶茶按照种类装到各个数组中,再将这些数组装到一个大数组中
mapper语句:
3.用户登录接口
用于用户使用微信进行登录的接口。先判断从小程序获得的openid是否为空,为空则登录失败返回空值,否则查询数据库该openid是否已存入数据库,未存入则将该openid与用户昵称插入数据库并且后端返回存有openid该用户对象,否则只更新用户昵称并返回存有对应用户信息的用户对象。
主要mapper语句:
4.下单接口
用于用户下单的接口。后端先将订单时间、总价格、用户openid和用户地址信息插入数据库中的orderinfo表(订单信息表),获取自增的orderid后将从小程序获取的奶茶信息拆分开来,按照奶茶的id组成为单条条目,依照orderid插入数据库中的comselectinfo表(订单详情表)中
mapper语句:
5.查询制作中订单接口
mapper语句:
6.查询已完成订单接口
mapper语句:
后台
前端
登录页面
防水墙
前端主页面主要有几个模块组成:左上角是LOGO,右上角是账户信息,左侧栏是菜单,占据页面大部分内容的是内容展示框

前端的菜单有
1.首页
首页向用户展示一些重要统计数据的图表信息,让经营者能够清楚知道自己的营收情况,订单数目,下单人数,品类销量排行

2.订单管理
给经营者管理订单,或是给制作者查看订单信息,根据信息制作相应奶茶




制作人员可以点击制作完成,这样用户就可以得到取餐号在前台取餐
可以在已完成订单中找到
用户则可以在自己的小程序端看到:
查看历史订单记录,也可以起到查账的作用

3.商品管理
经营者可以在这个页面添加或者删除商品



其中商品图标是动态获取的

添加商品操作:
通过COSBrowser,用户可以放自己的图片进去,然后就可以在添加奶茶的时候使用
banner管理
banner指的是小程序首页的展示图片,可以从此页面进行更换
后端
后端主要提供的功能:
1.管理员登录接口
管理员使用账号密码登录,后端判断是否可以登录,如果不能登录则返回错误信息,成功则可以得到相关权限并跳转到后台主界面
控制器:
实体类:
相关SQL语句
2.获取奶茶列表
管理员可以查看目前商品的列表,需要登录后操作
sql语句:
实体类:
Controller:
奶茶列表导出Excel:
数据库中的所有奶茶可以导出一份Excel方便管理员管理查看
实体类依旧是同上,不同的是接口实现:
Controller:
3.新增一个品种的奶茶
商品(奶茶)的增加操作
演示且看后台前端部分的内容
SQL语句:
对应实体类与2.一致
Controller:
4.根据ID修改奶茶信息
MilkteaMapper.xml:
Controller:
5.根据ID查询奶茶信息
对应实体类与2.一致
Controller:
6.根据ID删除奶茶信息
略
7.统计近N日每日销售量
给前端返回的是Json以便解析
对应实体类:
Controller:
将每日销售量 导出为Excel:
Controller:
提供给制作人员的接口:
1.查看未制作订单
制作人员可以在后台查看未制作订单以及订单描述信息,根据后台给出的提示进行制作商品

2.更新订单状态
订单制作完成以后,制作员可以更新订单状态
总结
本学期的课程以及本次实验让我们实践了本学期学习的SpringBoot和使用gitee协同开发,并在本次大实验中学习了小程序开发和前端的开发框架的使用。
本次实验困难重重,好在给足了时间让我们去学习,让我们在本次实验中收获颇丰。