营销:优化装修编辑器
This commit is contained in:
parent
0b0ba1f313
commit
434aa864da
@ -1,15 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div :class="['component', { active: active }]">
|
||||||
:style="{
|
<div
|
||||||
...style
|
:style="{
|
||||||
}"
|
...style
|
||||||
>
|
}"
|
||||||
<slot></slot>
|
>
|
||||||
|
<component :is="component.id" :property="component.property" />
|
||||||
|
</div>
|
||||||
|
<div class="component-wrap">
|
||||||
|
<!-- 左侧组件名 -->
|
||||||
|
<div class="component-name" v-if="component.name">
|
||||||
|
{{ component.name }}
|
||||||
|
</div>
|
||||||
|
<!-- 左侧:组件操作工具栏 -->
|
||||||
|
<div class="component-toolbar" v-if="showToolbar && component.name && active">
|
||||||
|
<VerticalButtonGroup type="primary">
|
||||||
|
<el-tooltip content="上移" placement="right">
|
||||||
|
<el-button :disabled="!canMoveUp" @click.stop="handleMoveComponent(-1)">
|
||||||
|
<Icon icon="ep:arrow-up" />
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="下移" placement="right">
|
||||||
|
<el-button :disabled="!canMoveDown" @click.stop="handleMoveComponent(1)">
|
||||||
|
<Icon icon="ep:arrow-down" />
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="复制" placement="right">
|
||||||
|
<el-button @click.stop="handleCopyComponent()">
|
||||||
|
<Icon icon="ep:copy-document" />
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="删除" placement="right">
|
||||||
|
<el-button @click.stop="handleDeleteComponent()">
|
||||||
|
<Icon icon="ep:delete" />
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</VerticalButtonGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
// 注册所有的组件
|
||||||
|
import { components } from '../components/mobile/index'
|
||||||
|
export default {
|
||||||
|
components: { ...components }
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ComponentStyle } from '@/components/DiyEditor/util'
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
import { object } from 'vue-types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组件容器
|
* 组件容器
|
||||||
@ -17,30 +59,164 @@ import { ComponentStyle } from '@/components/DiyEditor/util'
|
|||||||
*/
|
*/
|
||||||
defineOptions({ name: 'ComponentContainer' })
|
defineOptions({ name: 'ComponentContainer' })
|
||||||
|
|
||||||
const props = defineProps<{ property: ComponentStyle | undefined }>()
|
type DiyComponentWithStyle = DiyComponent<any> & { property: { style?: ComponentStyle } }
|
||||||
|
const props = defineProps({
|
||||||
|
component: object<DiyComponentWithStyle>().isRequired,
|
||||||
|
active: propTypes.bool.def(false),
|
||||||
|
canMoveUp: propTypes.bool.def(false),
|
||||||
|
canMoveDown: propTypes.bool.def(false),
|
||||||
|
showToolbar: propTypes.bool.def(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件样式
|
||||||
|
*/
|
||||||
const style = computed(() => {
|
const style = computed(() => {
|
||||||
if (!props.property) {
|
let componentStyle = props.component.property.style
|
||||||
|
if (!componentStyle) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
marginTop: `${props.property.marginTop || 0}px`,
|
marginTop: `${componentStyle.marginTop || 0}px`,
|
||||||
marginBottom: `${props.property.marginBottom || 0}px`,
|
marginBottom: `${componentStyle.marginBottom || 0}px`,
|
||||||
marginLeft: `${props.property.marginLeft || 0}px`,
|
marginLeft: `${componentStyle.marginLeft || 0}px`,
|
||||||
marginRight: `${props.property.marginRight || 0}px`,
|
marginRight: `${componentStyle.marginRight || 0}px`,
|
||||||
paddingTop: `${props.property.paddingTop || 0}px`,
|
paddingTop: `${componentStyle.paddingTop || 0}px`,
|
||||||
paddingRight: `${props.property.paddingRight || 0}px`,
|
paddingRight: `${componentStyle.paddingRight || 0}px`,
|
||||||
paddingBottom: `${props.property.paddingBottom || 0}px`,
|
paddingBottom: `${componentStyle.paddingBottom || 0}px`,
|
||||||
paddingLeft: `${props.property.paddingLeft || 0}px`,
|
paddingLeft: `${componentStyle.paddingLeft || 0}px`,
|
||||||
borderTopLeftRadius: `${props.property.borderTopLeftRadius || 0}px`,
|
borderTopLeftRadius: `${componentStyle.borderTopLeftRadius || 0}px`,
|
||||||
borderTopRightRadius: `${props.property.borderTopRightRadius || 0}px`,
|
borderTopRightRadius: `${componentStyle.borderTopRightRadius || 0}px`,
|
||||||
borderBottomRightRadius: `${props.property.borderBottomRightRadius || 0}px`,
|
borderBottomRightRadius: `${componentStyle.borderBottomRightRadius || 0}px`,
|
||||||
borderBottomLeftRadius: `${props.property.borderBottomLeftRadius || 0}px`,
|
borderBottomLeftRadius: `${componentStyle.borderBottomLeftRadius || 0}px`,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
background:
|
background:
|
||||||
props.property.bgType === 'color' ? props.property.bgColor : `url(${props.property.bgImg})`
|
componentStyle.bgType === 'color' ? componentStyle.bgColor : `url(${componentStyle.bgImg})`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'move', direction: number): void
|
||||||
|
(e: 'copy'): void
|
||||||
|
(e: 'delete'): void
|
||||||
|
}>()
|
||||||
|
/**
|
||||||
|
* 移动组件
|
||||||
|
* @param direction 移动方向
|
||||||
|
*/
|
||||||
|
const handleMoveComponent = (direction: number) => {
|
||||||
|
emits('move', direction)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 复制组件
|
||||||
|
*/
|
||||||
|
const handleCopyComponent = () => {
|
||||||
|
emits('copy')
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 删除组件
|
||||||
|
*/
|
||||||
|
const handleDeleteComponent = () => {
|
||||||
|
emits('delete')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss">
|
||||||
|
$active-border-width: 2px;
|
||||||
|
$hover-border-width: 1px;
|
||||||
|
$name-position: -85px;
|
||||||
|
$toolbar-position: -55px;
|
||||||
|
/* 组件 */
|
||||||
|
.component {
|
||||||
|
position: relative;
|
||||||
|
cursor: move;
|
||||||
|
.component-wrap {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: -$active-border-width;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* 鼠标放到组件上时 */
|
||||||
|
&:hover {
|
||||||
|
border: $hover-border-width dashed var(--el-color-primary);
|
||||||
|
box-shadow: 0 0 5px 0 rgba(24, 144, 255, 0.3);
|
||||||
|
.component-name {
|
||||||
|
/* 防止加了边框之后,位置移动 */
|
||||||
|
left: $name-position - $hover-border-width;
|
||||||
|
top: $hover-border-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 左侧:组件名称 */
|
||||||
|
.component-name {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 80px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 25px;
|
||||||
|
height: 25px;
|
||||||
|
background: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
left: $name-position;
|
||||||
|
top: $active-border-width;
|
||||||
|
box-shadow:
|
||||||
|
0 0 4px #00000014,
|
||||||
|
0 2px 6px #0000000f,
|
||||||
|
0 4px 8px 2px #0000000a;
|
||||||
|
/* 右侧小三角 */
|
||||||
|
&:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 7.5px;
|
||||||
|
right: -10px;
|
||||||
|
content: ' ';
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
border: 5px solid transparent;
|
||||||
|
border-left-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 右侧:组件操作工具栏 */
|
||||||
|
.component-toolbar {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: $toolbar-position;
|
||||||
|
/* 左侧小三角 */
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: -10px;
|
||||||
|
content: ' ';
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
border: 5px solid transparent;
|
||||||
|
border-right-color: #2d8cf0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 组件选中时 */
|
||||||
|
&.active {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
.component-wrap {
|
||||||
|
border: $active-border-width solid var(--el-color-primary) !important;
|
||||||
|
box-shadow: 0 0 10px 0 rgba(24, 144, 255, 0.3);
|
||||||
|
margin-bottom: $active-border-width + $active-border-width;
|
||||||
|
|
||||||
|
.component-name {
|
||||||
|
background: var(--el-color-primary);
|
||||||
|
color: #fff;
|
||||||
|
/* 防止加了边框之后,位置移动 */
|
||||||
|
left: $name-position - $active-border-width !important;
|
||||||
|
top: 0 !important;
|
||||||
|
&:after {
|
||||||
|
border-left-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.component-toolbar {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -38,15 +38,13 @@
|
|||||||
<!-- 手机顶部状态栏 -->
|
<!-- 手机顶部状态栏 -->
|
||||||
<img src="@/assets/imgs/diy/statusBar.png" alt="" class="status-bar" />
|
<img src="@/assets/imgs/diy/statusBar.png" alt="" class="status-bar" />
|
||||||
<!-- 手机顶部导航栏 -->
|
<!-- 手机顶部导航栏 -->
|
||||||
<NavigationBar
|
<ComponentContainer
|
||||||
v-if="showNavigationBar"
|
v-if="showNavigationBar"
|
||||||
:property="navigationBarComponent.property"
|
:component="navigationBarComponent"
|
||||||
|
:show-toolbar="false"
|
||||||
|
:active="selectedComponent?.id === navigationBarComponent.id"
|
||||||
@click="handleNavigationBarSelected"
|
@click="handleNavigationBarSelected"
|
||||||
:class="[
|
class="cursor-pointer!"
|
||||||
'component',
|
|
||||||
'cursor-pointer!',
|
|
||||||
{ active: selectedComponent?.id === navigationBarComponent.id }
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- 手机页面编辑区域 -->
|
<!-- 手机页面编辑区域 -->
|
||||||
@ -71,73 +69,27 @@
|
|||||||
@change="handleComponentChange"
|
@change="handleComponentChange"
|
||||||
>
|
>
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<div class="component" @click="handleComponentSelected(element, index)">
|
<ComponentContainer
|
||||||
<!-- 组件内容区 -->
|
:component="element"
|
||||||
<ComponentContainer :property="element.property.style">
|
:active="selectedComponentIndex === index"
|
||||||
<component
|
:can-move-up="index > 0"
|
||||||
:is="element.id"
|
:can-move-down="index < pageComponents.length - 1"
|
||||||
:property="element.property"
|
@move="(direction) => handleMoveComponent(index, direction)"
|
||||||
:data-type="element.id"
|
@copy="handleCopyComponent(index)"
|
||||||
/>
|
@delete="handleDeleteComponent(index)"
|
||||||
</ComponentContainer>
|
@click="handleComponentSelected(element, index)"
|
||||||
<div :class="['component-wrap', { active: selectedComponentIndex === index }]">
|
/>
|
||||||
<!-- 左侧组件名 -->
|
|
||||||
<div
|
|
||||||
:class="['component-name', { active: selectedComponentIndex === index }]"
|
|
||||||
v-if="element.name"
|
|
||||||
>
|
|
||||||
{{ element.name }}
|
|
||||||
</div>
|
|
||||||
<!-- 左侧:组件操作工具栏 -->
|
|
||||||
<div
|
|
||||||
class="component-toolbar"
|
|
||||||
v-if="element.name && selectedComponentIndex === index"
|
|
||||||
>
|
|
||||||
<el-button-group type="primary">
|
|
||||||
<el-tooltip content="上移" placement="right">
|
|
||||||
<el-button
|
|
||||||
:disabled="index === 0"
|
|
||||||
@click.stop="handleMoveComponent(index, -1)"
|
|
||||||
>
|
|
||||||
<Icon icon="ep:arrow-up" />
|
|
||||||
</el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
<el-tooltip content="下移" placement="right">
|
|
||||||
<el-button
|
|
||||||
:disabled="index === pageComponents.length - 1"
|
|
||||||
@click.stop="handleMoveComponent(index, 1)"
|
|
||||||
>
|
|
||||||
<Icon icon="ep:arrow-down" />
|
|
||||||
</el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
<el-tooltip content="复制" placement="right">
|
|
||||||
<el-button @click.stop="handleCopyComponent(index)">
|
|
||||||
<Icon icon="ep:copy-document" />
|
|
||||||
</el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
<el-tooltip content="删除" placement="right">
|
|
||||||
<el-button @click.stop="handleDeleteComponent(index)">
|
|
||||||
<Icon icon="ep:delete" />
|
|
||||||
</el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
</el-button-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
<!-- 手机底部导航 -->
|
<!-- 手机底部导航 -->
|
||||||
<div
|
<div v-if="showTabBar" :class="['editor-design-bottom', 'component', 'cursor-pointer!']">
|
||||||
v-if="showTabBar"
|
<ComponentContainer
|
||||||
:class="[
|
:component="tabBarComponent"
|
||||||
'editor-design-bottom',
|
:show-toolbar="false"
|
||||||
'component',
|
:active="selectedComponent?.id === tabBarComponent.id"
|
||||||
'cursor-pointer!',
|
@click="handleTabBarSelected"
|
||||||
{ active: selectedComponent?.id === tabBarComponent.id }
|
/>
|
||||||
]"
|
|
||||||
>
|
|
||||||
<TabBar :property="tabBarComponent.property" @click="handleTabBarSelected" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 右侧属性面板 -->
|
<!-- 右侧属性面板 -->
|
||||||
@ -178,8 +130,6 @@ export default {
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
import ComponentLibrary from './components/ComponentLibrary.vue'
|
import ComponentLibrary from './components/ComponentLibrary.vue'
|
||||||
import NavigationBar from './components/mobile/NavigationBar/index.vue'
|
|
||||||
import TabBar from './components/mobile/TabBar/index.vue'
|
|
||||||
import { cloneDeep, includes } from 'lodash-es'
|
import { cloneDeep, includes } from 'lodash-es'
|
||||||
import { component as PAGE_CONFIG_COMPONENT } from '@/components/DiyEditor/components/mobile/PageConfig/config'
|
import { component as PAGE_CONFIG_COMPONENT } from '@/components/DiyEditor/components/mobile/PageConfig/config'
|
||||||
import { component as NAVIGATION_BAR_COMPONENT } from './components/mobile/NavigationBar/config'
|
import { component as NAVIGATION_BAR_COMPONENT } from './components/mobile/NavigationBar/config'
|
||||||
@ -256,6 +206,9 @@ const handleSave = () => {
|
|||||||
return { id: component.id, property: component.property }
|
return { id: component.id, property: component.property }
|
||||||
})
|
})
|
||||||
} as PageConfig
|
} as PageConfig
|
||||||
|
if (!props.showTabBar) {
|
||||||
|
delete pageConfig.tabBar
|
||||||
|
}
|
||||||
// 发送数据更新通知
|
// 发送数据更新通知
|
||||||
const modelValue = isString(props.modelValue) ? JSON.stringify(pageConfig) : pageConfig
|
const modelValue = isString(props.modelValue) ? JSON.stringify(pageConfig) : pageConfig
|
||||||
emits('update:modelValue', modelValue)
|
emits('update:modelValue', modelValue)
|
||||||
@ -453,24 +406,12 @@ $toolbar-height: 42px;
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
/* 组件 */
|
|
||||||
.component {
|
|
||||||
width: $phone-width;
|
|
||||||
cursor: move;
|
|
||||||
/* 鼠标放到组件上时 */
|
|
||||||
&:hover {
|
|
||||||
border: 1px dashed var(--el-color-primary);
|
|
||||||
box-shadow: 0 0 5px 0 rgba(24, 144, 255, 0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 组件选中 */
|
|
||||||
.component.active {
|
|
||||||
border: 2px solid var(--el-color-primary);
|
|
||||||
}
|
|
||||||
/* 手机顶部 */
|
/* 手机顶部 */
|
||||||
.editor-design-top {
|
.editor-design-top {
|
||||||
width: $phone-width;
|
width: $phone-width;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
/* 手机顶部状态栏 */
|
/* 手机顶部状态栏 */
|
||||||
.status-bar {
|
.status-bar {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
@ -499,104 +440,6 @@ $toolbar-height: 42px;
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.component {
|
|
||||||
position: relative;
|
|
||||||
cursor: move;
|
|
||||||
|
|
||||||
.component-wrap {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
left: -2px;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
display: block;
|
|
||||||
border: 2px solid var(--el-color-primary);
|
|
||||||
box-shadow: 0 0 10px 0 rgba(24, 144, 255, 0.3);
|
|
||||||
}
|
|
||||||
/* 左侧:组件名称 */
|
|
||||||
.component-name {
|
|
||||||
position: absolute;
|
|
||||||
width: 80px;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 25px;
|
|
||||||
height: 25px;
|
|
||||||
background: #fff;
|
|
||||||
font-size: 12px;
|
|
||||||
left: -88px;
|
|
||||||
top: 0;
|
|
||||||
box-shadow:
|
|
||||||
0 0 4px #00000014,
|
|
||||||
0 2px 6px #0000000f,
|
|
||||||
0 4px 8px 2px #0000000a;
|
|
||||||
/* 右侧小三角 */
|
|
||||||
&:after {
|
|
||||||
position: absolute;
|
|
||||||
top: 7.5px;
|
|
||||||
right: -10px;
|
|
||||||
content: ' ';
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
border: 5px solid transparent;
|
|
||||||
border-left-color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 组件选中按钮 */
|
|
||||||
.component-name.active {
|
|
||||||
background: var(--el-color-primary);
|
|
||||||
color: #fff;
|
|
||||||
&:after {
|
|
||||||
border-left-color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 右侧:组件操作工具栏 */
|
|
||||||
.component-toolbar {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: -55px;
|
|
||||||
/* 左侧小三角 */
|
|
||||||
&:before {
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
left: -10px;
|
|
||||||
content: ' ';
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
border: 5px solid transparent;
|
|
||||||
border-right-color: #2d8cf0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 重写 Element 按钮组的样式(官方只支持水平显示,增加垂直显示的样式) */
|
|
||||||
.el-button-group {
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.el-button-group > .el-button:first-child {
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
border-top-right-radius: var(--el-border-radius-base);
|
|
||||||
border-bottom-color: var(--el-button-divide-border-color);
|
|
||||||
}
|
|
||||||
.el-button-group > .el-button:last-child {
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-left-radius: var(--el-border-radius-base);
|
|
||||||
border-top-color: var(--el-button-divide-border-color);
|
|
||||||
}
|
|
||||||
.el-button-group .el-button--primary:not(:first-child):not(:last-child) {
|
|
||||||
border-top-color: var(--el-button-divide-border-color);
|
|
||||||
border-bottom-color: var(--el-button-divide-border-color);
|
|
||||||
}
|
|
||||||
.el-button-group > .el-button:not(:last-child) {
|
|
||||||
margin-bottom: -1px;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ export interface PageConfig {
|
|||||||
// 顶部导航栏属性
|
// 顶部导航栏属性
|
||||||
navigationBar: NavigationBarProperty
|
navigationBar: NavigationBarProperty
|
||||||
// 底部导航菜单属性
|
// 底部导航菜单属性
|
||||||
tabBar: TabBarProperty
|
tabBar?: TabBarProperty
|
||||||
// 页面组件列表
|
// 页面组件列表
|
||||||
components: PageComponent[]
|
components: PageComponent[]
|
||||||
}
|
}
|
||||||
|
40
src/components/VerticalButtonGroup/index.vue
Normal file
40
src/components/VerticalButtonGroup/index.vue
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<el-button-group v-bind="$attrs">
|
||||||
|
<slot></slot>
|
||||||
|
</el-button-group>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 垂直按钮组
|
||||||
|
* Element官方的按钮组只支持水平显示,通过重写样式实现垂直布局
|
||||||
|
*/
|
||||||
|
defineOptions({ name: 'VerticalButtonGroup' })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.el-button-group {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.el-button-group > :deep(.el-button:first-child) {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
border-top-right-radius: var(--el-border-radius-base);
|
||||||
|
border-bottom-color: var(--el-button-divide-border-color);
|
||||||
|
}
|
||||||
|
.el-button-group > :deep(.el-button:last-child) {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-left-radius: var(--el-border-radius-base);
|
||||||
|
border-top-color: var(--el-button-divide-border-color);
|
||||||
|
}
|
||||||
|
.el-button-group :deep(.el-button--primary:not(:first-child):not(:last-child)) {
|
||||||
|
border-top-color: var(--el-button-divide-border-color);
|
||||||
|
border-bottom-color: var(--el-button-divide-border-color);
|
||||||
|
}
|
||||||
|
.el-button-group > :deep(.el-button:not(:last-child)) {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user