营销:适配商城装修组件【宫格导航】

This commit is contained in:
owen 2023-11-08 22:22:35 +08:00
parent 325e2e4ff2
commit ac42493659
5 changed files with 224 additions and 6 deletions

View File

@ -0,0 +1,78 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
import { cloneDeep } from 'lodash-es'
/** 宫格导航属性 */
export interface MenuGridProperty {
// 列数
column: number
// 导航菜单列表
list: MenuGridItemProperty[]
// 组件样式
style: ComponentStyle
}
/** 宫格导航项目属性 */
export interface MenuGridItemProperty {
// 图标链接
iconUrl: string
// 标题
title: string
// 标题颜色
titleColor: string
// 副标题
subtitle: string
// 副标题颜色
subtitleColor: string
// 链接
url: string
// 角标
badge: {
// 是否显示
show: boolean
// 角标文字
text: string
// 角标文字颜色
textColor: string
// 角标背景颜色
bgColor: string
}
}
export const EMPTY_MENU_GRID_ITEM_PROPERTY = {
title: '标题',
titleColor: '#333',
subtitle: '副标题',
subtitleColor: '#bbb',
badge: {
show: false,
textColor: '#fff',
bgColor: '#FF6000'
}
} as MenuGridItemProperty
// 定义组件
export const component = {
id: 'MenuGrid',
name: '宫格导航',
icon: 'fa-solid:list',
property: {
column: 3,
list: [cloneDeep(EMPTY_MENU_GRID_ITEM_PROPERTY)],
style: {
bgType: 'color',
bgColor: '#fff',
marginBottom: 8,
marginLeft: 8,
marginRight: 8,
padding: 8,
paddingTop: 8,
paddingRight: 8,
paddingBottom: 8,
paddingLeft: 8,
borderRadius: 8,
borderTopLeftRadius: 8,
borderTopRightRadius: 8,
borderBottomRightRadius: 8,
borderBottomLeftRadius: 8
} as ComponentStyle
}
} as DiyComponent<MenuGridProperty>

View File

@ -0,0 +1,35 @@
<template>
<div class="flex flex-row flex-wrap">
<div
v-for="(item, index) in property.list"
:key="index"
class="relative flex flex-col items-center p-b-14px p-t-20px"
:style="{ width: `${100 * (1 / property.column)}%` }"
>
<!-- 右上角角标 -->
<span
v-if="item.badge?.show"
class="absolute left-50% top-10px z-1 h-20px rounded-50% p-x-6px text-center text-12px leading-20px"
:style="{ color: item.badge.textColor, backgroundColor: item.badge.bgColor }"
>
{{ item.badge.text }}
</span>
<el-image v-if="item.iconUrl" class="h-28px w-28px" :src="item.iconUrl" />
<span class="m-t-8px h-16px text-12px leading-16px" :style="{ color: item.titleColor }">
{{ item.title }}
</span>
<span class="m-t-6px h-12px text-10px leading-12px" :style="{ color: item.subtitleColor }">
{{ item.subtitle }}
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { MenuGridProperty } from './config'
/** 宫格导航 */
defineOptions({ name: 'MenuGrid' })
defineProps<{ property: MenuGridProperty }>()
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,96 @@
<template>
<ComponentContainerProperty v-model="formData.style">
<!-- 表单 -->
<el-form label-width="80px" :model="formData" class="m-t-8px">
<el-form-item label="每行数量" prop="column">
<el-radio-group v-model="formData.column">
<el-radio :label="3">3</el-radio>
<el-radio :label="4">4</el-radio>
</el-radio-group>
</el-form-item>
<el-text tag="p"> 菜单设置 </el-text>
<el-text type="info" size="small"> 拖动左侧的小圆点可以调整顺序 </el-text>
<template v-if="formData.list.length">
<VueDraggable
class="m-t-8px"
:list="formData.list"
item-key="index"
handle=".drag-icon"
:forceFallback="true"
:animation="200"
>
<template #item="{ element, index }">
<div class="mb-4px flex flex-col gap-4px rounded bg-gray-100 p-8px">
<div class="flex flex-row justify-between">
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
<Icon icon="ep:delete" class="text-red-500" @click="handleDeleteMenu(index)" />
</div>
<el-form-item label="图标" prop="iconUrl">
<UploadImg v-model="element.iconUrl" height="80px" width="80px">
<template #tip> 建议尺寸44 * 44 </template>
</UploadImg>
</el-form-item>
<el-form-item label="标题" prop="title">
<InputWithColor v-model="element.title" v-model:color="element.titleColor" />
</el-form-item>
<el-form-item label="副标题" prop="subtitle">
<InputWithColor v-model="element.subtitle" v-model:color="element.subtitleColor" />
</el-form-item>
<el-form-item label="链接" prop="url">
<el-input v-model="element.url" />
</el-form-item>
<el-form-item label="显示角标" prop="badge.show">
<el-switch v-model="element.badge.show" />
</el-form-item>
<template v-if="element.badge.show">
<el-form-item label="角标内容" prop="badge.text">
<InputWithColor
v-model="element.badge.text"
v-model:color="element.badge.textColor"
/>
</el-form-item>
<el-form-item label="背景颜色" prop="badge.bgColor">
<ColorInput v-model="element.badge.bgColor" />
</el-form-item>
</template>
</div>
</template>
</VueDraggable>
</template>
<el-form-item label-width="0">
<el-button @click="handleAddMenu" type="primary" plain class="m-t-8px w-full">
<Icon icon="ep:plus" class="mr-5px" /> 添加菜单
</el-button>
</el-form-item>
</el-form>
</ComponentContainerProperty>
</template>
<script setup lang="ts">
import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util'
import {
EMPTY_MENU_GRID_ITEM_PROPERTY,
MenuGridProperty
} from '@/components/DiyEditor/components/mobile/MenuGrid/config'
import { cloneDeep } from 'lodash-es'
/** 宫格导航属性面板 */
defineOptions({ name: 'MenuGridProperty' })
const props = defineProps<{ modelValue: MenuGridProperty }>()
const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit)
/* 添加菜单 */
const handleAddMenu = () => {
formData.value.list.push(cloneDeep(EMPTY_MENU_GRID_ITEM_PROPERTY))
}
/* 删除菜单 */
const handleDeleteMenu = (index: number) => {
formData.value.list.splice(index, 1)
}
</script>
<style scoped lang="scss"></style>

