# 第10章 后台管理系统
今日内容介绍

学习目标
- 后台系统简介
- 搭建前端系统
- 实现登录功能
- 实现后台管理基本功能
1. 后台系统简介
【目标】
了解后台系统简介
【路径】
1:了解后台系统功能
2:掌握前端系统搭建
3:了解后台API文档
【讲解】
探花交友APP建立的后台管理系统,目的是完成探花交友项目的业务闭环,主要功能包括:用户管理、动态管理、审核管理已经系统管理。
1.1. 功能说明

课程中实现的功能有:登录、首页、用户管理、动态审核。
后台管理系统:****登录、用户管理、动态管理、审核管理等
1.2. 搭建前端系统
后台系统也是采用前后端分离的方式,前端采用Vue.js实现,关于前端系统我们不进行实现,拿来直接使用。

1.2.1. nginx安装
将资料中提供的nginx解压到没有中文没有空格的目录下(右击以管理员身份运行)

其中html目录中为,vue编译后的所有页面。
1.2.2. 配置
修改Nginx的/conf/nginx.conf配置文件:
server {
listen 8088; #请求端口
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /management {
proxy_pass http://127.0.0.1:18083/; #转发后台tanhua-manager地址
}
#....略
}
1.2.3. 测试
双击nginx.exe,待启动完成后访问:http://127.0.0.1:8088即可访问后台项目
1.3. 后台的API文档
登陆:http://192.168.137.160:3000/
(1) 在yapi中创建新项目

(2) 导入API文档数据

【小结】
了解后台系统简介
2. 环境搭建
【目标】
了解后台系统环境搭建
【路径】
1:后台系统环境搭建
【讲解】

2.1. 创建tanhua-manage
1、pom.xml添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringDataRedis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!--jwt依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--fastdfs文件存储-->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.7</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--dubbo的起步依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
<!-- zookeeper的api管理依赖 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<!-- zookeeper依赖 -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.12</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.mybatis-plus}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>cn.itcast</groupId>
<artifactId>tanhua-dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.itcast</groupId>
<artifactId>tanhua-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
2.2. application.yml
server:
port: 18083
#配置redis
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/tanhua-manager?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
username: root
password: root
redis:
host: 192.168.136.160
port: 6379
dubbo:
application:
name: tanhua-manage
registry:
address: zookeeper://192.168.136.160:2181
consumer:
check: false
#配置短信平台信息
tanhua:
secret: 76bd425b6f29f7fcc2e0bfc286043df1
#替换成自己的 oss存储信息
sms:
validateCodeTemplateCode: SMS_204661533
signName: 传智
parameterName: code
accessKeyId: LTAI4FynsGS7V2bPJqQqrzhH
accessKeySecret: c9fMcE7W8njMFNLJNJQT2vn5A0J1ey
oss:
endpoint: http://oss-cn-shenzhen.aliyuncs.com
bucketName: tanhua
url: https://tanhua.oss-cn-shenzhen.aliyuncs.com
accessKeyId: LTVI4FynsGS7V2bPJqQqrzhH
accessKeySecret: c9fDE7W8njMFNLJNJQT2vn5A0J1ey
face:
appId: 22837663
apiKey: nA43galrxfUZTGtYRVK8F8tb
secretKey: MQp567q4nGnIKfniURa2XAw8bT1SlPE3
huanxin:
url: http://a1.easemob.com/
orgName: 1112190901181842
appName: tanhua
clientId: YXA6VggstiTmSSi_dWvqeoCg
clientSecret: YXAvRviM513TuJLAeFTtef9Th4wo
#mybaits-plus
mybatis-plus:
global-config:
db-config:
table-prefix: tb_ #数据库表前缀
id-type: auto #数据库表主键的策略
2.3. 启动类
package com.tanhua.manage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
public class ManagerServerApplication {
public static void main(String[] args) {
SpringApplication.run(ManagerServerApplication.class,args);
}
}
2.4. 创建数据库

2.5. 基础代码
将今日资料中的基础代码,拷贝到工程中

