Browse Source

refactor(分享模块): 移除冗余的日志记录调用并优化代码格式

移除 `this.$fetch('addLogShareInfo', params)` 的调用,改用 `shareLog.insert(this.id)` 来记录分享日志。同时,统一了代码格式,提升了代码的可读性和维护性。
master
前端-胡立永 2 months ago
parent
commit
6aae5409b1
4 changed files with 617 additions and 557 deletions
  1. +1
    -1
      pages_order/sharing/article.vue
  2. +218
    -202
      pages_order/sharing/group.vue
  3. +212
    -196
      pages_order/sharing/personal.vue
  4. +186
    -158
      pages_order/sharing/video.vue

+ 1
- 1
pages_order/sharing/article.vue View File

@ -111,7 +111,7 @@
id: this.id, id: this.id,
state: "3", state: "3",
} }
this.$fetch('addLogShareInfo', params)
// this.$fetch('addLogShareInfo', params)
shareLog.insert(this.id) shareLog.insert(this.id)


+ 218
- 202
pages_order/sharing/group.vue View File

@ -1,234 +1,250 @@
<template> <template>
<view class="page">
<view class="page">
<navbar leftClick @leftClick="$utils.navigateBack" /> <navbar leftClick @leftClick="$utils.navigateBack" />
<view class="content">
<image class="avatar" :src="detail.headImage"></image>
<text class="nick-name">{{ `${detail.headTitle || ''}${detail.memberNum || 0}` }}</text>
<view class="content">
<image class="avatar" :src="detail.headImage"></image>
<text class="nick-name">{{ `${detail.headTitle || ''}${detail.memberNum || 0}` }}</text>
<template v-if="isLocked">
<button class="btn" type="success" @click="onAdd">加入</button>
</template>
<view v-else class="group-info flex">
<text>扫一扫加群主审核进群</text>
<image class="qr" :src="detail.wxCodeImage" :show-menu-by-longpress="true"></image>
</view>
</view>
<template v-if="isLocked">
<button class="btn" type="success" @click="onAdd">加入</button>
</template>
<view v-else class="group-info flex">
<text>扫一扫加群主审核进群</text>
<image class="qr" :src="detail.wxCodeImage" :show-menu-by-longpress="true"></image>
</view>
</view>
<popupUnlock ref="popupUnlock" src="../static/sharing/unlock-group.png"></popupUnlock>
<popupUnlock ref="popupUnlock" src="../static/sharing/unlock-group.png"></popupUnlock>
</view>
</view>
</template> </template>
<script> <script>
import { mapState } from 'vuex'
import shareLog from '@/utils/shareLog'
import {
mapState
} from 'vuex'
import shareLog from '@/utils/shareLog'
import popupUnlock from '../components/popupUnlock.vue'
import popupUnlock from '../components/popupUnlock.vue'
export default { export default {
components: {
popupUnlock,
},
components: {
popupUnlock,
},
data() { data() {
return { return {
id: null,
detail: {
id: null,
avatarUrl: null,
nickName: null,
imageUrl: null,
times: 0,
qrCode: null,
description: null,
},
isLocked: true,
}
},
id: null,
detail: {
id: null,
avatarUrl: null,
nickName: null,
imageUrl: null,
times: 0,
qrCode: null,
description: null,
},
isLocked: true,
}
},
computed: { computed: {
...mapState(['userInfo']), ...mapState(['userInfo']),
}, },
onShow() {
// if (this.id && uni.getStorageSync('token')) {
// this.detail.id ? this.refreshLockStatus() : this.fetchDetails()
// }
if (this.detail.id) { //
this.refreshLockStatus()
}
},
onLoad(option) {
const { id, state, shareId } = option
onShow() {
// if (this.id && uni.getStorageSync('token')) {
// this.detail.id ? this.refreshLockStatus() : this.fetchDetails()
// }
if (this.detail.id) { //
this.refreshLockStatus()
}
},
onLoad(option) {
const {
id,
state,
shareId
} = option
if (shareId) { if (shareId) {
uni.setStorageSync('shareId', shareId) uni.setStorageSync('shareId', shareId)
} }
if (state) { if (state) {
uni.setStorageSync('state', state) uni.setStorageSync('state', state)
} }
if (id) { if (id) {
uni.setStorageSync('id', id) uni.setStorageSync('id', id)
} }
this.id = id
// if (uni.getStorageSync('token')) {
// this.fetchDetails()
// } else {
// uni.navigateTo({
// url: '/pages_order/auth/wxLogin'
// })
// }
this.fetchDetails()
},
onShareAppMessage(res) {
const {
textDetails,
indexImage,
} = this.detail
let o = {
title : textDetails,
imageUrl: indexImage,
query: `id=${this.id}&state=2&shareId=${this.userInfo.id}`,
}
//
const params = {
id:this.id,
state:"2",
}
this.$fetch('addLogShareInfo', params)
shareLog.insert(this.id)
return o
},
methods: {
async fetchDetails() {
try {
this.detail = await this.$fetch('getGroupShareInfo', { id: this.id })
} catch (err) {
}
},
async fetchCheckShare() {
try {
return await shareLog.check(this.id, this.detail.num)
} catch (err) {
return {}
}
},
async refreshLockStatus() {
const result = await this.fetchCheckShare()
const { title, open } = result
console.log('--open', open)
this.$refs.popupUnlock.close();
if (open) {
this.isLocked = false
return
}
title && uni.showToast({
title,
icon: 'none',
duration: 3000
})
},
openPopup() {
this.$refs.popupUnlock.open();
},
async onAdd() {
const result = await this.fetchCheckShare()
const { open, need_num, num } = result
console.log('--open', open)
if (open) { //
this.isLocked = false
return
}
uni.showToast({
title: `还需转发${need_num - num}`,
icon: 'none',
})
this.openPopup()
}
},
}
this.id = id
// if (uni.getStorageSync('token')) {
// this.fetchDetails()
// } else {
// uni.navigateTo({
// url: '/pages_order/auth/wxLogin'
// })
// }
this.fetchDetails()
},
onShareAppMessage(res) {
const {
textDetails,
indexImage,
} = this.detail
let o = {
title: textDetails,
imageUrl: indexImage,
query: `id=${this.id}&state=2&shareId=${this.userInfo.id}`,
}
//
const params = {
id: this.id,
state: "2",
}
// this.$fetch('addLogShareInfo', params)
shareLog.insert(this.id)
return o
},
methods: {
async fetchDetails() {
try {
this.detail = await this.$fetch('getGroupShareInfo', {
id: this.id
})
} catch (err) {
}
},
async fetchCheckShare() {
try {
return await shareLog.check(this.id, this.detail.num)
} catch (err) {
return {}
}
},
async refreshLockStatus() {
const result = await this.fetchCheckShare()
const {
title,
open
} = result
console.log('--open', open)
this.$refs.popupUnlock.close();
if (open) {
this.isLocked = false
return
}
title && uni.showToast({
title,
icon: 'none',
duration: 3000
})
},
openPopup() {
this.$refs.popupUnlock.open();
},
async onAdd() {
const result = await this.fetchCheckShare()
const {
open,
need_num,
num
} = result
console.log('--open', open)
if (open) { //
this.isLocked = false
return
}
uni.showToast({
title: `还需转发${need_num - num}`,
icon: 'none',
})
this.openPopup()
}
},
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.page {
position: relative;
height: 100vh;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
}
.avatar {
width: 180rpx;
height: 180rpx;
margin-top: 127rpx;
}
.nick-name {
color: #1B1B1B;
font-size: 32rpx;
margin-top: 30rpx;
}
.desc {
margin-top: 30rpx;
}
.btn, .group-info {
position: absolute;
}
.btn {
width: calc(100% - 60rpx*2);
height: auto;
left: 60rpx;
bottom: 292rpx;
background-color: #07C160;
border: none;
color: #FFFFFF;
font-size: 28rpx;
line-height: 1;
border-radius: 45rpx;
padding: 25rpx 0;
box-sizing: border-box;
}
.group-info {
bottom: 269rpx;
flex-direction: column;
color: #1B1B1B;
font-size: 32rpx;
}
.qr {
margin-top: 40rpx;
width: 350rpx;
height: 350rpx;
}
.page {
position: relative;
height: 100vh;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
}
.avatar {
width: 180rpx;
height: 180rpx;
margin-top: 127rpx;
}
.nick-name {
color: #1B1B1B;
font-size: 32rpx;
margin-top: 30rpx;
}
.desc {
margin-top: 30rpx;
}
.btn,
.group-info {
position: absolute;
}
.btn {
width: calc(100% - 60rpx*2);
height: auto;
left: 60rpx;
bottom: 292rpx;
background-color: #07C160;
border: none;
color: #FFFFFF;
font-size: 28rpx;
line-height: 1;
border-radius: 45rpx;
padding: 25rpx 0;
box-sizing: border-box;
}
.group-info {
bottom: 269rpx;
flex-direction: column;
color: #1B1B1B;
font-size: 32rpx;
}
.qr {
margin-top: 40rpx;
width: 350rpx;
height: 350rpx;
}
</style> </style>

+ 212
- 196
pages_order/sharing/personal.vue View File

@ -1,228 +1,244 @@
<template> <template>
<view class="page">
<view class="page">
<navbar leftClick @leftClick="$utils.navigateBack" /> <navbar leftClick @leftClick="$utils.navigateBack" />
<view class="content">
<image class="avatar" :src="detail.headImage"></image>
<text class="nick-name">{{ detail.headTitle || '' }}</text>
<view class="content">
<image class="avatar" :src="detail.headImage"></image>
<text class="nick-name">{{ detail.headTitle || '' }}</text>
<template v-if="isLocked">
<button class="btn" type="success" @click="onAdd">添加</button>
</template>
<view v-else class="flex flex-column qr-popup">
<text class="tips">长按识别二维码了解更多内容</text>
<image class="qr" :src="detail.wxCodeImage" :show-menu-by-longpress="true"></image>
</view>
</view>
<template v-if="isLocked">
<button class="btn" type="success" @click="onAdd">添加</button>
</template>
<view v-else class="flex flex-column qr-popup">
<text class="tips">长按识别二维码了解更多内容</text>
<image class="qr" :src="detail.wxCodeImage" :show-menu-by-longpress="true"></image>
</view>
</view>
<popupUnlock ref="popupUnlock" src="../static/sharing/unlock-user.png"></popupUnlock>
<popupUnlock ref="popupUnlock" src="../static/sharing/unlock-user.png"></popupUnlock>
</view>
</view>
</template> </template>
<script> <script>
import { mapState } from 'vuex'
import shareLog from '@/utils/shareLog'
import {
mapState
} from 'vuex'
import shareLog from '@/utils/shareLog'
import popupUnlock from '../components/popupUnlock.vue'
import popupUnlock from '../components/popupUnlock.vue'
export default { export default {
components: {
popupUnlock,
},
components: {
popupUnlock,
},
data() { data() {
return { return {
id: null,
detail: {
id: null,
userId: null,
headImage: null,
headTitle: null,
indexImage: null,
num: 0,
wxCodeImage: null,
textDetails: null,
},
isLocked: true,
}
},
id: null,
detail: {
id: null,
userId: null,
headImage: null,
headTitle: null,
indexImage: null,
num: 0,
wxCodeImage: null,
textDetails: null,
},
isLocked: true,
}
},
computed: { computed: {
...mapState(['userInfo']), ...mapState(['userInfo']),
}, },
onShow() {
// if (this.id && uni.getStorageSync('token')) {
// this.detail.id ? this.refreshLockStatus() : this.fetchDetails()
// }
if (this.detail.id) { //
this.refreshLockStatus()
}
},
onLoad(option) {
const { id, state, shareId } = option
onShow() {
// if (this.id && uni.getStorageSync('token')) {
// this.detail.id ? this.refreshLockStatus() : this.fetchDetails()
// }
if (this.detail.id) { //
this.refreshLockStatus()
}
},
onLoad(option) {
const {
id,
state,
shareId
} = option
if (shareId) { if (shareId) {
uni.setStorageSync('shareId', shareId) uni.setStorageSync('shareId', shareId)
} }
if (state) { if (state) {
uni.setStorageSync('state', state) uni.setStorageSync('state', state)
} }
if (id) { if (id) {
uni.setStorageSync('id', id) uni.setStorageSync('id', id)
} }
this.id = id
// if (uni.getStorageSync('token')) {
// this.fetchDetails()
// } else {
// uni.navigateTo({
// url: '/pages_order/auth/wxLogin'
// })
// }
this.fetchDetails()
},
onShareAppMessage(res) {
const {
textDetails,
indexImage,
} = this.detail
let o = {
title : textDetails,
imageUrl: indexImage,
query: `id=${this.id}&state=0&shareId=${this.userInfo.id}`,
}
//
const params = {
id:this.id,
state:"0",
}
this.$fetch('addLogShareInfo', params)
shareLog.insert(this.id)
return o
},
methods: {
async fetchDetails() {
try {
this.detail = await this.$fetch('getShareInfo', { id: this.id })
} catch (err) {
}
},
async fetchCheckShare() {
try {
return await shareLog.check(this.id, this.detail.num)
} catch (err) {
return {}
}
},
async refreshLockStatus() {
const result = await this.fetchCheckShare()
const { title, open } = result
console.log('--open', open)
this.$refs.popupUnlock.close();
if (open) {
this.isLocked = false
return
}
title && uni.showToast({
title,
icon: 'none',
duration: 3000
})
},
openPopup() {
this.$refs.popupUnlock.open();
},
async onAdd() {
const result = await this.fetchCheckShare()
const { open, need_num, num } = result
console.log('--open', open)
if (open) { //
this.isLocked = false
return
}
uni.showToast({
title: `还需转发${need_num - num}`,
icon: 'none',
})
this.openPopup()
}
},
}
this.id = id
// if (uni.getStorageSync('token')) {
// this.fetchDetails()
// } else {
// uni.navigateTo({
// url: '/pages_order/auth/wxLogin'
// })
// }
this.fetchDetails()
},
onShareAppMessage(res) {
const {
textDetails,
indexImage,
} = this.detail
let o = {
title: textDetails,
imageUrl: indexImage,
query: `id=${this.id}&state=0&shareId=${this.userInfo.id}`,
}
//
const params = {
id: this.id,
state: "0",
}
// this.$fetch('addLogShareInfo', params)
shareLog.insert(this.id)
return o
},
methods: {
async fetchDetails() {
try {
this.detail = await this.$fetch('getShareInfo', {
id: this.id
})
} catch (err) {
}
},
async fetchCheckShare() {
try {
return await shareLog.check(this.id, this.detail.num)
} catch (err) {
return {}
}
},
async refreshLockStatus() {
const result = await this.fetchCheckShare()
const {
title,
open
} = result
console.log('--open', open)
this.$refs.popupUnlock.close();
if (open) {
this.isLocked = false
return
}
title && uni.showToast({
title,
icon: 'none',
duration: 3000
})
},
openPopup() {
this.$refs.popupUnlock.open();
},
async onAdd() {
const result = await this.fetchCheckShare()
const {
open,
need_num,
num
} = result
console.log('--open', open)
if (open) { //
this.isLocked = false
return
}
uni.showToast({
title: `还需转发${need_num - num}`,
icon: 'none',
})
this.openPopup()
}
},
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.page {
position: relative;
height: 100vh;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
}
.avatar {
width: 180rpx;
height: 180rpx;
margin-top: 127rpx;
}
.nick-name {
color: #1B1B1B;
font-size: 32rpx;
margin-top: 30rpx;
}
.btn, .qr-popup {
position: absolute;
}
.btn {
width: calc(100% - 60rpx*2);
height: auto;
left: 60rpx;
bottom: 292rpx;
background-color: #07C160;
border: none;
color: #FFFFFF;
font-size: 28rpx;
line-height: 1;
border-radius: 45rpx;
padding: 25rpx 0;
box-sizing: border-box;
}
.qr-popup {
width: 100vw;
bottom: 269rpx;
.tips {
color: #1B1B1B;
font-size: 32rpx;
}
}
.qr {
margin-top: 40rpx;
width: 350rpx;
height: 350rpx;
}
.page {
position: relative;
height: 100vh;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
}
.avatar {
width: 180rpx;
height: 180rpx;
margin-top: 127rpx;
}
.nick-name {
color: #1B1B1B;
font-size: 32rpx;
margin-top: 30rpx;
}
.btn,
.qr-popup {
position: absolute;
}
.btn {
width: calc(100% - 60rpx*2);
height: auto;
left: 60rpx;
bottom: 292rpx;
background-color: #07C160;
border: none;
color: #FFFFFF;
font-size: 28rpx;
line-height: 1;
border-radius: 45rpx;
padding: 25rpx 0;
box-sizing: border-box;
}
.qr-popup {
width: 100vw;
bottom: 269rpx;
.tips {
color: #1B1B1B;
font-size: 32rpx;
}
}
.qr {
margin-top: 40rpx;
width: 350rpx;
height: 350rpx;
}
</style> </style>

+ 186
- 158
pages_order/sharing/video.vue View File

@ -1,189 +1,217 @@
<template> <template>
<view class="page">
<view class="page">
<navbar leftClick @leftClick="$utils.navigateBack" /> <navbar leftClick @leftClick="$utils.navigateBack" />
<view class="content">
<video class="video"
id="video"
:src="detail.vio"
autoplay
play-btn-position="center"
:controls="!timeIsUp"
:show-fullscreen-btn="false"
:show-center-play-btn="true"
@timeupdate="onTimeupdate"
@ended="onTimeEnd"
></video>
<view class="info">
<view class="author">{{ detail.author || '' }}</view>
<view class="title">{{ detail.headTitle || '' }}</view>
<view class="desc">{{ detail.textDetails || '' }}</view>
</view>
</view>
<uv-overlay :show="timeIsUp" @click="onPlay" zIndex="998">
<popupUnlock ref="popupUnlock" src="../static/sharing/unlock-video.png"></popupUnlock>
</uv-overlay>
<popupQrCode ref="popupQrCode" :src="detail.wxCodeImage"></popupQrCode>
</view>
<view class="content">
<video class="video" id="video" :src="detail.vio" autoplay play-btn-position="center" :controls="!timeIsUp"
:show-fullscreen-btn="false" :show-center-play-btn="true" @timeupdate="onTimeupdate"
@ended="onTimeEnd"></video>
<view class="info">
<view class="author">{{ detail.author || '' }}</view>
<view class="title">{{ detail.headTitle || '' }}</view>
<view class="desc">{{ detail.textDetails || '' }}</view>
</view>
</view>
<uv-overlay :show="timeIsUp" @click="onPlay" zIndex="998">
<popupUnlock ref="popupUnlock" src="../static/sharing/unlock-video.png"></popupUnlock>
</uv-overlay>
<popupQrCode ref="popupQrCode" :src="detail.wxCodeImage"></popupQrCode>
</view>
</template> </template>
<script> <script>
import { mapState } from 'vuex'
import {
mapState
} from 'vuex'
import popupUnlock from '../components/popupUnlock.vue'
import popupQrCode from '../components/popupQrCode.vue'
import popupUnlock from '../components/popupUnlock.vue'
import popupQrCode from '../components/popupQrCode.vue'
export default { export default {
components: {
popupUnlock,
popupQrCode,
},
components: {
popupUnlock,
popupQrCode,
},
data() { data() {
return { return {
id: null,
detail: {
id: null,
headTitle: null,
indexImage: null,
vio: null,
timeNum: 0,
num: 0,
wxCodeImage: null,
textDetails: null,
},
timeIsUp: false,
isLocked: true,
videoContext: null,
}
},
id: null,
detail: {
id: null,
headTitle: null,
indexImage: null,
vio: null,
timeNum: 0,
num: 0,
wxCodeImage: null,
textDetails: null,
},
timeIsUp: false,
isLocked: true,
videoContext: null,
}
},
computed: { computed: {
...mapState(['userInfo']), ...mapState(['userInfo']),
}, },
onShow() {
// if (this.id && uni.getStorageSync('token')) {
// this.detail.id ? this.refreshLockStatus() : this.initData()
// }
if (this.detail.id) { //
this.refreshLockStatus()
}
},
async onLoad(option) {
const { id, state, shareId } = option
onShow() {
// if (this.id && uni.getStorageSync('token')) {
// this.detail.id ? this.refreshLockStatus() : this.initData()
// }
if (this.detail.id) { //
this.refreshLockStatus()
}
},
async onLoad(option) {
const {
id,
state,
shareId
} = option
if (shareId) { if (shareId) {
uni.setStorageSync('shareId', shareId) uni.setStorageSync('shareId', shareId)
} }
if (state) { if (state) {
uni.setStorageSync('state', state) uni.setStorageSync('state', state)
} }
if (id) { if (id) {
uni.setStorageSync('id', id) uni.setStorageSync('id', id)
} }
this.id = id
// if(uni.getStorageSync('token')){
// this.initData()
// }else{
// uni.navigateTo({
// url: '/pages_order/auth/wxLogin'
// })
// }
this.initData()
},
onShareAppMessage(res) {
const {
headTitle,
indexImage,
} = this.detail
let o = {
title : headTitle,
imageUrl: indexImage,
query: `id=${this.id}&state=1&shareId=${this.userInfo.id}`,
}
//
const params = {
id:this.id,
state:"1",
}
this.$fetch('addLogShareInfo', params)
return o
},
methods: {
async fetchDetails(id) {
try {
this.detail = await this.$fetch('getVideoShareInfo', { id })
} catch (err) {
}
},
async initData() {
this.isLocked = true
await this.fetchDetails(this.id)
this.videoContext = uni.createVideoContext('video');
},
refreshLockStatus() {
this.isLocked = false
this.timeIsUp = false
setTimeout(() => {
this.videoContext.play()
console.log('--play')
})
},
async onPlay() {
if (!this.isLocked) {
return
}
this.videoContext.pause()
this.timeIsUp = true
this.$refs.popupUnlock.open();
},
async onTimeupdate(e) {
const { currentTime } = e.target
if (currentTime >= this.detail.timeNum && this.isLocked) {
this.videoContext.pause()
this.timeIsUp = true
this.onPlay()
}
},
onTimeEnd() {
this.$refs.popupQrCode.open()
},
},
}
</script>
this.id = id
<style scoped lang="scss">
.video {
width: 100%;
height: calc(100vh - #{$navbar-height} - var(--status-bar-height) - 20rpx);
}
// if(uni.getStorageSync('token')){
// this.initData()
// }else{
// uni.navigateTo({
// url: '/pages_order/auth/wxLogin'
// })
// }
.info {
color: #FFFFFF;
font-size: 28rpx;
this.initData()
position: fixed;
left: 40rpx;
bottom: 100rpx;
},
onShareAppMessage(res) {
const {
headTitle,
indexImage,
} = this.detail
let o = {
title: headTitle,
imageUrl: indexImage,
query: `id=${this.id}&state=1&shareId=${this.userInfo.id}`,
}
.title {
font-size: 32rpx;
margin: 5rpx 0;
}
}
//
const params = {
id: this.id,
state: "1",
}
// this.$fetch('addLogShareInfo', params)
shareLog.insert(this.id)
return o
},
methods: {
async fetchDetails(id) {
try {
this.detail = await this.$fetch('getVideoShareInfo', {
id
})
} catch (err) {
}
},
async initData() {
this.isLocked = true
await this.fetchDetails(this.id)
this.videoContext = uni.createVideoContext('video');
},
async refreshLockStatus() {
this.isLocked = false
this.timeIsUp = false
setTimeout(async () => {
const result = await this.fetchCheckShare()
const {
open,
need_num,
num
} = result
console.log('--open', open)
if (open) { //
this.videoContext.play()
this.isLocked = false
return
}
uni.showToast({
title: `还需转发${need_num - num}`,
icon: 'none',
})
})
},
async fetchCheckShare() {
try {
return await shareLog.check(this.id, this.detail.num)
} catch (err) {
return {}
}
},
async onPlay() {
if (!this.isLocked) {
return
}
this.videoContext.pause()
this.timeIsUp = true
this.$refs.popupUnlock.open();
},
async onTimeupdate(e) {
const {
currentTime
} = e.target
if (currentTime >= this.detail.timeNum && this.isLocked) {
this.videoContext.pause()
this.timeIsUp = true
this.onPlay()
}
},
onTimeEnd() {
this.$refs.popupQrCode.open()
},
},
}
</script>
<style scoped lang="scss">
.video {
width: 100%;
height: calc(100vh - #{$navbar-height} - var(--status-bar-height) - 20rpx);
}
.info {
color: #FFFFFF;
font-size: 28rpx;
position: fixed;
left: 40rpx;
bottom: 100rpx;
.title {
font-size: 32rpx;
margin: 5rpx 0;
}
}
</style> </style>

Loading…
Cancel
Save