营销:装修页面适配搜索框
This commit is contained in:
parent
a9faeb1bdb
commit
aedf014407
45
src/components/DiyEditor/components/ComponentContainer.vue
Normal file
45
src/components/DiyEditor/components/ComponentContainer.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
...style,
|
||||||
|
background: property.bgType === 'color' ? property.bgColor : `url(${property.bgImg})`
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ComponentStyle } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件容器
|
||||||
|
* 用于包裹组件,为组件提供 背景、外边距、内边距、边框等样式
|
||||||
|
*/
|
||||||
|
defineOptions({ name: 'ComponentContainer' })
|
||||||
|
|
||||||
|
const props = defineProps<{ property: ComponentStyle }>()
|
||||||
|
|
||||||
|
const style = computed(() => {
|
||||||
|
if (!props.property) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
marginTop: `${props.property.marginTop || 0}px`,
|
||||||
|
marginBottom: `${props.property.marginBottom || 0}px`,
|
||||||
|
marginLeft: `${props.property.marginLeft || 0}px`,
|
||||||
|
marginRight: `${props.property.marginRight || 0}px`,
|
||||||
|
paddingTop: `${props.property.paddingTop || 0}px`,
|
||||||
|
paddingRight: `${props.property.paddingRight || 0}px`,
|
||||||
|
paddingBottom: `${props.property.paddingBottom || 0}px`,
|
||||||
|
paddingLeft: `${props.property.paddingLeft || 0}px`,
|
||||||
|
borderTopLeftRadius: `${props.property.borderTopLeftRadius || 0}px`,
|
||||||
|
borderTopRightRadius: `${props.property.borderTopRightRadius || 0}px`,
|
||||||
|
borderBottomRightRadius: `${props.property.borderBottomRightRadius || 0}px`,
|
||||||
|
borderBottomLeftRadius: `${props.property.borderBottomLeftRadius || 0}px`,
|
||||||
|
overflow: 'hidden'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
@ -0,0 +1,164 @@
|
|||||||
|
<template>
|
||||||
|
<el-tabs stretch>
|
||||||
|
<el-tab-pane label="内容">
|
||||||
|
<slot></slot>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="样式" lazy>
|
||||||
|
<el-card header="组件样式" class="property-group">
|
||||||
|
<el-form :model="formData" label-width="80px">
|
||||||
|
<el-form-item label="组件背景" prop="bgType">
|
||||||
|
<el-radio-group v-model="formData.bgType">
|
||||||
|
<el-radio label="color">纯色</el-radio>
|
||||||
|
<el-radio label="img">图片</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="选择颜色" prop="bgColor" v-if="formData.bgType === 'color'">
|
||||||
|
<ColorInput v-model="formData.bgColor" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上传图片" prop="bgImg" v-else>
|
||||||
|
<UploadImg v-model="formData.bgImg" :limit="1">
|
||||||
|
<template #tip>建议宽度 750px</template>
|
||||||
|
</UploadImg>
|
||||||
|
</el-form-item>
|
||||||
|
<el-tree :data="treeData" :expand-on-click-node="false">
|
||||||
|
<template #default="{ node, data }">
|
||||||
|
<el-form-item
|
||||||
|
:label="data.label"
|
||||||
|
:prop="data.prop"
|
||||||
|
:label-width="node.level === 1 ? '80px' : '62px'"
|
||||||
|
class="tree-form-item w-full m-b-0!"
|
||||||
|
>
|
||||||
|
<el-slider
|
||||||
|
v-model="formData[data.prop]"
|
||||||
|
:max="100"
|
||||||
|
:min="0"
|
||||||
|
show-input
|
||||||
|
input-size="small"
|
||||||
|
:show-input-controls="false"
|
||||||
|
@input="handleSliderChange(data.prop)"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ComponentStyle, usePropertyForm } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件容器属性
|
||||||
|
* 用于包裹组件,为组件提供 背景、外边距、内边距、边框等样式
|
||||||
|
*/
|
||||||
|
defineOptions({ name: 'ComponentContainer' })
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: ComponentStyle }>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||||
|
|
||||||
|
const treeData = [
|
||||||
|
{
|
||||||
|
label: '外部边距',
|
||||||
|
prop: 'margin',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: '上',
|
||||||
|
prop: 'marginTop'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '右',
|
||||||
|
prop: 'marginRight'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '下',
|
||||||
|
prop: 'marginBottom'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '左',
|
||||||
|
prop: 'marginLeft'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '内部边距',
|
||||||
|
prop: 'padding',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: '上',
|
||||||
|
prop: 'paddingTop'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '右',
|
||||||
|
prop: 'paddingRight'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '下',
|
||||||
|
prop: 'paddingBottom'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '左',
|
||||||
|
prop: 'paddingLeft'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '边框圆角',
|
||||||
|
prop: 'borderRadius',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: '上左',
|
||||||
|
prop: 'borderTopLeftRadius'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '上右',
|
||||||
|
prop: 'borderTopRightRadius'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '下右',
|
||||||
|
prop: 'borderBottomRightRadius'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '下左',
|
||||||
|
prop: 'borderBottomLeftRadius'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const handleSliderChange = (prop: string) => {
|
||||||
|
switch (prop) {
|
||||||
|
case 'margin':
|
||||||
|
formData.value.marginTop = formData.value.margin
|
||||||
|
formData.value.marginRight = formData.value.margin
|
||||||
|
formData.value.marginBottom = formData.value.margin
|
||||||
|
formData.value.marginLeft = formData.value.margin
|
||||||
|
break
|
||||||
|
case 'padding':
|
||||||
|
formData.value.paddingTop = formData.value.padding
|
||||||
|
formData.value.paddingRight = formData.value.padding
|
||||||
|
formData.value.paddingBottom = formData.value.padding
|
||||||
|
formData.value.paddingLeft = formData.value.padding
|
||||||
|
break
|
||||||
|
case 'borderRadius':
|
||||||
|
formData.value.borderTopLeftRadius = formData.value.borderRadius
|
||||||
|
formData.value.borderTopRightRadius = formData.value.borderRadius
|
||||||
|
formData.value.borderBottomRightRadius = formData.value.borderRadius
|
||||||
|
formData.value.borderBottomLeftRadius = formData.value.borderRadius
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.tree-form-item {
|
||||||
|
:deep(.el-slider__runway) {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
:deep(.el-input-number) {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-aside class="editor-left" width="260px">
|
<el-aside class="editor-left" width="261px">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<el-collapse v-model="extendGroups">
|
<el-collapse v-model="extendGroups">
|
||||||
<el-collapse-item
|
<el-collapse-item
|
||||||
|
@ -29,7 +29,7 @@ export const component = {
|
|||||||
title: '页面标题',
|
title: '页面标题',
|
||||||
description: '',
|
description: '',
|
||||||
navBarHeight: 35,
|
navBarHeight: 35,
|
||||||
backgroundColor: '#f5f5f5',
|
backgroundColor: '#fff',
|
||||||
backgroundImage: '',
|
backgroundImage: '',
|
||||||
styleType: 'default',
|
styleType: 'default',
|
||||||
alwaysShow: true,
|
alwaysShow: true,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { DiyComponent } from '@/components/DiyEditor/util'
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
/** 搜索框属性 */
|
/** 搜索框属性 */
|
||||||
export interface SearchProperty {
|
export interface SearchProperty {
|
||||||
@ -7,10 +7,10 @@ export interface SearchProperty {
|
|||||||
borderRadius: number // 框体样式
|
borderRadius: number // 框体样式
|
||||||
placeholder: string // 占位文字
|
placeholder: string // 占位文字
|
||||||
placeholderPosition: PlaceholderPosition // 占位文字位置
|
placeholderPosition: PlaceholderPosition // 占位文字位置
|
||||||
backgroundColor: string // 背景颜色
|
backgroundColor: string // 框体颜色
|
||||||
borderColor: string // 框体颜色
|
|
||||||
textColor: string // 字体颜色
|
textColor: string // 字体颜色
|
||||||
hotKeywords: string[] // 热词
|
hotKeywords: string[] // 热词
|
||||||
|
style: ComponentStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文字位置
|
// 文字位置
|
||||||
@ -27,9 +27,17 @@ export const component = {
|
|||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
placeholder: '搜索商品',
|
placeholder: '搜索商品',
|
||||||
placeholderPosition: 'left',
|
placeholderPosition: 'left',
|
||||||
backgroundColor: 'rgb(249, 249, 249)',
|
backgroundColor: 'rgb(238, 238, 238)',
|
||||||
borderColor: 'rgb(255, 255, 255)',
|
|
||||||
textColor: 'rgb(150, 151, 153)',
|
textColor: 'rgb(150, 151, 153)',
|
||||||
hotKeywords: []
|
hotKeywords: [],
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '#fff',
|
||||||
|
marginBottom: 8,
|
||||||
|
paddingTop: 8,
|
||||||
|
paddingRight: 8,
|
||||||
|
paddingBottom: 8,
|
||||||
|
paddingLeft: 8
|
||||||
|
} as ComponentStyle
|
||||||
}
|
}
|
||||||
} as DiyComponent<SearchProperty>
|
} as DiyComponent<SearchProperty>
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
<div
|
<div
|
||||||
class="search-bar"
|
class="search-bar"
|
||||||
:style="{
|
:style="{
|
||||||
background: property.backgroundColor,
|
|
||||||
border: `1px solid ${property.backgroundColor}`,
|
|
||||||
color: property.textColor
|
color: property.textColor
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
@ -12,7 +10,7 @@
|
|||||||
class="inner"
|
class="inner"
|
||||||
:style="{
|
:style="{
|
||||||
height: `${property.height}px`,
|
height: `${property.height}px`,
|
||||||
background: property.borderColor,
|
background: property.backgroundColor,
|
||||||
borderRadius: `${property.borderRadius}px`
|
borderRadius: `${property.borderRadius}px`
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
@ -44,13 +42,11 @@ defineProps<{ property: SearchProperty }>()
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.search-bar {
|
.search-bar {
|
||||||
position: relative;
|
width: 375px;
|
||||||
/* 搜索框 */
|
/* 搜索框 */
|
||||||
.inner {
|
.inner {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: calc(100% - 16px);
|
|
||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
margin: 5px auto;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -1,78 +1,77 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-text tag="p"> 搜索热词 </el-text>
|
<ComponentContainerProperty v-model="formData.style">
|
||||||
<el-text type="info" size="small"> 拖动左侧的小圆点可以调整热词顺序 </el-text>
|
<el-text tag="p"> 搜索热词 </el-text>
|
||||||
|
<el-text type="info" size="small"> 拖动左侧的小圆点可以调整热词顺序 </el-text>
|
||||||
|
|
||||||
<!-- 表单 -->
|
<!-- 表单 -->
|
||||||
<el-form label-width="80px" :model="formData" class="m-t-8px">
|
<el-form label-width="80px" :model="formData" class="m-t-8px">
|
||||||
<div v-if="formData.hotKeywords.length">
|
<div v-if="formData.hotKeywords.length">
|
||||||
<VueDraggable
|
<VueDraggable
|
||||||
:list="formData.hotKeywords"
|
:list="formData.hotKeywords"
|
||||||
item-key="index"
|
item-key="index"
|
||||||
handle=".drag-icon"
|
handle=".drag-icon"
|
||||||
:forceFallback="true"
|
:forceFallback="true"
|
||||||
:animation="200"
|
:animation="200"
|
||||||
>
|
>
|
||||||
<template #item="{ index }">
|
<template #item="{ index }">
|
||||||
<div class="mb-4px flex flex-row items-center gap-4px rounded bg-gray-100 p-8px">
|
<div class="mb-4px flex flex-row items-center gap-4px rounded bg-gray-100 p-8px">
|
||||||
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
|
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
|
||||||
<el-input v-model="formData.hotKeywords[index]" placeholder="请输入热词" />
|
<el-input v-model="formData.hotKeywords[index]" placeholder="请输入热词" />
|
||||||
<Icon icon="ep:delete" class="text-red-500" @click="deleteHotWord(index)" />
|
<Icon icon="ep:delete" class="text-red-500" @click="deleteHotWord(index)" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VueDraggable>
|
</VueDraggable>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item label-width="0">
|
<el-form-item label-width="0">
|
||||||
<el-button @click="handleAddHotWord" type="primary" plain class="m-t-8px w-full">
|
<el-button @click="handleAddHotWord" type="primary" plain class="m-t-8px w-full">
|
||||||
添加热词
|
添加热词
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="框体样式">
|
<el-form-item label="框体样式">
|
||||||
<el-radio-group v-model="formData!.borderRadius">
|
<el-radio-group v-model="formData!.borderRadius">
|
||||||
<el-tooltip content="方形" placement="top">
|
<el-tooltip content="方形" placement="top">
|
||||||
<el-radio-button :label="0">
|
<el-radio-button :label="0">
|
||||||
<Icon icon="tabler:input-search" />
|
<Icon icon="tabler:input-search" />
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="圆形" placement="top">
|
<el-tooltip content="圆形" placement="top">
|
||||||
<el-radio-button :label="10">
|
<el-radio-button :label="10">
|
||||||
<Icon icon="iconoir:input-search" />
|
<Icon icon="iconoir:input-search" />
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="提示文字" prop="placeholder">
|
<el-form-item label="提示文字" prop="placeholder">
|
||||||
<el-input v-model="formData.placeholder" />
|
<el-input v-model="formData.placeholder" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="文本位置" prop="placeholderPosition">
|
<el-form-item label="文本位置" prop="placeholderPosition">
|
||||||
<el-radio-group v-model="formData!.placeholderPosition">
|
<el-radio-group v-model="formData!.placeholderPosition">
|
||||||
<el-tooltip content="居左" placement="top">
|
<el-tooltip content="居左" placement="top">
|
||||||
<el-radio-button label="left">
|
<el-radio-button label="left">
|
||||||
<Icon icon="ant-design:align-left-outlined" />
|
<Icon icon="ant-design:align-left-outlined" />
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="居中" placement="top">
|
<el-tooltip content="居中" placement="top">
|
||||||
<el-radio-button label="center">
|
<el-radio-button label="center">
|
||||||
<Icon icon="ant-design:align-center-outlined" />
|
<Icon icon="ant-design:align-center-outlined" />
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="扫一扫" prop="showScan">
|
<el-form-item label="扫一扫" prop="showScan">
|
||||||
<el-switch v-model="formData!.showScan" />
|
<el-switch v-model="formData!.showScan" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="框体高度" prop="height">
|
<el-form-item label="框体高度" prop="height">
|
||||||
<el-slider v-model="formData!.height" :max="50" :min="28" show-input input-size="small" />
|
<el-slider v-model="formData!.height" :max="50" :min="28" show-input input-size="small" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="背景颜色" prop="backgroundColor">
|
<el-form-item label="框体颜色" prop="backgroundColor">
|
||||||
<ColorInput v-model="formData.backgroundColor" />
|
<ColorInput v-model="formData.backgroundColor" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="框体颜色" prop="borderColor">
|
<el-form-item class="lef" label="文本颜色" prop="textColor">
|
||||||
<ColorInput v-model="formData.borderColor" />
|
<ColorInput v-model="formData.textColor" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item class="lef" label="文本颜色" prop="textColor">
|
</el-form>
|
||||||
<ColorInput v-model="formData.textColor" />
|
</ComponentContainerProperty>
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -427,11 +427,13 @@ $phone-width: 375px;
|
|||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
}
|
}
|
||||||
/* 属性面板分组 */
|
/* 属性面板分组 */
|
||||||
.property-group {
|
:deep(.property-group) {
|
||||||
/* 属性分组 */
|
margin: 0 -20px;
|
||||||
:deep(.el-card__header) {
|
/* 属性分组名称 */
|
||||||
|
.el-card__header {
|
||||||
border: none;
|
border: none;
|
||||||
background: var(--el-bg-color-page);
|
background: var(--el-bg-color-page);
|
||||||
|
padding: 8px 32px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,34 @@ export interface DiyComponentLibrary {
|
|||||||
components: string[]
|
components: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 组件样式
|
||||||
|
export interface ComponentStyle {
|
||||||
|
// 背景类型
|
||||||
|
bgType: 'color' | 'img'
|
||||||
|
// 背景颜色
|
||||||
|
bgColor: string
|
||||||
|
// 背景图片
|
||||||
|
bgImg: string
|
||||||
|
// 外边距
|
||||||
|
margin: number
|
||||||
|
marginTop: number
|
||||||
|
marginRight: number
|
||||||
|
marginBottom: number
|
||||||
|
marginLeft: number
|
||||||
|
// 内边距
|
||||||
|
padding: number
|
||||||
|
paddingTop: number
|
||||||
|
paddingRight: number
|
||||||
|
paddingBottom: number
|
||||||
|
paddingLeft: number
|
||||||
|
// 边框圆角
|
||||||
|
borderRadius: number
|
||||||
|
borderTopLeftRadius: number
|
||||||
|
borderTopRightRadius: number
|
||||||
|
borderBottomRightRadius: number
|
||||||
|
borderBottomLeftRadius: number
|
||||||
|
}
|
||||||
|
|
||||||
// 页面配置
|
// 页面配置
|
||||||
export interface PageConfig {
|
export interface PageConfig {
|
||||||
// 页面属性
|
// 页面属性
|
||||||
|
Loading…
Reference in New Issue
Block a user