封装拖拽组件,提供移动、新增、删除功能

This commit is contained in:
owen 2023-12-08 21:54:11 +08:00
parent 9ff4f1f7a9
commit 59ff6b13fb
10 changed files with 325 additions and 462 deletions

View File

@ -39,87 +39,60 @@
</el-form-item> </el-form-item>
</el-card> </el-card>
<el-card header="内容设置" class="property-group" shadow="never"> <el-card header="内容设置" class="property-group" shadow="never">
<el-text type="info" size="small"> 拖动左上角的小圆点可对其排序 </el-text> <Draggable v-model="formData.items" :empty-item="{ type: 'img' }">
<template v-if="formData.items[0]"> <template #default="{ element }">
<draggable <el-form-item label="类型" prop="type" class="m-b-8px!" label-width="40px">
:list="formData.items" <el-radio-group v-model="element.type">
:force-fallback="true" <el-radio label="img">图片</el-radio>
:animation="200" <el-radio label="video">视频</el-radio>
handle=".drag-icon" </el-radio-group>
class="m-t-8px" </el-form-item>
item-key="index" <el-form-item
> label="图片"
<template #item="{ element, index }"> class="m-b-8px!"
<div class="content mb-4px flex flex-col gap-4px rounded bg-gray-50 p-8px"> label-width="40px"
<div v-if="element.type === 'img'"
class="m--8px m-b-8px flex flex-row items-center justify-between bg-gray-100 p-8px" >
> <UploadImg
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" /> v-model="element.imgUrl"
<Icon draggable="false"
icon="ep:delete" height="80px"
class="cursor-pointer text-red-5" width="100%"
@click="handleDeleteImage(index)" class="min-w-80px"
v-if="formData.items.length > 1" />
/> </el-form-item>
</div> <template v-else>
<el-form-item label="类型" prop="type" class="m-b-8px!" label-width="50px"> <el-form-item label="封面" class="m-b-8px!" label-width="40px">
<el-radio-group v-model="element.type"> <UploadImg
<el-radio label="img">图片</el-radio> v-model="element.imgUrl"
<el-radio label="video">视频</el-radio> draggable="false"
</el-radio-group> height="80px"
</el-form-item> width="100%"
<el-form-item class="min-w-80px"
label="图片" />
class="m-b-8px!" </el-form-item>
label-width="50px" <el-form-item label="视频" class="m-b-8px!" label-width="40px">
v-if="element.type === 'img'" <UploadFile
> v-model="element.videoUrl"
<UploadImg :file-type="['mp4']"
v-model="element.imgUrl" :limit="1"
draggable="false" :file-size="100"
height="80px" class="min-w-80px"
width="100%" />
class="min-w-80px" </el-form-item>
/>
</el-form-item>
<template v-else>
<el-form-item label="封面" class="m-b-8px!" label-width="50px">
<UploadImg
v-model="element.imgUrl"
draggable="false"
height="80px"
width="100%"
class="min-w-80px"
/>
</el-form-item>
<el-form-item label="视频" class="m-b-8px!" label-width="50px">
<UploadFile
v-model="element.videoUrl"
:file-type="['mp4']"
:limit="1"
:file-size="100"
class="min-w-80px"
/>
</el-form-item>
</template>
<el-form-item label="链接" class="m-b-8px!" label-width="50px">
<AppLinkInput v-model="element.url" />
</el-form-item>
</div>
</template> </template>
</draggable> <el-form-item label="链接" class="m-b-8px!" label-width="40px">
</template> <AppLinkInput v-model="element.url" />
<el-button @click="handleAddImage" type="primary" plain class="w-full"> </el-form-item>
添加图片 </template>
</el-button> </Draggable>
</el-card> </el-card>
</el-form> </el-form>
</ComponentContainerProperty> </ComponentContainerProperty>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import draggable from 'vuedraggable' // import { CarouselProperty } from './config'
import { CarouselItemProperty, CarouselProperty } from './config'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
// //
@ -128,15 +101,6 @@ defineOptions({ name: 'CarouselProperty' })
const props = defineProps<{ modelValue: CarouselProperty }>() const props = defineProps<{ modelValue: CarouselProperty }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit) const { formData } = usePropertyForm(props.modelValue, emit)
//
const handleAddImage = () => {
formData.value.items.push({} as CarouselItemProperty)
}
//
const handleDeleteImage = (index: number) => {
formData.value.items.splice(index, 1)
}
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@ -9,72 +9,50 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-text tag="p"> 菜单设置 </el-text> <el-card header="菜单设置" class="property-group" shadow="never">
<el-text type="info" size="small"> 拖动左侧的小圆点可以调整顺序 </el-text> <Draggable v-model="formData.list" :empty-item="EMPTY_MENU_GRID_ITEM_PROPERTY">
<template v-if="formData.list.length"> <template #default="{ element }">
<VueDraggable <el-form-item label="图标" prop="iconUrl">
class="m-t-8px" <UploadImg v-model="element.iconUrl" height="80px" width="80px">
:list="formData.list" <template #tip> 建议尺寸44 * 44 </template>
item-key="index" </UploadImg>
handle=".drag-icon" </el-form-item>
:forceFallback="true" <el-form-item label="标题" prop="title">
:animation="200" <InputWithColor v-model="element.title" v-model:color="element.titleColor" />
> </el-form-item>
<template #item="{ element, index }"> <el-form-item label="副标题" prop="subtitle">
<div class="mb-4px flex flex-col gap-4px rounded bg-gray-100 p-8px"> <InputWithColor v-model="element.subtitle" v-model:color="element.subtitleColor" />
<div class="flex flex-row justify-between"> </el-form-item>
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" /> <el-form-item label="链接" prop="url">
<Icon icon="ep:delete" class="text-red-500" @click="handleDeleteMenu(index)" /> <AppLinkInput v-model="element.url" />
</div> </el-form-item>
<el-form-item label="图标" prop="iconUrl"> <el-form-item label="显示角标" prop="badge.show">
<UploadImg v-model="element.iconUrl" height="80px" width="80px"> <el-switch v-model="element.badge.show" />
<template #tip> 建议尺寸44 * 44 </template> </el-form-item>
</UploadImg> <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>
<el-form-item label="标题" prop="title"> <el-form-item label="背景颜色" prop="badge.bgColor">
<InputWithColor v-model="element.title" v-model:color="element.titleColor" /> <ColorInput v-model="element.badge.bgColor" />
</el-form-item> </el-form-item>
<el-form-item label="副标题" prop="subtitle"> </template>
<InputWithColor v-model="element.subtitle" v-model:color="element.subtitleColor" />
</el-form-item>
<el-form-item label="链接" prop="url">
<AppLinkInput 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> </template>
</VueDraggable> </Draggable>
</template> </el-card>
<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> </el-form>
</ComponentContainerProperty> </ComponentContainerProperty>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
import { import {
EMPTY_MENU_GRID_ITEM_PROPERTY, EMPTY_MENU_GRID_ITEM_PROPERTY,
MenuGridProperty MenuGridProperty
} from '@/components/DiyEditor/components/mobile/MenuGrid/config' } from '@/components/DiyEditor/components/mobile/MenuGrid/config'
import { cloneDeep } from 'lodash-es'
/** 宫格导航属性面板 */ /** 宫格导航属性面板 */
defineOptions({ name: 'MenuGridProperty' }) defineOptions({ name: 'MenuGridProperty' })
@ -82,15 +60,6 @@ defineOptions({ name: 'MenuGridProperty' })
const props = defineProps<{ modelValue: MenuGridProperty }>() const props = defineProps<{ modelValue: MenuGridProperty }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit) 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> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@ -5,55 +5,34 @@
<!-- 表单 --> <!-- 表单 -->
<el-form label-width="60px" :model="formData" class="m-t-8px"> <el-form label-width="60px" :model="formData" class="m-t-8px">
<div v-if="formData.list.length"> <Draggable v-model="formData.list" :empty-item="EMPTY_MENU_LIST_ITEM_PROPERTY">
<VueDraggable <template #default="{ element }">
:list="formData.list" <el-form-item label="图标" prop="iconUrl">
item-key="index" <UploadImg v-model="element.iconUrl" height="80px" width="80px">
handle=".drag-icon" <template #tip> 建议尺寸44 * 44 </template>
:forceFallback="true" </UploadImg>
:animation="200" </el-form-item>
> <el-form-item label="标题" prop="title">
<template #item="{ element, index }"> <InputWithColor v-model="element.title" v-model:color="element.titleColor" />
<div class="mb-4px flex flex-col gap-4px rounded bg-gray-100 p-8px"> </el-form-item>
<div class="flex flex-row justify-between"> <el-form-item label="副标题" prop="subtitle">
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" /> <InputWithColor v-model="element.subtitle" v-model:color="element.subtitleColor" />
<Icon icon="ep:delete" class="text-red-500" @click="handleDeleteMenu(index)" /> </el-form-item>
</div> <el-form-item label="链接" prop="url">
<el-form-item label="图标" prop="iconUrl"> <AppLinkInput v-model="element.url" />
<UploadImg v-model="element.iconUrl" height="80px" width="80px"> </el-form-item>
<template #tip> 建议尺寸44 * 44 </template> </template>
</UploadImg> </Draggable>
</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">
<AppLinkInput v-model="element.url" />
</el-form-item>
</div>
</template>
</VueDraggable>
</div>
<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> </el-form>
</ComponentContainerProperty> </ComponentContainerProperty>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
import { import {
EMPTY_MENU_LIST_ITEM_PROPERTY, EMPTY_MENU_LIST_ITEM_PROPERTY,
MenuListProperty MenuListProperty
} from '@/components/DiyEditor/components/mobile/MenuList/config' } from '@/components/DiyEditor/components/mobile/MenuList/config'
import { cloneDeep } from 'lodash-es'
/** 列表导航属性面板 */ /** 列表导航属性面板 */
defineOptions({ name: 'MenuListProperty' }) defineOptions({ name: 'MenuListProperty' })
@ -61,15 +40,6 @@ defineOptions({ name: 'MenuListProperty' })
const props = defineProps<{ modelValue: MenuListProperty }>() const props = defineProps<{ modelValue: MenuListProperty }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit) const { formData } = usePropertyForm(props.modelValue, emit)
/* 添加菜单 */
const handleAddMenu = () => {
formData.value.list.push(cloneDeep(EMPTY_MENU_LIST_ITEM_PROPERTY))
}
/* 删除菜单 */
const handleDeleteMenu = (index: number) => {
formData.value.list.splice(index, 1)
}
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@ -22,63 +22,42 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-text tag="p"> 菜单设置 </el-text> <el-card header="菜单设置" class="property-group" shadow="never">
<el-text type="info" size="small"> 拖动左侧的小圆点可以调整顺序 </el-text> <Draggable v-model="formData.list" :empty-item="cloneDeep(EMPTY_MENU_SWIPER_ITEM_PROPERTY">
<template v-if="formData.list.length"> <template #default="{ element }">
<VueDraggable <el-form-item label="图标" prop="iconUrl">
class="m-t-8px" <UploadImg v-model="element.iconUrl" height="80px" width="80px">
:list="formData.list" <template #tip> 建议尺寸98 * 98 </template>
item-key="index" </UploadImg>
handle=".drag-icon" </el-form-item>
:forceFallback="true" <el-form-item label="标题" prop="title">
:animation="200" <InputWithColor v-model="element.title" v-model:color="element.titleColor" />
> </el-form-item>
<template #item="{ element, index }"> <el-form-item label="链接" prop="url">
<div class="mb-4px flex flex-col gap-4px rounded bg-gray-100 p-8px"> <AppLinkInput v-model="element.url" />
<div class="flex flex-row justify-between"> </el-form-item>
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" /> <el-form-item label="显示角标" prop="badge.show">
<Icon icon="ep:delete" class="text-red-500" @click="handleDeleteMenu(index)" /> <el-switch v-model="element.badge.show" />
</div> </el-form-item>
<el-form-item label="图标" prop="iconUrl"> <template v-if="element.badge.show">
<UploadImg v-model="element.iconUrl" height="80px" width="80px"> <el-form-item label="角标内容" prop="badge.text">
<template #tip> 建议尺寸98 * 98 </template> <InputWithColor
</UploadImg> v-model="element.badge.text"
v-model:color="element.badge.textColor"
/>
</el-form-item> </el-form-item>
<el-form-item label="标题" prop="title"> <el-form-item label="背景颜色" prop="badge.bgColor">
<InputWithColor v-model="element.title" v-model:color="element.titleColor" /> <ColorInput v-model="element.badge.bgColor" />
</el-form-item> </el-form-item>
<el-form-item label="链接" prop="url"> </template>
<AppLinkInput 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> </template>
</VueDraggable> </Draggable>
</template> </el-card>
<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> </el-form>
</ComponentContainerProperty> </ComponentContainerProperty>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
import { import {
EMPTY_MENU_SWIPER_ITEM_PROPERTY, EMPTY_MENU_SWIPER_ITEM_PROPERTY,
@ -92,15 +71,6 @@ defineOptions({ name: 'MenuSwiperProperty' })
const props = defineProps<{ modelValue: MenuSwiperProperty }>() const props = defineProps<{ modelValue: MenuSwiperProperty }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit) const { formData } = usePropertyForm(props.modelValue, emit)
/* 添加菜单 */
const handleAddMenu = () => {
formData.value.list.push(cloneDeep(EMPTY_MENU_SWIPER_ITEM_PROPERTY))
}
/* 删除菜单 */
const handleDeleteMenu = (index: number) => {
formData.value.list.splice(index, 1)
}
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@ -1,4 +1,4 @@
import { DiyComponent } from '@/components/DiyEditor/util' import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
/** 公告栏属性 */ /** 公告栏属性 */
export interface NoticeBarProperty { export interface NoticeBarProperty {
@ -10,6 +10,8 @@ export interface NoticeBarProperty {
backgroundColor: string backgroundColor: string
// 文字颜色 // 文字颜色
textColor: string textColor: string
// 组件样式
style: ComponentStyle
} }
/** 内容属性 */ /** 内容属性 */
@ -34,6 +36,11 @@ export const component = {
} }
], ],
backgroundColor: '#fff', backgroundColor: '#fff',
textColor: '#333' textColor: '#333',
style: {
bgType: 'color',
bgColor: '#fff',
marginBottom: 8
} as ComponentStyle
} }
} as DiyComponent<NoticeBarProperty> } as DiyComponent<NoticeBarProperty>

