谷粒学院项目
项目前台设计
登录前端整合:
拦截器位置:
登出前端整合:
OAuth2介绍:
授权方式:
方式一:
方式二:
方式三:
微信扫码登录:略
微信扫码登录:
// 生成微信二维码
@GetMapping("login")
public String getWxCode() {
// 方式一
// String url = "http://open.wenxin.qq.com/connect/qrconnect?appid="+ ConstantWxUtils.WX_OPEN_APP_ID + "&response_type=code";
System.out.println("debug");
// 微信开放平台授权baseUrl
String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
"?appid=%s" +
"&redirect_uri=%s" +
"&response_type=code" +
"&scope=snsapi_login" +
"&state=%s" +
"#wechat_redirect";
// 对redirect_url进行URLEncoder编码
String redirect_url = ConstantWxUtils.WX_OPEN_REDIRECT_URL;
try {
redirect_url = URLEncoder.encode(redirect_url, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
// 设置%s里面的值
String url = String.format(
baseUrl,
ConstantWxUtils.WX_OPEN_APP_ID,
redirect_url,
"atguigu"
);
// 重定向到请求微信地址里面
return "redirect:http://localhost:3000";
}
扫码以后的执行过程:
首页用户信息显示:
首页用户信息显示(操作流程):
课程列表接口:
课程列表前端:
二级联动效果:
课程详情后端:
controller:
service:
Mapper.xml:
课程详情前端:
定义接口api ----> 前端页面整合
整合阿里云视频播放器:
课程评论功能:
课程支付功能:
数据库表:
接口:根据用户id返回用户信息:
接口:根据课程id返回课程信息:
生成订单的controller:
生成订单的service:
controller:
生成订单页面前端整合:
生成微信支付二维码:
生成微信二维码的Service:
@Service
public class TPayLogServiceImpl extends ServiceImpl<TPayLogMapper, TPayLog> implements TPayLogService {
@Autowired
private TOrderService orderService;
// 生成微信支付二维码
@Override
public Map createNative(String orderNo) {
try {
// 1.根据订单号查询出订单信息
QueryWrapper<TOrder> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_no", orderNo);
TOrder order = orderService.getOne(queryWrapper);
// 2.使用map设置生成二维码需要的参数
Map m = new HashMap();
m.put("appid", "wx74862e0dfcf69954");
m.put("mch_id", "1558950191");
m.put("nonce_str", WXPayUtil.generateNonceStr());
m.put("body", order.getCourseTitle());
m.put("out_trade_no", orderNo);
m.put("total_fee", order.getTotalFee().multiply(new
BigDecimal("100")).longValue() + "");
m.put("spbill_create_ip", "127.0.0.1");
m.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify\n");
m.put("trade_type", "NATIVE");
// 3.发送httpclient请求,传递参数xml格式
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
// 设置xml格式的参数
client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
// 支持https访问
client.setHttps(true);
// 执行post发送请求
client.post();
// 4.得到发送请求返回结果
// 返回内容是xml格式的
String content = client.getContent();
// 把xml格式的数据转化为map集合
Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
// 最终返回数据的封装
Map map = new HashMap<>();
map.put("out_trade_no", orderNo); // 订单id
map.put("course_id", order.getCourseId()); // 课程id
map.put("total_fee", order.getTotalFee()); // 价格
map.put("result_code", resultMap.get("result_code")); // 返回二维码操作的状态码
map.put("code_url", resultMap.get("code_url")); // 二维码地址
return map;
} catch (Exception e) {
throw new GuliException(20001, "生成二维码失败");
}
}
}
查询支付状态的接口:
课程支付流程总结:
课程详情页显示效果完善:
后端接口:
讲师分页:
讲师详情功能:
统计分析模块:
后端接口:
package com.atguigu.staservice.service.impl;
import com.atguigu.commonutils.R;
import com.atguigu.commonutils.ordervo.UcenterMemberOrder;
import com.atguigu.staservice.client.UcenterClient;
import com.atguigu.staservice.entity.StatisticsDaily;
import com.atguigu.staservice.mapper.StatisticsDailyMapper;
import com.atguigu.staservice.service.StatisticsDailyService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* <p>
* 网站统计日数据 服务实现类
* </p>
*
* @author testjava
* @since 2022-11-03
*/
@Service
public class StatisticsDailyServiceImpl extends ServiceImpl<StatisticsDailyMapper, StatisticsDaily> implements StatisticsDailyService {
@Autowired
private UcenterClient ucenterClient;
@Override
public void registerCount(String day) {
// 添加记录之前删除表中相同日期的数据
QueryWrapper<StatisticsDaily> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("date_calculated", day);
baseMapper.delete(queryWrapper);
// 得到某一天的注册人数
R registerR = ucenterClient.countRegister(day);
Map<String, Object> data = registerR.getData();
Integer countRegister = (Integer) data.get("countRegister");
// 把获取到的数据添加到数据库中,统计分析表里面
StatisticsDaily statisticsDaily = new StatisticsDaily();
statisticsDaily.setRegisterNum(countRegister); // 设置注册人数
statisticsDaily.setDateCalculated(day); // 统计日期
statisticsDaily.setVideoViewNum(RandomUtils.nextInt(100, 200));
statisticsDaily.setLoginNum(RandomUtils.nextInt(100, 200));
statisticsDaily.setCourseNum(RandomUtils.nextInt(100, 200));
// 如果表中已经有数据了,我们需要添加数据,而不是更新数据
baseMapper.insert(statisticsDaily);
}
}
生成统计数据前端:
项目中整合定时任务:
Echarts简介:
项目整合Echarts:
项目整合Echarts ---- 后端接口:
controller:
// 图表显示,返回两部分数据,日期json数据,数量json数据
@GetMapping("showData/{type}/{begin}/{end}")
public R showData(@PathVariable String type, @PathVariable String begin, @PathVariable String end) {
Map<String, Object> map = staservice.getShowData(type, begin, end);
return R.ok().data(map);
}
service:
// 图表显示,返回两部分数据,日期json数据,数量json数据
@Override
public Map<String, Object> getShowData(String type, String begin, String end) {
// 根据条件查询对应数据
QueryWrapper<StatisticsDaily> wrapper = new QueryWrapper<>();
wrapper.between("date_calculated", begin, end);
// 选择指定字段
wrapper.select("date_calculated", type);
List<StatisticsDaily> statisticsDailies = baseMapper.selectList(wrapper);
// 两部分数据:日期和日期对应数量
// 前端要求数组json结构,对应后端java代码中是一个list集合
// 创建两个list集合,一个日期list,一个数量list
List<String> date_calculated = new ArrayList<>();
List<Integer> numDataList = new ArrayList<>();
// 遍历查询出来的所有数据
for (StatisticsDaily statisticsDaily : statisticsDailies) {
// 封装日期list集合
date_calculated.add(statisticsDaily.getDateCalculated());
// 封装数量list集合
switch (type) {
case "login_num":
numDataList.add(statisticsDaily.getLoginNum());
break;
case "register_num":
numDataList.add(statisticsDaily.getRegisterNum());
break;
case "video_view_num":
numDataList.add(statisticsDaily.getVideoViewNum());
break;
case "course_num":
numDataList.add(statisticsDaily.getCourseNum());
break;
default:
break;
}
}
// 把封装以后的list集合放到map中去
Map<String, Object> map = new HashMap<>();
map.put("date_calculated", date_calculated);
map.put("numDataList", numDataList);
return map;
}