dongzuo-lianxi-history.vue 8.97 KB
<template>
  <up-popup :show="historyShow" mode="bottom" round="24rpx" bgColor="#2c2c2e" @close="historyShow = false">
    <scroll-view scroll-y class="history-popup">
      <!-- 标题栏 -->
      <view class="header">
        <view class="title">{{ actionName }}</view>
      </view>
      <!-- 顶部数据卡片-->
      <view class="top-cards">
        <view class="card">
          <view class="label">最高重量</view>
          <view class="value">{{ maxWeight }} × {{ maxReps }}次</view>
          <view class="date">{{ recordDate }}</view>
        </view>
        <view class="card">
          <view class="label">最高容量</view>
          <view class="value">{{ maxCapacity }}kg · 共{{ maxCapacitySets }}组</view>
          <view class="date">{{ recordDate }}</view>
        </view>
      </view>

      <!-- 历史记录列表 -->
      <view class="list">
        <view class="record-item" v-for="(item, index) in formattedSetList" :key="index">
          <view class="date">{{ item.date }}</view>
          <view class="name">{{ item.name }}</view>
          <view class="info">共{{ item.setCount }}组 · 容量{{ item.capacity }}kg</view>
          <view class="set-list">
            <view class="set" v-for="(set, idx) in item.sets" :key="idx">
              <view class="num">{{ set.idx }}</view>
              <text class="text">{{ set.text }}</text>
            </view>
          </view>
        </view>
      </view>
    </scroll-view>
  </up-popup>
</template>

<script setup>
import { ref, computed } from 'vue'
import TrainingApi from '@/sheep/api/Training/traininghistory'

const historyShow = ref(false)
const historyActionId = ref(0)
const historyList = ref([])

const props = defineProps({
  actionName: {
    type: String,
    default: '杠铃划船'
  }
})

const emit = defineEmits(['close'])

// 模拟数据(和原型图一致)
const maxWeight = '10kg'
const maxReps = 10
const maxCapacity = '200'
const maxCapacitySets = 2
const recordDate = '2026/04/29'

const openHistoryPopup = (id) => {
  console.log('传递到历史子组件的动作id', id)
  historyActionId.value = id;
  console.log('传递到历史子组件的动作idhistoryActionId', historyActionId.value)
  if (id !== undefined && id !== null && id !== '') {
    loadTrainHistoryDetail(id)
  }
  historyShow.value = true;
}

// 加载训练历史
const loadTrainHistoryDetail = async (id) => {
  try {
    console.log("即将查询的历史ID =", id);
    const res = await TrainingApi.getTrainHistoryList(id);
    console.log('接口完整返回:', res);
    historyList.value = res.data;
    console.log('动作训练的训练历史列表接口返回结果historyList.value', historyList.value);
  } catch (error) {
    console.error('加载训练历史失败:', error);
  }
}

// 1. 格式化日期数组为 YYYY/MM/DD 字符串
const formatDateArr = (dateArr) => {
  if (!Array.isArray(dateArr) || dateArr.length < 3) return ''
  const [year, month, day] = dateArr
  return `${year}/${String(month).padStart(2, '0')}/${String(day).padStart(2, '0')}`
}

// 2. 把每一组的 setConfigList 转成「可渲染的文本」
const formattedSetList = computed(() => {
  return historyList.value.map(item => {
    const sets = (item.setConfigList || []).map(set => {
      // 自动拼接:优先显示重量/次数,再显示时长/距离
      const parts = []
      if (set.weight != null && set.weight !== '') {
        parts.push(`${set.weight}kg`)
      }
      if (set.reps != null && set.reps !== '') {
        parts.push(`${set.reps}次`)
      }
      if (set.duration != null && set.duration > 0) {
        // 秒转成 HH:MM:SS
        const h = Math.floor(set.duration / 3600)
        const m = Math.floor((set.duration % 3600) / 60)
        const s = set.duration % 60
        const hh = h > 0 ? `${h}:` : ''
        parts.push(`${hh}${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`)
      }
      if (set.distance != null && set.distance !== '') {
        parts.push(`${set.distance}m`)
      }
      return {
        idx: set.setIndex + 1,
        text: parts.length > 0 ? parts.join(' × ') : '无数据'
      }
    })
    return {
      date: formatDateArr(item.date),
      name: item.name || '训练记录',
      setCount: item.setCount || 0,
      // 容量:如果有重量,就是 重量×次数×组数;如果没有,留空或0
      capacity: item.weight != null ? (item.weight * item.setCount) : 0,
      sets: sets
    }
  })
})

