Files
lucky_shop/components-diy/diy-group.vue
2026-01-05 11:22:38 +08:00

259 lines
7.5 KiB
Vue

<template>
<view data-component-name="diy-group" class="diy-group">
<view v-for="(item, index) in diyDataArray" :key="index" :style="item.pageStyle">
<!-- 动态组件加载 -->
<component
:is="getComponent(item.componentName)"
v-if="shouldShowComponent(item)"
:value="item"
v-bind="getComponentProps(item)"
></component>
<!-- 自定义扩展组件 -->
<diy-comp-extend :value="item"></diy-comp-extend>
</view>
</view>
</template>
<script>
// 组件组展示
import DiyMinx from './minx.js'
import diyCompExtend from './diy-comp-extend.vue'
export default {
name: 'DiyGroup',
mixins: [DiyMinx],
components: {
diyCompExtend
},
props: {
diyData: {
type: Object,
default: () => ({})
},
scrollTop: {
type: [String, Number],
default: '0'
},
haveTopCategory: {
type: Boolean,
default: false
},
followOfficialAccount: {
type: Object,
default: () => ({})
},
},
data() {
return {
diyGlobalData: null,
// 动态组件映射
componentMap: {
StoreShow: () => import('./diy-store.vue'),
Kefu: () => import('./diy-kefu.vue'),
Form: () => import('./diy-form.vue'),
StoreLabel: () => import('./diy-store-label.vue'),
Picture: () => import('./diy-picture.vue'),
Listmenu: () => import('./diy-listmenu.vue'),
Text: () => import('./diy-text.vue'),
Notice: () => import('./diy-notice.vue'),
GraphicNav: () => import('./diy-graphic-nav.vue'),
ImageAds: () => import('./diy-img-ads.vue'),
Search: () => import('./diy-search.vue'),
RichText: () => import('./diy-rich-text.vue'),
HorzLine: () => import('./diy-horz-line.vue'),
HorzBlank: () => import('./diy-horz-blank.vue'),
Coupon: () => import('./diy-coupon.vue'),
GoodsList: () => import('./diy-goods-list.vue'),
ManyGoodsList: () => import('./diy-many-goods-list.vue'),
RubikCube: () => import('./diy-rubik-cube.vue'),
Video: () => import('./diy-video.vue'),
Seckill: () => import('./diy-seckill.vue'),
Pintuan: () => import('./diy-pintuan.vue'),
Groupbuy: () => import('./diy-groupbuy.vue'),
Pinfan: () => import('./diy-pinfan.vue'),
Bargain: () => import('./diy-bargain.vue'),
Presale: () => import('./diy-presale.vue'),
Notes: () => import('./diy-notes.vue'),
FloatBtn: () => import('./diy-float-btn.vue'),
LiveInfo: () => import('./diy-live.vue'),
FenxiaoGoodsList: () => import('./diy-fenxiao-goods-list.vue'),
GoodsRecommend: () => import('./diy-goods-recommend.vue'),
GoodsBrand: () => import('./diy-goods-brand.vue'),
Article: () => import('./diy-article.vue'),
MerchList: () => import('./diy-merch-list.vue'),
MemberInfo: () => import('./diy-member-info.vue'),
MemberMyOrder: () => import('./diy-member-my-order.vue'),
QuickNav: () => import('./diy-quick-nav.vue'),
PaymentQrcode: () => import('./diy-payment-qrcode.vue'),
HotArea: () => import('./diy-hot-area.vue'),
FollowOfficialAccount: () => import('./diy-follow-official-account.vue'),
Map: () => import('./diy-map.vue'),
Audio: () => import('./diy-audio.vue'),
ImageNav: () => import('./diy-image-nav.vue'),
Digit: () => import('./diy-digit.vue'),
VideoList: () => import('./diy-video-list.vue'),
BottomNav: () => import('./diy-bottom-nav.vue'),
CategoryItem: () => import('./diy-category-item.vue'),
Category: () => import('./diy-category.vue'),
Icon: () => import('./diy-icon.vue'),
Group: () => import('./diy-group.vue')
}
};
},
created() {
this.diyGlobalData = JSON.parse(JSON.stringify(this.diyData || {}));
},
computed: {
topNavColor() {
var color = '';
if (this.diyData.global && this.diyData.global.topNavBg) {
color = 'transparent';
if (this.scrollTop > 20 && this.diyData.global.topNavColor) {
color = this.diyData.global.topNavColor;
} else {
color = 'transparent';
}
} else if (this.diyData.global && this.diyData.global.topNavColor) {
color = this.diyData.global.topNavColor;
}
return color;
},
// 修改属性样式
setPagestyle() {
if (!this.diyGlobalData || !this.diyGlobalData.value || !Array.isArray(this.diyGlobalData.value)) {
return [];
}
this.diyGlobalData.value.forEach((item, index) => {
item.pageStyle = '';
// 给每个组件增加位置属性,用于定位,搜索、分类导航等定位
item.moduleIndex = index + 1;
// 特殊处理搜索框 当显示位置为滚动至顶部固定时,只设置背景颜色
if (item.componentName == 'Search' && item.positionWay == 'fixed') {
// item.pageStyle = 'background-color:' + item.pageBgColor + ';';
return false;
}
item.pageStyle += 'background-color:' + (item.pageBgColor || '') + ';';
if (item.margin) {
item.pageStyle += 'padding-top:' + (item.margin.top || 0) * 2 + 'rpx' + ';';
item.pageStyle += 'padding-bottom:' + (item.margin.bottom || 0) * 2 + 'rpx' + ';';
item.pageStyle += 'padding-right:' + (item.margin.both || 0) * 2 + 'rpx' + ';';
item.pageStyle += 'padding-left:' + (item.margin.both || 0) * 2 + 'rpx' + ';';
}
});
return this.diyGlobalData.value;
},
// 过滤组件的渲染
diyDataArray() {
let data = [];
let showModuleData = [];
// 安全获取store中的模块显示数据
try {
if (this.$store && this.$store.state && this.$store.state.diyGroupShowModule) {
showModuleData = JSON.parse(this.$store.state.diyGroupShowModule);
// 确保showModuleData是数组
if (!Array.isArray(showModuleData)) {
showModuleData = [];
}
}
} catch (e) {
showModuleData = [];
}
const diyDataArr = this.setPagestyle;
if (showModuleData.length) {
if (showModuleData.includes('null')) return [];
diyDataArr.forEach((item, index) => {
if (item && item.componentName && showModuleData.includes(item.componentName)) {
data.push(item);
}
});
} else {
data = diyDataArr;
}
return data;
}
},
methods: {
// 获取组件
getComponent(componentName) {
return this.componentMap[componentName] || null;
},
// 判断组件是否应该显示
shouldShowComponent(item) {
// 检查是否有对应的组件映射
if (!this.componentMap[item.componentName]) {
return false;
}
// 根据组件名称和附加组件状态进行判断
const addonChecks = {
StoreShow: 'store',
StoreLabel: 'store',
Coupon: 'coupon',
Seckill: 'seckill',
Pintuan: 'pintuan',
Groupbuy: 'groupbuy',
Pinfan: 'pinfan',
Bargain: 'bargain',
Presale: 'bargain',
Notes: 'notes'
};
const addonName = addonChecks[item.componentName];
if (addonName) {
return this.addonIsExist[addonName];
}
// 小程序直播组件特殊处理
if (item.componentName === 'LiveInfo') {
// #ifdef MP-WEIXIN
return true;
// #endif
// #ifndef MP-WEIXIN
return false;
// #endif
}
return true;
},
// 获取组件属性
getComponentProps(item) {
const props = {};
// 为特定组件添加额外属性
switch (item.componentName) {
case 'Search':
props.topNavColor = this.topNavColor;
props.global = this.diyGlobalData.global;
props.haveTopCategory = this.haveTopCategory;
props.followOfficialAccount = this.followOfficialAccount;
break;
case 'ManyGoodsList':
props.global = this.diyGlobalData.global;
props.scrollTop = this.scrollTop;
break;
case 'MemberInfo':
props.global = this.diyGlobalData.global;
break;
}
return props;
}
}
};
</script>
<style lang="scss">
.diy-group {
width: 100%;
}
</style>