You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ionic 3 数据展示问题:按学生分组显示扫描时间

Ionic 3 考勤数据分组展示解决方案

我来帮你搞定这个数据展示的问题!目前你的代码会把每个学生的每条扫描记录都单独渲染一次姓名,导致重复显示。核心问题是数据没有按学生分组,我们只需要把同一个学生的所有扫描时间聚合到一起,就能实现你想要的效果。

问题分析

当前你的API返回的是扁平结构的数组,每条扫描记录对应一条学生数据(比如Wafi Dania有两条扫描记录,就会返回两条带她姓名的条目)。前端*ngFor循环时会逐条渲染,所以姓名重复出现。我们需要把数据整理成「学生→多条扫描时间」的层级结构。

解决方案步骤

1. 前端处理数据分组(TS代码修改)

在获取到API数据后,我们先按pelajar_id(学生ID,比姓名更可靠)分组,把同一个学生的所有扫描时间收集到一个数组里:

getAttendance(){
  this.restProvider.getAttendance().then(data => {
    // 初始化分组对象
    const groupedStudents = {};
    
    // 遍历原始数据,按学生ID分组
    (data as any[]).forEach(record => {
      // 如果该学生还没在分组里,先创建基础结构
      if (!groupedStudents[record.pelajar_id]) {
        groupedStudents[record.pelajar_id] = {
          pelajar_id: record.pelajar_id,
          pelajar_nama: record.pelajar_nama,
          scanTimes: []
        };
      }
      
      // 格式化扫描时间为 hh:mm:ss 格式,添加到对应学生的时间数组
      const formattedTime = new Date(record.jadual_scan).toLocaleTimeString('en-GB', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      });
      groupedStudents[record.pelajar_id].scanTimes.push(formattedTime);
    });
    
    // 把分组对象转换为数组,供前端模板循环使用
    this.data = Object.values(groupedStudents);
    console.log('分组后的数据:', this.data);
  });
}

2. 修改HTML模板,渲染分组后的数据

现在数据已经是「学生+多条时间」的结构,模板可以先循环每个学生,再循环该学生的所有扫描时间:

<ion-label> Date: {{myDate}} </ion-label>

<!-- 循环每个学生 -->
<ion-list *ngFor="let student of data">
  <!-- 学生姓名标题行 -->
  <ion-item color="primary">
    <ion-label><h2>{{student.pelajar_nama}}</h2></ion-label>
  </ion-item>
  
  <!-- 扫描时间表格 -->
  <ion-grid>
    <!-- 表头 -->
    <ion-row color="primary">
      <ion-col> Scan </ion-col>
      <ion-col> Time </ion-col>
    </ion-row>
    
    <!-- 循环该学生的所有扫描时间 -->
    <ion-row *ngFor="let time of student.scanTimes">
      <ion-col> Scan </ion-col>
      <ion-col> {{ time }} </ion-col>
    </ion-row>
  </ion-grid>
</ion-list>

可选:后端API直接返回分组数据(Laravel优化)

如果你想在后端完成分组,减少前端逻辑,可以修改Laravel的查询代码,用GROUP_CONCAT聚合扫描时间:

$parentId = \Auth::guard('api')->user()->id;

$student = DB::table('pelajar')
    ->join('jadual','jadual.pelajar_id','pelajar.pelajar_id')
    ->select(
        'pelajar.pelajar_id',
        'pelajar.pelajar_nama',
        // 聚合扫描时间为逗号分隔的字符串
        DB::raw("GROUP_CONCAT(DATE_FORMAT(jadual.jadual_scan, '%H:%i:%s') SEPARATOR ',') as scan_times")
    )
    ->whereDate('jadual.jadual_scan', DB::raw('CURDATE()'))
    ->where('pelajar.penjaga_id',$parentId)
    ->groupBy('pelajar.pelajar_id', 'pelajar.pelajar_nama')
    ->orderBy('pelajar.pelajar_id','asc')
    ->get();

// 把聚合的字符串拆分为数组,方便前端使用
$student = $student->map(function($item) {
    $item->scan_times = explode(',', $item->scan_times);
    return $item;
});

return $student;

这种情况下,前端TS代码不需要做分组,直接用student.scan_times循环即可。

最终效果

修改完成后,页面会按你期望的方式展示:每个学生姓名只显示一次,下方列出该学生当天所有的扫描时间。

内容的提问来源于stack exchange,提问作者MrlinY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:25:07