Browse Source

‘优化页面内容’

master
Lj 3 weeks ago
parent
commit
37bbd05789
6 changed files with 260 additions and 125 deletions
  1. +1
    -1
      config.js
  2. +98
    -17
      pages/component/home.vue
  3. +72
    -18
      pages/component/recycle.vue
  4. +1
    -1
      pages/index/index.vue
  5. +83
    -87
      pages/subcomponent/promo-qrcode.vue
  6. +5
    -1
      wxcomponents/privacy-popup/privacy-popup.vue

+ 1
- 1
config.js View File

@ -1,5 +1,5 @@
// config.js
const type = 'local'
const type = 'prod'
const config = {
local: {


+ 98
- 17
pages/component/home.vue View File

@ -3,11 +3,33 @@
<!-- 顶部banner -->
<view class="banner">
<swiper :indicator-dots="false" :autoplay="true" :interval="3000" :duration="500" circular
style="width: 100%; height: 320rpx;">
style="width: 100%; height: 400rpx;">
<swiper-item v-for="(item, index) in bannerList" :key="item.id || index">
<video v-if="item.type == 1" :src="item.voUrl" autoplay muted loop :controls="false"
:show-play-btn="false" :show-center-play-btn="false" object-fit="cover"
style="width: 100%; height: 100%;"></video>
<view v-if="item.type == 1" class="video-container" @click="playVideo(item, index)">
<video
:id="`video-${index}`"
:src="item.voUrl"
:autoplay="false"
:muted="true"
:loop="false"
:controls="true"
:show-play-btn="true"
:show-center-play-btn="true"
:show-fullscreen-btn="true"
:enable-play-gesture="true"
object-fit="cover"
:poster="item.image || ''"
style="width: 100%; height: 100%;"
@fullscreenchange="onFullscreenChange"
@play="onVideoPlay(index)"
@pause="onVideoPause(index)"
></video>
<view v-if="!videoPlayingStates[index]" class="video-overlay">
<view class="play-button">
<uni-icons type="play-filled" size="60" color="#fff"></uni-icons>
</view>
</view>
</view>
<image v-else :src="item.image" mode="aspectFill" style="width: 100%; height: 100%;" />
</swiper-item>
</swiper>
@ -171,6 +193,7 @@
processes: [],
priceList: [],
records: [],
videoPlayingStates: {}, //
destinations: [
// {
// icon: '/static/home/.png',
@ -345,6 +368,30 @@
this.addressCion = address ? address.keyContent : '';
this.sbkCion = sbk ? sbk.keyContent : '';
},
//
playVideo(item, index) {
const videoContext = uni.createVideoContext(`video-${index}`, this);
if (this.videoPlayingStates[index]) {
//
videoContext.pause();
} else {
//
videoContext.play();
}
},
onVideoPlay(index) {
this.$set(this.videoPlayingStates, index, true);
},
onVideoPause(index) {
this.$set(this.videoPlayingStates, index, false);
},
onFullscreenChange(e) {
console.log('全屏状态改变:', e.detail);
},
//
initializePageData() {
const query = this.queryParams || {}
@ -425,7 +472,7 @@
.banner {
width: 100%;
height: 330rpx;
height: 400rpx;
position: relative;
overflow: hidden;
border-radius: 0 0 30rpx 30rpx;
@ -434,12 +481,43 @@
width: 100%;
height: 100%;
}
.video-container {
position: relative;
width: 100%;
height: 100%;
.video-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
.play-button {
width: 120rpx;
height: 120rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
backdrop-filter: blur(10rpx);
}
}
}
}
.content {
// flex: 1;
width: 90%;
margin: -70rpx auto 0;
margin: -80rpx auto 0;
position: relative;
z-index: 3;
padding-bottom: 20rpx;
@ -672,39 +750,42 @@
background-color: #fff8ea;
.item-icon {
width: 100rpx;
height: 100rpx;
margin-bottom: 10rpx;
width: 120rpx;
height: 120rpx;
margin-bottom: 12rpx;
&.placeholder {
width: 80rpx;
height: 80rpx;
margin-bottom: 10rpx;
width: 120rpx;
height: 120rpx;
margin-bottom: 12rpx;
background: #f5f5f5;
border-radius: 16rpx;
}
}
.item-name {
font-size: 26rpx;
font-size: 30rpx;
color: #333;
margin-bottom: 6rpx;
margin-bottom: 8rpx;
font-weight: 500;
}
.item-price {
font-family: PingFang SC;
font-weight: 400;
font-size: 24rpx;
font-weight: 600;
font-size: 28rpx;
line-height: 140%;
letter-spacing: 0%;
text-align: center;
color: #181818;
.item-price-right {
text-align: center;
font-size: 24rpx;
font-size: 26rpx;
color: #666;
line-height: 140%;
letter-spacing: 0%;
font-weight: 400;
}
}
}


+ 72
- 18
pages/component/recycle.vue View File

@ -250,16 +250,15 @@
</view>
<!-- 回收规则弹窗 -->
<view v-if="showRulePopup" class="rule-popup-mask" @click.self="closeRulePopup">
<view v-if="showRulePopup" class="rule-popup-mask" @click.self="handleRulePopupMaskClick">
<view class="rule-popup">
<view class="rule-popup-title">回收规则</view>
<scroll-view class="rule-popup-content" scroll-y>
<scroll-view class="rule-popup-content" scroll-y @scroll="onRuleContentScroll">
<uv-parse :content="ruleHtml"></uv-parse>
<view class="rule-content-bottom-indicator"></view>
</scroll-view>
<button class="rule-popup-btn" @click="closeRulePopup">我知道了</button>
<!-- <view class="rule-popup-close" @tap="closeRulePopup">
<uni-icons type="close" size="36" color="#fff" />
</view> -->
<view v-if="!hasScrolledToBottom" class="scroll-tip">请滚动到底部阅读完整内容</view>
<button class="rule-popup-btn" :class="{ disabled: !hasScrolledToBottom }" @click="closeRulePopup">我知道了</button>
</view>
</view>
@ -361,6 +360,7 @@ export default {
isUserBlacklisted: false, //
currentProductId: null, // ID
searchTimer: null, //
hasScrolledToBottom: false, //
}
},
computed: {
@ -664,6 +664,9 @@ export default {
return;
}
//
this.hasScrolledToBottom = false;
//
this.$api('getGoodsRecycleRule', { goodsId: item.id }, res => {
if (res.code === 200 && res.result) {
@ -692,16 +695,9 @@ export default {
return
}
if (this.totalCount < 3) {
if (this.totalCount < 3 || Number(this.totalPrice) < this.minMoney) {
uni.showToast({
title: `各品类混合需要满3${this.totalUnitText}才能回收哦`,
icon: 'none'
})
return
}
if (Number(this.totalPrice) < this.minMoney) {
uni.showToast({
title: `回收总价需满${this.minMoney}元才能预约`,
title: `各品类混合需要满3${this.totalUnitText}并且各品类混合需要满${this.minMoney}元才能回收哦`,
icon: 'none'
})
return
@ -874,7 +870,18 @@ export default {
this.showRulePopup = true
},
closeRulePopup() {
//
if (!this.hasScrolledToBottom) {
uni.showToast({
title: '请阅读完整回收规则',
icon: 'none'
})
return
}
this.showRulePopup = false;
this.hasScrolledToBottom = false; //
//
if (this.isWaitingForBrandSelection) {
this.isWaitingForBrandSelection = false; //
@ -888,6 +895,29 @@ export default {
this.showBrandPopup = true; //
}
},
//
handleRulePopupMaskClick() {
if (!this.hasScrolledToBottom) {
uni.showToast({
title: '请阅读完整回收规则',
icon: 'none'
})
return
}
this.closeRulePopup()
},
//
onRuleContentScroll(e) {
const { scrollTop, scrollHeight, deltaY } = e.detail
const containerHeight = 500 // rpxpx
//
if (scrollTop + containerHeight >= scrollHeight - 20) {
this.hasScrolledToBottom = true
}
},
loadMoreGoods() {
const categoryId = this.categories[this.currentCategory]?.id
const page = (this.allProductsPage[categoryId] || 1) + 1
@ -1951,8 +1981,9 @@ export default {
justify-content: center;
}
.rule-popup {
width: 90vw;
max-width: 600rpx;
width: 95vw;
max-width: 750rpx;
max-height: 85vh;
background: #fff;
border-radius: 48rpx;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.12);
@ -1972,7 +2003,8 @@ export default {
}
.rule-popup-content {
width: 100%;
max-height: 420rpx;
max-height: 60vh;
min-height: 400rpx;
padding: 0 40rpx;
box-sizing: border-box;
overflow-y: auto;
@ -1983,6 +2015,21 @@ export default {
display: none; /* Chrome, Safari, Opera */
}
}
.rule-content-bottom-indicator {
height: 20rpx;
width: 100%;
}
.scroll-tip {
font-size: 24rpx;
color: #ff6b35;
text-align: center;
margin: 16rpx 0 8rpx 0;
animation: tipPulse 2s infinite;
}
@keyframes tipPulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
.rule-popup-desc {
font-size: 26rpx;
color: #888;
@ -2025,12 +2072,19 @@ export default {
margin: 0 auto;
margin-top: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
transition: all 0.3s ease;
&::after {
border: none;
}
&:active {
opacity: 0.9;
}
&.disabled {
background: #ccc;
color: #999;
box-shadow: none;
opacity: 0.6;
}
}
.rule-popup-close {
position: absolute;


+ 1
- 1
pages/index/index.vue View File

@ -36,7 +36,7 @@
<!-- <view class="admin-login" @click="goToAdminLogin">管理员登录</view> -->
<PrivacyPopup ref="privacyPopup" :needPhone="needPhone" @agree="handleAgreePrivacy"
<PrivacyPopup ref="privacyPopup" :needPhone="needPhone" :appName="logoName" @agree="handleAgreePrivacy"
@reject="handleRejectPrivacy" @open-protocol="openProtocol" />
<ProtocolDialog ref="protocolDialog" :show="showProtocolDialog" :title="protocolDialogTitle"
:content="protocolDialogContent" @close="showProtocolDialog = false" @agree="handleProtocolAgree"


+ 83
- 87
pages/subcomponent/promo-qrcode.vue View File

@ -1,33 +1,32 @@
<template>
<view class="promo-modal-page">
<!-- 顶部导航栏 -->
<view class="nav-bar" :style="{height: navBarTotalHeight + 'px', paddingTop: statusBarHeight + 'px'}">
<view class="nav-bar-inner">
<view class="back-icon" @tap="navigateBack">
<uni-icons type="left" size="22" color="#222" />
</view>
<view class="nav-bar-title">推广链接</view>
<view class="nav-bar-right">
<uni-icons type="more-filled" size="22" color="#222" />
</view>
<view class="nav-bar">
<view class="back" @tap="navigateBack">
<uni-icons type="left" size="20" />
</view>
<text class="title">推广链接</text>
</view>
<!-- 用户信息 -->
<view class="user-info-modal" :style="{ marginTop: navBarTotalHeight + 'px' }">
<view class="avatar-frame">
<image class="avatar-img" :src="userInfo.avatar" mode="aspectFill" />
<!-- 页面内容 -->
<view class="content">
<!-- 用户信息 -->
<view class="user-info-modal">
<view class="avatar-frame">
<image class="avatar-img" :src="userInfo.headImage || '/static/avatar.png'" mode="aspectFill" />
</view>
<view class="nickname">{{userInfo.nickName || '用户'}}</view>
</view>
<!-- 二维码区 -->
<view class="qrcode-modal-section">
<image class="qrcode-img" :src="qrcodeUrl" mode="widthFix" />
<!-- <view class="invite-code">邀请码{{inviteCode}}</view> -->
</view>
<!-- 底部按钮 -->
<view class="bottom-btns-modal">
<button class="btn gray" open-type="share">分享给好友</button>
<button class="btn green" @tap="saveToAlbum">保存到本地</button>
</view>
<view class="nickname">{{userInfo.name}}</view>
</view>
<!-- 二维码区 -->
<view class="qrcode-modal-section">
<image class="qrcode-img" :src="qrcodeUrl" mode="widthFix" />
<!-- <view class="invite-code">邀请码{{inviteCode}}</view> -->
</view>
<!-- 底部按钮 -->
<view class="bottom-btns-modal">
<button class="btn gray" open-type="share">分享给好友</button>
<button class="btn green" @tap="saveToAlbum">保存到本地</button>
</view>
</view>
</template>
@ -40,37 +39,28 @@
mixins: [pullRefreshMixin],
data() {
return {
statusBarHeight: 0,
navBarHeight: 44,
navBarTotalHeight: 44,
userInfo: {
avatar: '/static/avatar.png',
name: '战斗世界',
},
userInfo: {},
qrcodeUrl: '/static/qrcode.png',
inviteCode: '888888',
}
},
onLoad() {
const sysInfo = uni.getSystemInfoSync()
this.statusBarHeight = sysInfo.statusBarHeight
this.navBarHeight = 44
this.navBarTotalHeight = this.statusBarHeight + this.navBarHeight
//
//
this.fetchUserInfo()
this.getQrcode()
},
//
// #ifdef MP-WEIXIN
onShareAppMessage() {
return {
title: `${this.userInfo.name}邀请您一起参与旧衣回收`,
title: `${this.userInfo.nickName || '用户'}邀请您一起参与旧衣回收`,
path: `/pages/component/home?shareId=${this.inviteCode}`,
imageUrl: this.qrcodeUrl || '/static/share-default.png'
}
},
onShareTimeline() {
return {
title: `${this.userInfo.name}邀请您一起参与旧衣回收,环保从我做起!`,
title: `${this.userInfo.nickName || '用户'}邀请您一起参与旧衣回收,环保从我做起!`,
query: `shareId=${this.inviteCode}`,
imageUrl: this.qrcodeUrl || '/static/share-default.png'
}
@ -85,6 +75,21 @@
navigateBack() {
uni.navigateBack()
},
//
fetchUserInfo() {
if (uni.getStorageSync('token')) {
this.$api("getUserByToken", {}, (res) => {
if (res.code == 200) {
this.userInfo = res.result
//
if (res.result.intentioCode) {
this.inviteCode = res.result.intentioCode
}
}
})
}
},
getQrcode(){
//
if (getApp().globalData.qr_path) {
@ -171,64 +176,55 @@
<style lang="scss" scoped>
.promo-modal-page {
min-height: 100vh;
background: linear-gradient(to bottom, #f6fff2 0%, #fff 100%);
background: #f8f8f8;
padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
overflow: hidden;
height: 100vh;
}
.nav-bar {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
.nav-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
width: 100vw;
background: linear-gradient(to right, #b2f08d 0%, #39e9d2 100%);
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.03);
height: calc(150rpx + var(--status-bar-height));
padding: 0 32rpx;
padding-top: var(--status-bar-height);
background: #fff;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
box-sizing: border-box;
.nav-bar-inner {
display: flex;
align-items: center;
height: 44px;
width: 100vw;
position: relative;
}
.back-icon,
.nav-bar-right {
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
}
.back-icon {
left: 0;
}
.nav-bar-right {
right: 0;
}
.back {
padding: 20rpx;
margin-left: -20rpx;
}
.nav-bar-title {
flex: 1;
text-align: center;
font-size: 36rpx;
font-weight: bold;
color: #222;
letter-spacing: 2rpx;
line-height: 44px;
}
.title {
flex: 1;
text-align: center;
font-size: 34rpx;
font-weight: 500;
color: #222;
}
}
.content {
padding: 30rpx 0 0 0;
margin-top: calc(150rpx + var(--status-bar-height) + 80rpx);
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
overflow: hidden;
box-sizing: border-box;
.user-info-modal {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 48rpx;
.avatar-frame {
width: 104rpx;
@ -256,11 +252,11 @@
}
.qrcode-modal-section {
margin-top: 48rpx;
width: 300rpx;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 48rpx;
.qrcode-img {
width: 100%;


+ 5
- 1
wxcomponents/privacy-popup/privacy-popup.vue View File

@ -6,7 +6,7 @@
<!-- 内容 -->
<view class="popup-content">
在你使用瀚海回收服务之前请仔细阅读
在你使用{{ appName || '瀚海回收' }}服务之前请仔细阅读
<text class="highlight" @click="openProtocol('service')">用户服务协议</text>
<text class="highlight" @click="openProtocol('privacy')">隐私政策</text>
@ -39,6 +39,10 @@ export default {
needPhone: {
type: Boolean,
default: false
},
appName: {
type: String,
default: '瀚海回收'
}
},
methods: {


Loading…
Cancel
Save