feat: 新增成组,解组,图层处理

This commit is contained in:
奔跑的面条 2022-08-06 17:20:56 +08:00
parent ffb6b2f68c
commit d7b74ed90d
10 changed files with 300 additions and 33 deletions

View File

@ -1,7 +1,7 @@
// 鼠标点击左右键
export enum MouseEventButton {
LEFT = 1,
RIGHT = 2
RIGHT = 2,
}
// 页面拖拽键名
@ -24,6 +24,9 @@ export enum MenuEnum {
UP = 'up',
DOWN = 'down',
CLEAR = 'clear',
GROUP = 'group',
UN_GROUP = 'unGroup',
BACK = 'back',
FORWORD = 'forward'
}

View File

@ -1,6 +1,7 @@
import { getUUID } from '@/utils'
import { PublicConfigType, CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { groupTitle } from '@/settings/designSetting'
import {
RequestHttpEnum,
RequestDataTypeEnum,
@ -83,7 +84,7 @@ export class PublicGroupConfigClass implements CreateComponentGroupType {
public isGroup = true
// 名称
public chartConfig = {
title: '分组'
title: groupTitle
}
// 组成员列表
public groupList: Array<CreateComponentType> = []

View File

@ -55,7 +55,9 @@ import {
Search as SearchIcon,
ChevronUpOutline as ChevronUpOutlineIcon,
ChevronDownOutline as ChevronDownOutlineIcon,
Pulse as PulseIcon
Pulse as PulseIcon,
Folder as FolderIcon,
FolderOpen as FolderOpenIcon
} from '@vicons/ionicons5'
import {
@ -205,7 +207,11 @@ const ionicons5 = {
// 向下
ChevronDownOutlineIcon,
// 脉搏
PulseIcon
PulseIcon,
// 文件夹
FolderIcon,
// 文件夹打开
FolderOpenIcon
}
const carbon = {

View File

@ -8,6 +8,9 @@ export const lang = LangEnum.ZH
// 水印文字
export const watermarkText = "GoView 低代码平台"
// 分组名称
export const groupTitle = "分组"
// 主题配置
export const theme = {
// 默认是否开启深色主题
@ -37,7 +40,7 @@ export const asideCollapsedWidth = 60
// 弹窗是否可以通过点击遮罩关闭
export const maskClosable = false
// 修改边框圆角
// 全局边框圆角
export const borderRadius = '6px'
// 轮播间隔

View File

@ -236,6 +236,32 @@ export const useChartEditStore = defineStore({
}
return index
},
// * 找到组数据的下标位置id可为父级或子集数组无则返回-1
fetchTargetGroupIndex(id?: string): number {
const targetId = id || this.getTargetChart.selectId.length && this.getTargetChart.selectId[0] || undefined
if(!targetId) {
loadingFinish()
return -1
}
const targetIndex = this.fetchTargetIndex(targetId)
// 当前
if(targetIndex !== -1) {
return targetIndex
} else {
const length = this.getComponentList.length
for(let i = 0; i < length; i++) {
if(this.getComponentList[i].isGroup) {
for(const cItem of (this.getComponentList[i] as CreateComponentGroupType).groupList) {
if(cItem.id === targetId) {
return i
}
}
}
}
}
return -1
},
/**
* *
* @param chartConfig
@ -575,12 +601,33 @@ export const useChartEditStore = defineStore({
groupClass.groupList.push(item)
})
this.addComponentList(groupClass)
// todo 输出
console.log(this.getComponentList)
},
// * 解除分组
setUnGroup() {
const selectGroupIdArr = this.getTargetChart.selectId
if(selectGroupIdArr.length > 1) {
window['$message'].error('解除分组失败,请联系管理员!')
return
}
// 解组
const unGroup = (targetIndex: number) => {
const targetGroup = this.getComponentList[targetIndex] as CreateComponentGroupType
targetGroup.groupList.forEach(item => {
this.addComponentList(item)
})
this.setTargetSelectChart(targetGroup.id)
// 删除分组
this.removeComponentList(false)
}
const targetIndex = this.fetchTargetGroupIndex(selectGroupIdArr[0])
// 判断目标是否为分组父级
if(targetIndex !== -1) {
unGroup(targetIndex)
} else {
window['$message'].error('解除分组失败,请联系管理员!')
}
},
// ----------------
// * 设置页面大小

View File

@ -31,7 +31,7 @@
@mousedown="mousedownHandle($event, item)"
@mouseenter="mouseenterHandle($event, item)"
@mouseleave="mouseleaveHandle($event, item)"
@contextmenu="handleContextMenu($event, item)"
@contextmenu="handleContextMenu($event, item, optionsHandle)"
>
<component
class="edit-content-chart"
@ -66,8 +66,11 @@
<script lang="ts" setup>
import { onMounted, computed } from 'vue'
import { chartColors } from '@/settings/chartThemes/index'
import { MenuEnum } from '@/enums/editPageEnum'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { animationsClass, getFilterStyle, getTransformStyle } from '@/utils'
import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useLayout } from './hooks/useLayout.hook'
@ -90,6 +93,20 @@ useLayout()
//
const { mouseenterHandle, mouseleaveHandle, mousedownHandle, mouseClickHandle } = useMouseHandle()
//
const optionsHandle = (targetList: MenuOptionsItemType[], allList: MenuOptionsItemType[], item: CreateComponentType | CreateComponentGroupType) => {
//
if(chartEditStore.getTargetChart.selectId.length > 1) {
targetList.forEach(item => {
if(item.key !== MenuEnum.GROUP) {
item.disabled = true
}
})
return targetList
}
return targetList
}
//
const themeSetting = computed(() => {
const chartThemeSetting = chartEditStore.getEditCanvasConfig.chartThemeSetting

View File

@ -0,0 +1,3 @@
import LayersGroupListItem from './index.vue'
export { LayersGroupListItem }

View File

@ -0,0 +1,170 @@
<template>
<div class="go-content-layers-group-list-item">
<div
class="root-item-content"
:class="{ hover: hover, select: select }"
@click="clickHandle($event)"
@mousedown="groupMousedownHandle()"
@mouseenter="mouseenterHandle(componentGroupData)"
@mouseleave="mouseleaveHandle(componentGroupData)"
@contextmenu="handleContextMenu($event, componentGroupData, undefined, undefined, pickOptionsList)"
>
<div class="go-flex-items-center item-content">
<n-icon size="20" class="go-ml-1">
<template v-if="expend">
<folder-open-icon></folder-open-icon>
</template>
<template v-else>
<folder-icon></folder-icon>
</template>
</n-icon>
<n-ellipsis>
<n-text class="go-ml-2 list-text" :depth="2">
{{ componentGroupData.chartConfig.title }}
</n-text>
</n-ellipsis>
</div>
<div :class="{ 'select-modal': select }"></div>
</div>
<n-collapse-transition :show="expend">
<LayersListItem
v-for="element in componentGroupData.groupList"
:key="element.id"
:componentData="element"
@mousedown="mousedownHandle(element)"
@mouseenter="mouseenterHandle(element)"
@mouseleave="mouseleaveHandle(element)"
@contextmenu="handleContextMenu($event, componentGroupData, undefined, undefined, pickOptionsList)"
></LayersListItem>
</n-collapse-transition>
</div>
</template>
<script setup lang="ts">
import { ref, computed, PropType } from 'vue'
import { MouseEventButton } from '@/enums/editPageEnum'
import { MenuEnum } from '@/enums/editPageEnum'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { LayersListItem } from '../LayersListItem'
import throttle from 'lodash/throttle'
import { icon } from '@/plugins'
const props = defineProps({
componentGroupData: {
type: Object as PropType<CreateComponentGroupType>,
required: true
}
})
//
const pickOptionsList = [MenuEnum.UN_GROUP]
//
const designStore = useDesignStore()
const { FolderIcon, FolderOpenIcon } = icon.ionicons5
const chartEditStore = useChartEditStore()
const { handleContextMenu, onClickOutSide } = useContextMenu()
const themeColor = ref(designStore.getAppTheme)
const expend = ref(false)
//
const clickHandle = (e: MouseEvent) => {
//
expend.value = !expend.value
mousedownHandle(props.componentGroupData)
}
//
const select = computed(() => {
const id = props.componentGroupData.id
return chartEditStore.getTargetChart.selectId.find((e: string) => e === id)
})
//
const hover = computed(() => {
return props.componentGroupData.id === chartEditStore.getTargetChart.hoverId
})
//
const groupMousedownHandle = () => {
onClickOutSide()
chartEditStore.setTargetSelectChart(props.componentGroupData.id)
}
//
const mousedownHandle = (item: CreateComponentType | CreateComponentGroupType) => {
onClickOutSide()
chartEditStore.setTargetSelectChart(item.id)
}
//
const mouseenterHandle = (item: CreateComponentType | CreateComponentGroupType) => {
chartEditStore.setTargetHoverChart(item.id)
}
//
const mouseleaveHandle = (item: CreateComponentType | CreateComponentGroupType) => {
chartEditStore.setTargetHoverChart(undefined)
}
</script>
<style lang="scss" scoped>
$centerHeight: 52px;
$textSize: 10px;
@include go(content-layers-group-list-item) {
position: relative;
width: 90%;
margin: 10px 5%;
margin-bottom: 5px;
@extend .go-transition-quick;
.root-item-content {
height: $centerHeight;
cursor: pointer;
border-radius: 5px;
border: 1px solid rgba(0, 0, 0, 0);
&.hover,
&:hover {
@include fetch-bg-color('background-color4');
}
/* 选中 */
&.select {
border: 1px solid v-bind('themeColor');
/* 需要设置最高级,覆盖 hover 的颜色 */
background-color: rgba(0, 0, 0, 0);
.list-img {
border: 1px solid v-bind('themeColor') !important;
}
}
}
.select-modal,
.item-content {
position: absolute;
top: 0;
left: 0;
}
.item-content {
z-index: 1;
padding: 6px 5px;
justify-content: start !important;
width: calc(100% - 10px);
height: calc(#{$centerHeight} - 10px);
}
.select-modal {
width: 100%;
height: calc(#{$centerHeight} + 2px);
opacity: 0.3;
background-color: v-bind('themeColor');
}
.list-text {
padding-left: 6px;
font-size: $textSize;
}
}
</style>

View File

@ -16,20 +16,21 @@
<n-text class="not-layer-text">暂无图层~</n-text>
</n-space>
<!-- https://github.com/SortableJS/vue.draggable.next -->
<draggable
item-key="id"
v-model="reverseList"
ghostClass="ghost"
@change="onMoveCallback"
>
<draggable item-key="id" v-model="reverseList" ghostClass="ghost" @change="onMoveCallback">
<template #item="{ element }">
<layers-list-item
:componentData="element"
@mousedown="mousedownHandle(element)"
@mouseenter="mouseenterHandle(element)"
@mouseleave="mouseleaveHandle(element)"
@contextmenu="handleContextMenu($event, element)"
></layers-list-item>
<div>
<!-- 组合 -->
<LayersGroupListItem v-if="element.isGroup" :componentGroupData="element"></LayersGroupListItem>
<!-- 单组件 -->
<LayersListItem
v-else
:componentData="element"
@mousedown="mousedownHandle(element)"
@mouseenter="mouseenterHandle(element)"
@mouseleave="mouseleaveHandle(element)"
@contextmenu="handleContextMenu($event, element)"
></LayersListItem>
</div>
</template>
</draggable>
</content-box>
@ -44,22 +45,24 @@ import { ContentBox } from '../ContentBox/index'
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { CreateComponentType } from '@/packages/index.d'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
import { MenuEnum } from '@/enums/editPageEnum'
import { LayersListItem } from './components/LayersListItem/index'
import { LayersGroupListItem } from './components/LayersGroupListItem/index'
import { icon } from '@/plugins'
const { LayersIcon } = icon.ionicons5
const chartLayoutStore = useChartLayoutStore()
const chartEditStore = useChartEditStore()
const { handleContextMenu } = useContextMenu()
const { handleContextMenu, onClickOutSide } = useContextMenu()
//
const reverseList = computed(() => {
const list: CreateComponentType[] = cloneDeep(chartEditStore.getComponentList)
const list: Array<CreateComponentType | CreateComponentGroupType> = cloneDeep(chartEditStore.getComponentList)
return list.reverse()
})
@ -89,6 +92,7 @@ const onMoveCallback = (val: any) => {
//
const mousedownHandle = (item: CreateComponentType) => {
onClickOutSide()
chartEditStore.setTargetSelectChart(item.id)
}

View File

@ -1,10 +1,11 @@
import { ref, nextTick } from 'vue'
import { ref, nextTick, toRaw } from 'vue';
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { CreateComponentType } from '@/packages/index.d'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { renderIcon, loadingError } from '@/utils'
import { icon } from '@/plugins'
import { MenuOptionsItemType } from './useContextMenu.hook.d'
import { MenuEnum } from '@/enums/editPageEnum'
import cloneDeep from 'lodash/cloneDeep'
const { CopyIcon, CutIcon, ClipboardOutlineIcon, TrashIcon, ChevronDownIcon, ChevronUpIcon } = icon.ionicons5
const { UpToTopIcon, DownToBottomIcon, PaintBrushIcon, Carbon3DSoftwareIcon, Carbon3DCursorIcon } = icon.carbon
@ -81,10 +82,16 @@ const defaultOptions: MenuOptionsItemType[] = [
const defaultMultiSelectOptions: MenuOptionsItemType[] = [
{
label: '创建分组',
key: MenuEnum.COPY,
key: MenuEnum.GROUP,
icon: renderIcon(Carbon3DSoftwareIcon),
fnHandle: chartEditStore.setGroup
}
},
{
label: '解除分组',
key: MenuEnum.UN_GROUP,
icon: renderIcon(Carbon3DCursorIcon),
fnHandle: chartEditStore.setUnGroup
},
]
// * 无数据传递拥有的选项
@ -123,7 +130,7 @@ const menuOptions = ref<MenuOptionsItemType[]>([])
const handleContextMenu = (
e: MouseEvent,
// 右键对象
item?: CreateComponentType,
item?: CreateComponentType | CreateComponentGroupType,
// 判断函数
optionsHandle?: Function,
// 隐藏选项列表
@ -133,10 +140,13 @@ const handleContextMenu = (
) => {
e.stopPropagation()
e.preventDefault()
let target = e.target
while (target instanceof SVGElement) {
target = target.parentNode
}
// 展示列表
chartEditStore.setRightMenuShow(false)
// * 多选默认选项
@ -148,16 +158,17 @@ const handleContextMenu = (
}
if (!item) {
menuOptions.value = pickOption(menuOptions.value, defaultNoItemKeys)
menuOptions.value = pickOption(toRaw(menuOptions.value), defaultNoItemKeys)
}
if (hideOptionsList) {
menuOptions.value = hideOption(menuOptions.value, hideOptionsList)
menuOptions.value = hideOption([...defaultMultiSelectOptions, ...defaultOptions], hideOptionsList)
}
if (pickOptionsList) {
menuOptions.value = hideOption(menuOptions.value, pickOptionsList)
menuOptions.value = pickOption([...defaultMultiSelectOptions, ...defaultOptions], pickOptionsList)
}
if (optionsHandle) {
menuOptions.value = optionsHandle(menuOptions.value)
// 自定义函数能够拿到当前选项和所有选项
menuOptions.value = optionsHandle(cloneDeep(toRaw(menuOptions.value)), [...defaultMultiSelectOptions, ...defaultOptions], item)
}
nextTick().then(() => {
chartEditStore.setMousePosition(e.clientX, e.clientY)
@ -197,6 +208,8 @@ export const useContextMenu = () => {
return {
menuOptions,
defaultOptions,
defaultMultiSelectOptions,
handleContextMenu,
onClickOutSide,
handleMenuSelect,