diff --git a/src/enums/editPageEnum.ts b/src/enums/editPageEnum.ts
index 773963f4..a987d59e 100644
--- a/src/enums/editPageEnum.ts
+++ b/src/enums/editPageEnum.ts
@@ -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'
 }
diff --git a/src/packages/public/publicConfig.ts b/src/packages/public/publicConfig.ts
index 37b8fb05..cc752b8f 100644
--- a/src/packages/public/publicConfig.ts
+++ b/src/packages/public/publicConfig.ts
@@ -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> = []
diff --git a/src/plugins/icon.ts b/src/plugins/icon.ts
index fd880959..90bf057c 100644
--- a/src/plugins/icon.ts
+++ b/src/plugins/icon.ts
@@ -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 = {
diff --git a/src/settings/designSetting.ts b/src/settings/designSetting.ts
index dbb86da5..0988c7a5 100644
--- a/src/settings/designSetting.ts
+++ b/src/settings/designSetting.ts
@@ -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'
 
 // 轮播间隔
diff --git a/src/store/modules/chartEditStore/chartEditStore.ts b/src/store/modules/chartEditStore/chartEditStore.ts
index 828314d0..53f13c35 100644
--- a/src/store/modules/chartEditStore/chartEditStore.ts
+++ b/src/store/modules/chartEditStore/chartEditStore.ts
@@ -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('解除分组失败,请联系管理员!')
+      }
     },
     // ----------------
     // * 设置页面大小
diff --git a/src/views/chart/ContentEdit/index.vue b/src/views/chart/ContentEdit/index.vue
index 02f7b974..f08cb06c 100644
--- a/src/views/chart/ContentEdit/index.vue
+++ b/src/views/chart/ContentEdit/index.vue
@@ -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
diff --git a/src/views/chart/ContentLayers/components/LayersGroupListItem/index.ts b/src/views/chart/ContentLayers/components/LayersGroupListItem/index.ts
new file mode 100644
index 00000000..25939326
--- /dev/null
+++ b/src/views/chart/ContentLayers/components/LayersGroupListItem/index.ts
@@ -0,0 +1,3 @@
+import LayersGroupListItem from './index.vue'
+
+export { LayersGroupListItem }
diff --git a/src/views/chart/ContentLayers/components/LayersGroupListItem/index.vue b/src/views/chart/ContentLayers/components/LayersGroupListItem/index.vue
new file mode 100644
index 00000000..77ef5b98
--- /dev/null
+++ b/src/views/chart/ContentLayers/components/LayersGroupListItem/index.vue
@@ -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>
diff --git a/src/views/chart/ContentLayers/index.vue b/src/views/chart/ContentLayers/index.vue
index bebfae42..13ec488f 100644
--- a/src/views/chart/ContentLayers/index.vue
+++ b/src/views/chart/ContentLayers/index.vue
@@ -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)
 }
 
diff --git a/src/views/chart/hooks/useContextMenu.hook.ts b/src/views/chart/hooks/useContextMenu.hook.ts
index 5272ea17..bb08e154 100644
--- a/src/views/chart/hooks/useContextMenu.hook.ts
+++ b/src/views/chart/hooks/useContextMenu.hook.ts
@@ -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,