Skip to content

Commit 76025b6

Browse files
committed
营销:适配商城装修组件【弹窗广告】
1 parent 605f906 commit 76025b6

File tree

5 files changed

+177
-1
lines changed

5 files changed

+177
-1
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { DiyComponent } from '@/components/DiyEditor/util'
2+
3+
/** 弹窗广告属性 */
4+
export interface PopoverProperty {
5+
list: PopoverItemProperty[]
6+
}
7+
8+
export interface PopoverItemProperty {
9+
// 图片地址
10+
imgUrl: string
11+
// 跳转连接
12+
url: string
13+
// 显示类型:仅显示一次、每次启动都会显示
14+
showType: 'once' | 'always'
15+
}
16+
17+
// 定义组件
18+
export const component = {
19+
id: 'Popover',
20+
name: '弹窗广告',
21+
icon: 'carbon:popup',
22+
position: 'fixed',
23+
property: {
24+
list: [{ showType: 'once' }]
25+
}
26+
} as DiyComponent<PopoverProperty>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<template>
2+
<div
3+
v-for="(item, index) in property.list"
4+
:key="index"
5+
class="absolute bottom-50% right-50% h-454px w-292px border-1px border-gray border-rounded-4px border-solid bg-white p-1px"
6+
:style="{
7+
zIndex: 100 + index + (activeIndex === index ? 100 : 0),
8+
marginRight: `${-146 - index * 20}px`,
9+
marginBottom: `${-227 - index * 20}px`
10+
}"
11+
@click="handleActive(index)"
12+
>
13+
<el-image :src="item.imgUrl" fit="contain" class="h-full w-full">
14+
<template #error>
15+
<div class="h-full w-full flex items-center justify-center">
16+
<Icon icon="ep:picture" />
17+
</div>
18+
</template>
19+
</el-image>
20+
<div class="absolute right-1 top-1 text-12px">{{ index + 1 }}</div>
21+
</div>
22+
</template>
23+
<script setup lang="ts">
24+
import { PopoverProperty } from './config'
25+
26+
/** 弹窗广告 */
27+
defineOptions({ name: 'Popover' })
28+
// 定义属性
29+
defineProps<{ property: PopoverProperty }>()
30+
31+
// 处理选中
32+
const activeIndex = ref(0)
33+
const handleActive = (index: number) => {
34+
activeIndex.value = index
35+
}
36+
</script>
37+
38+
<style scoped lang="scss"></style>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<template>
2+
<el-form label-width="80px" :model="formData">
3+
<Draggable v-model="formData.list" :empty-item="{ showType: 'once' }">
4+
<template #default="{ element, index }">
5+
<el-form-item label="图片" :prop="`list[${index}].imgUrl`">
6+
<UploadImg v-model="element.imgUrl" height="56px" width="56px" />
7+
</el-form-item>
8+
<el-form-item label="跳转链接" :prop="`list[${index}].url`">
9+
<AppLinkInput v-model="element.url" />
10+
</el-form-item>
11+
<el-form-item label="显示次数" :prop="`list[${index}].showType`">
12+
<el-radio-group v-model="element.showType">
13+
<el-tooltip content="只显示一次,下次打开时不显示" placement="bottom">
14+
<el-radio label="once">一次</el-radio>
15+
</el-tooltip>
16+
<el-tooltip content="每次打开时都会显示" placement="bottom">
17+
<el-radio label="always">不限</el-radio>
18+
</el-tooltip>
19+
</el-radio-group>
20+
</el-form-item>
21+
</template>
22+
</Draggable>
23+
</el-form>
24+
</template>
25+
26+
<script setup lang="ts">
27+
import { PopoverProperty } from './config'
28+
import { usePropertyForm } from '@/components/DiyEditor/util'
29+
30+
// 弹窗广告属性面板
31+
defineOptions({ name: 'PopoverProperty' })
32+
33+
const props = defineProps<{ modelValue: PopoverProperty }>()
34+
const emit = defineEmits(['update:modelValue'])
35+
const { formData } = usePropertyForm(props.modelValue, emit)
36+
</script>
37+
38+
<style scoped lang="scss"></style>

