当前位置: 首页 > article >正文

用户统计开发思路

1. 需求分析

所谓用户统计,实际上统计的是用户的数量。通过折线图来展示,上面这根蓝色线代表的是用户总量,下边这根绿色线代表的是新增用户数量,是具体到每一天。所以说用户统计主要统计两个数据,一个是总的用户数量,另外一个是新增用户数量

  • 基于可视化报表的折线图展示用户数据,X轴为日期,Y轴为用户数

  • 根据时间选择区间,展示每天的用户总量和新增用户量数据

2. 开发思路

Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。

官网地址:Apache ECharts

前端开发,可以基于Apache ECharts,展示各种各样的图表。

不管是哪种形式的图形,最本质的东西实际上是数据,它其实是对数据的一种可视化展示。

所以后端需要提供符合格式要求的动态数据,然后响应给前端来展示图表。

3. 代码开发

3.1 VO设计

/**
 * 用户数据报告视图对象 (UserReportVO)。
 * 用于封装在指定时间范围内用户数据统计的输出结果,
 * 包含日期列表、用户总量列表、新增用户列表等信息。
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserReportVO implements Serializable {

    /**
     * 日期列表,以逗号分隔的字符串格式表示。
     * 每个日期对应一天的用户统计数据,如"2024-10-01,2024-10-10,2024-10-29"。
     * 在前端展示时可以使用此字段来标识统计数据的时间范围。
     */
    private String dateList;

    /**
     * 用户总量列表,以逗号分隔的字符串格式表示。
     * 对应日期列表中每个日期的累计用户总数,如"200,210,220"。
     * 可以用于分析用户数量的增长趋势。
     */
    private String totalUserList;

    /**
     * 新增用户数量列表,以逗号分隔的字符串格式表示。
     * 对应日期列表中每个日期的新增用户数量,如"20,21,10"。
     * 可以用于分析每日的用户增长情况。
     */
    private String newUserList;

}

3.2 Controller层

/**
 * 用户数据统计接口,提供给前端用于获取在指定时间范围内的用户统计数据。
 *
 * @param begin 开始日期,查询统计数据的起始时间,格式为"yyyy-MM-dd"。
 *              使用 @DateTimeFormat 注解确保请求参数格式正确。
 * @param end   结束日期,查询统计数据的结束时间,格式为"yyyy-MM-dd"。
 *              使用 @DateTimeFormat 注解确保请求参数格式正确。
 * @return 返回封装在 Result 对象中的 UserReportVO 数据,
 *         包含统计信息,如用户增长数量、活跃用户数等。
 */
@GetMapping("/userStatistics")
@ApiOperation("用户数据统计")  // 描述接口功能,便于生成 API 文档
public Result<UserReportVO> userStatistics(
        @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,  // 确保接收参数的格式正确
        @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {  // 确保接收参数的格式正确

    // 调用 reportService 的 getUserStatistics 方法,
    // 使用传入的 begin 和 end 时间段获取用户统计数据
    UserReportVO reportData = reportService.getUserStatistics(begin, end);

    // 将统计数据封装在 Result 对象中并返回,表示调用成功和所请求的统计数据
    return Result.success(reportData);
}

3.3 Service层

reportService层方法实现思路如下:

@Service
public class ReportServiceImpl implements ReportService {

    /**
     * 根据时间区间统计用户数量
     * @param begin 开始日期
     * @param end   结束日期
     * @return 用户统计结果的封装对象 UserReportVO
     */
    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        // 创建一个日期列表,用于存放从开始日期到结束日期的每一天
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);  // 将起始日期加入日期列表

        // 循环遍历,将每一天依次加入日期列表,直到达到结束日期
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);  // 将日期加一天
            dateList.add(begin);  // 加入列表
        }

        // 初始化新增用户数量列表和总用户数量列表
        List<Integer> newUserList = new ArrayList<>(); // 存放每一天的新增用户数量
        List<Integer> totalUserList = new ArrayList<>(); // 存放每一天的累计用户总数

        // 遍历日期列表,逐日统计用户数据
        for (LocalDate date : dateList) {
            // 创建当日的开始时间(beginTime)和结束时间(endTime)
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);  // 当日0点
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);  // 当日23:59:59

            // 查询新增用户数量: 从数据库中统计在beginTime和endTime之间创建的用户数量
            Integer newUser = getUserCount(beginTime, endTime);
            
            // 查询总用户数量: 从数据库中统计在endTime之前创建的所有用户数量
            Integer totalUser = getUserCount(null, endTime);

            // 将统计结果加入相应的列表
            newUserList.add(newUser);
            totalUserList.add(totalUser);
        }

        // 构建并返回 UserReportVO 对象,使用逗号分隔的字符串来格式化各个列表
        return UserReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))  // 日期列表
                .newUserList(StringUtils.join(newUserList, ","))  // 新增用户数量列表
                .totalUserList(StringUtils.join(totalUserList, ","))  // 用户总量列表
                .build();
    }

    /**
     * 根据给定的时间区间统计用户数量
     * @param beginTime 起始时间,用于限定查询的开始范围;传入null表示不限定开始时间
     * @param endTime   结束时间,用于限定查询的结束范围;传入null表示不限定结束时间
     * @return Integer  用户数量,表示在指定时间区间内创建的用户数量
     */
    private Integer getUserCount(LocalDateTime beginTime, LocalDateTime endTime) {
        // 创建一个参数映射,用于传递到查询方法中
        Map<String, LocalDateTime> map = new HashMap<>();
        map.put("begin", beginTime);  // 将起始时间放入映射,键为"begin"
        map.put("end", endTime);      // 将结束时间放入映射,键为"end"
        
        // 调用 userMapper 的方法,传入参数映射以执行数据库查询
        // 返回查询到的用户数量
        return userMapper.countByMap(map);
    }
}