View File

@ -1,58 +1,37 @@
<template> <template>
<el-form label-width="80px" :model="formData" :rules="rules"> <ComponentContainerProperty v-model="formData.style">
<el-form-item label="公告图标" prop="iconUrl"> <el-form label-width="80px" :model="formData" :rules="rules">
<UploadImg v-model="formData.iconUrl" height="48px"> <el-form-item label="公告图标" prop="iconUrl">
<template #tip>建议尺寸24 * 24</template> <UploadImg v-model="formData.iconUrl" height="48px">
</UploadImg> <template #tip>建议尺寸24 * 24</template>
</el-form-item> </UploadImg>
<el-form-item label="背景颜色" prop="backgroundColor"> </el-form-item>
<ColorInput v-model="formData.backgroundColor" /> <el-form-item label="背景颜色" prop="backgroundColor">
</el-form-item> <ColorInput v-model="formData.backgroundColor" />
<el-form-item label="文字颜色" prop="文字颜色"> </el-form-item>
<ColorInput v-model="formData.textColor" /> <el-form-item label="文字颜色" prop="文字颜色">
</el-form-item> <ColorInput v-model="formData.textColor" />
<el-text tag="p"> 公告内容 </el-text> </el-form-item>
<el-text type="info" size="small"> 拖动左上角的小圆点可以调整热词顺序 </el-text>
<template v-if="formData.contents.length"> <el-card header="公告内容" class="property-group" shadow="never">
<VueDraggable <Draggable v-model="formData.contents">
:list="formData.contents" <template #default="{ element }">
item-key="index" <el-form-item label="公告" prop="text" label-width="40px">
handle=".drag-icon"
:forceFallback="true"
:animation="200"
class="m-t-8px"
>
<template #item="{ element, index }">
<div class="mb-4px flex flex-row gap-4px rounded bg-gray-100 p-8px">
<div class="flex flex-col items-start justify-between">
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
<Icon
icon="ep:delete"
class="cursor-pointer text-red-5"
@click="handleDeleteContent(index)"
v-if="formData.contents.length > 1"
/>
</div>
<div class="w-full flex flex-col gap-8px">
<el-input v-model="element.text" placeholder="请输入公告" /> <el-input v-model="element.text" placeholder="请输入公告" />
</el-form-item>
<el-form-item label="链接" prop="url" label-width="40px">
<AppLinkInput v-model="element.url" /> <AppLinkInput v-model="element.url" />
</div> </el-form-item>
</div> </template>
</template> </Draggable>
</VueDraggable> </el-card>
</template> </el-form>
<el-form-item label-width="0"> </ComponentContainerProperty>
<el-button @click="handleAddContent" type="primary" plain class="m-t-8px w-full">
添加内容
</el-button>
</el-form-item>
</el-form>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { NoticeBarProperty, NoticeContentProperty } from './config' import { NoticeBarProperty } from './config'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
import VueDraggable from 'vuedraggable'
// //
defineOptions({ name: 'NoticeBarProperty' }) defineOptions({ name: 'NoticeBarProperty' })
// //
@ -63,15 +42,6 @@ const rules = {
const props = defineProps<{ modelValue: NoticeBarProperty }>() const props = defineProps<{ modelValue: NoticeBarProperty }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit) const { formData } = usePropertyForm(props.modelValue, emit)
/* 添加公告 */
const handleAddContent = () => {
formData.value.contents.push({} as NoticeContentProperty)
}
/* 删除公告 */
const handleDeleteContent = (index: number) => {
formData.value.contents.splice(index, 1)
}
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@ -1,81 +1,64 @@
<template> <template>
<ComponentContainerProperty v-model="formData.style"> <ComponentContainerProperty v-model="formData.style">
<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"> <el-card header="搜索热词" class="property-group" shadow="never">
<VueDraggable <Draggable v-model="formData.hotKeywords" :empty-item="''">
:list="formData.hotKeywords" <template #default="{ index }">
item-key="index" <el-input v-model="formData.hotKeywords[index]" placeholder="请输入热词" />
handle=".drag-icon"
:forceFallback="true"
:animation="200"
>
<template #item="{ index }">
<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" />
<el-input v-model="formData.hotKeywords[index]" placeholder="请输入热词" />
<Icon icon="ep:delete" class="text-red-500" @click="deleteHotWord(index)" />
</div>
</template> </template>
</VueDraggable> </Draggable>
</div> </el-card>
<el-form-item label-width="0"> <el-card header="搜索样式" class="property-group" shadow="never">
<el-button @click="handleAddHotWord" type="primary" plain class="m-t-8px w-full"> <el-form-item label="框体样式">
添加热词 <el-radio-group v-model="formData!.borderRadius">
</el-button> <el-tooltip content="方形" placement="top">
</el-form-item> <el-radio-button :label="0">
<el-form-item label="框体样式"> <Icon icon="tabler:input-search" />
<el-radio-group v-model="formData!.borderRadius"> </el-radio-button>
<el-tooltip content="方形" placement="top"> </el-tooltip>
<el-radio-button :label="0"> <el-tooltip content="圆形" placement="top">
<Icon icon="tabler:input-search" /> <el-radio-button :label="10">
</el-radio-button> <Icon icon="iconoir:input-search" />
</el-tooltip> </el-radio-button>
<el-tooltip content="圆形" placement="top"> </el-tooltip>
<el-radio-button :label="10"> </el-radio-group>
<Icon icon="iconoir:input-search" /> </el-form-item>
</el-radio-button> <el-form-item label="提示文字" prop="placeholder">
</el-tooltip> <el-input v-model="formData.placeholder" />
</el-radio-group> </el-form-item>
</el-form-item> <el-form-item label="文本位置" prop="placeholderPosition">
<el-form-item label="提示文字" prop="placeholder"> <el-radio-group v-model="formData!.placeholderPosition">
<el-input v-model="formData.placeholder" /> <el-tooltip content="居左" placement="top">
</el-form-item> <el-radio-button label="left">
<el-form-item label="文本位置" prop="placeholderPosition"> <Icon icon="ant-design:align-left-outlined" />
<el-radio-group v-model="formData!.placeholderPosition"> </el-radio-button>
<el-tooltip content="居左" placement="top"> </el-tooltip>
<el-radio-button label="left"> <el-tooltip content="居中" placement="top">
<Icon icon="ant-design:align-left-outlined" /> <el-radio-button label="center">
</el-radio-button> <Icon icon="ant-design:align-center-outlined" />
</el-tooltip> </el-radio-button>
<el-tooltip content="居中" placement="top"> </el-tooltip>
<el-radio-button label="center"> </el-radio-group>
<Icon icon="ant-design:align-center-outlined" /> </el-form-item>
</el-radio-button> <el-form-item label="扫一扫" prop="showScan">
</el-tooltip> <el-switch v-model="formData!.showScan" />
</el-radio-group> </el-form-item>
</el-form-item> <el-form-item label="框体高度" prop="height">
<el-form-item label="扫一扫" prop="showScan"> <el-slider v-model="formData!.height" :max="50" :min="28" show-input input-size="small" />
<el-switch v-model="formData!.showScan" /> </el-form-item>
</el-form-item> <el-form-item label="框体颜色" prop="backgroundColor">
<el-form-item label="框体高度" prop="height"> <ColorInput v-model="formData.backgroundColor" />
<el-slider v-model="formData!.height" :max="50" :min="28" show-input input-size="small" /> </el-form-item>
</el-form-item> <el-form-item class="lef" label="文本颜色" prop="textColor">
<el-form-item label="框体颜色" prop="backgroundColor"> <ColorInput v-model="formData.textColor" />
<ColorInput v-model="formData.backgroundColor" /> </el-form-item>
</el-form-item> </el-card>
<el-form-item class="lef" label="文本颜色" prop="textColor">
<ColorInput v-model="formData.textColor" />
</el-form-item>
</el-form> </el-form>
</ComponentContainerProperty> </ComponentContainerProperty>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
import { SearchProperty } from '@/components/DiyEditor/components/mobile/SearchBar/config' import { SearchProperty } from '@/components/DiyEditor/components/mobile/SearchBar/config'
@ -85,15 +68,6 @@ defineOptions({ name: 'SearchProperty' })
const props = defineProps<{ modelValue: SearchProperty }>() const props = defineProps<{ modelValue: SearchProperty }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit) const { formData } = usePropertyForm(props.modelValue, emit)
/* 添加热词 */
const handleAddHotWord = () => {
formData.value.hotKeywords.push('')
}
/* 删除热词 */
const deleteHotWord = (index: number) => {
formData.value.hotKeywords.splice(index, 1)
}
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@ -12,7 +12,13 @@
}" }"
> >
<div v-for="(item, index) in property.items" :key="index" class="tab-bar-item"> <div v-for="(item, index) in property.items" :key="index" class="tab-bar-item">
<img :src="index === 0 ? item.activeIconUrl : item.iconUrl" alt="" /> <el-image :src="index === 0 ? item.activeIconUrl : item.iconUrl">
<template #error>
<div class="h-full w-full flex items-center justify-center">
<Icon icon="ep:picture" />
</div>
</template>
</el-image>
<span :style="{ color: index === 0 ? property.style.activeColor : property.style.color }"> <span :style="{ color: index === 0 ? property.style.activeColor : property.style.color }">
{{ item.text }} {{ item.text }}
</span> </span>
@ -48,7 +54,8 @@ defineProps<{ property: TabBarProperty }>()
align-items: center; align-items: center;
justify-content: center; justify-content: center;
img { :deep(img),
.el-icon {
width: 26px; width: 26px;
height: 26px; height: 26px;
border-radius: 4px; border-radius: 4px;

View File

@ -42,80 +42,44 @@
<el-text tag="p">图标设置</el-text> <el-text tag="p">图标设置</el-text>
<el-text type="info" size="small"> 拖动左上角的小圆点可对其排序, 图标建议尺寸 44*44 </el-text> <el-text type="info" size="small"> 拖动左上角的小圆点可对其排序, 图标建议尺寸 44*44 </el-text>
<draggable <Draggable v-model="formData.items" :limit="5">
:list="formData!.items" <template #default="{ element }">
item-key="index" <div class="m-b-8px flex items-center justify-around">
:forceFallback="true" <div class="flex flex-col items-center justify-between">
:animation="200" <UploadImg
handle=".drag-icon" v-model="element.iconUrl"
class="m-t-8px" width="40px"
> height="40px"
<template #item="{ element, index }"> :show-delete="false"
<div class="mb-4px flex flex-row gap-4px rounded bg-gray-100 p-8px"> :show-btn-text="false"
<div class="flex flex-col items-start justify-between">
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
<Icon
icon="ep:delete"
class="cursor-pointer text-red-5"
@click="handleDeleteItem(index)"
v-if="formData.items.length > 1"
/> />
<el-text size="small">未选中</el-text>
</div> </div>
<div class="w-full flex flex-col"> <div>
<div class="m-b-8px flex items-center justify-around"> <UploadImg
<div class="flex flex-col items-center justify-between"> v-model="element.activeIconUrl"
<UploadImg width="40px"
v-model="element.iconUrl" height="40px"
width="40px" :show-delete="false"
height="40px" :show-btn-text="false"
:show-delete="false" />
:show-btn-text="false" <el-text>已选中</el-text>
/>
<el-text size="small">默认图片</el-text>
</div>
<div>
<UploadImg
v-model="element.activeIconUrl"
width="40px"
height="40px"
:show-delete="false"
:show-btn-text="false"
/>
<el-text>选中图片</el-text>
</div>
</div>
<el-form-item prop="text" label-width="0" class="m-b-8px!">
<el-input v-model="element.text" placeholder="请输入文字" />
</el-form-item>
<el-form-item prop="url" label-width="0" class="m-b-0!">
<AppLinkInput v-model="element.url" />
</el-form-item>
</div> </div>
</div> </div>
<el-form-item prop="text" label="文字" label-width="48px" class="m-b-8px!">
<el-input v-model="element.text" placeholder="请输入文字" />
</el-form-item>
<el-form-item prop="url" label="链接" label-width="48px" class="m-b-0!">
<AppLinkInput v-model="element.url" />
</el-form-item>
</template> </template>
</draggable> </Draggable>
<el-form-item label-width="0">
<!-- 添加导航按钮 -->
<el-tooltip content="最多添加5个">
<el-button
@click="handleAddItem"
class="m-b-16px w-full"
type="primary"
plain
:disabled="formData!.items.length >= 5"
>
添加导航
</el-button>
</el-tooltip>
</el-form-item>
</el-form> </el-form>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import draggable from 'vuedraggable' // import { TabBarProperty, THEME_LIST } from './config'
import { TabBarItemProperty, TabBarProperty, THEME_LIST } from './config'
import { usePropertyForm } from '@/components/DiyEditor/util' import { usePropertyForm } from '@/components/DiyEditor/util'
// //
defineOptions({ name: 'TabBarProperty' }) defineOptions({ name: 'TabBarProperty' })
@ -124,15 +88,6 @@ const props = defineProps<{ modelValue: TabBarProperty }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit) const { formData } = usePropertyForm(props.modelValue, emit)
/** 添加导航项 */
const handleAddItem = () => {
formData?.value?.items?.push({} as TabBarItemProperty)
}
/** 删除导航项 */
const handleDeleteItem = (index: number) => {
formData?.value?.items?.splice(index, 1)
}
// //
const handleThemeChange = () => { const handleThemeChange = () => {
const theme = THEME_LIST.find((theme) => theme.id === formData.value.theme) const theme = THEME_LIST.find((theme) => theme.id === formData.value.theme)

View File

@ -0,0 +1,77 @@
<template>
<el-text type="info" size="small"> 拖动左上角的小圆点可对其排序 </el-text>
<VueDraggable
:list="formData"
:force-fallback="true"
:animation="200"
handle=".drag-icon"
class="m-t-8px"
item-key="index"
>
<template #item="{ element, index }">
<div
class="mb-4px flex flex-col gap-4px border border-gray-2 border-rounded rounded border-solid p-8px"
>
<!-- 操作按钮区 -->
<div class="m--8px m-b-4px flex flex-row items-center justify-between bg-gray-1 p-8px">
<el-tooltip content="拖动排序">
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
</el-tooltip>
<el-tooltip content="删除">
<Icon
icon="ep:delete"
class="cursor-pointer text-red-5"
v-if="formData.length > 1"
@click="handleDelete(index)"
/>
</el-tooltip>
</div>
<!-- 内容区 -->
<slot :element="element" :index="index"></slot>
</div>
</template>
</VueDraggable>
<el-tooltip :disabled="limit < 1" :content="`最多添加${limit}个`">
<el-button
type="primary"
plain
class="m-t-4px w-full"
:disabled="limit > 0 && formData.length >= limit"
@click="handleAdd"
>
<Icon icon="ep:plus" /><span>添加</span>
</el-button>
</el-tooltip>
</template>
<script setup lang="ts">
//
import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util'
import { any, array } from 'vue-types'
import { propTypes } from '@/utils/propTypes'
import { cloneDeep } from 'lodash-es'
//
defineOptions({ name: 'Draggable' })
//
const props = defineProps({
//
modelValue: array<any>().isRequired,
//
emptyItem: any<unknown>().def({}),
// 0
limit: propTypes.number.def(0)
})
//
const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit)
//
const handleAdd = () => formData.value.push(cloneDeep(props.emptyItem || {}))
//
const handleDelete = (index: number) => formData.value.splice(index, 1)
</script>
<style scoped lang="scss"></style>