将资料中exception统一异常处理代码和Interceptor拦截器代码copy到工程合适位置
【小结】
了解后台系统环境搭建
3. 登录
【目标】
掌握登录退出功能实现
【路径】
1:验证码功能实现
2:登录功能实现
3:用户基础信息实现
4:退出功能实现
【讲解】
后台系统的登录模块独立于APP端的登录。
表结构:
CREATE TABLE `tb_admin` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`username` varchar(255) NOT NULL COMMENT '账号',
`password` varchar(255) NOT NULL COMMENT '密码',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`created` datetime NOT NULL COMMENT '创建时间',
`updated` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='后台管理员表';
INSERT INTO `tb_admin` (`id`, `username`, `password`, `avatar`, `created`, `updated`) VALUES ('1', 'admin', 'e10adc3949ba59abbe56e057f20f883e', NULL, '2020-09-07 17:55:28', '2020-09-07 17:55:28');
3.1. 验证码
3.1.1. 接口说明

3.1.2. AdminController
package com.tanhua.manage.controller;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.tanhua.manage.service.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
@RequestMapping("/system/users")
@Slf4j
public class AdminController {
@Autowired
private AdminService adminService;
/**
* 后台登陆时 图片验证码 生成
*/
@GetMapping("/verification")
public void showValidateCodePic(String uuid,HttpServletRequest req, HttpServletResponse res){
res.setDateHeader("Expires",0);
res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
res.addHeader("Cache-Control", "post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
res.setHeader("Pragma", "no-cache");
res.setContentType("image/jpeg");
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(299, 97);
String code = lineCaptcha.getCode();
log.debug("uuid={},code={}",uuid,code);
adminService.saveCode(uuid,code);
try {
lineCaptcha.write(res.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.1.3. AdminService
package com.tanhua.manage.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.manage.domain.Admin;
import com.tanhua.manage.mapper.AdminMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.time.Duration;
@Service
@Slf4j
public class AdminService extends ServiceImpl<AdminMapper, Admin> {
private static final String CACHE_KEY_CAP_PREFIX = "MANAGE_CAP_";
@Autowired
private RedisTemplate redisTemplate;
/**
* 保存生成的验证码
* @param uuid
* @param code
*/
public void saveCode(String uuid, String code) {
String key = CACHE_KEY_CAP_PREFIX + uuid;
// 缓存验证码,10分钟后失效
redisTemplate.opsForValue().set(key,code, Duration.ofMinutes(10));
}
}
3.1.4. 测试
地址:http://localhost:8088/management/system/users/verification


3.2. 登录

3.2.1. 接口说明

3.2.3. AdminController
/**
* 登录功能
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
public ResponseEntity login(@RequestBody Map<String,String> params){
String username = params.get("username");
String password = params.get("password");
String verificationCode = params.get("verificationCode");
String uuid = params.get("uuid");
Map map = adminService.login(username,password,verificationCode,uuid);
return ResponseEntity.ok(map);
}
3.2.3. AdminService
/**
* 登录
* @param username
* @param password
* @param verificationCode
* @param uuid
* @return
*/
public Map login(String username, String password, String verificationCode, String uuid) {
Map map = new HashMap();
//1 校验验证码
String key = CACHE_KEY_CAP_PREFIX + uuid;
String redisCode = (String)redisTemplate.opsForValue().get(key);
if(StringUtils.isEmpty(redisCode)){
throw new BusinessException("验证码失效");
}
if(!redisCode.equals(verificationCode)){
throw new BusinessException("验证码不正确");
}
//2 校验用户名(通用service)
Admin admin = query().eq("username", username).one();
if(admin == null){
throw new BusinessException("用户名不存在");
}
//3 校验密码
if(!admin.getPassword().equals(SecureUtil.md5(password))){
throw new BusinessException("密码错误");
}
//4 生成token
String token = jwtUtils.createJWT(username, admin.getId());
map.put("token",token);
//5 存入redis
String tokenKey = CACHE_KEY_TOKEN_PREFIX + token;
String adminStr = JSON.toJSONString(admin);
redisTemplate.opsForValue().set(tokenKey,adminStr,30,TimeUnit.MINUTES);
return map;
}
3.3. 用户基本信息
3.3.1. 接口说明

3.3.2. AdminController
/**
* 用户基本信息
*/
@RequestMapping(value = "/profile",method = RequestMethod.POST)
public ResponseEntity profile(){
Admin admin = AdminHolder.getAdmin();
AdminVo adminVo = new AdminVo();
BeanUtils.copyProperties(admin,adminVo);
return ResponseEntity.ok(adminVo);
}
3.4. 退出
3.4.1. 接口说明

3.4.2. AdminController
/**
* 退出
*/
@RequestMapping(value = "/logout",method = RequestMethod.POST)
public ResponseEntity logout(@RequestHeader("Authorization") String token){
String headToken = token.replace("Bearer ", "");
adminService.logout(headToken);
return ResponseEntity.ok(null);
}
3.4.3. AdminService
/**
* 登出
* @param headToken
*/
public void logout(String headToken) {
String tokenKey = CACHE_KEY_TOKEN_PREFIX + headToken;
redisTemplate.delete(tokenKey);
}
【小结】
掌握登录退出功能实现
4. 首页
【目标】
掌握概要统计信息功能实现
【路径】
1:概要统计信息功能分析
2:概要统计信息功能实现
【讲解】


在首页中,显示各种的数据,比如:累计用户数、新增用户数、登录次数等内容。这些数据是需要基于用户的操作来进行统计的,所以需要建立tb_log表来记录用户的操作。
基于log表的数据进行计算,将计算的结果保存到tb_analysis_by_day表中。
4.1. 表结构
CREATE TABLE `tb_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL COMMENT '用户id',
`type` varchar(255) NOT NULL COMMENT '操作类型,\r\n01为登录,0201为发动态,0202为浏览动态,0203为动态点赞,0204为动态喜欢,0205为评论,0206为动态取消点赞,0207为动态取消喜欢,0301为发小视频,0302为小视频点赞,0303为小视频取消点赞,0304为小视频评论',
`log_time` varchar(10) DEFAULT NULL COMMENT '操作日期',
`place` varchar(255) DEFAULT NULL COMMENT '操作地点',
`equipment` varchar(255) DEFAULT NULL COMMENT '操作设备',
`created` datetime DEFAULT NULL COMMENT '创建时间',
`updated` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `time_type_user` (`log_time`,`type`,`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=152668 DEFAULT CHARSET=utf8 COMMENT='用户日志表';
CREATE TABLE `tb_analysis_by_day` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`record_date` date NOT NULL COMMENT '日期',
`num_registered` int(8) NOT NULL DEFAULT '0' COMMENT '新注册用户数',
`num_active` int(8) NOT NULL DEFAULT '0' COMMENT '活跃用户数',
`num_login` int(8) NOT NULL DEFAULT '0' COMMENT '登陆次数',
`num_retention1d` int(8) NOT NULL DEFAULT '0' COMMENT '次日留存用户数',
`created` datetime NOT NULL COMMENT '创建时间',
`updated` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `record_date` (`record_date`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8;
4.2. 概要统计信息
4.2.1. 接口说明

返回数据:
| 名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
|---|---|---|---|---|---|
| cumulativeUsers | integer | 必须 | 累计用户 | 最大值: 500最小值: 0 | |
| activePassMonth | integer | 必须 | 过去30天活跃用户 | 最大值: 500最小值: 0 | |
| activePassWeek | integer | 必须 | 过去7天活跃用户 | 最大值: 500最小值: 0 | |
| newUsersToday | integer | 必须 | 今日新增用户 | 最大值: 500最小值: 0 | |
| newUsersTodayRate | integer | 必须 | 今日新增用户涨跌率,单位百分数,正数为涨,负数为跌 | ||
| loginTimesToday | integer | 必须 | 今日登录次数 | 最大值: 500最小值: 0 | |
| loginTimesTodayRate | integer | 必须 | 今日登录次数涨跌率,单位百分数,正数为涨,负数为跌 | ||
| activeUsersToday | integer | 必须 | 今日活跃用户 | 最大值: 500最小值: 0 | |
| activeUsersTodayRate | integer | 必须 | 今日活跃用户涨跌率,单位百分数,正数为涨,负数为跌 | ||
| useTimePassWeek | integer | 必须 | 过去7天平均日使用时长,单位秒 | ||
| activeUsersYesterday | integer | 必须 | 昨日活跃用户 | ||
| activeUsersYesterdayRate | integer | 必须 | 昨日活跃用户涨跌率,单位百分数,正数为涨,负数为跌 |
4.2.2. AnalysisController
package com.tanhua.manage.controller;
import com.tanhua.manage.service.AnalysisService;
import com.tanhua.manage.vo.AnalysisSummaryVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 概要统计分析控制层
*/
@RestController
@RequestMapping("/dashboard")
@Slf4j
public class AnalysisController {
@Autowired
private AnalysisService analysisService;
/**
* 概要统计分析数据展示
*/
@RequestMapping(value = "/summary",method = RequestMethod.GET)
public ResponseEntity summary(){
AnalysisSummaryVo analysisSummaryVo =analysisService.summary();
return ResponseEntity.ok(analysisSummaryVo);
}
}
4.2.3. AnalysisService
package com.tanhua.manage.service;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.manage.domain.AnalysisByDay;
import com.tanhua.manage.mapper.AnalysisByDayMapper;
import com.tanhua.manage.utils.ComputeUtil;
import com.tanhua.manage.vo.AnalysisSummaryVo;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTimeUtils;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 概要统计业务逻辑处理类
*/
@Service
@Slf4j
public class AnalysisService extends ServiceImpl<AnalysisByDayMapper, AnalysisByDay> {
/**
* 概要统计分析数据展示
*/
public AnalysisSummaryVo summary() {
AnalysisSummaryVo vo = new AnalysisSummaryVo();
//SELECT SUM(num_registered) as numRegistered FROM tb_analysis_by_day;
vo.setCumulativeUsers(findCumulativeUsers());//累计用户数
DateTime today = DateTime.now();//今天时间
String endDate = today.toDateStr();//今天时间字符串
String yesterday = ComputeUtil.offsetDay(today, -1);
//计算得到30天之前时间 ComputeUtil.offsetDay(today,-30)
//计算得到7天之前时间 ComputeUtil.offsetDay(today,-7)
//计算得到昨天时间 ComputeUtil.offsetDay(today,-1)
vo.setActivePassMonth(findCount("num_active", ComputeUtil.offsetDay(today,-30),endDate));//过去30天活跃用户数
vo.setActivePassWeek(findCount("num_active", ComputeUtil.offsetDay(today,-7),endDate));//过去7天活跃用户
Long todayNumRegistered = findCount("num_registered", endDate, endDate);//今天新增用户数量
Long yesterdayNumRegistered = findCount("num_registered", yesterday, yesterday);//昨天新增用户数量
vo.setNewUsersToday(todayNumRegistered);//今日新增用户数量
vo.setNewUsersTodayRate(ComputeUtil.computeRate(todayNumRegistered,yesterdayNumRegistered));//今日新增用户涨跌率
Long todayNumLogin = findCount("num_login", endDate, endDate);
Long yesterdayNumLogin = findCount("num_login", yesterday, yesterday);
vo.setLoginTimesToday(todayNumLogin);//今日登录次数
vo.setLoginTimesTodayRate(ComputeUtil.computeRate(todayNumLogin,yesterdayNumLogin));//今日登录次数涨跌率
Long todayNumActive = findCount("num_active", endDate, endDate);
Long yesterdayNumActive = findCount("num_active", yesterday, yesterday);
vo.setActiveUsersToday(todayNumActive);//今日活跃用户数量
vo.setActiveUsersTodayRate(ComputeUtil.computeRate(todayNumActive,yesterdayNumActive));//今日活跃用户涨跌率
return vo;
}
/**
* 查询累计用户
*/
private Long findCumulativeUsers(){
AnalysisByDay analysisByDay = query().select("SUM(num_registered) as numRegistered").one();
return analysisByDay.getNumRegistered().longValue();
}
/**
* 过去30天活跃用户数
* 过去7天活跃用户
* 今日新增用户数量
* 今日登录次数
* 今日活跃用户数量
*
* 公共方法
* 例如:SELECT SUM(num_login) AS num_active
* FROM tb_analysis_by_day
* WHERE record_date <= '2021-11-05' AND record_date >= '2021-11-05'
*/
private Long findCount(String column,String startDate,String endDate){
AnalysisByDay analysisByDay = query()
.select("SUM("+column+") as numRegistered")
.ge("record_date",startDate)
.le("record_date",endDate)
.one();
return analysisByDay.getNumRegistered().longValue();
}
}
4.2.5. 测试
postman测试

页面效果

4.4. 新增、活跃用户、次日留存率-作业
4.4.1. 接口说明

返回数据:
| 名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
|---|---|---|---|---|---|
| thisYear | object [] | 必须 | 本年 | 最小数量: 12元素是否都不同: true最大数量: 12item 类型: object | |
| title | string | 必须 | 日期 | 枚举: 1,2,3,4,5,6,7,8,9,10,11,12 | |
| amount | integer | 必须 | 数量 | 最大值: 9999最小值: 50 | |
| lastYear | object [] | 必须 | 去年 | 最小数量: 12元素是否都不同: true最大数量: 12item 类型: object | |
| title | string | 必须 | 日期 | 枚举: 1,2,3,4,5,6,7,8,9,10,11,12 | |
| amount | integer | 必须 | 数量 | 最大值: 9999最小值: 50 |
4.4.2. AnalysisController
@GetMapping("/users")
public AnalysisUsersVo getUsers(@RequestParam(name = "sd") Long sd
, @RequestParam("ed") Long ed
, @RequestParam("type") Integer type) {
return this.analysisService.queryAnalysisUsersVo(sd, ed, type);
}
4.4.3. AnalysisService
/**
* 新增、活跃用户、次日留存率
*/
public AnalysisUsersVo queryAnalysisUsersVo(Long sd, Long ed, Integer type) {
DateTime startDate = DateUtil.date(sd);
DateTime endDate = DateUtil.date(ed);
AnalysisUsersVo analysisUsersVo = new AnalysisUsersVo();
//今年数据
analysisUsersVo.setThisYear(this.queryDataPointVos(startDate, endDate, type));
//去年数据
analysisUsersVo.setLastYear(this.queryDataPointVos(
DateUtil.offset(startDate, DateField.YEAR, -1),
DateUtil.offset(endDate, DateField.YEAR, -1), type)
);
return analysisUsersVo;
}
private List<DataPointVo> queryDataPointVos(DateTime sd, DateTime ed, Integer type) {
String startDate = sd.toDateStr();
String endDate = ed.toDateStr();
String column = null;
switch (type) { //101 新增 102 活跃用户 103 次日留存率
case 101:
column = "num_registered";
break;
case 102:
column = "num_active";
break;
case 103:
column = "num_retention1d";
break;
default:
column = "num_active";
break;
}
List<AnalysisByDay> analysisByDayList = super.list(Wrappers.<AnalysisByDay>query()
.select("record_date , " + column + " as num_active")
.ge("record_date", startDate)
.le("record_date", endDate));
return analysisByDayList.stream()
.map(analysisByDay -> new DataPointVo(DateUtil.date(analysisByDay.getRecordDate()).toDateStr(), analysisByDay.getNumActive().longValue()))
.collect(Collectors.toList());
}
4.4.4. 测试
postman测试

页面效果

【小结】
掌握概要统计信息功能实现
作业
1.新增、活跃用户、次日留存率
总结
1.会搭建前端环境
2.会搭建后端工程环境(掌握能够看懂工程结构 在对应包下编码 调试)
3.登录功能-重点掌握
4.首页-概要统计信息-重点掌握(讲清楚整个业务流程)
5.新增、活跃用户、次日留存率-作业
浙公网安备 33010602011771号