View File

@ -1,4 +1,5 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
import { cloneDeep } from 'lodash-es'
/** 列表导航属性 */ /** 列表导航属性 */
export interface MenuListProperty { export interface MenuListProperty {
@ -23,13 +24,20 @@ export interface MenuListItemProperty {
url: string url: string
} }
export const EMPTY_MENU_LIST_ITEM_PROPERTY = {
title: '标题',
titleColor: '#333',
subtitle: '副标题',
subtitleColor: '#bbb'
}
// 定义组件 // 定义组件
export const component = { export const component = {
id: 'MenuList', id: 'MenuList',
name: '列表导航', name: '列表导航',
icon: 'fa-solid:list', icon: 'fa-solid:list',
property: { property: {
list: [], list: [cloneDeep(EMPTY_MENU_LIST_ITEM_PROPERTY)],
style: { style: {
bgType: 'color', bgType: 'color',
bgColor: '#fff', bgColor: '#fff',

View File

@ -49,7 +49,11 @@
<script setup lang="ts"> <script setup lang="ts">
import VueDraggable from 'vuedraggable' import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
import { MenuListProperty } from '@/components/DiyEditor/components/mobile/MenuList/config' import {
EMPTY_MENU_LIST_ITEM_PROPERTY,
MenuListProperty
} from '@/components/DiyEditor/components/mobile/MenuList/config'
import { cloneDeep } from 'lodash-es'
/** 列表导航属性面板 */ /** 列表导航属性面板 */
defineOptions({ name: 'MenuListProperty' }) defineOptions({ name: 'MenuListProperty' })
@ -60,10 +64,7 @@ const { formData } = usePropertyForm(props.modelValue, emit)
/* 添加菜单 */ /* 添加菜单 */
const handleAddMenu = () => { const handleAddMenu = () => {
formData.value.list.push({ formData.value.list.push(cloneDeep(EMPTY_MENU_LIST_ITEM_PROPERTY))
titleColor: '#333',
subtitleColor: '#bbb'
})
} }
/* 删除菜单 */ /* 删除菜单 */
const handleDeleteMenu = (index: number) => { const handleDeleteMenu = (index: number) => {