按照年月定位

  • 页面顶部有一个固定的年月选择器,点击后会打开一个时间选择面板,用户可以选择不同的年月来切换显示的数据;
  • 页面主体部分是一个可滚动区域,展示了按年月分组的服务评分变动记录;
  • 当用户在年月选择器中选定某个年月后,页面会自动滚动到相应月份的数据区域;
  • 数据中涉及到了服务评分的原因和涨跌分数,这些原因通过查询预先获取的字典数据转化为文本描述;
  • 页面滚动时,顶部年月选择器会在滚动到一定程度时自动显示。

 

<template>
    <view>
        <!-- 显示年月选择器的部分 -->
        <view class="dd-gd" v-show="showgd">
            <span style="color:#CDCDCD;" @click="show = true">{{formattedDatestart}}</span>
            <u-datetime-picker ref="datetimePicker" :show="show" v-model="value1" mode="year-month"
                :formatter="formatter" @confirm="confirm" @cancel="close"
                @change="handleTimeChange"></u-datetime-picker>
        </view>

        <!-- 可滚动内容区域 -->
        <div ref="scrollView" class="dd-header-xq" style="height: 100%;">
            <!-- 遍历处理后的数据,按年月分组显示 -->
            <view class="dd-box" v-for="(entry, index) in processedData" :key="entry.yearMonth">
              <!-- 年月标题 -->
              <view class="dd-yy">
                <span> {{ entry.yearMonth.replace('-', '年') + '月' }}</span>
              </view>
              <!-- 显示每月具体评分变动记录 -->
              <view v-for="item in entry.data" :key="item.id" style="padding: 20rpx 0;">
                <view class="flex justify-between">
                  <!-- 显示评分变动原因及涨跌分数 -->
                  <span :style="{color: item.score < 0 ? 'red' : '#999999'}">
                    {{getDictTextByType(item.servicePointsReason)}} {{ item.score > 0 ? '上涨' : '减少' }}{{ Math.abs(item.score) }}分
                  </span>
                  <!-- 显示日期 -->
                  <span>{{ item.formattedDate }}</span>
                </view>
              </view>
            </view>

        </div>
    </view>
</template>

<script>
import fwf from "@/api/fwf.js"; // 引入数据源API模块

export default {
  data() {
    return {
      apiResults: [], // 原始API数据
      show: false, // 控制日期选择器显示隐藏状态
      value1: Number(new Date()), // 初始化日期选择器默认值为当前时间戳
      formattedDatestart: '', // 当前显示的年月
      showgd: false, // 控制年月选择器区域是否显示
      ddBoxHeights: [], // 存储各个月份盒子的高度
      processedData: [], // 处理后的按年月分组的数据
      dataDict: [], // 字典数据
    };
  },
  
  onReady() {
    uni.onPageScroll(this.onPageScroll); // 页面滚动事件绑定
  },

  mounted() {
    this.getDict("service_points_reason"); // 获取字典数据
    this.selectFwf(); // 获取服务评分数据
    // 设置初始显示的年月
    const currentDate = new Date();
    this.formattedDatestart = `${currentDate.getFullYear()}年${currentDate.getMonth() + 1}月`;
    
    // 计算每个年月盒子的高度
    this.$nextTick(() => {
      this.calculateBoxHeights();
    });
  },

  onUnload() {
    uni.offPageScroll(this.onPageScroll); // 页面卸载时解除滚动事件监听
  },

  beforeDestroy() {
    this.ddBoxHeights = []; // 页面销毁前清除盒子高度数据
  },

  methods: {
    // 根据字典类型获取文本描述
    getDictTextByType(type) {
      let dictItem = this.dataDict.find(item => item.value === type);
      return dictItem ? dictItem.text : '未知类型';
    },

    // 获取字典数据
    getDict(code) {
      this.$http.get(`/site/site/getDictItemsApp/${code}`).then(res => {
        this.dataDict = res.data.result;
      });
    },

    // 异步获取服务评分数据
    async selectFwf() {
      try {
        let res = await fwf.selectFwf();
        if (res.data.success) {
          this.processData(res.data.result);
        }
      } catch (err) {
        console.error(err);
      }
    },

    // 处理服务评分数据,按年月分组
    processData(results) {
      const yearMonthMap = new Map();
      
      results.forEach(item => {
        const date = new Date(item.createtime);
        const key = `${date.getFullYear()}-${date.getMonth() + 1}`;
        if (!yearMonthMap.has(key)) {
          yearMonthMap.set(key, []);
        }
        yearMonthMap.get(key).push({
          ...item,
          formattedDate: `${("0" + (date.getMonth() + 1)).slice(-2)}/${("0" + date.getDate()).slice(-2)}`
        });
      });

      this.processedData = Array.from(yearMonthMap, ([key, value]) => ({ yearMonth: key, data: value }));
    },

    onPageScroll(e) {
      this.showgd = e.scrollTop >= 20; // 当页面滚动超过20px时,显示年月选择器区域
    },

    formatYearMonth(item) {
      // 将年月数据转换为中文格式(未被实际调用)
      return `${item.year}年${item.month}月`;
    },

    calculateBoxHeights() {
      this.$nextTick(() => {
        uni.createSelectorQuery()
          .selectAll('.dd-box')
          .boundingClientRect(rects => {
            this.ddBoxHeights = rects.map(rect => rect.height);
          })
          .exec();
      });
    },

    scrollToTarget(index) {
      // 根据索引滚动到相应的年月盒子
      let offset = 0;
      for (let i = 0; i < index; i++) {
        offset += this.ddBoxHeights[i];
      }

      const topBarHeight = 50; // 假设顶部固定元素高度为50px
      offset -= topBarHeight;

      uni.pageScrollTo({
        scrollTop: offset,
        duration: 300,
      });
    },

    // 日期选择器格式化回调函数
    formatter(type, value) {
      if (type === 'year') return `${value}年`;
      if (type === 'month') return `${value}月`;
      return value;
    },

    // 日期选择器确定事件
    confirm(e) {
      let timestamp = this.selectedTime;
      this.selectedTime = null;

      if (!timestamp) {
        timestamp = new Date().getTime();
      }

      const date = new Date(timestamp);
      const year = date.getFullYear();
      const month = date.getMonth() + 1;
      this.formattedDatestart = `${year}年${month}月`;

      const selectedYearMonthKey = `${year}-${month}`;

      const matchIndex = this.processedData.findIndex(entry => entry.yearMonth === selectedYearMonthKey);

      this.$nextTick(() => {
        uni.createSelectorQuery()
          .selectAll('.dd-box')
          .boundingClientRect(rects => {
            this.ddBoxHeights = rects.map(rect => rect.height);
            if (matchIndex !== -1) {
              this.scrollToTarget(matchIndex);
            } else {
              uni.showToast({
                title: '该月份无数据',
                icon: 'none',
              });
            }
          })
          .exec();
      });

      this.show = false; // 关闭日期选择器
    },

    close(e) {
      this.show = false; // 关闭日期选择器
    },

    handleTimeChange(newTime) {
      this.selectedTime = newTime.value; // 在选择过程中实时更新选中的时间戳
    },
  },
};
</script>

<style>
  .dd-yy { /* 年月标题样式 */
    padding-bottom: 20rpx;
    border-bottom: 1px solid #F1F1F1;
  }

  .dd-gd { /* 年月选择器区域样式 */
    background-color: white;
    width: 100vw;
    position: fixed;
    padding: 40rpx 60rpx;
    z-index: 999;
  }
</style>

 

posted @ 2024-04-10 18:32  有只小菜猫  阅读(6)  评论(0编辑  收藏  举报