src/components/DiyEditor/index.vue

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@
4747
class="cursor-pointer!"
4848
/>
4949
</div>
50+
<!-- 绝对定位的组件:例如 弹窗、浮动按钮等 -->
51+
<div
52+
v-for="(component, index) in pageComponents"
53+
:key="index"
54+
@click="handleComponentSelected(component, index)"
55+
>
56+
<component
57+
v-if="component.position === 'fixed' && selectedComponent?.uid === component.uid"
58+
:is="component.id"
59+
:property="component.property"
60+
/>
61+
</div>
5062
<!-- 手机页面编辑区域 -->
5163
<el-scrollbar
5264
height="100%"
@@ -70,6 +82,7 @@
7082
>
7183
<template #item="{ element, index }">
7284
<ComponentContainer
85+
v-if="!element.position || element.position === 'center'"
7386
:component="element"
7487
:active="selectedComponentIndex === index"
7588
:can-move-up="index > 0"
@@ -91,6 +104,33 @@
91104
@click="handleTabBarSelected"
92105
/>
93106
</div>
107+
<!-- 固定布局的组件 操作按钮区 -->
108+
<div class="fixed-component-action-group">
109+
<el-tag
110+
v-if="showPageConfig"
111+
size="large"
112+
:effect="selectedComponent?.uid === pageConfigComponent.uid ? 'dark' : 'plain'"
113+
:type="selectedComponent?.uid === pageConfigComponent.uid ? '' : 'info'"
114+
@click="handleComponentSelected(pageConfigComponent)"
115+
>
116+
<Icon :icon="pageConfigComponent.icon" :size="12" />
117+
<span>{{ pageConfigComponent.name }}</span>
118+
</el-tag>
119+
<template v-for="(component, index) in pageComponents" :key="index">
120+
<el-tag
121+
v-if="component.position === 'fixed'"
122+
size="large"
123+
closable
124+
:effect="selectedComponent?.uid === component.uid ? 'dark' : 'plain'"
125+
:type="selectedComponent?.uid === component.uid ? '' : 'info'"
126+
@click="handleComponentSelected(component)"
127+
@close="handleDeleteComponent(index)"
128+
>
129+
<Icon :icon="component.icon" :size="12" />
130+
<span>{{ component.name }}</span>
131+
</el-tag>
132+
</template>
133+
</div>
94134
</div>
95135
<!-- 右侧属性面板 -->
96136
<el-aside class="editor-right" width="350px" v-if="selectedComponent?.property">
@@ -485,6 +525,31 @@ $toolbar-height: 42px;
485525
}
486526
}
487527
}
528+
529+
/* 固定布局的组件 操作按钮区 */
530+
.fixed-component-action-group {
531+
position: absolute;
532+
top: 0;
533+
right: 16px;
534+
display: flex;
535+
flex-direction: column;
536+
gap: 8px;
537+
538+
:deep(.el-tag) {
539+
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
540+
border: none;
541+
.el-tag__content {
542+
width: 100%;
543+
display: flex;
544+
align-items: center;
545+
justify-content: flex-start;
546+
547+
.el-icon {
548+
margin-right: 4px;
549+
}
550+
}
551+
}
552+
}
488553
}
489554
}
490555
}

src/components/DiyEditor/util.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ export interface DiyComponent<T> {
1313
name: string
1414
// 组件图标
1515
icon: string
16+
/*
17+
组件位置:
18+
top: 固定于手机顶部,例如 顶部的导航栏
19+
bottom: 固定于手机底部,例如 底部的菜单导航栏
20+
center: 位于手机中心,每个组件占一行,顺序向下排列
21+
空:同center
22+
fixed: 由组件自己决定位置,如弹窗位于手机中心、浮动按钮一般位于手机右下角
23+
*/
24+
position: 'top' | 'bottom' | 'center' | '' | 'fixed'
1625
// 组件属性
1726
property: T
1827
}
@@ -102,7 +111,7 @@ export const PAGE_LIBS = [
102111
{
103112
name: '基础组件',
104113
extended: true,
105-
components: ['SearchBar', 'NoticeBar', 'MenuSwiper', 'MenuGrid', 'MenuList']
114+
components: ['SearchBar', 'NoticeBar', 'MenuSwiper', 'MenuGrid', 'MenuList', 'Popover']
106115
},
107116
{
108117
name: '图文组件',

0 commit comments

Comments
 (0)