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

【方案设计】针对监控服务-功能时长统计的几个实现方案

在这里插入图片描述

实现前后端针对用户功能时长的使用,可以从记录用户操作开始,到存储和展示功能使用时长。以下是几个实现方案的简单介绍:

方案一:基于时间戳记录

这种方案通过记录用户开始和结束使用功能的时间戳,然后在后端计算时长并存储,前端从后端获取数据进行展示。

前端实现
  • 记录开始时间:在用户进入功能页面时,使用 Date.now() 获取当前时间戳并存储在本地变量中。
// 在进入功能页面时
let startTime = Date.now();
  • 记录结束时间:在用户离开功能页面或完成操作时,再次获取当前时间戳。
// 在离开功能页面时
let endTime = Date.now();
  • 发送时长数据到后端:将计算出的时长(endTime - startTime)发送到后端服务器。可以使用 fetchaxios 等库进行 HTTP 请求。
import axios from 'axios';

let duration = endTime - startTime;
axios.post('/api/function-usage', {
    functionName: '特定功能名称',
    duration: duration
}).then(response => {
    console.log('时长数据发送成功');
}).catch(error => {
    console.log('发送时长数据失败', error);
});
后端实现(以 Spring Boot 为例)
  • 接收前端数据:创建一个控制器来接收前端发送的时长数据。
@RestController
@RequestMapping("/api")
public class FunctionUsageController {

    @Autowired
    private FunctionUsageService functionUsageService;

    @PostMapping("/function-usage")
    public ResponseEntity<String> saveFunctionUsage(@RequestBody FunctionUsage functionUsage) {
        functionUsageService.saveFunctionUsage(functionUsage);
        return ResponseEntity.ok("时长数据保存成功");
    }
}
  • 存储数据:创建一个服务类和对应的实体类来处理数据存储。
@Service
public class FunctionUsageService {

    @Autowired
    private FunctionUsageRepository functionUsageRepository;

    public void saveFunctionUsage(FunctionUsage functionUsage) {
        functionUsageRepository.save(functionUsage);
    }
}
@Entity
@Table(name = "function_usage")
public class FunctionUsage {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String functionName;
    private Long duration;
    // 可以添加用户标识字段,如 userId
    private Long userId;

    // 构造函数、getter 和 setter
    public FunctionUsage() {}

    public FunctionUsage(String functionName, Long duration, Long userId) {
        this.functionName = functionName;
        this.duration = duration;
        this.userId = userId;
    }

    // getters 和 setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFunctionName() {
        return functionName;
    }

    public void setFunctionName(String functionName) {
        this.functionName = functionName;
    }

    public Long getDuration() {
        return duration;
    }

    public void setDuration(Long duration) {
        this.duration = duration;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }
}
@Repository
public interface FunctionUsageRepository extends JpaRepository<FunctionUsage, Long> {
}

方案二:使用 WebSocket 实时记录

这种方案通过 WebSocket 实时传输用户操作状态,后端可以更精确地记录功能使用时长。

前端实现
  • 连接 WebSocket:使用 WebSocket API 连接到后端服务器。
let socket = new WebSocket('ws://localhost:8080/function-usage');

socket.onopen = function (event) {
    console.log('WebSocket 连接成功');
    // 发送用户进入功能的消息
    socket.send(JSON.stringify({
        action: 'enter',
        functionName: '特定功能名称',
        userId: 1 // 假设用户 ID
    }));
};

socket.onclose = function (event) {
    console.log('WebSocket 连接关闭');
    // 发送用户离开功能的消息
    socket.send(JSON.stringify({
        action: 'leave',
        functionName: '特定功能名称',
        userId: 1
    }));
};
后端实现(以 Spring Boot + Spring WebSocket 为例)
  • 配置 WebSocket:在 Spring Boot 中配置 WebSocket。
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(functionUsageHandler(), "/function-usage").withSockJS();
    }

    @Bean
    public WebSocketHandler functionUsageHandler() {
        return new FunctionUsageHandler();
    }
}
  • 处理 WebSocket 消息:创建一个 WebSocketHandler 来处理前端发送的消息。
@Component
public class FunctionUsageHandler extends TextWebSocketHandler {

    private final Map<String, Long> userFunctionStartTime = new HashMap<>();
    private final FunctionUsageService functionUsageService;

    public FunctionUsageHandler(FunctionUsageService functionUsageService) {
        this.functionUsageService = functionUsageService;
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        FunctionUsageMessage usageMessage = new ObjectMapper().readValue(message.getPayload(), FunctionUsageMessage.class);
        String userId = session.getId(); // 简单示例,实际应从消息中获取用户标识
        if ("enter".equals(usageMessage.getAction())) {
            userFunctionStartTime.put(userId, System.currentTimeMillis());
        } else if ("leave".equals(usageMessage.getAction())) {
            Long startTime = userFunctionStartTime.remove(userId);
            if (startTime!= null) {
                Long duration = System.currentTimeMillis() - startTime;
                FunctionUsage functionUsage = new FunctionUsage(usageMessage.getFunctionName(), duration, Long.parseLong(userId));
                functionUsageService.saveFunctionUsage(functionUsage);
            }
        }
    }
}
public class FunctionUsageMessage {
    private String action;
    private String functionName;
    private Long userId;

