# spring-boot微信小程序 **Repository Path**: yeqqcom/spring-boot-wechat-applet ## Basic Information - **Project Name**: spring-boot微信小程序 - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 3 - **Created**: 2020-12-22 - **Last Updated**: 2025-12-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 期末大作业 基于微信小程序的新零售移动电商系统设计与实现
#猫制茶 微信小程序+springboot 设计报告
| 组员1:叶梓茵 | 学号:201841413427 | 班级:18网工4班 | |---|---|---| | 组员2:叶慧铧| 学号:201841413236 | 班级:18网工2班 | |---|---|---| | 组员3:黄小妹 | 学号:201841413413 | 班级:18网工4班 | |---|---|---| | 实验地址:学校 |实验日期:2020-12-14 | 指导老师:黎志雄 | | 教师评语:XXX | 实验成绩:XXX | 百分制:XXX | ### 一、项目简介     受2020年的疫情影响,消费者闭门不出,线下门店纷纷关闭,实体经济受到重大冲击。除了疫情的挑战,传统零售与传统电商,一直被效率、场景、管控等问题困扰。     新零售,赋能传统零售转型升级。线上商城与线下门店的交易无缝融合,通过技术改变消费者的购物习惯,结合高效的物流配送,极大提升消费者的购物体验。基于微信的生态圈用户流量,让平台更快的传播获客,吸引海量用户资源。     基于上诉的背景,本实验项目作为课程的期末大作业,要求学生团队研发基于微信小程序的新零售移动电商系统,专门为新零售而生的电商系统解决方案。 ### 二、项目简介 本实验项目分为两个客户端,一是用户端微信小程序;二是后台管理端。 (1)小程序      a)使用了微信开发者开发,使用微信用户授权登陆      b)获取微信用户的openid作为唯一标识,并且可根据openid查询订单等状态 (2)后台管理端     a)本实验的后台管理系统是基于开源项目ruoyi-vue前后端分离版本做的二次开发,是一个基于Spring Boot 、Spring Boot Jpa、JWT、Spring Security、Redis、Vue、Element-UI 的前后端分离的后台管理系统。
     b)基本实现的功能有:    
    管理员、后台账户角色的增删改查
    客户管理模块(查询客户的详细信息,并且可以设定某个客户不可交易)
    使用Spring Security安全框架实现认证、访问控制;
    登录逻辑接入腾讯防水墙
    微信小程序界面定制模块(可定制展示在小程序广告图片、可定制展示在小程序的菜单等)
    商品管理模块(CURD)
    订单数据统计模型,包括各种数据图、表来展示
    所有列表可以进行综合查询,特别是时间字段
    这次项目因为经验、能力不足,不能做的很完善,完成所有的要求,大致上实现了基本要求。 ### 三、实现结果 a) 用户端 1.使用微信小程序构建;
2.使用微信账号登录客户端;
获取住户的微信openid,保存在数据库,以关联相关订单信息;

