xc-app/pages/index/ranking.vue

1043 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<scroll-view class="scroll-list-view" scroll-y="true" scroll-with-animation @scroll="onScroll">
<view class="header-top" :class="{'header-active':scrollTop > 0}">
<image src="@/static/rank/fh.png" mode="aspectFit" class="header-back" @click="goBack"></image>
<view class="tab">
<view class="tab-item" :class="{'active':currentTab === item.value}" v-for="(item,index) in tabList"
:key="index" @click="changeTab(item)">
{{item.label}}
<view class="active-heng" v-if="currentTab === item.value"></view>
<view class="heng" v-else></view>
</view>
</view>
<view class="last" @click="lastChange" v-if="currentTab != 'ALL'">上期榜单</view>
<view style="width: 115rpx;height: 33rpx;" v-else></view>
<image src="@/static/rank/bdsm.png" mode="" class="header-wen" @click="isRule = true"></image>
</view>
<view class="header">
<!-- 前三名 -->
<view class="top">
<view class="top-header">
<view class="top-two-main">
<view class="top-two">TOP2</view>
<template v-if="topThree[1]">
<image :src="topThree[1].avatarResource.url" mode="" class="avatar-icon"></image>
</template>
</view>
<view class="top-one-main">
<view class="top-one">TOP1</view>
<template v-if="topThree[0]">
<image :src="topThree[0].avatarResource.url" mode="" class="avatar-icon"></image>
</template>
</view>
<view class="top-three-main">
<view class="top-three">TOP3</view>
<template v-if="topThree[2]">
<image :src="topThree[2].avatarResource.url" mode="" class="avatar-icon"></image>
</template>
</view>
</view>
<view class="top-info">
<view class="info-item info-two">
<view>
<template v-if="topThree[1]">
{{topThree[1].nickname | maskString}}
</template>
</view>
<view class="small-txt">
<template v-if="topThree[1]">
<!-- {{topThree[1].nickname}} -->
<template v-if="topThree[1].rewardEntityList.length > 0">
<template v-for="(childItem,childIndex) in topThree[1].rewardEntityList">
{{childItem.info.abbreviation}}
<text v-if="childIndex+1 < topThree[1].rewardEntityList.length">、</text>
</template>
</template>
</template>
</view>
</view>
<view class="info-item info-one">
<view>
<template v-if="topThree[0]">
{{topThree[0].nickname | maskString}}
</template>
</view>
<view class="small-txt">
<template v-if="topThree[0]">
<!-- {{topThree[0].nickname}} -->
<template v-if="topThree[0].rewardEntityList.length > 0">
<template v-for="(childItem,childIndex) in topThree[0].rewardEntityList">
{{childItem.info.abbreviation}}
<text v-if="childIndex+1 < topThree[0].rewardEntityList.length">、</text>
</template>
</template>
</template>
</view>
</view>
<view class="info-item info-three">
<view>
<template v-if="topThree[2]">
{{topThree[2].nickname | maskString}}
</template>
</view>
<view class="small-txt">
<template v-if="topThree[2]">
<!-- {{topThree[2].nickname}} -->
<template v-if="topThree[2].rewardEntityList.length > 0">
<template v-for="(childItem,childIndex) in topThree[2].rewardEntityList">
{{Number(childItem.info.salePrice)}}元 {{childItem.info.abbreviation}}
<text v-if="childIndex+1 < topThree[2].rewardEntityList.length">、</text>
</template>
</template>
</template>
</view>
</view>
</view>
</view>
</view>
<view class="rank-info" v-if="currentTab != 'ALL'">
<view class="rank-info-left">
<view class="title">本期榜单</view>
<view class="rank-time">
<view class="time-tip">距本场活动结束</view>
<view class="time">
<template>{{expiredTime || '00时00分00秒'}}</template>
</view>
</view>
</view>
<view class="rank-darw" @click="darwCk">本期奖励</view>
</view>
<view v-if="list.length === 0" style="padding-top: 200rpx;">
<empty></empty>
</view>
<view class="list">
<view class="list-item" v-for="(item, index) in rankingList" :key="index">
<view class="rank-num">
<image src="@/static/rank/l-dym.png" mode="" v-if="item.num == 1" class="num-icon"></image>
<image src="@/static/rank/l-dem.png" mode="" v-else-if="item.num == 2" class="num-icon"></image>
<image src="@/static/rank/l-dsm.png" mode="" v-else-if="item.num == 3" class="num-icon"></image>
<rankNumCom :rank="item.num" v-else></rankNumCom>
</view>
<view class="rank-avatar">
<image :src="item.avatarResource.url" mode="" class="rank-avatar-icon"></image>
</view>
<view class="rank-detail">
<view class="detail">
<view class="name">{{ item.nickname | maskString }}</view>
<view class="point">{{ item.points }}积分</view>
</view>
<view class="prize" v-if="item.rewardEntityList.length > 0">
<template v-for="(childItem,childIndex) in item.rewardEntityList">
<!-- {{Number(childItem.info.salePrice)}}元 -->
{{childItem.info.abbreviation}}
<text v-if="childIndex+1 < item.rewardEntityList.length">、</text>
</template>
</view>
</view>
</view>
<template v-if="Object.keys(selfData).length > 0">
<view style="height: 180rpx;"></view>
<view class="self">
<view class="self-info">
<view class="self-avatar">
<image :src="selfData.avatarResource.url" mode="" class="self-avatar-icon"></image>
</view>
<view class="self-num">
我的排名:
<span v-if="selfData.num == -1" class="self-num-txt">999+</span>
<template v-else>
<rankNumCom :rank="selfData.num"></rankNumCom>
</template>
</view>
</view>
<view class="self-point">{{ selfData.points }}积分</view>
</view>
</template>
</view>
<!-- 其他名次列表显示 -->
<!-- <view class="ranking-list">
<view class="list-item" v-for="(item, index) in rankingList" :key="index">
<view class="info">
<view class="rank">
<rankNumCom :rank="item.num"></rankNumCom>
</view>
<template v-if="item.avatarResource">
<image class="avatar" :src="item.avatarResource.url" />
</template>
<view class="name">{{ item.nickname }}</view>
</view>
<view class="score">积分:{{ item.points }}</view>
</view>
<template v-if="Object.keys(selfData).length > 0">
<view class="self-footer list-item">
<view class="info">
<template v-if="selfData.avatarResource">
<image class="avatar" :src="selfData.avatarResource.url" />
</template>
<view class="name">{{ selfData.nickname }}
<view style="display: flex;align-items: center;">
排名:
<span v-if="selfData.num == -1">999+</span>
<template v-else>
<rankNumCom :rank="selfData.num"></rankNumCom>
</template>
</view>
</view>
</view>
<view class="score">积分:{{ selfData.points }}</view>
</view>
</template>
</view> -->
</scroll-view>
<popup-view v-model="isRule" mode="center" border-radius="15" z-index="1000" :maskCloseAble="false">
<view class="rule-main">
<view class="rule-title">榜单说明</view>
<view class="rule-time" v-if="currentTab != 'ALL'">活动时间:{{detail.startTime}}-{{detail.endTime}}</view>
<scroll-view class="rule-view ql-snow" scroll-y="true" scroll-with-animation>
<rich-text :nodes="ruleTxt" class="ql-editor"></rich-text>
</scroll-view>
<view class="rule-submit" @click="isRule = false">确定</view>
</view>
</popup-view>
<!-- 榜单奖励 -->
<popup-view v-model="show" mode="center" border-radius="18" z-index="1000">
<listBonusCom @close="show = false" :detail="detail.rewardsMap" :description="detail.description"></listBonusCom>
</popup-view>
</view>
</template>
<script>
import HeaderCom from '@/pages/components/header.vue'
import rankNumCom from './components/rankNum.vue';
import listBonusCom from './components/listBonus.vue'
import {
topUserListApi,
topUserSelfApi,
topStatusApi,
topRuleApi,
topUserListLastApi,
topUserSelfLastApi,
topExpiredTimeApi,
topDetailApi
} from '@/API/ranking.js'
import '@/static/quill.snow.css'
import reportClickFn from '@/utils/report.js'
export default {
data() {
return {
currentTab: '',
tabObjs: {
DAY: "日榜",
WEEK: "周榜",
MONTH: "月榜",
ALL: "总榜",
},
tabList: [],
list: [],
selfData: {}, //自己的排名
isRule: false, //规则弹框
ruleTxt: '', //规则文本
lastStatus: false, //是否上期排名
computedIndex: 0, //用户切换
expiredTime: '',
timer: null,
scrollTop: 0,
show:false,
ruleVisible:false,
detail:{
rewardsMap:{}
},//详情
};
},
components: {
HeaderCom,
rankNumCom,
listBonusCom
},
computed: {
topThree() {
// return this.currentTab === 'week' ?
// this.weekRanking.slice(0, 3) :
// this.monthRanking.slice(0, 3);
// let arr = this.list.slice(0, 3)
// // 保存第一个元素
// let firstElement = arr[0];
// // 移除第一个元素
// arr.shift();
// // 在第二个位置索引为1插入元素
// arr.splice(1, 0, firstElement);
// this.computedIndex++
return this.list.slice(0, 3)
},
rankingList() {
// return this.list.slice(3)
return this.list
}
},
filters: {
maskString(value) {
if (!value) return ''; // 如果值为空,直接返回空字符串
if (value.length > 2) {
// 字符串长度超过两个字符时
return value.charAt(0) + '**' + value.charAt(value.length - 1);
} else if (value.length === 2) {
// 字符串长度为两个字符时
return value.charAt(0) + '**';
} else {
// 字符串长度小于或等于一个字符时,直接返回原字符串
return value;
}
}
},
mounted() {
this.getTopStatus()
},
methods: {
goBack(){
uni.switchTab({
url:`/pages/index/new-index`
})
},
formatTime(timestamp) {
var date = new Date(timestamp * 1000); // 注意时间戳通常需要乘以1000因为JavaScript的Date对象接收的是毫秒数
var year = date.getFullYear();
var month = (date.getMonth() + 1).toString().padStart(2, '0'); // getMonth() 返回的月份是从 0 开始的
var day = date.getDate().toString().padStart(2, '0');
var hours = date.getHours().toString().padStart(2, '0');
var minutes = date.getMinutes().toString().padStart(2, '0');
var seconds = date.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
getTopDetail(){
topDetailApi({type:this.currentTab}).then(res => {
if(res.code === 200){
this.detail = res.data
console.log("this.detail,",this.detail)
this.detail.startTime = this.formatTime(this.detail.startTime)
this.detail.endTime = this.formatTime(this.detail.endTime)
let newData = {};
let prevKey = 3; // 用于保存前一个key
let rangeStart = 4; // 初始范围开始值
for (let key in this.detail.rewardsMap) {
key = parseInt(key); // 将key转换为整数类型
if (key <= 3) {
newData[key] = this.detail.rewardsMap[key];
} else {
let newKey = prevKey + 1; // 计算新的key
let rangeKey = rangeStart + '-' + key;
newData[rangeKey] = this.detail.rewardsMap[key];
prevKey = key;
rangeStart = newKey;
}
}
console.log(newData);
this.detail.rewardsMap = newData
}else{
this.$api.msg(res.message)
}
})
},
darwCk(){
this.show = true
},
onScroll(event) {
this.scrollTop = event.detail.scrollTop
},
// 获取过期时间
getTopExpiredTime() {
clearInterval(this.timer)
this.timer = null
topExpiredTimeApi({
type: this.currentTab
}).then(res => {
console.log(res)
if (res.code === 200) {
if (res.data == -1) {
this.expiredTime = '无期限'
} else {
this.timer = setInterval(() => {
this.updateRemainingTime(res.data);
}, 1000);
}
} else {
this.$api.msg(res.message)
}
})
},
updateRemainingTime(targetTime = 0) {
// const currentTime = Math.floor(Date.now() / 1000);
// const countdown = targetTime - currentTime;
// if (countdown <= 0) {
// this.isNo = false
// }
// console.log("countdown:", countdown)
// const hours = Math.floor(countdown / 3600);
// const minutes = Math.floor((countdown % 3600) / 60);
// const seconds = countdown % 60;
// if (!isNaN(hours)) {
// this.expiredTime = `${this.padZero(hours)}:${this.padZero(minutes)}:${this.padZero(seconds)}`;
// }
const currentTime = Math.floor(Date.now() / 1000);
const countdown = targetTime - currentTime;
if (countdown <= 0) {
this.isNo = false;
this.expiredTime = "00时00分00秒"; // 如果时间已过可以设置为00天
} else {
const days = Math.floor(countdown / (3600 * 24)); // 计算天数
const hours = Math.floor((countdown % (3600 * 24)) / 3600);
const minutes = Math.floor((countdown % 3600) / 60);
const seconds = countdown % 60;
if(days > 0){
this.expiredTime = `${days}${this.padZero(hours)}${this.padZero(minutes)}${this.padZero(seconds)}`;
}else{
this.expiredTime = `${this.padZero(hours)}${this.padZero(minutes)}${this.padZero(seconds)}`;
}
}
},
padZero(num) {
return num.toString().padStart(2, '0');
},
// 切换上期/本期排名
lastChange() {
uni.navigateTo({
url:`/pages/index/lastRanking?type=${this.currentTab}`
})
// this.lastStatus = !this.lastStatus
// if (this.lastStatus) {
// this.getTopUserListLast(this.currentTab)
// this.getTopUserSelfLast(this.currentTab)
// } else {
// this.getTopUserList(this.currentTab)
// this.getTopUserSelf(this.currentTab)
// }
},
// 获取规则
getTopRule() {
topRuleApi({
type: this.currentTab
}).then(res => {
if (res.code === 200) {
this.ruleTxt = res.data
} else {
this.$api.msg(res.message)
}
})
},
// 获取榜单
getTopStatus() {
topStatusApi().then(res => {
if (res.code === 200) {
// 创建一个新的数组,只包含值为 true 的属性
this.tabList = Object.keys(res.data)
.filter(key => res.data[key] === true)
.map(key => ({
label: this.tabObjs[key],
value: key
}));
// 定义一个排序函数,根据 DAY, WEEK, MONTH, ALL 的顺序
const sortOrder = ['DAY', 'WEEK', 'MONTH', 'ALL'];
this.tabList.sort((a, b) => {
const orderA = sortOrder.indexOf(a.value);
const orderB = sortOrder.indexOf(b.value);
return orderA - orderB;
});
this.currentTab = this.tabList[0].value
this.getTopUserList(this.currentTab)
this.getTopUserSelf(this.currentTab)
this.getTopRule()
this.getTopExpiredTime()
this.getTopDetail()
this.show = true
} else {
this.$api.msg(res.message)
}
})
},
changeTab(row) {
this.currentTab = row.value
// this.getTopUserList(this.currentTab)
// this.getTopUserSelf(this.currentTab)
if (this.lastStatus) {
this.getTopUserListLast(this.currentTab)
this.getTopUserSelfLast(this.currentTab)
} else {
this.getTopUserList(this.currentTab)
this.getTopUserSelf(this.currentTab)
}
this.getTopRule()
this.getTopExpiredTime()
this.getTopDetail()
},
// 获取所有排行榜
getTopUserList(type) {
topUserListApi({
type
}).then(res => {
this.computedIndex++
if(type === 'DAY'){
// 排行榜日榜查看数
reportClickFn('ranking_day')
}
if(type === 'WEEK'){
// 排行榜周榜查看数
reportClickFn('ranking_week')
}
this.list = []
if (res.code === 200) {
this.list = res.data
} else {
this.$api.msg(res.message)
}
})
},
// 当前自己的排名
getTopUserSelf(type) {
topUserSelfApi({
type
}).then(res => {
this.computedIndex++
this.selfData = {}
if (res.code === 200 && res.data) {
this.selfData = res.data
} else if (res.code !== 200) {
this.$api.msg(res.message)
}
})
},
// 获取上期所有排行榜
getTopUserListLast(type) {
topUserListLastApi({
type
}).then(res => {
this.computedIndex++
this.list = []
if (res.code === 200) {
this.list = res.data
} else {
this.$api.msg(res.message)
}
})
},
// 当前上期自己的排名
getTopUserSelfLast(type) {
topUserSelfLastApi({
type
}).then(res => {
this.computedIndex++
this.selfData = {}
if (res.code === 200 && res.data) {
this.selfData = res.data
} else if (res.code !== 200) {
this.$api.msg(res.message)
}
})
},
}
};
</script>
<style lang="scss" scoped>
page {
background-color: #fff;
}
.container {
.scroll-list-view {
height: 100vh;
.header-top {
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 10;
padding-top: 16rpx;
.header-back {
width: 40rpx;
height: 45rpx;
margin-left: 20rpx;
}
.header-wen {
position: absolute;
width: 56rpx;
height: 56rpx;
top: 80rpx;
right: 20rpx;
}
.tab {
display: flex;
align-items: center;
justify-content: center;
width: 500rpx;
.tab-item {
width: 188rpx;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-size: 23rpx;
color: #808080;
.active-heng {
width: 51rpx;
height: 8rpx;
background-image: url('@/static/rank/heng.png');
background-repeat: no-repeat;
background-size: 100%;
// background-color: #000;
// background: linear-gradient(90deg, #00AAFF 0%, rgba(0, 170, 255, 0) 100%);
border-radius: 4rpx;
}
.heng {
width: 48rpx;
height: 8rpx;
}
}
.active {
font-size: 23rpx;
color: #000000;
}
}
.last {
width: 115rpx;
height: 33rpx;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/static/rank/sqbd.png');
background-repeat: no-repeat;
background-size: 100%;
font-size: 23rpx;
color: #000000;
}
}
.header-active {
background-color: #fff;
}
.header {
width: 100%;
height: 409rpx;
background-image: url('@/static/rank/bg.jpg');
background-repeat: no-repeat;
background-size: 100%;
padding-top: 70rpx;
.top {
.top-header {
display: flex;
position: relative;
height: 215rpx;
.top-two-main {
position: absolute;
left: 57rpx;
top: 25rpx;
.top-two {
position: relative;
width: 156rpx;
height: 215rpx;
background-image: url('@/static/rank/dem.png');
background-repeat: no-repeat;
background-size: 100%;
z-index: 3;
font-family: YouSheBiaoTiHei;
font-size: 22rpx;
color: #000000;
text-align: center;
padding-top: 162rpx;
}
.avatar-icon {
position: relative;
z-index: 1;
position: absolute;
width: 126rpx;
height: 126rpx;
border-radius: 50%;
top: 55rpx;
left: 15rpx;
}
}
.top-one-main {
position: absolute;
left: 298rpx;
top: 0;
.top-one {
position: relative;
z-index: 2;
width: 156rpx;
height: 215rpx;
background-image: url('@/static/rank/dym.png');
background-repeat: no-repeat;
background-size: 100%;
font-family: YouSheBiaoTiHei;
font-size: 22rpx;
color: #000000;
text-align: center;
padding-top: 160rpx;
}
.avatar-icon {
position: relative;
z-index: 1;
position: absolute;
width: 126rpx;
height: 126rpx;
border-radius: 50%;
top: 55rpx;
left: 15rpx;
}
}
.top-three-main {
position: absolute;
left: 534rpx;
top: 35rpx;
.top-three {
position: relative;
z-index: 2;
width: 156rpx;
height: 215rpx;
background-image: url('@/static/rank/dsm.png');
background-repeat: no-repeat;
background-size: 100%;
font-family: YouSheBiaoTiHei;
font-size: 22rpx;
color: #000000;
text-align: center;
padding-top: 166rpx;
}
.avatar-icon {
position: relative;
z-index: 1;
position: absolute;
width: 126rpx;
height: 126rpx;
border-radius: 50%;
top: 55rpx;
left: 15rpx;
}
}
}
.top-info {
position: relative;
margin-top: 26rpx;
.info-item {
width: 136rpx;
text-align: center;
font-weight: 600;
font-size: 23rpx;
color: #000000;
}
.small-txt {
font-weight: 400;
font-size: 19rpx;
width: 136rpx;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
}
.info-one {
position: absolute;
left: 309rpx;
}
.info-two {
position: absolute;
left: 72rpx;
}
.info-three {
position: absolute;
right: 66rpx;
}
}
}
}
.rank-info {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 52rpx 18rpx 0rpx 25rpx;
.rank-info-left {
.title {
font-weight: 500;
font-size: 25rpx;
color: #000000;
}
.rank-time {
margin-top: -10rpx;
.time-tip {
display: inline-block;
font-weight: 500;
font-size: 25rpx;
color: #000000;
}
.time {
// background-image: url('@/static/rank/time.png');
background-repeat: no-repeat;
background-size: 100%;
display: inline-block;
// width: 185rpx;
height: 52rpx;
font-weight: 800;
font-size: 40rpx;
color: #FF0000;
text-align: center;
line-height: 52rpx;
margin-left: 20rpx;
}
}
}
.rank-darw {
width: 154rpx;
height: 56rpx;
font-size: 23rpx;
color: #000000;
background-image: url('@/static/rank/bqjl.png');
background-repeat: no-repeat;
background-size: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
}
}
.list {
padding: 0 25rpx 0 30rpx;
.list-item {
display: flex;
align-items: center;
height: 142rpx;
border-bottom: 1px solid #eee;
.rank-num {
width: 69rpx;
height: 87rpx;
display: flex;
align-items: center;
.num-icon {
width: 40rpx;
height: 64rpx;
}
}
.rank-avatar {
width: 87rpx;
height: 87rpx;
.rank-avatar-icon {
width: 87rpx;
height: 87rpx;
border-radius: 50%;
}
}
.rank-detail {
margin-left: 15rpx;
height: 87rpx;
width: 528rpx;
padding-top: 15rpx;
.detail {
width: 528rpx;
display: flex;
align-items: center;
justify-content: space-between;
.name {
font-size: 23rpx;
color: #000000;
}
.point {
font-size: 23rpx;
color: #7CCEF0;
}
}
.prize {
height: 32rpx;
width: 528rpx;
line-height: 32rpx;
padding-left: 6rpx;
margin-top: 11rpx;
font-size: 23rpx;
color: #FF1253;
background-color: #e9e9e9;
}
}
}
.self{
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 160rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 25rpx 0 23rpx;
background-color: #fff;
.self-info{
display: flex;
align-items: center;
.self-avatar{
width: 52rpx;
height: 52rpx;
.self-avatar-icon{
width: 52rpx;
height: 52rpx;
border-radius: 50%;
}
}
.self-num{
display: flex;
align-items: center;
font-size: 23rpx;
color: #000000;
margin-left: 20rpx;
.self-num-txt{
font-weight: 600;
font-size: 31rpx;
color: #5CD1F4;
}
}
}
.self-point{
font-size: 23rpx;
color: #5CD1F4;
}
}
}
}
}
.self-footer {
position: fixed;
width: 100%;
bottom: 0;
left: 0;
padding-left: 32rpx !important;
padding-right: 32rpx !important;
background: linear-gradient(90deg, #00AAFF 0%, rgba(0, 170, 255, 0) 100%);
}
.rule-main {
width: 598rpx;
height: 712rpx;
background-image: url('@/static/rank/rule.jpg');
background-repeat: no-repeat;
background-size: 100%;
.rule-title{
font-weight: 500;
font-size: 34rpx;
color: #000000;
text-align: center;
padding-top: 51rpx;
}
.rule-time{
font-size: 23rpx;
color: #000000;
text-align: center;
margin-top: 10rpx;
}
.rule-view {
width: 465rpx;
height: 400rpx;
margin: 20rpx 0 45rpx 65rpx;
}
.rule-submit{
width: 257rpx;
height: 91rpx;
line-height: 91rpx;
text-align: center;
display: block;
margin: 0 auto;
background-image: url('@/static/rank/qd.png');
background-repeat: no-repeat;
background-size: 100%;
font-family: YouSheBiaoTiHei;
font-size: 48rpx;
color: #FFFFFF;
}
}
</style>