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