// 3. 自动计算「最高重量、最高容量、最新日期」
const statData = computed(() => {
  if (!historyList.value.length) return { maxWeight: '0kg', maxReps: 0, maxCapacity: '0', maxCapacitySets: 0, recordDate: '' }

  let maxW = 0, maxR = 0, maxC = 0, maxCS = 0
  let latestDate = ''

  historyList.value.forEach(item => {
    // 最高重量:遍历每组数据找最大 weight
    item.setConfigList?.forEach(set => {
      if (set.weight > maxW) {
        maxW = set.weight
        maxR = set.reps || 0
      }
    })
    // 最高容量:按 重量×次数×组数 计算
    const capacity = item.weight ? item.weight * (item.setConfigList?.length || 0) : 0
    if (capacity > maxC) {
      maxC = capacity
      maxCS = item.setConfigList?.length || 0
    }
    // 最新日期:取最大的 date 数组
    const currentDateStr = formatDateArr(item.date)
    if (!latestDate || item.date > latestDate) {
      latestDate = currentDateStr
    }
  })

  return {
    maxWeight: maxW > 0 ? `${maxW}kg` : '0kg',
    maxReps: maxR,
    maxCapacity: maxC,
    maxCapacitySets: maxCS,
    recordDate: latestDate
  }
})

defineExpose({ openHistoryPopup });

</script>

<style lang="scss" scoped>
$bg-dark: #2c2c2e;
$card-bg: #3a3a3c;
$text-main: #ffffff;
$text-gray: #8e8e93;
$theme-yellow: #f8d714;

.history-popup {
  width: 100%;
  max-height: 80vh;
  background-color: $bg-dark;
  border-radius: 24rpx 24rpx 0 0;
  padding: 30rpx;
  box-sizing: border-box;

  .header {
    .title {
      font-size: 40rpx;
      font-weight: bold;
      color: $text-main;
      margin-bottom: 30rpx;
    }
  }

  .top-cards {
    display: flex;
    gap: 20rpx;
    margin-bottom: 20rpx;

    .card {
      flex: 1;
      background-color: $card-bg;
      border-radius: 16rpx;
      padding: 30rpx;

      .label {
        font-size: 28rpx;
        color: $text-gray;
        margin-bottom: 16rpx;
      }

      .value {
        font-size: 36rpx;
        font-weight: bold;
        color: $theme-yellow;
        margin-bottom: 10rpx;
      }

      .date {
        font-size: 24rpx;
        color: $text-gray;
      }
    }
  }

  .chart-card {
    background-color: $card-bg;
    border-radius: 16rpx;
    padding: 30rpx;
    margin-bottom: 20rpx;

    .chart-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 30rpx;

      .title {
        font-size: 28rpx;
        color: $text-main;
      }

      .unit {
        font-size: 24rpx;
        color: $text-gray;
      }
    }

    .chart-placeholder {
      height: 200rpx;
      position: relative;

      .line {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 160rpx;
        border-bottom: 1rpx solid #444;

        .point {
          position: absolute;
          top: 0;
          transform: translateX(-50%);

          .dot {
            width: 12rpx;
            height: 12rpx;
            border-radius: 50%;
            background-color: $theme-yellow;
            margin: 0 auto;
          }

          .val {
            display: block;
            font-size: 26rpx;
            color: $theme-yellow;
            text-align: center;
            margin-bottom: 10rpx;
          }
        }
      }

      .axis {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        display: flex;
        justify-content: space-between;

        .axis-item {
          font-size: 24rpx;
          color: $text-gray;
          position: absolute;
          transform: translateX(-50%);
        }
      }
    }
  }

  .list {
    .record-item {
      background-color: $card-bg;
      border-radius: 16rpx;
      padding: 30rpx;
      margin-bottom: 20rpx;

      .date {
        font-size: 26rpx;
        color: $text-gray;
        margin-bottom: 20rpx;
      }

      .name {
        font-size: 32rpx;
        font-weight: bold;
        color: $text-main;
        margin-bottom: 16rpx;
      }

      .info {
        font-size: 26rpx;
        color: $text-gray;
        margin-bottom: 20rpx;
      }

      .set-list {
        .set {
          display: flex;
          align-items: center;
          margin-bottom: 12rpx;

          .num {
            width: 40rpx;
            height: 40rpx;
            border-radius: 50%;
            background-color: #444;
            color: $text-main;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24rpx;
            margin-right: 16rpx;
          }

          .text {
            font-size: 28rpx;
            color: $text-main;
          }
        }
      }
    }
  }
}
</style>