    // 构造函数、getter 和 setter
    public FunctionUsageMessage() {}

    public FunctionUsageMessage(String action, String functionName, Long userId) {
        this.action = action;
        this.functionName = functionName;
        this.userId = userId;
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }

    public String getFunctionName() {
        return functionName;
    }

    public void setFunctionName(String functionName) {
        this.functionName = functionName;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }
}

方案三:前端定时上报

前端定时向后端发送用户是否正在使用功能的状态,后端根据这些状态记录时长。

前端实现
  • 定时发送状态:使用 setInterval 定时发送用户状态。
let isUsingFunction = true; // 假设用户正在使用功能
let intervalId = setInterval(() => {
    axios.post('/api/function-status', {
        functionName: '特定功能名称',
        isUsing: isUsingFunction,
        userId: 1
    }).then(response => {
        console.log('状态数据发送成功');
    }).catch(error => {
        console.log('发送状态数据失败', error);
    });
}, 60 * 1000); // 每分钟发送一次
后端实现
  • 接收状态数据:创建控制器接收前端发送的状态数据。
@RestController
@RequestMapping("/api")
public class FunctionStatusController {

    @Autowired
    private FunctionUsageService functionUsageService;

    @PostMapping("/function-status")
    public ResponseEntity<String> saveFunctionStatus(@RequestBody FunctionStatus functionStatus) {
        functionUsageService.saveFunctionStatus(functionStatus);
        return ResponseEntity.ok("状态数据保存成功");
    }
}
  • 处理状态数据并计算时长:在服务类中根据状态数据计算时长。
@Service
public class FunctionUsageService {

    private final Map<Long, FunctionStatus> userFunctionStatusMap = new HashMap<>();

    public void saveFunctionStatus(FunctionStatus functionStatus) {
        Long userId = functionStatus.getUserId();
        FunctionStatus previousStatus = userFunctionStatusMap.get(userId);
        if (previousStatus!= null && previousStatus.isUsing() &&!functionStatus.isUsing()) {
            // 用户停止使用功能,计算时长
            Long duration = System.currentTimeMillis() - previousStatus.getLastUpdateTime();
            // 保存时长数据
            FunctionUsage functionUsage = new FunctionUsage(functionStatus.getFunctionName(), duration, userId);
            // 这里可以添加实际的存储逻辑
        }
        userFunctionStatusMap.put(userId, functionStatus);
    }
}
public class FunctionStatus {
    private String functionName;
    private boolean isUsing;
    private Long userId;
    private Long lastUpdateTime;

    // 构造函数、getter 和 setter
    public FunctionStatus() {
        this.lastUpdateTime = System.currentTimeMillis();
    }

    public FunctionStatus(String functionName, boolean isUsing, Long userId) {
        this.functionName = functionName;
        this.isUsing = isUsing;
        this.userId = userId;
        this.lastUpdateTime = System.currentTimeMillis();
    }

    public String getFunctionName() {
        return functionName;
    }

    public void setFunctionName(String functionName) {
        this.functionName = functionName;
    }

    public boolean isUsing() {
        return isUsing;
    }

    public void setIsUsing(boolean isUsing) {
        this.isUsing = isUsing;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public Long getLastUpdateTime() {
        return lastUpdateTime;
    }

    public void setLastUpdateTime(Long lastUpdateTime) {
        this.lastUpdateTime = lastUpdateTime;
    }
}

以上方案可以根据项目的具体需求和技术栈进行选择和调整,实现对用户功能时长的有效记录和使用。


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

相关文章:

  • 用户界面软件01
  • 图数据库 | 17、高可用分布式设计(上)
  • nginx-灰度发布策略(split_clients)
  • 【Uniapp-Vue3】swiper滑块视图容器的用法
  • HTML5 文件上传(File Upload)详解
  • v-model与 mvvm 回顾
  • 云备份项目--服务端编写
  • Oracle 11g rac + Dataguard 环境调整 redo log 大小
  • React虚拟DOM:理解和应用
  • torch.reciprocal介绍
  • 游戏引擎学习第70天
  • 面试题解,Java中的“对象”剖析
  • 【js引擎】quickjs 中的两个 proto
  • 5 Linux 网络编程基础 API
  • 家教老师预约平台小程序系统开发方案
  • 数据结构-顺序表及其应用
  • 【pytorch练习】使用pytorch神经网络架构拟合余弦曲线
  • 电商项目-基于ElasticSearch实现商品搜索功能(一)
  • 2025-01-04 Unity插件 YodaSheet1 —— 插件介绍
  • 【深度学习入门_基础篇】线性代数本质
  • 进军AI大模型-Langchain程序部署
  • DS复习提纲模版
  • asp.net core 发布到iis后,一直500.19,IIS设置没问题,安装了sdk,文件夹权限都有,还是报错
  • RestClient操作Elasticsearch
  • 【Java】集合中的List【主线学习笔记】
  • 蓝色简洁引导页网站源码