关于前后端学习记录的实现-山大软院创新实训项目博客_8

 一、结果展示

二、设计思路

这个模块采用了以下技术栈和设计理念:

  • 前端:Vue 3 + Composition API + TypeScript

  • UI框架:Tailwind CSS

  • 图表库:ECharts (通过vue-echarts集成)

  • 后端:Spring Boot + MyBatis

  • 数据可视化:柱状图、饼图等多样化展示方式

三、实现功能详解

1. 语音练习记录

  • 展示用户的所有语音练习历史

  • 每个记录包含四大评分维度:

    • 发音评分 (Pronunciation)

    • 准确度 (Accuracy)

    • 流利度 (Fluency)

    • 完整度 (Completeness)

  • 支持按主题搜索和筛选

  • 时间倒序排列最新记录优先显示

2. 语音统计

  • 阅读频率统计:柱状图展示最近7天的练习频率

  • 故事分布统计:饼图展示不同主题的练习分布比例

  • 数据驱动决策:帮助用户了解学习习惯和偏好

3. 故事统计

  • 柱状图展示故事生成频率

  • 按天统计用户生成故事的数量

  • 直观展示学习投入程度

四、核心代码解析

后端实现关键点

历史记录控制器(HistoryController.java)

@RestController
@RequestMapping("/api/history")
public class HistoryController {

    @Autowired
    private StoryHistoryService storyHistoryService;

    // 获取当前用户所有历史故事
    @GetMapping("/all")
    public List<Story> getAllHistoryByCurrentUser() {
        User user = JwtInterceptor.userThreadLocal.get();
        return storyHistoryService.getAllByUserId(user.getId());
    }

    // 保存故事记录
    @PostMapping("/save")
    public String saveStory(@RequestBody Story story) {
        User user = JwtInterceptor.userThreadLocal.get();
        story.setUserId(user.getId());
        story.setCreateTime(new Date());
        int success = storyHistoryMapper.insert(story);
        return success > 0 ? "保存成功" : "保存失败";
    }
}

语音评分控制器(SpeechScoreController.java)

@RestController
@RequestMapping("/api/score")
public class SpeechScoreController {

    @Autowired
    private SpeechScoreService speechScoreService;

    // 保存语音评分
    @PostMapping("/save")
    public ResponseEntity<String> saveScore(@RequestBody Map<String, Object> body) {
        // 解析评分数据
        Map<String, Object> assessment = (Map<String, Object>) body.get("pronunciationAssessment");
        String text = (String) body.get("recognizedText");
        String topic = (String) body.get("storyTopic");
        
        // 创建评分对象
        SpeechScore score = new SpeechScore();
        score.setUserId(currentUser.getId());
        score.setStoryTopic(topic);
        score.setRecognizedText(text);
        
        // 设置各项评分
        score.setAccuracyScore(String.valueOf(assessment.get("AccuracyScore")));
        score.setFluencyScore(String.valueOf(assessment.get("FluencyScore")));
        score.setCompletenessScore(String.valueOf(assessment.get("CompletenessScore")));
        score.setPronScore(String.valueOf(assessment.get("PronScore")));
        
        // 保存到数据库
        speechScoreService.saveSpeechScore(score);
        return ResponseEntity.ok("评分结果保存成功");
    }

    // 获取用户所有评分记录
    @GetMapping("/titles")
    public ResponseEntity<List<ScoreResponse>> getStoryTitlesByUser() {
        User user = JwtInterceptor.userThreadLocal.get();
        List<ScoreResponse> scoreList = new ArrayList<>();
        
        // 按主题组织评分数据
        List<String> titles = storyHistoryService.getTitlesByUserId(user.getId());
        for (String title : titles) {
            ScoreResponse scoreResponse = new ScoreResponse();
            scoreResponse.setTitle(title);
            scoreResponse.setScoreList(speechScoreService.getSpeechScoreByTopic(user.getId(), title));
            scoreList.add(scoreResponse);
        }
        return ResponseEntity.ok(scoreList);
    }
}

前端实现关键点

数据获取与处理

// 获取所有评分记录
async function fetchAllScores() {
  loading.value = true;
  try {
    const response = await fetch('/api/score/titles');
    const data: ScoreTitle[] = await response.json();
    
    // 展平评分数据并按时间排序
    allScores.value = data.flatMap(item => item.scoreList);
    allScores.value.sort((a, b) => 
      new Date(b.createTime).getTime() - new Date(a.createTime).getTime()
    );
    
    // 应用显示数量限制
    updateDisplayCount();
  } finally {
    loading.value = false;
  }
}

// 获取故事记录
async function fetchStoryRecords() {
  loading.value = true;
  try {
    const response = await fetch('/api/history/all');
    const data = await response.json();
    storyRecords.value = data;
  } finally {
    loading.value = false;
  }
}

图表配置逻辑

// 语音统计图表配置
const chartOption = computed(() => {
  // 获取最近7天日期
  const dates = Array.from({ length: 7 }, (_, i) => {
    const date = new Date();
    date.setDate(date.getDate() - i);
    return formatDate(date, 'MM-dd');
  }).reverse();

  // 统计每天故事数量
  const storyCounts = dates.map(date => {
    return allScores.value.filter(score => {
      const scoreDate = formatDate(new Date(score.createTime), 'MM-dd');
      return scoreDate === date;
    }).length;
  });

  return {
    xAxis: { data: dates },
    yAxis: { name: '故事数量' },
    series: [{
      type: 'bar',
      data: storyCounts,
      itemStyle: { color: '#3b82f6' }
    }]
  };
});

五、总结

这个学习记录模块不仅提供了基础的数据展示功能,还通过数据可视化帮助用户更好地理解自己的学习模式和进步情况。后端API设计合理,前端交互体验流畅,整体实现体现了现代Web应用的最佳实践。

通过这个模块,用户可以:

  1. 回顾历史练习记录

  2. 分析自己的强弱项

  3. 了解学习习惯和模式

  4. 基于数据调整学习英语的策略

  5. 保持学习动力和持续性

该实现既满足了功能需求,又通过丰富的可视化界面提供了良好的用户体验,这个模块实现比较不错!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值