3.4 Mapper层

在UserMapper接口中声明countByMap方法:

/**
     * 根据动态条件统计用户数量
     * @param map
     * @return
     */
    Integer countByMap(Map map);

在UserMapper.xml文件中编写动态SQL:

<!--
    根据指定的时间区间统计用户数量的查询语句。
    该查询语句通过 `begin` 和 `end` 参数的值确定统计范围:
    - 若 `begin` 有值,则统计范围从 `begin` 开始;
    - 若 `end` 有值,则统计范围到 `end` 结束。
    该方法返回在此时间区间内创建的用户数量。
-->
<select id="countByMap" resultType="java.lang.Integer">
    <!-- 执行统计用户数量的查询 -->
    select count(id) from user
    <where>
        <!-- 若参数 `begin` 非空,则增加时间范围条件 -->
        <if test="begin != null">
            and create_time &gt;= #{begin} <!-- 查询用户创建时间在 `begin` 之后或等于 `begin` 的记录 -->
        </if>
        
        <!-- 若参数 `end` 非空,则增加结束时间条件 -->
        <if test="end != null">
            and create_time &lt;= #{end} <!-- 查询用户创建时间在 `end` 之前或等于 `end` 的记录 -->
        </if>
    </where>
</select>

4. 总结

对于图表统计的场景,前端开发,可以基于Apache ECharts,展示各种各样的图表。

不管是哪种形式的图形,最本质的东西实际上是数据,它其实是对数据的一种可视化展示。

所以后端只需要提供符合格式要求的动态数据,然后响应给前端来展示图表。

  • 日期生成

    • getUserStatistics 方法中,使用开始和结束日期生成一个完整的日期列表。通过逐日增加的方式,从 beginend 遍历每一天,以便逐日统计数据。
  • 数据统计

    • 通过循环遍历日期列表,生成每一天的起始时间(beginTime)和结束时间(endTime)。
    • 对于每一天,调用 getUserCount 方法分别获取:
      • 新增用户数:在 beginTimeendTime 之间创建的用户数。
      • 累计用户数:在 endTime 之前创建的所有用户数。
  • 查询逻辑

    • getUserCount 方法中,构造一个 Map 将起始时间和结束时间作为参数传递给 countByMap 查询方法。
    • SQL 查询 countByMap 根据提供的 beginend 参数动态生成 SQL 语句,通过条件判断确保查询范围正确。
  • 结果构建

    • 收集各天的日期、新增用户数和累计用户数列表,构建 UserReportVO 返回结果,将这些列表以逗号分隔的字符串格式化返回,便于前端展示。

http://www.kler.cn/a/372366.html

相关文章:

  • 【小程序】自定义组件的data、methods、properties
  • 打破视障壁垒,百度文心快码无障碍版本助力视障IT从业者就业无“碍”
  • LeetCode2108 找出数组中的第一个回文字符串
  • Web安全攻防入门教程——hvv行动详解
  • 掌握软件工程基础:知识点全面解析【chap03、chap05、chap06、chap08、chap09】
  • Elasticsearch:normalizer
  • aarch64-opencv341交叉编译,并在arm上部署helloopencv
  • 【灯光数据最新整理】 2000至2023年“NPP-VIIRS“夜间灯光数据(500m分辨率)-最新出炉_附下载链接
  • HCIP--以太网交换安全(总实验)
  • ssm基于web的网络游戏交易平台信息管理系统的设计与实现+vue
  • Linux_02 Linux常用软件——vi、vim
  • 从0开始深度学习(22)——从全连接层到卷积
  • 【牛客算法】某司面试算法题:循环右移二叉树
  • 2024 CCF CSP-J/S 2024 第二轮认证 真题试卷
  • ubuntu下快捷键启动程序
  • Kotlin学习第三课
  • WPF入门_07模板控件
  • 2. STM32 HAL库MDK工程模板创建
  • JavaFx -- chapter05(多用户服务器)
  • C++ 模板专题 - 标签分派(Tag Dispatching)
  • Spring Boot与Web技术的酒店客房服务管理系统
  • 深入理解C++ Lambda表达式:语法、用法与原理及其包装器的使用
  • 智能进化:强化学习如何模拟自然选择,揭示适应性优化的秘密
  • 利用kimi编程助手从0到1开始搭建小程序!
  • 贷中额度策略调整
  • 智能网关有什么用处