Merge branch 'bd-test' of 47.94.45.65:angelo/web-base-h5 into bd-online

This commit is contained in:
woody 2025-09-28 09:18:37 +08:00
commit 399a894ef0
11 changed files with 1336 additions and 82 deletions

997
components/RankingPopup.vue Normal file
View File

@ -0,0 +1,997 @@
<template>
<view>
<!-- 直推人数排行榜弹窗 -->
<u-popup
class="ranking-popup"
mode="center"
:show="showPeopleRanking"
:closeOnClickOverlay="false"
border-radius="20"
>
<view style="width: 90vw; height: 85vh" class="popup-container">
<!-- 弹窗头部 -->
<view class="popup-header">
<view class="header-title">直推人数排行榜</view>
</view>
<!-- 前三名特殊展示区域 -->
<view class="top-three-section">
<view class="podium-container">
<!-- 第二名 -->
<view class="podium-item second-place" v-if="peopleTopThree[1]">
<view class="player-area">
<view class="rank-number">
<img src="@/static/images/rank-2.svg" alt="" />
</view>
<view class="member-code">{{
peopleTopThree[1].memberCode
}}</view>
<view
class="member-name"
:class="{ highlight: peopleTopThree[1].isLoginMember == 1 }"
>
{{ peopleTopThree[1].memberName | formatMemberName }}
</view>
<view class="score">{{ peopleTopThree[1].count }}</view>
</view>
</view>
<!-- 第一名 -->
<view class="podium-item first-place" v-if="peopleTopThree[0]">
<view class="player-area">
<view class="rank-number">
<img src="@/static/images/rank-1.svg" alt="" />
</view>
<view class="member-code">
{{ peopleTopThree[0].memberCode }}
</view>
<view
class="member-name"
:class="{ highlight: peopleTopThree[0].isLoginMember == 1 }"
>
{{ peopleTopThree[0].memberName | formatMemberName }}
</view>
<view class="score">{{ peopleTopThree[0].count }}</view>
</view>
</view>
<!-- 第三名 -->
<view class="podium-item third-place" v-if="peopleTopThree[2]">
<view class="player-area">
<view class="rank-number">
<img src="@/static/images/rank-3.svg" alt="" />
</view>
<view class="member-code">{{
peopleTopThree[2].memberCode
}}</view>
<view
class="member-name"
:class="{ highlight: peopleTopThree[2].isLoginMember == 1 }"
>
{{ peopleTopThree[2].memberName | formatMemberName }}
</view>
<view class="score">{{ peopleTopThree[2].count }}</view>
</view>
</view>
</view>
</view>
<!-- 4-30名滚动列表 -->
<view class="ranking-list">
<scroll-view
class="scroll-container"
scroll-y="true"
:show-scrollbar="false"
>
<view
class="list-item"
v-for="(item, index) in peopleRemainingList"
:key="index"
>
<view class="item-rank">{{ index + 4 }}</view>
<view class="item-info">
<view class="item-code">{{ item.memberCode }}</view>
<view
class="item-name"
:class="{ highlight: item.isLoginMember == 1 }"
>
{{ item.memberName | formatMemberName }}
</view>
</view>
<view class="item-score">
<span>{{ item.count }}</span>
<span></span>
</view>
</view>
<view class="list-footer" v-if="peopleRemainingList.length === 0">
<text class="empty-text">暂无更多数据</text>
</view>
</scroll-view>
</view>
<!-- 底部关闭按钮 -->
<view class="popup-footer">
<view class="close-text-btn" @click="closePeopleRanking">
</view>
</view>
</view>
</u-popup>
<!-- 直推金额排行榜弹窗 -->
<u-popup
class="ranking-popup"
width="85%"
height="85%"
mode="center"
:show="showAmountRanking"
:closeOnClickOverlay="false"
border-radius="20"
>
<view style="width: 90vw; height: 85vh" class="popup-container">
<!-- 弹窗头部 -->
<view class="popup-header">
<view class="header-title">直推金额排行榜</view>
</view>
<!-- 前三名特殊展示区域 -->
<view class="top-three-section">
<view class="podium-container">
<!-- 第二名 -->
<view class="podium-item second-place" v-if="amountTopThree[1]">
<view class="player-area">
<view class="rank-number">
<img src="@/static/images/rank-2.svg" alt="" />
</view>
<view
class="member-name"
:class="{ highlight: amountTopThree[1].isLoginMember == 1 }"
>
{{ amountTopThree[1].memberName | formatMemberName }}
</view>
<view class="member-code">{{
amountTopThree[1].memberCode
}}</view>
<view class="score">{{
formatAmount(amountTopThree[1].amount)
}}</view>
</view>
</view>
<!-- 第一名 -->
<view class="podium-item first-place" v-if="amountTopThree[0]">
<view class="player-area">
<view class="rank-number">
<img src="@/static/images/rank-1.svg" alt="" />
</view>
<view
class="member-name"
:class="{ highlight: amountTopThree[0].isLoginMember == 1 }"
>
{{ amountTopThree[0].memberName | formatMemberName }}
</view>
<view class="member-code">{{
amountTopThree[0].memberCode
}}</view>
<view class="score">{{
formatAmount(amountTopThree[0].amount)
}}</view>
</view>
</view>
<!-- 第三名 -->
<view class="podium-item third-place" v-if="amountTopThree[2]">
<view class="player-area">
<view class="rank-number">
<img src="@/static/images/rank-3.svg" alt="" />
</view>
<view
class="member-name"
:class="{ highlight: amountTopThree[2].isLoginMember == 1 }"
>
{{ amountTopThree[2].memberName | formatMemberName }}
</view>
<view class="member-code">{{
amountTopThree[2].memberCode
}}</view>
<view class="score">{{
formatAmount(amountTopThree[2].amount)
}}</view>
</view>
</view>
</view>
</view>
<!-- 4-30名滚动列表 -->
<view class="ranking-list">
<!-- <view class="list-header">
<text class="list-title">完整排行榜</text>
</view> -->
<scroll-view
class="scroll-container"
scroll-y="true"
:show-scrollbar="false"
>
<view
class="list-item"
v-for="(item, index) in amountRemainingList"
:key="index"
>
<view class="item-rank">{{ index + 4 }}</view>
<view class="item-info">
<view class="item-code">{{ item.memberCode }}</view>
<view
class="item-name"
:class="{ highlight: item.isLoginMember == 1 }"
>
{{ item.memberName | formatMemberName }}
</view>
</view>
<view class="item-score">
<span>{{ item.amount }}</span>
</view>
</view>
<view class="list-footer" v-if="amountRemainingList.length === 0">
<text class="empty-text">暂无更多数据</text>
</view>
</scroll-view>
</view>
<!-- 底部关闭按钮 -->
<view class="popup-footer">
<view class="close-text-btn" @click="closeAmountRanking">
</view>
</view>
</view>
</u-popup>
<!-- 加载状态 -->
<u-loading-page
:loading="loading"
loading-text="加载中..."
></u-loading-page>
</view>
</template>
<script>
import * as api from '@/config/index.js'
export default {
name: 'RankingPopup',
data() {
return {
//
showPeopleRanking: false,
showAmountRanking: false,
loading: false,
//
peopleRankingList: [],
peopleTopThree: [],
peopleRemainingList: [],
//
amountRankingList: [],
amountTopThree: [],
amountRemainingList: [],
//
userInfo: uni.getStorageSync('User') || {},
}
},
filters: {
formatMemberName(val) {
return val?.slice(0, 8) || ''
},
},
methods: {
//
async showRankingPopups() {
this.loading = true
try {
//
await Promise.all([this.loadPeopleRanking(), this.loadAmountRanking()])
//
if (this.peopleTopThree.length > 0) {
this.showPeopleRanking = true
} else if (this.amountTopThree.length > 0) {
this.showAmountRanking = true
} else {
this.$emit('onRankingComplete')
}
} catch (error) {
console.error('加载排行榜数据失败:', error)
uni.showToast({
title: '加载失败',
icon: 'error',
})
} finally {
this.loading = false
}
},
//
getCurrentYearMonth() {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0') // 0
return { year, month }
},
//
async loadPeopleRanking() {
try {
const { year, month } = this.getCurrentYearMonth()
const params = {
year,
month,
faker: true,
}
const res = await api.getTopPeople(params)
console.log(res.data)
if (res.code === 200 && res.data) {
//
const mappedData = res.data.map(item => ({
...item,
memberName: item.memberName,
memberCode: item.memberCode,
count: item.numberOfPeople, //
isLoginMember: item.memberId === this.userInfo.memberId ? 1 : 0, //
}))
this.peopleRankingList = mappedData.slice(0, 30) // 30
this.peopleTopThree = this.peopleRankingList.slice(0, 3)
this.peopleRemainingList = this.peopleRankingList.slice(3)
}
} catch (error) {
console.error('加载人数排行榜失败:', error)
throw error
}
},
//
async loadAmountRanking() {
try {
const { year, month } = this.getCurrentYearMonth()
const params = {
year,
month,
faker: true,
}
const res = await api.getTopAmount(params)
if (res.code === 200 && res.data) {
//
const mappedData = res.data.map(item => ({
...item,
memberName: item.memberName,
memberCode: item.memberCode,
amount: item.numberOfAmount, //
isLoginMember: item.memberId === this.userInfo.memberId ? 1 : 0, //
}))
this.amountRankingList = mappedData.slice(0, 30) // 30
this.amountTopThree = this.amountRankingList.slice(0, 3)
this.amountRemainingList = this.amountRankingList.slice(3)
}
} catch (error) {
console.error('加载金额排行榜失败:', error)
throw error
}
},
//
closePeopleRanking() {
this.showPeopleRanking = false
if (this.amountTopThree.length > 0) {
setTimeout(() => {
this.showAmountRanking = true
}, 300)
} else {
this.$emit('onRankingComplete')
}
},
//
closeAmountRanking() {
this.showAmountRanking = false
//
this.$emit('onRankingComplete')
},
//
formatAmount(amount) {
return amount
},
},
}
</script>
<style lang="scss" scoped>
::v-deep .u-popup__content {
background-color: rgba(0, 0, 0, 0);
}
.popup-container {
width: 100%;
height: 100%;
background: linear-gradient(
135deg,
#003d7a 0%,
#005bac 30%,
#0077cc 70%,
#4a90e2 100%
);
border-radius: 20rpx;
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
//
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(
ellipse at 30% 20%,
rgba(255, 255, 255, 0.1) 0%,
transparent 50%
);
pointer-events: none;
z-index: 1;
}
}
@keyframes sparkle {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-100rpx);
}
}
.popup-header {
padding: 30rpx 40rpx 20rpx;
flex-shrink: 0;
position: relative;
z-index: 2;
.header-title {
font-size: 38rpx;
font-weight: bold;
color: #ffffff;
text-shadow:
0 2rpx 8rpx rgba(0, 0, 0, 0.6),
0 0 15rpx rgba(74, 144, 226, 0.8),
0 0 25rpx rgba(255, 255, 255, 0.4);
text-align: center;
position: relative;
animation: title-bling 2s ease-in-out infinite alternate;
}
}
.top-three-section {
padding: 20rpx 20rpx 40rpx;
flex-shrink: 0;
position: relative;
z-index: 2;
}
.podium-container {
display: flex;
justify-content: center;
align-items: flex-end;
position: relative;
margin: 0 10rpx;
height: 290rpx;
//
// &::after {
// content: '';
// position: absolute;
// bottom: 0;
// left: 50%;
// transform: translateX(-50%);
// width: 85%;
// height: 30rpx;
// background: linear-gradient(135deg, #424242 0%, #616161 50%, #424242 100%);
// border-radius: 15rpx 15rpx 0 0;
// box-shadow: 0 -6rpx 20rpx rgba(0, 0, 0, 0.3);
// }
}
.podium-item {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
margin: 0 8rpx;
.player-area {
border-radius: 20rpx;
min-width: 140rpx;
text-align: center;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
position: relative;
z-index: 3;
}
//
// &::after {
// content: '';
// position: absolute;
// bottom: 0;
// left: 50%;
// transform: translateX(-50%);
// border-radius: 12rpx 12rpx 0 0;
// box-shadow:
// 0 -6rpx 15rpx rgba(0, 0, 0, 0.25),
// inset 0 3rpx 6rpx rgba(255, 255, 255, 0.15);
// }
.rank-number {
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
font-weight: bold;
color: #fff;
margin-bottom: 15rpx;
position: relative;
img {
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.3));
transition: all 0.3s ease;
}
}
.member-name {
font-size: 24rpx;
color: #fff;
text-align: center;
margin-bottom: 8rpx;
font-weight: bold;
max-width: 110rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 6rpx 10rpx;
border-radius: 15rpx;
}
.member-code {
color: #fff;
text-align: center;
margin-top: 8rpx;
font-size: 24rpx;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 4rpx 8rpx;
border-radius: 12rpx;
backdrop-filter: blur(5rpx);
}
.score {
font-size: 22rpx;
color: #fff;
font-weight: bold;
min-width: 60rpx;
text-align: center;
}
}
//
.second-place {
.player-area {
transform: translateY(10rpx);
}
&::after {
width: 130rpx;
height: 100rpx;
background: linear-gradient(135deg, #c0c0c0 0%, #e8e8e8 50%, #c0c0c0 100%);
}
// .member-name {
// font-size: 26rpx;
// }
// .member-code {
// font-size: 26rpx;
// }
// .score {
// font-size: 26rpx;
// }
.rank-number img {
height: 70rpx;
width: 70rpx;
animation: silver-glow 2s ease-in-out infinite alternate;
}
}
// -
.first-place {
.player-area {
transform: translateY(-40rpx);
}
&::after {
width: 150rpx;
height: 140rpx;
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 50%, #ffd700 100%);
box-shadow:
0 -8rpx 20rpx rgba(0, 0, 0, 0.3),
inset 0 3rpx 6rpx rgba(255, 255, 255, 0.3),
0 0 25rpx rgba(255, 215, 0, 0.4);
}
.rank-number img {
height: 80rpx;
width: 80rpx;
animation: champion-glow 2s ease-in-out infinite alternate;
}
.member-name {
font-size: 28rpx;
color: #ffd700;
animation: champion-text-glow 2s ease-in-out infinite alternate;
}
.member-code {
font-size: 28rpx;
color: #ffd700;
font-weight: 600;
}
.score {
color: #ffd700;
font-size: 28rpx;
font-weight: 900;
}
}
//
.third-place {
.player-area {
transform: translateY(10rpx);
}
.rank-number img {
height: 65rpx;
width: 65rpx;
animation: bronze-glow 2s ease-in-out infinite alternate;
}
// .member-name {
// font-size: 22rpx;
// }
// .member-code {
// font-size: 22rpx;
// }
// .score {
// font-size: 22rpx;
// }
}
@keyframes title-bling {
0% {
text-shadow:
0 2rpx 8rpx rgba(0, 0, 0, 0.6),
0 0 15rpx rgba(74, 144, 226, 0.8),
0 0 25rpx rgba(255, 255, 255, 0.4);
}
100% {
text-shadow:
0 2rpx 8rpx rgba(0, 0, 0, 0.6),
0 0 25rpx rgba(74, 144, 226, 1),
0 0 35rpx rgba(255, 255, 255, 0.7),
0 0 45rpx rgba(0, 119, 204, 0.5);
}
}
@keyframes golden-pulse {
0% {
background: radial-gradient(
ellipse at center,
rgba(255, 215, 0, 0.2) 0%,
transparent 70%
);
}
100% {
background: radial-gradient(
ellipse at center,
rgba(255, 215, 0, 0.4) 0%,
transparent 70%
);
}
}
@keyframes champion-glow {
0% {
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.3))
drop-shadow(0 0 10rpx rgba(255, 215, 0, 0.3));
transform: scale(1);
}
100% {
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.3))
drop-shadow(0 0 20rpx rgba(255, 215, 0, 0.6));
transform: scale(1.05);
}
}
@keyframes champion-text-glow {
0% {
text-shadow: 0 2rpx 8rpx rgba(255, 215, 0, 0.8);
}
100% {
text-shadow:
0 2rpx 8rpx rgba(255, 215, 0, 0.8),
0 0 15rpx rgba(255, 215, 0, 0.5);
}
}
@keyframes silver-glow {
0% {
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.3))
drop-shadow(0 0 8rpx rgba(192, 192, 192, 0.3));
}
100% {
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.3))
drop-shadow(0 0 15rpx rgba(192, 192, 192, 0.5));
}
}
@keyframes bronze-glow {
0% {
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.3))
drop-shadow(0 0 8rpx rgba(205, 127, 50, 0.3));
}
100% {
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.3))
drop-shadow(0 0 15rpx rgba(205, 127, 50, 0.5));
}
}
.ranking-list {
flex: 1;
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.98) 0%,
rgba(248, 250, 252, 0.95) 100%
);
margin: 20rpx 20rpx 0 20rpx;
border-radius: 25rpx 25rpx 0 0;
overflow: hidden;
backdrop-filter: blur(15rpx);
display: flex;
flex-direction: column;
position: relative;
z-index: 2;
box-shadow:
0 -8rpx 25rpx rgba(0, 0, 0, 0.1),
inset 0 1rpx 0 rgba(255, 255, 255, 0.8);
}
.list-header {
padding: 30rpx 40rpx 20rpx;
border-bottom: 2rpx solid rgba(139, 69, 19, 0.1);
flex-shrink: 0;
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.9) 0%,
rgba(248, 250, 252, 0.8) 100%
);
.list-title {
font-size: 28rpx;
font-weight: bold;
color: #2d3748;
position: relative;
text-align: center;
&::after {
content: '';
position: absolute;
bottom: -8rpx;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 3rpx;
background: linear-gradient(90deg, transparent, #9c27b0, transparent);
border-radius: 2rpx;
}
}
}
.scroll-container {
flex: 1;
height: 0; /* 关键在flex布局中scroll-view需要明确高度 */
}
.list-item {
display: flex;
align-items: center;
padding: 24rpx 30rpx;
border-bottom: 1rpx solid rgba(226, 232, 240, 0.8);
position: relative;
transition: all 0.3s ease;
&:last-child {
border-bottom: none;
}
&:hover {
background: linear-gradient(
135deg,
rgba(159, 122, 234, 0.05) 0%,
rgba(139, 92, 246, 0.03) 100%
);
transform: translateX(5rpx);
}
.item-rank {
font-size: 24rpx;
font-weight: bold;
color: #64748b;
text-align: center;
margin-right: 20rpx;
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
border-radius: 50%;
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
}
.item-info {
flex: 2;
display: flex;
align-items: center;
justify-content: space-between;
}
.item-name {
font-size: 28rpx;
color: #1e293b;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 600;
&.highlight {
color: #7c3aed;
font-weight: bold;
background: linear-gradient(135deg, #7c3aed, #a855f7);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
position: relative;
&::before {
content: '';
position: absolute;
left: -8rpx;
top: 50%;
transform: translateY(-50%);
width: 4rpx;
height: 20rpx;
background: linear-gradient(135deg, #7c3aed, #a855f7);
border-radius: 2rpx;
}
}
}
.item-code {
font-size: 22rpx;
color: #64748b;
white-space: nowrap;
}
.item-score {
flex: 1;
font-size: 24rpx;
color: #374151;
font-weight: bold;
min-width: 100rpx;
text-align: center;
border-radius: 20rpx;
display: flex;
justify-content: flex-end;
}
}
.list-footer {
padding: 40rpx;
text-align: center;
.empty-text {
font-size: 26rpx;
color: #64748b;
font-style: italic;
}
}
.popup-footer {
padding: 20rpx;
flex-shrink: 0;
position: relative;
z-index: 2;
.close-text-btn {
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.95) 0%,
rgba(248, 250, 252, 0.9) 100%
);
color: #005bac;
text-align: center;
padding: 20rpx 50rpx;
border-radius: 50rpx;
font-size: 30rpx;
font-weight: bold;
box-shadow:
0 8rpx 25rpx rgba(0, 0, 0, 0.15),
inset 0 1rpx 0 rgba(255, 255, 255, 0.8),
0 0 0 1rpx rgba(0, 91, 172, 0.3);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.4),
transparent
);
transition: left 0.5s ease;
}
&:active {
transform: scale(0.98);
background: linear-gradient(
135deg,
rgba(248, 250, 252, 0.9) 0%,
rgba(241, 245, 249, 0.85) 100%
);
box-shadow:
0 4rpx 15rpx rgba(0, 0, 0, 0.1),
inset 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
&::before {
left: 100%;
}
}
&:hover::before {
left: 100%;
}
}
}
</style>

