3213
This commit is contained in:
parent
db6ae0837f
commit
475dc60cbd
95
components/detail-popup/README.md
Normal file
95
components/detail-popup/README.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# DetailPopup 弹窗组件
|
||||
|
||||
这是一个简单的弹窗组件,支持自定义内容,提供开启和关闭方法。
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 导入组件
|
||||
|
||||
```vue
|
||||
<script>
|
||||
import DetailPopup from '@/components/detail-popup';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DetailPopup
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 2. 在模板中使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view>
|
||||
<!-- 按钮触发弹窗 -->
|
||||
<button @click="openPopup">打开弹窗</button>
|
||||
|
||||
<!-- 弹窗组件 -->
|
||||
<detail-popup ref="popup">
|
||||
<!-- 自定义弹窗内容 -->
|
||||
<view class="custom-content">
|
||||
<view class="title">这是弹窗标题</view>
|
||||
<view class="content">这是弹窗内容</view>
|
||||
<button @click="closePopup">确定</button>
|
||||
</view>
|
||||
</detail-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
// 打开弹窗
|
||||
openPopup() {
|
||||
this.$refs.popup.open();
|
||||
},
|
||||
|
||||
// 关闭弹窗
|
||||
closePopup() {
|
||||
this.$refs.popup.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.custom-content {
|
||||
padding: 20rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.content {
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### 3. 事件监听
|
||||
|
||||
组件会在打开和关闭时触发相应的事件:
|
||||
|
||||
```vue
|
||||
<detail-popup ref="popup" @open="onPopupOpen" @close="onPopupClose">
|
||||
<!-- 内容 -->
|
||||
</detail-popup>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
onPopupOpen() {
|
||||
console.log('弹窗已打开');
|
||||
},
|
||||
onPopupClose() {
|
||||
console.log('弹窗已关闭');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
111
components/detail-popup/detail-popup.vue
Normal file
111
components/detail-popup/detail-popup.vue
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
<template>
|
||||
<uni-popup ref="popupbase" type="center" maskBackgroundColor="rgba(0,0,0,0.8)">
|
||||
<view v-if="visible" class="detail-popup" :style="{
|
||||
width: width,
|
||||
backgroundColor: bgColor,
|
||||
maxHeight: '80vh',
|
||||
overflowY: 'auto'
|
||||
}">
|
||||
<!-- 默认插槽,可以设置弹窗的内容 -->
|
||||
<slot></slot>
|
||||
|
||||
<!-- 关闭按钮 -->
|
||||
<view class="close-btn" @click="close" v-if="showClose">
|
||||
<image :src="$img1('common/close.png')" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DetailPopup',
|
||||
props: {
|
||||
// 自定义弹窗背景色
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#FFFFFF'
|
||||
},
|
||||
// 自定义弹窗宽度
|
||||
width: {
|
||||
type: String,
|
||||
default: '570rpx'
|
||||
},
|
||||
// 是否显示关闭按钮
|
||||
showClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 可以在这里初始化数据
|
||||
},
|
||||
methods: {
|
||||
// 打开弹窗方法
|
||||
open() {
|
||||
this.visible = true;
|
||||
|
||||
// 使用nextTick确保DOM更新后再打开弹窗
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.popupbase) {
|
||||
// 小程序环境下需要额外延迟
|
||||
setTimeout(() => {
|
||||
this.$refs.popupbase.open();
|
||||
}, 50);
|
||||
} else {
|
||||
console.error('popup ref不存在,请检查组件是否正确挂载');
|
||||
// 延迟后再次尝试
|
||||
setTimeout(() => {
|
||||
if (this.$refs.popupbase) {
|
||||
this.$refs.popupbase.open();
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
|
||||
// 触发open事件
|
||||
this.$emit('open');
|
||||
},
|
||||
|
||||
// 关闭弹窗方法
|
||||
close() {
|
||||
this.visible = false;
|
||||
if (this.$refs.popupbase) {
|
||||
this.$refs.popupbase.close();
|
||||
}
|
||||
|
||||
// 触发close事件
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detail-popup {
|
||||
position: relative;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
// 关闭按钮
|
||||
.close-btn {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -80rpx;
|
||||
transform: translateX(-50%);
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
131
components/detail-popup/example.vue
Normal file
131
components/detail-popup/example.vue
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
<template>
|
||||
<view class="example-container">
|
||||
<view class="btn-group">
|
||||
<button class="btn" @click="openBasicPopup">基础弹窗</button>
|
||||
<button class="btn" @click="openCustomPopup">自定义弹窗</button>
|
||||
</view>
|
||||
|
||||
<!-- 基础弹窗 -->
|
||||
<detail-popup ref="basicPopup">
|
||||
<view class="popup-content">
|
||||
<view class="popup-title">基础弹窗</view>
|
||||
<view class="popup-text">这是一个基础弹窗示例,使用了默认配置。</view>
|
||||
<button class="popup-btn" @click="$refs.basicPopup.close()">关闭</button>
|
||||
</view>
|
||||
</detail-popup>
|
||||
|
||||
<!-- 自定义弹窗 -->
|
||||
<detail-popup
|
||||
ref="customPopup"
|
||||
bgColor="#F5F5F5"
|
||||
width="650rpx"
|
||||
@open="onPopupOpen"
|
||||
@close="onPopupClose"
|
||||
>
|
||||
<view class="popup-content custom">
|
||||
<view class="popup-title">自定义弹窗</view>
|
||||
<view class="popup-text">这是一个自定义弹窗示例,修改了背景色和宽度。</view>
|
||||
<image class="popup-image" :src="$img1('common/chouTitle.png')" mode="aspectFit"></image>
|
||||
<button class="popup-btn custom-btn" @click="$refs.customPopup.close()">确定</button>
|
||||
</view>
|
||||
</detail-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetailPopup from './index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DetailPopup
|
||||
},
|
||||
methods: {
|
||||
// 打开基础弹窗
|
||||
openBasicPopup() {
|
||||
this.$refs.basicPopup.open();
|
||||
},
|
||||
|
||||
// 打开自定义弹窗
|
||||
openCustomPopup() {
|
||||
this.$refs.customPopup.open();
|
||||
},
|
||||
|
||||
// 弹窗打开回调
|
||||
onPopupOpen() {
|
||||
console.log('自定义弹窗已打开');
|
||||
},
|
||||
|
||||
// 弹窗关闭回调
|
||||
onPopupClose() {
|
||||
console.log('自定义弹窗已关闭');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.example-container {
|
||||
padding: 30rpx;
|
||||
|
||||
.btn-group {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
.btn {
|
||||
width: 280rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
background: #3b3941;
|
||||
color: #FFFFFF;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
padding: 20rpx;
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.popup-text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.popup-image {
|
||||
width: 100%;
|
||||
height: 150rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.popup-btn {
|
||||
width: 80%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background: #3b3941;
|
||||
color: #FFFFFF;
|
||||
border-radius: 40rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
&.custom {
|
||||
padding: 30rpx;
|
||||
|
||||
.popup-title {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.custom-btn {
|
||||
background: linear-gradient(90deg, #2dcbff 0%, #ff873a 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
3
components/detail-popup/index.js
Normal file
3
components/detail-popup/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import DetailPopup from './detail-popup.vue';
|
||||
|
||||
export default DetailPopup;
|
||||
|
|
@ -1,24 +1,43 @@
|
|||
<template>
|
||||
<uni-popup ref="popup" type="center" maskBackgroundColor="rgba(0,0,0,0.9)">
|
||||
<view v-if="visible" class="preview-popup">
|
||||
<!-- 商品图片 -->
|
||||
<view class="pic center relative">
|
||||
<image :src="innerImgUrl" lazy-load></image>
|
||||
<view class="type-tag justify-center" v-if="innerTipTitle">{{ innerTipTitle }}</view>
|
||||
<!-- 赏品列表 -->
|
||||
<view class="list" v-if="showList">
|
||||
<scroll-view :scroll-y="true">
|
||||
<view class="res-list">
|
||||
<view class="res-item" v-for="(item, i) in dataItem.children" :key="i">
|
||||
<view class="pic center">
|
||||
<image :src="item.imgurl" lazy-load></image>
|
||||
<view class="tag center"
|
||||
:style="{ backgroundColor: item.shang_info ? item.shang_info.color : '#000000' }">{{ item.shang_info ?
|
||||
item.shang_info.title : "" }}</view>
|
||||
<view class="num center">{{ item.surplus_stock }}/{{ item.stock }}</view>
|
||||
</view>
|
||||
<view class="title hang1 flex center " style="padding: 0px;margin: 0px;text-align: center;width: 100%;">
|
||||
<text> {{ item.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 商品图片 -->
|
||||
<view class="pic center relative" v-if="!showList">
|
||||
<image :src="innerImgUrl" lazy-load></image>
|
||||
<view class="type-tag justify-center"
|
||||
:style="{ backgroundColor: dataItem.shang_info ? dataItem.shang_info.color : '#000000' }"
|
||||
v-if="innerTipTitle">{{ innerTipTitle }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品标题 -->
|
||||
<view class="title">
|
||||
<text class="hang1">{{ innerTitle }}</text>
|
||||
<text class="hang1">{{ !showList?innerTitle:'抽中宝箱后,会在奖品列表中随机抽取一个奖品' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 商品信息列表 -->
|
||||
<view class="info-list">
|
||||
<view class="info-item" v-if="innerProbability">{{ innerProbability }}</view>
|
||||
<view class="info-item" v-if="isTips" @click="showList = !showList">{{ showList ? '收起' : '查看奖品' }}</view>
|
||||
<view class="info-item" v-if="innerProductType">产品类型: {{ innerProductType }}</view>
|
||||
<view class="info-item" v-for="(item, index) in innerExtraInfo" :key="index">{{ item }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 关闭按钮 -->
|
||||
<view class="close icon" @click="closePopup">
|
||||
<image :src="$img('/static/img/close.png')" lazy-load></image>
|
||||
|
|
@ -28,8 +47,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'DetailPreviewPopup',
|
||||
|
||||
props: {
|
||||
// 商品标题
|
||||
title: {
|
||||
|
|
@ -61,6 +82,7 @@ export default {
|
|||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -71,7 +93,10 @@ export default {
|
|||
innerTipTitle: '',
|
||||
innerProductType: '',
|
||||
innerProbability: '',
|
||||
innerExtraInfo: []
|
||||
innerExtraInfo: [],
|
||||
dataItem: {},
|
||||
showList: false,
|
||||
isTips: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -103,7 +128,7 @@ export default {
|
|||
this.innerProductType = this.productType;
|
||||
this.innerProbability = this.probability;
|
||||
this.innerExtraInfo = this.extraInfo;
|
||||
|
||||
|
||||
// 监听全局预览事件
|
||||
uni.$on('global-preview-event', this.handleGlobalEvent);
|
||||
},
|
||||
|
|
@ -118,11 +143,12 @@ export default {
|
|||
this.setPreviewData(options);
|
||||
},
|
||||
|
||||
|
||||
// 设置预览数据并打开弹窗
|
||||
setPreviewData(data) {
|
||||
console.log('设置预览数据', data);
|
||||
if (!data) return;
|
||||
|
||||
|
||||
// 更新内部数据
|
||||
if (data.title !== undefined) this.innerTitle = data.title;
|
||||
if (data.imgUrl !== undefined) this.innerImgUrl = data.imgUrl;
|
||||
|
|
@ -130,19 +156,28 @@ export default {
|
|||
if (data.productType !== undefined) this.innerProductType = data.productType;
|
||||
if (data.probability !== undefined) this.innerProbability = data.probability;
|
||||
if (data.extraInfo !== undefined) this.innerExtraInfo = data.extraInfo;
|
||||
|
||||
this.showList = false;
|
||||
this.isTips = false;
|
||||
if (data.dataItem !== undefined) {
|
||||
this.dataItem = data.dataItem;
|
||||
if (data.dataItem != null && data.dataItem.children != null && data.dataItem.children.length > 0) {
|
||||
this.showList = false;
|
||||
this.isTips = true;
|
||||
}
|
||||
}
|
||||
// 打开弹窗
|
||||
this.open();
|
||||
},
|
||||
|
||||
|
||||
// 打开弹窗
|
||||
open() {
|
||||
console.log('尝试打开弹窗', this.$refs.popup);
|
||||
this.visible = true;
|
||||
|
||||
console.log('打开弹窗', this.dataItem);
|
||||
|
||||
// 使用nextTick确保DOM更新后再打开弹窗
|
||||
this.$nextTick(() => {
|
||||
console.log('DOM已更新,准备打开弹窗');
|
||||
console.log(' ');
|
||||
if (this.$refs.popup) {
|
||||
// 小程序环境下需要额外延迟
|
||||
setTimeout(() => {
|
||||
|
|
@ -161,7 +196,7 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 关闭弹窗
|
||||
closePopup() {
|
||||
this.visible = false;
|
||||
|
|
@ -177,25 +212,96 @@ export default {
|
|||
<style lang="scss" scoped>
|
||||
.preview-popup {
|
||||
position: relative;
|
||||
width: 570rpx;
|
||||
width: 80vw;
|
||||
box-sizing: border-box;
|
||||
height: 850rpx;
|
||||
|
||||
.list {
|
||||
|
||||
width: 100%;
|
||||
height: 598rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
margin: 0rpx auto;
|
||||
|
||||
.res-list {
|
||||
padding: 20rpx 10rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 33%);
|
||||
gap: 24rpx 10rpx;
|
||||
|
||||
.res-item {
|
||||
width: 180rpx;
|
||||
height: 240rpx;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 16rpx;
|
||||
|
||||
.pic {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
position: relative;
|
||||
background: #d8d8d8;
|
||||
border-radius: 16rpx 16rpx 0rpx 0rpx;
|
||||
|
||||
>image {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
border-radius: 16rpx 16rpx 0rpx 0rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.num {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 10rpx;
|
||||
min-width: 90rpx;
|
||||
height: 28rpx;
|
||||
font-weight: 400;
|
||||
font-size: 20rpx;
|
||||
color: #333333;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 22rpx 10rpx 0;
|
||||
font-weight: 400;
|
||||
font-size: 16rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.exchange {
|
||||
padding: 10rpx 10rpx;
|
||||
font-weight: 400;
|
||||
font-size: 20rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 商品图片区域
|
||||
.pic {
|
||||
width: 570rpx;
|
||||
width: 100%;
|
||||
height: 598rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
|
||||
image {
|
||||
width: 548rpx;
|
||||
height: 549rpx;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
// 商品标签
|
||||
.type-tag {
|
||||
width: 68rpx;
|
||||
height: 32rpx;
|
||||
width: 100rpx;
|
||||
height: 40rpx;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -203,17 +309,18 @@ export default {
|
|||
top: 12rpx;
|
||||
left: 24rpx;
|
||||
font-weight: 400;
|
||||
font-size: 14rpx;
|
||||
line-height: 40rpx;
|
||||
font-size: 20rpx;
|
||||
color: #FFFFFF;
|
||||
box-sizing: border-box;
|
||||
background: url($imgurl + 'common/chouLabel.png') no-repeat 0 0 / 100% 100%;
|
||||
border-radius: 25rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 商品标题
|
||||
.title {
|
||||
margin: 40rpx auto 0;
|
||||
width: 564rpx;
|
||||
width: 100%;
|
||||
height: 60rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
|
|
@ -248,17 +355,32 @@ export default {
|
|||
|
||||
// 关闭按钮
|
||||
.close {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translate(-50%, 160%);
|
||||
|
||||
width: 100%;
|
||||
margin-top:40rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
// transform: translate(-50%, 160%);
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 5%;
|
||||
left: 5%;
|
||||
font-weight: 400;
|
||||
font-size: 20rpx;
|
||||
color: #fff;
|
||||
box-sizing: border-box;
|
||||
padding: 5rpx 15rpx;
|
||||
border-radius: 25rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
@ -164,7 +164,6 @@
|
|||
<view class="title hang1 flex center">
|
||||
<text> {{ item.goodslist_title }}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
|
@ -332,7 +331,8 @@
|
|||
imgUrl: item.imgurl,
|
||||
tipTitle: item.shang_info ? item.shang_info.title : '',
|
||||
productType: this.optData.type_text,
|
||||
probability: item.pro
|
||||
probability: item.pro,
|
||||
dataItem: item
|
||||
}).then(() => {
|
||||
console.log('预览弹窗打开成功');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user