# 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进行处理

```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


3.要求界面美观,主题统一;
小程序页面大致如下:








b) 后端管理端
1.可以使用vue或其他前端框架构建。
2.实现管理后台各个功能界面。要求界面简洁精美。
3.后台登录逻辑需接入腾讯防水墙。
只在前端部分接入了
```java
登 录
登 录 中...
```

c) 后台管理端功能模块:
1.管理员账号管理模块(CURD)
2.用户管理模块(查询用户的详细信息)
用户登录了小程序后,通过相关接口获取其他信息,如果检测到是新用户,则存入数据库并进行部分信息的初始化

```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{(下单成功与否判断)}
```

3.使用Spring Security安全框架实现认证、访问控制;
若依框架已将使用Spring Security安全框架实现认证、访问控制

4.微信小程序界面定制模块(可定制展示在小程序广告图片、可定制展示在小程序的菜单等)
a)定制展示在小程序广告图片
通过在后台添加banner图片、修改图片的启用状态,可以进行首页广告图的定制

```java
/**
* 根据状态获取画报详细地址
*/
@GetMapping(value = "/getbystate/{State}")
public AjaxResult getInfo(@PathVariable("State") String State)
{
return AjaxResult.success(sysBigbannerService.selectSysBigbannerByState(State));
}
```
小程序端调用接口,获取相应数据,实现刷新

5.商品管理模块(CURD)

分级管理功能:
菜单分级中可以定制菜单级别,定制菜单顺序,一个商品可指定属于某一个分级

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);
});
}
}
```



7.所有列表可以进行综合查询,特别是时间字段;
8.所有列表可以导出Excel文件或pdf文件.
若依框架生成可带导出文件