View File

@ -0,0 +1,127 @@
<template>
<view class="example-page">
<view class="header">
<text class="title">排行榜弹窗组件示例</text>
</view>
<view class="content">
<view class="button-group">
<u-button
type="primary"
size="large"
@click="showRanking"
:loading="loading"
>
显示排行榜
</u-button>
</view>
<view class="info-section">
<text class="info-title">使用说明</text>
<text class="info-text"
>1. 点击按钮将依次显示直推人数和直推金额排行榜</text
>
<text class="info-text">2. 前三名会特殊展示在顶部</text>
<text class="info-text">3. 4-30名可在下方滚动查看</text>
<text class="info-text">4. 关闭人数排行后自动显示金额排行</text>
</view>
</view>
<!-- 排行榜弹窗组件 -->
<RankingPopup ref="rankingPopup" @onRankingComplete="onRankingComplete" />
</view>
</template>
<script>
import RankingPopup from './RankingPopup.vue'
export default {
name: 'RankingPopupExample',
components: {
RankingPopup,
},
data() {
return {
loading: false,
}
},
methods: {
//
async showRanking() {
this.loading = true
try {
await this.$refs.rankingPopup.showRankingPopups()
} catch (error) {
console.error('显示排行榜失败:', error)
} finally {
this.loading = false
}
},
//
onRankingComplete() {
console.log('排行榜展示完成')
uni.showToast({
title: '排行榜展示完成',
icon: 'success',
})
},
},
}
</script>
<style lang="scss" scoped>
.example-page {
min-height: 100vh;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
padding: 40rpx;
}
.header {
text-align: center;
margin-bottom: 60rpx;
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
}
.content {
max-width: 600rpx;
margin: 0 auto;
}
.button-group {
text-align: center;
margin-bottom: 60rpx;
}
.info-section {
background: rgba(255, 255, 255, 0.9);
padding: 40rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
.info-title {
display: block;
font-size: 28rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
}
.info-text {
display: block;
font-size: 24rpx;
color: #666;
line-height: 1.6;
margin-bottom: 12rpx;
&:last-child {
margin-bottom: 0;
}
}
}
</style>

