按照年月定位
- 页面主体部分是一个可滚动区域,展示了按年月分组的服务评分变动记录;
- 当用户在年月选择器中选定某个年月后,页面会自动滚动到相应月份的数据区域;
- 数据中涉及到了服务评分的原因和涨跌分数,这些原因通过查询预先获取的字典数据转化为文本描述;
- 页面滚动时,顶部年月选择器会在滚动到一定程度时自动显示。
<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>