通过查看官方文档,了解了获取openid的流程,首先小程序授权登录,将带有openid和session的code传到处理的后台 ``` onLaunch: function () { // 展示本地存储能力 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) // 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId if (res.code) { wx.request({ url: 'http://localhost:8080/getopenid', data: { code: res.code }, header: { 'content-type': 'application/x-www-form-urlencoded' }, success(res) { console.log("openid:" + res.data.openid); console.log("session_key:" + res.data.session_key); if (res.data.openid != "" || res.data.openid != null) { // 登录成功 wx.setStorageSync("openid", res.data.openid);//将用户id保存到缓存中 wx.setStorageSync("session_key", res.data.session_key);//将session_key保存到缓存中 } else { // 登录失败 // TODO 跳转到错误页面,要求用户重试 return false; } } }) } else { console.log('获取用户登录态失败!' + res.errMsg) } } }) ```
在后台,相关controller、service进行处理
![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/024412_f0b7ed82_8149149.png "屏幕截图.png")
```java @RestController public class WeChatUserLoginController { @Autowired WeChatUserLoginService wc; @RequestMapping("/getopenid") public String getcode(@RequestParam(value = "code")String code){ System.out.println(code); return wc.codetoopenid(code); } } @Service public class WeChatUserLoginimpl implements WeChatUserLoginService { @Override public String codetoopenid(String code) { Map data = new HashMap(); data.put("appid", "wx79f3a07c0ccb456c"); data.put("secret", "小程序的密钥(按实际填写了)"); data.put("js_code", code); data.put("grant_type", "authorization_code"); String response = HttpRequest.get("https://api.weixin.qq.com/sns/jscode2session").form(data).body(); System.out.println("Response was: " + response); JSONObject obj= JSON.parseObject(response);//将json字符串转换为json对 System.out.println(obj); return response; } } ```
最后成功登录并返回openid
![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/024713_8d2c3a8c_8149149.png "屏幕截图.png")
![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/024733_c91d7472_8149149.png "屏幕截图.png")
3.要求界面美观,主题统一;
小程序页面大致如下:
![输入图片说明](https://images.gitee.com/uploads/images/2021/0103/215501_5796b723_8170428.png "微信图片_20210103212226.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/021856_d517e7df_8149149.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/021954_594381b0_8149149.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/022054_98f71787_8149149.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/022025_d2f583ba_8149149.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/022141_c68bdb24_8149149.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/022151_63557e56_8149149.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/022200_c52c2cb5_8149149.png "屏幕截图.png")
b) 后端管理端 1.可以使用vue或其他前端框架构建。 2.实现管理后台各个功能界面。要求界面简洁精美。 3.后台登录逻辑需接入腾讯防水墙。
只在前端部分接入了 ```java 登 录 登 录 中... ``` ![输入图片说明](https://images.gitee.com/uploads/images/2021/0108/105557_a25d8882_7556170.png "屏幕截图.png") c) 后台管理端功能模块: 1.管理员账号管理模块(CURD) 2.用户管理模块(查询用户的详细信息)
用户登录了小程序后,通过相关接口获取其他信息,如果检测到是新用户,则存入数据库并进行部分信息的初始化
![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/025103_b5a6fb5c_8149149.png "屏幕截图.png")
```java /** * 根据userinfo查询客户个人信息,如果新用户则添加 */ @RequestMapping("/getcustomerInfoAndadd") public SysCustomers getcustomerInfoAndadd(String openid,String cusName,String cusImg,int cusSex) { String sex; if(cusSex == 1 ){ sex = "男"; } else { sex ="女"; } return sysCustomersService.getcustomerInfo(openid,cusName,cusImg,sex); } /** * 查询客户个人信息,如果是新用户则同时存入数据库里 * * @param openid 客户个人openid * @return 结果 */ @Override public SysCustomers getcustomerInfo(String openid,String cusName,String cusImg,String cusSex){ SysCustomers cus = new SysCustomers(); SysCustomers cus2 = new SysCustomers(); SysCustomers cusadd = new SysCustomers(); cus = sysCustomersMapper.selectSysCustomersByOpenid(openid); if(cus == null){ cusadd.setCusName(cusName); cusadd.setCusImg(cusImg); cusadd.setOpenid(openid); cusadd.setCusSex(cusSex); cusadd.setCusPoint((long)0); cusadd.setCusLevel("青铜会员"); cusadd.setCusState("正常"); sysCustomersMapper.insertSysCustomers(cusadd); } cus2 = sysCustomersMapper.selectSysCustomersByOpenid(openid); return cus2; } ```
#同时,可以设置用户状态,正常或是禁止交易,在后台设置更新用户状态,下单时先查询,根据状态返回相应信息,小程序端通过获取到的回应弹出相应弹窗。
```java @Override public String addOneOrderByStr(String openid,String userName,String goodsStr,String Phone) { String returnstr; SysCustomers thiscus = sysCustomersMapper.selectSysCustomersByOpenid(openid); System.out.println(thiscus.getCusState()); if(thiscus.getCusState().equals("禁止下单")){ returnstr = "该客户被禁止下单"; return returnstr; } else{(下单成功与否判断)} ```
![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/025707_6f235384_8149149.png "屏幕截图.png") 3.使用Spring Security安全框架实现认证、访问控制;
若依框架已将使用Spring Security安全框架实现认证、访问控制
![输入图片说明](https://images.gitee.com/uploads/images/2021/0108/110152_b1a85644_7556170.png "屏幕截图.png") 4.微信小程序界面定制模块(可定制展示在小程序广告图片、可定制展示在小程序的菜单等)
a)定制展示在小程序广告图片
通过在后台添加banner图片、修改图片的启用状态,可以进行首页广告图的定制
![输入图片说明](https://images.gitee.com/uploads/images/2021/0103/215727_fc8124da_8170428.png "微信图片_20210103212259.png")
```java /** * 根据状态获取画报详细地址 */ @GetMapping(value = "/getbystate/{State}") public AjaxResult getInfo(@PathVariable("State") String State) { return AjaxResult.success(sysBigbannerService.selectSysBigbannerByState(State)); } ```
小程序端调用接口,获取相应数据,实现刷新
![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/023020_b0b076b6_8149149.png "屏幕截图.png") 5.商品管理模块(CURD) ![输入图片说明](https://images.gitee.com/uploads/images/2021/0103/215643_5bac9813_8170428.png "微信图片_20210103212252.png") 分级管理功能:
菜单分级中可以定制菜单级别,定制菜单顺序,一个商品可指定属于某一个分级 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0108/102950_2be85a7c_7556170.png "屏幕截图.png") 6.订单数据统计模型,包括各种数据图、表来展示,金额的数据类型使用decimal类型;
编写相应方法,获取统计数据
```java @Override public List getWeeklyDayStatistical(){ List weeklystatical = new ArrayList(); Date date = new Date(); SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd"); dateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); System.out.println(dateFormat.format(date)); int a[]={6,5,4,3,2,1,0}; for(int i=0;i<7;i++){ int diff = a[i]; long time = 24*60*60*1000*diff; Date newdate = new Date(date.getTime()-time); System.out.println(dateFormat.format(newdate)); BigDecimal thisdaysales = sysOrderNewMapper.selectcompareTotalsales(diff); BigDecimal comdaysales = sysOrderNewMapper.selectcompareTotalsales(diff + 1); System.out.println("thisdaysales:"+thisdaysales); if(thisdaysales == null) { thisdaysales = new BigDecimal(0); } if (comdaysales == null){ comdaysales = new BigDecimal(0); } BigDecimal comparesales = thisdaysales.subtract(comdaysales); int thisdayordernum = sysOrderNewMapper.selectcompareTotalOrderNum(diff); int condayordernum = sysOrderNewMapper.selectcompareTotalOrderNum(diff + 1); int compareordernum = thisdayordernum - condayordernum; dayStatistical daliystatiscal = new dayStatistical(); daliystatiscal.setDaysales(thisdaysales); daliystatiscal.setComsales(comparesales); daliystatiscal.setDaliyordernum(thisdayordernum); daliystatiscal.setComdaliyordernum(compareordernum); daliystatiscal.setDate(newdate); daliystatiscal.setNewdate(dateFormat.format(newdate)); weeklystatical.add(daliystatiscal); } return weeklystatical; } @Override public List getOrderStatistical(){ List orderStatisticals = new ArrayList(); BigDecimal TodayTotalSales = sysOrderNewMapper.selectTotalsales(); System.out.println("TodayTotalSales:"+TodayTotalSales); BigDecimal ComTotalSales = sysOrderNewMapper.selectcompareTotalallsales(1); if(TodayTotalSales == null) { TodayTotalSales = new BigDecimal(0); } if (ComTotalSales == null){ ComTotalSales = new BigDecimal(0); } BigDecimal com = TodayTotalSales.subtract(ComTotalSales); OrderStatistical orderstatistical = new OrderStatistical(); orderstatistical.setSales(TodayTotalSales); orderstatistical.setTotalOrderNum(sysOrderNewMapper.selectTotalOrderNum()); orderstatistical.setCustomerNum(sysOrderNewMapper.selectcustomerNum()); // orderstatistical.setWeekStatistical(getWeeklyDayStatistical()); orderstatistical.setComsales(com); orderStatisticals.add(orderstatistical); return orderStatisticals; } //通过接口返回 /**获取订单总体情况统计**/ @GetMapping("/getorderstatistical") public List getorderstatistical(){ return sysOrderNewService.getOrderStatistical(); } /**获取订单七天情况统计**/ @GetMapping("/getweeklyorderstatistical") public List getWeeklyorderstatistical(){ return sysOrderNewService.getWeeklyDayStatistical(); } //前端部分通过api获取数据进行渲染 import {listShow_Weeklyorder,listShow_order} from "@/api/order_date_chart/show_order_data_chart"; export default { name: "index", data() { return { loading: true, // 存放表格数据 orderservendate: [], ordertotaldate:[], // 总条数 total: 0, s:0 } }, created() { this.getOrderTotalData(); this.getOrderWeeklydate(); }, methods:{ getOrderWeeklydate(){ const _this = this this.loading = true; listShow_Weeklyorder().then( (response) => { _this.orderservendate = response; _this.total = response.total; _this.loading = false; console.log(response) }); }, getOrderTotalData(){ const _this=this; this.loading = true; listShow_order().then( (response) => { _this.ordertotaldate = response; _this.loading = false; console.log(response); // console.log(ordertotaldate); }); } } ``` ![输入图片说明](https://images.gitee.com/uploads/images/2021/0108/102800_7f90c94b_7556170.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0108/102746_6ebf5f47_7556170.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/030027_62d71123_8149149.png "屏幕截图.png") 7.所有列表可以进行综合查询,特别是时间字段;
8.所有列表可以导出Excel文件或pdf文件.
若依框架生成可带导出文件
![输入图片说明](https://images.gitee.com/uploads/images/2021/0107/031758_b63303c5_8149149.png "屏幕截图.png")