View File

@ -19,7 +19,6 @@
<u-icon name="close"></u-icon>
</div>
<div class="img-auto" v-html="content.content"></div>
</u-popup>
</template>
@ -42,12 +41,12 @@ export default {
}
},
mounted() {
this.getUserTc()
// this.getUserTc()
},
methods: {
closeTap() {
this.noticeFlag = false
// this.$emit("getTree");
this.$emit('close')
},
getUserTc(data) {
api
@ -63,6 +62,8 @@ export default {
if (items == this.publishLocationIndex) {
this.noticeFlag = true
this.content = res.data[0]
} else {
this.$emit('close')
}
})
}

View File

@ -101,20 +101,24 @@ export default {
if (!this.autoTrigger) {
return
}
uni.showLoading({
title: '加载中...',
})
this.getRegionSelect()
.then(selectedList => {
this.selectedList = selectedList
const area = selectedList.shift()
this.open(area)
})
.catch(() => {
uni.hideLoading()
})
this.init()
},
methods: {
init() {
uni.showLoading({
title: '加载中...',
})
this.getRegionSelect()
.then(selectedList => {
this.selectedList = selectedList
const area = selectedList.shift()
this.open(area)
})
.catch(() => {
this.$emit('success')
uni.hideLoading()
})
},
async getRegionSelect() {
return new Promise(async (resolve, reject) => {
try {
@ -125,7 +129,6 @@ export default {
.filter(key => res.data[key])
.filter(key => !res.data?.data?.[`${key}Data`])
.reverse()
console.log(needSelected, 'needSelected')
if (
needSelected?.length &&
Object.keys(res.data?.data || {}).length < needSelected?.length
@ -274,6 +277,7 @@ export default {
throw new Error(res.message || 'Failed to set region')
}
} catch (error) {
this.$emit('success')
console.error('Failed to set region:', error)
}
},

View File

@ -1,19 +1,30 @@
const http = uni.$u.http
//首页
export const userIndex = (params) => http.get('/sale/api/wares/get-app-index', { params })
export const userIndex = params =>
http.get('/sale/api/wares/get-app-index', { params })
//修改头像
export const updateHead = (data) => http.post('/member/api/member/update-head', data)
export const updateHead = data =>
http.post('/member/api/member/update-head', data)
//提货记录列表
export const pickList = (params) => http.get('/activity/api/pick/list', { params })
export const pickList = params =>
http.get('/activity/api/pick/list', { params })
//提货专区列表
export const pickLogList = (params) => http.get('/activity/api/pick/pick-log', { params })
export const pickLogList = params =>
http.get('/activity/api/pick/pick-log', { params })
//植树活动
export const queryTreeActivity = (params) => http.get('/activity/api/sa-tree-order/queryTreeActivity', { params })
export const queryTreeActivity = params =>
http.get('/activity/api/sa-tree-order/queryTreeActivity', { params })
//创客空间列表
export const marketList = (params) => http.get('/member/api/maker-space/list', { params })
export const marketList = params =>
http.get('/member/api/maker-space/list', { params })
export const getTopPeople = params =>
http.post('/member/api/member-statistics/topPeople', params)
export const getTopAmount = params =>
http.post('/member/api/member-statistics/topAmount', params)

View File

@ -57,7 +57,6 @@ module.exports = vm => {
// 响应拦截
uni.$u.http.interceptors.response.use(
response => {
console.log(response, '......response')
const data = response.data
// uni.$u.toast(data.msg)
// if (data.code == 200) {

View File

@ -27,6 +27,7 @@
</swiper>
</view>
</view>
<view class="goods-sort">
<view v-if="!newShareMember" class="goods-flexs">
<view v-for="(item, index) in recommendSpecialAreaList" :key="index">
@ -54,7 +55,7 @@
<div>
<!-- 公告弹窗 -->
<notice-popup
@getTree="getTree"
@close="noticePopupHandleClose"
:userInfo="userInfo"
ref="child"
:publishLocationIndex="10"
@ -67,11 +68,11 @@
ref="child2"
@childMethodTrigger="callChildMethod"
></znNewsPopup>
<!-- 直推排行弹窗
<directrank-popup
@callznMethodTrigger="callznMethod"
></directrank-popup>
-->
<!-- 直推排行弹窗 -->
<RankingPopup
ref="rankingPopup"
@onRankingComplete="handleRankingComplete"
/>
<u-modal
:show="promptFlag"
@ -87,7 +88,11 @@
></u-modal>
</div>
</view>
<RegionSelect v-if="userInfo.memberCode != 'BD68880628'" />
<RegionSelect
:autoTrigger="false"
ref="regionSelect"
@success="regionSelectSuccess"
/>
</view>
</template>
@ -107,6 +112,7 @@ import { mapGetters } from 'vuex'
import RegionSelect from '@/components/region-select/index.vue'
import RaisedTabbar from '@/components/raised-tabbar.vue'
import GoodsList from '@/components/goods-list.vue'
import RankingPopup from '@/components/RankingPopup.vue'
export default {
components: {
noticePopup,
@ -116,6 +122,7 @@ export default {
areaProductList,
RegionSelect,
GoodsList,
RankingPopup,
},
filters: {
seles(value) {
@ -128,6 +135,7 @@ export default {
},
data() {
return {
rankingComplete: false,
newShareMember: false,
promptFlag: false,
promptMsg: '',
@ -353,6 +361,7 @@ export default {
// this.getLanguage();
this.getService()
// this.showRankingPopups()
},
onShow() {
this.$store.dispatch('getCarLength')
@ -360,6 +369,10 @@ export default {
this.user = uni.getStorageSync('User')
this.getAreaGoods()
this.newShareMember = this.user?.loginType !== 0
if (this.user.memberCode !== 'BD68880628') {
console.log('init')
this.$refs.regionSelect.init()
}
})
},
onPullDownRefresh() {
@ -379,6 +392,33 @@ export default {
}
},
//
async showRankingPopups() {
try {
this.$nextTick(async () => {
await this.$refs.rankingPopup.showRankingPopups()
})
} catch (error) {
console.error('显示排行榜失败:', error)
uni.showToast({
title: '加载排行榜失败',
icon: 'error',
})
}
},
//
handleRankingComplete() {
this.rankingComplete = true
this.$refs.child.getUserTc()
},
regionSelectSuccess() {
if (this.rankingComplete) {
return
}
this.showRankingPopups()
},
goAreaUrl() {
ban.agreementName().then(res => {
if (res.data == 0) {
@ -450,15 +490,11 @@ export default {
}
})
},
callChildMethod() {
this.$refs.child.getUserTc()
},
callznMethod() {
this.$refs.child2.getUserTc2()
},
//
getTree() {
this.$refs.tree.getData()
noticePopupHandleClose() {
// this.$refs.regionSelect.getRegionSelect()
},
isEmpty(v) {
switch (typeof v) {
@ -619,6 +655,37 @@ export default {
height: 100%;
}
}
//
.ranking-entry {
padding: 20rpx 30rpx;
.ranking-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 25rpx;
padding: 20rpx 30rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.3);
.ranking-icon {
font-size: 32rpx;
margin-right: 12rpx;
}
.ranking-text {
color: #fff;
font-size: 28rpx;
font-weight: bold;
}
&:active {
transform: scale(0.98);
transition: transform 0.1s ease;
}
}
}
.content1 {
background: url('~@/static/images/fBgd.jpg') no-repeat;
background-size: 100% 100%;

View File

@ -20,7 +20,12 @@
<u-icon name="arrow-down"></u-icon>
</view>
</u-form-item> -->
<view v-if="(specialArea != 2 && specialArea != 25 && specialArea != 27) || newShareMember">
<view
v-if="
(specialArea != 2 && specialArea != 25 && specialArea != 27) ||
newShareMember
"
>
<u-form-item
:label="'会员编号'"
required
@ -43,7 +48,12 @@
</u-form-item>
</view>
<view v-if="(specialArea == 2 || specialArea == 25 || specialArea == 27) && !newShareMember">
<view
v-if="
(specialArea == 2 || specialArea == 25 || specialArea == 27) &&
!newShareMember
"
>
<u-form-item
:label="'升级编号'"
required
@ -54,6 +64,7 @@
v-model="form.upgradeMemberCode"
:disabled="isSpace"
border="none"
@blur="upgradeMemberCodeHandleCb"
/>
</u-form-item>
<u-form-item
@ -672,7 +683,7 @@ export default {
//
this.getAddressList()
this.newShareMember = uni.getStorageSync('User')?.loginType !== 0
if(this.newShareMember){
if (this.newShareMember) {
uni.setNavigationBarTitle({
title: '会员专区',
})
@ -693,22 +704,30 @@ export default {
}
},
getMember() {
let deleteList = []
this.shoppingArr.forEach(item => {
deleteList.push({
shoppingId: item,
return new Promise((resolve, reject) => {
let deleteList = []
this.shoppingArr.forEach(item => {
deleteList.push({
shoppingId: item,
})
})
})
this.allGoodsData.deleteList = deleteList
this.allGoodsData.upgradeMemberCode = this.form.upgradeMemberCode
this.allGoodsData.deleteList = deleteList
this.allGoodsData.upgradeMemberCode = this.form.upgradeMemberCode
api.memLevel(this.allGoodsData).then(res => {
if (res.data.isEnough) {
console.log(res.data, 'res.data...memLevel')
this.form.pkGradeVal = res.data.pkGradeVal
} else {
this.isLoading.close()
}
api
.memLevel(this.allGoodsData)
.then(res => {
if (res.data.isEnough) {
this.form.pkGradeVal = res.data.pkGradeVal
resolve()
} else {
this.isLoading.close()
reject()
}
})
.catch(err => {
reject(err)
})
})
},
addAdress() {
@ -827,34 +846,60 @@ export default {
// name
upgradeMemberCodePass(rule, value, callback) {
if (!value) {
callback(new Error('请输入会员编号'))
} else {
return callback(new Error('请输入会员编号'))
}
callback()
// else {
// api
// .upgRel({
// upgradeMemberCode: value,
// })
// .then(res => {
// if (res.code == 200) {
// this.form.upgradeMemberName = res.data.upgradeMemberName
// if (
// this.specialArea == 2 ||
// this.specialArea == 25 ||
// this.specialArea == 27
// ) {
// this.getMember()
// }
// this.$forceUpdate()
// callback()
// } else {
// callback(new Error(res.msg))
// }
// })
// .catch(err => {
// callback(new Error(err))
// })
// }
},
getMemberName(val) {
return new Promise((resolve, reject) => {
const promiseResolve = resolve
const promiseReject = reject
api
.upgRel({
upgradeMemberCode: value,
upgradeMemberCode: val || this.form.upgradeMemberCode,
})
.then(res => {
if (res.code == 200) {
if (res.code === 200) {
promiseResolve()
this.form.upgradeMemberName = res.data.upgradeMemberName
if (
this.specialArea == 2 ||
this.specialArea == 25 ||
this.specialArea == 27
) {
this.getMember()
}
this.$forceUpdate()
callback()
} else {
callback(new Error(res.msg))
promiseReject()
}
})
.catch(err => {
callback(new Error(err))
})
}
})
},
upgradeMemberCodeHandleCb(val) {
this.getMemberName(val).then(() => {
this.getMember()
})
},
sureCk(e) {
const { value } = e
this.form.pkStorehouse = value[0].id
@ -1017,16 +1062,8 @@ export default {
uni.setStorageSync('mToken', res.msg)
})
},
goBuy() {
this.$refs.uForm.validate().then(res => {
if (this.agreementShow.length == 0) {
uni.showToast({
title: '请阅读并同意购买协议',
icon: 'none',
duration: 1500,
})
return
}
async goBuy() {
this.$refs.uForm.validate().then(async res => {
if (this.specialArea == 31) {
if (this.totalAmont < 1000) {
uni.showToast({
@ -1038,6 +1075,14 @@ export default {
}
}
this.isLoading = true
try {
await this.getMemberName()
await this.getMember()
} catch (err) {
this.isLoading = false
return
}
let deleteList = []
this.shoppingArr.forEach(item => {
deleteList.push({

1
static/images/rank-1.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1758763283426" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1585" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="256"><path d="M144.304 429.375A371.701 371.701 0 1 0 516.006 57.553a371.701 371.701 0 0 0-371.702 371.701z" fill="#FFFFFF" p-id="1586"></path><path d="M284.347 509.666L57.057 889.589l138.988 27.798 92.67 106.553 227.29-379.953zM895.96 745.962l-138.99-236.296-236.295 129.743 227.02 379.923 92.639-106.553 138.989-27.798z m0 0" fill="#D9403C" p-id="1587"></path><path d="M284.347 509.666L163.88 708.888a473.616 473.616 0 0 0 231.658 138.99l125.106-208.5z m472.593 0L520.644 639.409l125.105 208.498a473.646 473.646 0 0 0 231.658-138.989z m0 0" fill="#B91C22" p-id="1588"></path><path d="M923.877 472.592a68.998 68.998 0 0 0 18.522-41.711 45.175 45.175 0 0 0-18.522-41.712 20.389 20.389 0 0 1-4.638-23.16 53.126 53.126 0 0 0 4.638-46.32 72.04 72.04 0 0 0-27.798-37.073c-4.638 0-9.276-9.276-4.638-18.522a80.11 80.11 0 0 0-4.638-46.32 72.07 72.07 0 0 0-37.074-27.797c-9.276 0-13.914-9.276-13.914-18.522a50.295 50.295 0 0 0-18.521-41.712 56.59 56.59 0 0 0-41.712-18.522c-9.276 0-13.914-4.638-18.522-13.914a72.04 72.04 0 0 0-27.798-37.073 54.813 54.813 0 0 0-46.32-4.638c-9.275 0-18.521 0-23.16-9.276a57.553 57.553 0 0 0-37.073-27.798 80.11 80.11 0 0 0-46.32 4.638c-9.275 4.638-18.521 4.638-23.16-4.638A68.998 68.998 0 0 0 511.278 0a258.673 258.673 0 0 0-37.074 23.16c-4.638 9.276-13.913 9.276-23.16 4.638a53.126 53.126 0 0 0-46.319-4.638 72.04 72.04 0 0 0-37.074 27.798 24.093 24.093 0 0 1-18.521 9.276 54.813 54.813 0 0 0-46.32 4.638 72.04 72.04 0 0 0-27.798 37.073c0 9.276-9.276 13.914-18.522 13.914a74.72 74.72 0 0 0-41.711 13.914 53.728 53.728 0 0 0-18.522 46.32c0 9.276-4.638 13.914-13.914 18.522a34.845 34.845 0 0 0-32.436 23.16 54.813 54.813 0 0 0-4.638 46.319c0 9.276 0 18.522-9.276 23.16a52.975 52.975 0 0 0-32.436 37.073 80.11 80.11 0 0 0 4.638 46.32c4.638 9.276 4.638 18.522-4.638 23.16a69.058 69.058 0 0 0-13.913 37.074 45.175 45.175 0 0 0 18.521 41.711 20.389 20.389 0 0 1 4.638 23.16 57.222 57.222 0 0 0-9.276 46.32 72.07 72.07 0 0 0 27.798 37.073c9.276 4.638 9.276 13.914 9.276 23.16a54.813 54.813 0 0 0 4.759 46.41 72.04 72.04 0 0 0 37.073 27.798c9.276 0 13.914 9.276 13.914 18.522a50.295 50.295 0 0 0 18.522 41.711 56.59 56.59 0 0 0 41.712 18.522c9.276 0 13.914 4.638 18.522 13.914a72.04 72.04 0 0 0 27.797 37.074 54.813 54.813 0 0 0 46.32 4.638c9.276 0 18.522 0 23.16 9.276a57.553 57.553 0 0 0 37.073 27.798 80.11 80.11 0 0 0 46.32-4.638 11.474 11.474 0 0 1 18.522-4.638 68.998 68.998 0 0 0 41.712 18.521 45.175 45.175 0 0 0 41.711-18.521 20.389 20.389 0 0 1 23.16-4.638 53.126 53.126 0 0 0 46.32 4.638 72.07 72.07 0 0 0 37.073-27.798c4.638-9.276 13.914-9.276 23.16-9.276a54.813 54.813 0 0 0 46.32-4.638 72.07 72.07 0 0 0 27.797-37.074c0-9.276 9.276-13.914 18.522-13.914a50.295 50.295 0 0 0 41.712-18.522 56.59 56.59 0 0 0 18.522-41.711c0-9.276 4.638-13.914 13.914-18.522a72.07 72.07 0 0 0 37.073-27.798 54.813 54.813 0 0 0 4.638-46.32c0-9.275 0-18.521 9.276-23.16a57.553 57.553 0 0 0 27.798-37.073 80.11 80.11 0 0 0-4.638-46.32c-13.914 4.638-9.276-4.638-4.638-13.914z m-361.401 138.99h-69.6v-250.18h-88.031v-46.32c23.16 0 37.073-4.638 46.32-4.638a93.121 93.121 0 0 0 37.073-18.522 75.292 75.292 0 0 0 13.914-27.798c0-4.638 4.638-9.276 4.638-13.914h60.233v361.401z m0 0" fill="#EEB317" p-id="1589"></path><path d="M516.036 55.355a363.54 363.54 0 0 1 264.094 111.19A371.49 371.49 0 0 1 891.32 430.64a363.54 363.54 0 0 1-111.19 264.093 371.49 371.49 0 0 1-264.094 111.192 363.54 363.54 0 0 1-264.094-111.192A371.49 371.49 0 0 1 140.75 430.64 379.742 379.742 0 0 1 516.036 55.355z m245.572 129.984a346.343 346.343 0 0 0-491.144-0.272 340.32 340.32 0 0 0-101.946 245.814 331.616 331.616 0 0 0 101.946 245.572 339.235 339.235 0 0 0 245.572 101.945 331.616 331.616 0 0 0 245.572-101.945 346.764 346.764 0 0 0 0-491.145z m0 0" fill="#FFFFFF" p-id="1590"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

1
static/images/rank-2.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 4.9 KiB

1
static/images/rank-3.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.2 KiB