Ver Fonte

feat(growth-main): S-cfc-139 growth.history.dayGroupView 实现使绿 - 成长主页按日期分组视图落地(单文件入库合入 cfclub 主线)

Agnes Agent há 1 dia atrás
pai
commit
d9ed19ddf
1 ficheiros alterados com 93 adições e 1 exclusões
  1. 93 1
      cfc-frontend/pages/growth-main/index.vue

+ 93 - 1
cfc-frontend/pages/growth-main/index.vue

@@ -224,6 +224,27 @@
         </view>
       </view>
 
+      <!-- 成长历史记录(按日期分组,变更B) -->
+      <view class="section history-group-section">
+        <view class="section-header">
+          <text class="section-title">📅 成长历史记录</text>
+        </view>
+        <view v-if="dateGroups.length === 0" class="history-empty">
+          <text class="history-empty-text">暂无记录,去记录第一笔成长吧</text>
+        </view>
+        <view v-else class="history-group-list">
+          <view class="history-group" v-for="group in dateGroups" :key="group.date">
+            <view class="history-group-title">
+              <text class="history-group-date">{{ group.date }}</text>
+              <text class="history-group-count">{{ group.records.length }} 条</text>
+            </view>
+            <view class="history-group-item" v-for="(rec, idx) in group.records" :key="getHistoryItemKey(group.date, idx)">
+              <text class="history-group-item-title">{{ getHistoryItemTitle(rec) }}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+
       <DimensionActivities :isLoggedIn="true" @activityClick="goActivityDetail" @moreActivities="goMoreActivities" style="margin-bottom:60rpx" />
 
       <!-- 推荐阅读 -->
@@ -254,7 +275,7 @@ import LoginGuideCard from '../../components/LoginGuideCard.vue'
 import DimensionActivities from '../../components/DimensionActivities.vue'
 import DimensionProducts from '../../components/DimensionProducts.vue'
 import ArticleFeed from '../../components/ArticleFeed.vue'
-import { healthCheckinList, getHealthMealList, getGrowthRecommendations, getExerciseRecords, getSleepRecords, getEmotionCheckinList, getCheckinList, getTodayTasks, reportAppEnter } from '../../utils/api.js'
+import { healthCheckinList, getHealthMealList, getGrowthRecommendations, getExerciseRecords, getSleepRecords, getEmotionCheckinList, getCheckinList, getTodayTasks, reportAppEnter, getGrowthRecordList } from '../../utils/api.js'
 import { parseDate, recordDateOf } from '../../utils/format.js'
 import fontScaleMixin from '@/mixins/font-scale.js'
 import shareMixin from '../../components/share-mixin.js'
@@ -264,6 +285,7 @@ export default {
   data() { return { memberId: '', todayDate: '', hasIncomplete: false, incompleteCount: 0, progressItems: [], todayTaskList: [], streakDays: 0, activeChallenges: 0, completeness: 0,
       healthArticles: [],
       growthArticles: [],
+      dateGroups: [],
       isLoggedIn: false } },
   computed: {
     doneCount: function() { var c = 0; for (var i = 0; i < this.progressItems.length; i++) if (this.progressItems[i] && this.progressItems[i].done) c++; return c },
@@ -359,6 +381,75 @@ export default {
       if (!d) return ''
       return this.pad(d.getMonth() + 1) + '-' + this.pad(d.getDate())
     },
+    /** 按日期分组(变更B):把打卡/档案记录流按业务日期 recordDate>startTime>sleepTime>checkinDate>createdAt
+     *  分组合并——同日合并、分组键 yyyy-MM-dd、多日倒序(新在前)、无有效日期的记录平稳跳过 */
+    groupByDate: function(records) {
+      var list = Array.isArray(records) ? records : []
+      var map = {}
+      var order = []
+      for (var i = 0; i < list.length; i++) {
+        var r = list[i]
+        if (!r) continue
+        var key = this.recordDateKeyOf(r)
+        if (!key) continue
+        if (!map[key]) {
+          map[key] = { date: key, records: [] }
+          order.push(key)
+        }
+        map[key].records.push(r)
+      }
+      order.sort(function(a, b) { return a < b ? 1 : -1 })
+      var groups = []
+      for (var j = 0; j < order.length; j++) {
+        groups.push(map[order[j]])
+      }
+      return groups
+    },
+    getHistoryItemKey: function(dateKey, idx) { return dateKey + '-' + idx },
+    getHistoryItemTitle: function(rec) {
+      if (!rec) return ''
+      var t = rec.recordTitle || rec.name || rec.note || rec.mood || rec.content || ''
+      if (t) return t
+      if (rec.type) return rec.type
+      return '记录'
+    },
+    /** 单条记录的业务日期键(分组口径):recordDate>startTime>sleepTime>checkinDate,
+     *  无效业务日期(空串/无法解析,如手填 'not-a-date')视为无日期记录予以跳过;不取 createdAt 兜底 */
+    recordDateKeyOf: function(rec) {
+      if (!rec) return ''
+      var fields = ['recordDate', 'startTime', 'sleepTime', 'checkinDate']
+      for (var i = 0; i < fields.length; i++) {
+        var key = fields[i]
+        var v = rec[key]
+        if (v === null || v === undefined || v === '') continue
+        var d = parseDate(v)
+        if (!d) continue
+        return d.getFullYear() + '-' + this.pad(d.getMonth() + 1) + '-' + this.pad(d.getDate())
+      }
+      return ''
+    },
+    /** 成长历史记录加载:档案列表与全部打卡记录汇成一条记录流,按日期分组存入 dateGroups */
+    async loadGrowthHistoryGroups() {
+      var self = this
+      var streams = []
+      try {
+        var gRes = await getGrowthRecordList()
+        if (gRes && gRes.code === 200 && Array.isArray(gRes.data)) streams = streams.concat(gRes.data)
+      } catch(e) {}
+      var checkinStreams = [
+        getHealthMealList(self.memberId ? { memberId: self.memberId } : {}),
+        getExerciseRecords(self.memberId ? { memberId: self.memberId } : {}),
+        getSleepRecords(self.memberId ? { memberId: self.memberId } : {}),
+        getEmotionCheckinList({ page: 1, size: 50, memberId: self.memberId || undefined }),
+        getCheckinList(self.memberId ? { memberId: self.memberId } : {})
+      ]
+      var results = await Promise.all(checkinStreams.map(function(p) { return p.catch(function() { return null }) }))
+      for (var i = 0; i < results.length; i++) {
+        var res = results[i]
+        if (res && res.code === 200 && Array.isArray(res.data)) streams = streams.concat(res.data)
+      }
+      self.dateGroups = self.groupByDate(streams)
+    },
     mealTypeLabel: function(type) {
       var m = { breakfast: '早餐', lunch: '午餐', dinner: '晚餐', snack: '加餐', extra: '零食' }
       if (!type) return '饮食'
@@ -377,6 +468,7 @@ export default {
       try { await self.loadProgressItems() } catch(e) {}
       try { await self.loadGrowthRecommendations() } catch(e) {}
       try { await self.loadMilestones() } catch(e) {}
+      try { await self.loadGrowthHistoryGroups() } catch(e) {}
     },
     async loadProgressItems() {
       var self = this