houyaf 3 년 전
부모
커밋
aeeee9574a

+ 209 - 0
src/views/biz/biz/components/BizList.vue

@@ -0,0 +1,209 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup>
+import { ElMessage, ElMessageBox } from 'element-plus'
+import BizComponent from './Biz.vue'
+import { deleteBizById, getBizByList } from '@/api/biz/bizApi'
+const emit = defineEmits(['onItemSelect'])
+
+interface TreeNode {
+  label: string
+  isLeaf: boolean
+  bizId: number
+  children?: TreeNode[]
+}
+
+const state = reactive({
+  loading: false,
+  keywords: '',
+  treeData: [] as TreeNode[],
+  curBizId: 0,
+  dialogState: 1,
+  search: {
+    keywords: '',
+  },
+})
+
+const leftTreeRef = ref()
+const bizRef = ref()
+
+const getData = async () => {
+  const { data } = await getBizByList(state.search)
+  const treeNodes: TreeNode[] = []
+  data.forEach((item: any) => {
+    return treeNodes.push({
+      label: item.bizTitle,
+      bizId: item.bizId,
+      isLeaf: true,
+    })
+  })
+  state.treeData = treeNodes
+
+  if (data && data.length > 0) {
+    state.curBizId = data[0].bizId
+    nextTick(() => {
+      leftTreeRef.value.setCurrentKey(state.curBizId)
+      emit('onItemSelect', state.curBizId)
+    })
+  }
+}
+
+onMounted(() => {
+  getData()
+})
+
+// 业务新增
+const onBizAdd = () => {
+  bizRef.value.showAddModel()
+}
+
+// 业务编辑
+const onBizEdit = (data: { bizId: number }) => {
+  const bizId = data.bizId
+  bizRef.value.showEditModel(bizId)
+}
+
+// 业务删除
+const onBizDelete = (data: any) => {
+  ElMessageBox.confirm(`确认删除「${data.bizTitle}」吗?`, '确认信息').then(async () => {
+    const { msg } = await deleteBizById(data.bizId)
+    ElMessage.success(msg)
+    await getData()
+  })
+}
+
+// 业务选择
+const onTreeNodeClick = (node: TreeNode) => {
+  if (node.isLeaf) {
+    state.curBizId = node.bizId
+    emit('onItemSelect', state.curBizId)
+  }
+}
+</script>
+
+<template>
+  <div>
+    <el-scrollbar class="tree">
+      <el-button-group class="btns">
+        <el-button type="primary" class="add" @click="onBizAdd()">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:plus" />
+            </el-icon>
+          </template>
+          事务模型
+        </el-button>
+        <el-button @click="getData">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:refresh" />
+            </el-icon>
+          </template>
+        </el-button>
+      </el-button-group>
+      <ElTree ref="leftTreeRef" :data="state.treeData" default-expand-all node-key="bizId" @node-click="onTreeNodeClick">
+        <template #default="{ node, data }">
+          <div class="custom-tree-node">
+            <div class="label" :title="node.label">
+              <el-icon v-if="data.isLeaf" size="16px" style="margin-right: 5px;">
+                <svg-icon name="bx:bxs-component" />
+              </el-icon>
+              <div class="text">
+                {{ data.label }}
+              </div>
+            </div>
+            <div v-if="data.isLeaf" class="actions">
+              <el-button-group>
+                <el-button type="info" plain size="small" @click.stop="onBizEdit(data)">
+                  <template #icon>
+                    <el-icon>
+                      <svg-icon name="i-ep:edit" />
+                    </el-icon>
+                  </template>
+                </el-button>
+
+                <el-button type="danger" plain size="small" @click.stop="onBizDelete(data)">
+                  <template #icon>
+                    <el-icon>
+                      <svg-icon name="i-ep:delete" />
+                    </el-icon>
+                  </template>
+                </el-button>
+              </el-button-group>
+            </div>
+          </div>
+        </template>
+      </ElTree>
+    </el-scrollbar>
+    <BizComponent ref="bizRef" @success="getData" />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.btns {
+  display: inline-flex;
+  width: 100%;
+  margin-bottom: var(--container-padding);
+
+  .add {
+    width: 100%;
+  }
+}
+
+.tree {
+  flex: 1;
+  overflow-y: auto;
+
+  .el-tree {
+    .el-tree-node__content {
+      height: 40px!important;
+    }
+
+    .is-current > .el-tree-node__content {
+      background-color: var(--el-color-primary-light-9);
+    }
+
+    .custom-tree-node {
+      flex: 1;
+      position: relative;
+      width: 0;
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+
+      .label {
+        display: inline-flex;
+        align-items: center;
+        width: calc(100% - 10px);
+        color: var(--el-text-color-primary);
+
+        .text {
+          @include text-overflow;
+        }
+      }
+
+      &:hover {
+        .actions {
+          display: block;
+        }
+      }
+
+      .actions {
+        display: none;
+        position: absolute;
+        right: 10px;
+        top: 50%;
+        transform: translateY(-50%);
+
+        .el-button {
+          padding: 5px 8px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 152 - 0
src/views/biz/biz/components/Object.vue

@@ -0,0 +1,152 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="bizObject">
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { createObject, getObjectById, updateObject } from '@/api/biz/bizObjectApi'
+const emit = defineEmits(['success'])
+
+// 数据
+const state = reactive({
+  title: '',
+  dialogVisible: false,
+  loading: false,
+  search: {
+    keywords: '',
+  },
+  formData: {
+    bizId: 0,
+    objectId: 0,
+    objectType: 1,
+    objectCode: '',
+    objectTitle: '',
+    comment: '',
+  },
+  actionType: 1,
+})
+
+onMounted(() => {})
+
+const getData = async () => {
+  const { bizId, objectId } = state.formData
+  state.loading = true
+  const { data } = await getObjectById(bizId, objectId)
+  state.loading = false
+  state.formData = data
+}
+
+const formRef = ref<FormInstance>()
+const formRules = reactive<FormRules>({
+  objectTitle: [
+    { required: true, message: '请输入对象标题', trigger: 'blur' },
+  ],
+  objectType: [
+    { required: true, message: '请输入对象类型', trigger: 'blur' },
+  ],
+  objectCode: [
+    { required: true, message: '请输入对像代码', trigger: 'blur' },
+  ],
+  comment: [
+    { required: false, message: '请输入简要描述', trigger: 'blur' },
+  ],
+})
+
+function onCancel() {
+  state.dialogVisible = false
+}
+
+function onSubmit() {
+  formRef.value && formRef.value.validate(async (valid) => {
+    if (valid) {
+      if (state.actionType === 1) {
+        const { msg } = await createObject(state.formData)
+        ElMessage.success(msg)
+        state.dialogVisible = false
+        emit('success')
+      }
+      else {
+        const { msg } = await updateObject(state.formData)
+        ElMessage.success(msg)
+        state.dialogVisible = false
+        emit('success')
+      }
+    }
+  })
+}
+
+function resetFormData() {
+  state.formData = {
+    bizId: 0,
+    objectId: 0,
+    objectType: 0,
+    objectCode: '',
+    objectTitle: '',
+    comment: '',
+  }
+}
+
+defineExpose({
+  showAddModel(bizId: number) {
+    resetFormData()
+    state.title = '新增业务对象'
+    state.actionType = 1
+    state.formData.bizId = bizId
+    state.dialogVisible = true
+  },
+
+  showEditModel(bizId: number, objectId: number) {
+    resetFormData()
+    state.title = '编辑业务对象'
+    state.actionType = 2
+    state.formData.bizId = bizId
+    state.formData.objectId = objectId
+    state.dialogVisible = true
+    getData()
+  },
+})
+</script>
+
+<template>
+  <el-drawer v-model="state.dialogVisible" :title="state.title" size="30%">
+    <el-scrollbar class="form-el-scrollbar">
+      <div class="form-content">
+        <el-form ref="formRef" :model="state.formData" :rules="formRules" label-position="top">
+          <el-form-item label="对象名称" prop="objectTitle">
+            <el-input v-model="state.formData.objectTitle" placeholder="请输入标题" />
+          </el-form-item>
+
+          <el-form-item label="类型" prop="objectType">
+            <el-radio-group v-model="state.formData.objectType">
+              <el-radio :label="1">
+                实体对象
+              </el-radio>
+              <el-radio :label="2">
+                视图对象
+              </el-radio>
+            </el-radio-group>
+          </el-form-item>
+
+          <el-form-item label="对象代码" prop="objectCode">
+            <el-input v-model="state.formData.objectCode" placeholder="请输入代码" />
+          </el-form-item>
+
+          <el-form-item label="简要说明" prop="comment">
+            <el-input v-model="state.formData.comment" type="textarea" rows="10" placeholder="请输入标题" />
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-scrollbar>
+
+    <template #footer>
+      <el-button size="large" @click="onCancel">
+        取消
+      </el-button>
+      <el-button type="primary" size="large" @click="onSubmit">
+        保存
+      </el-button>
+    </template>
+  </el-drawer>
+</template>

+ 196 - 0
src/views/biz/biz/components/ObjectList.vue

@@ -0,0 +1,196 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup>
+import { ElMessage, ElMessageBox } from 'element-plus'
+import BizObjectComponent from './Object.vue'
+import { deleteObjectById, getObjectByList } from '@/api/biz/bizObjectApi'
+import useSettingsStore from '@/store/modules/settings'
+
+const settingsStore = useSettingsStore()
+const router = useRouter()
+const tabbar = useTabbar()
+
+interface Object {
+  bizId: number
+  objectId: number
+  objectTitle: string
+  objectCode: string
+  comment: string
+}
+
+const state = reactive({
+  loading: false,
+  objectList: [] as Object[],
+  dialogState: 1,
+  search: {
+    bizId: 0,
+    keywords: '',
+  },
+})
+
+const getData = async () => {
+  const curBizId = state.search.bizId
+  if (curBizId > 0) {
+    state.loading = true
+    const { data } = await getObjectByList({ bizId: curBizId })
+    state.objectList = data
+    state.loading = false
+  }
+}
+
+onMounted(() => {
+})
+
+const bizObjectRef = ref()
+const objectTableRef = ref()
+
+// 检索对象
+const onSearch = () => {
+  getData()
+}
+
+// 新增对象
+const onObjectAdd = () => {
+  const bizId = state.search.bizId
+  bizObjectRef.value.showAddModel(bizId)
+}
+
+// 编辑对象
+const onObjectDetails = (row: { bizId: any; objectId: any }) => {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.open({
+      name: 'bizObjectDetails',
+      params: {
+        bizId: row.bizId,
+        objectId: row.objectId,
+      },
+    })
+  }
+  else {
+    router.push({
+      name: 'bizObjectDetails',
+      params: {
+        bizId: row.bizId,
+        objectId: row.objectId,
+      },
+    })
+  }
+}
+
+const onObjectOAM = (row: any) => {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.open({
+      name: 'bizObjectOAM',
+      params: {
+        bizId: row.bizId,
+        objectId: row.objectId,
+      },
+    })
+  }
+  else {
+    router.push({
+      name: 'bizObjectOAM',
+      params: {
+        bizId: row.bizId,
+        objectId: row.objectId,
+      },
+    })
+  }
+}
+
+// 删除对象
+const onObjectDelete = (row: any) => {
+  const { bizId, objectId, objectTitle } = row
+  ElMessageBox.confirm(`确认删除「${objectTitle}」吗?`, '确认信息').then(async () => {
+    const { msg } = await deleteObjectById(bizId, objectId)
+    ElMessage.success(msg)
+    await getData()
+  })
+}
+
+defineExpose({
+  loadData(bizId: number) {
+    state.search.bizId = bizId
+    getData()
+  },
+})
+</script>
+
+<template>
+  <div class="container">
+    <tool-bar>
+      <template #right>
+        <el-input v-model="state.search.keywords" placeholder="请输入名称,支持模糊查询" style="padding-right: 10px;" clearable />
+        <el-button type="primary" @click="onSearch">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:search" />
+            </el-icon>
+          </template>
+        </el-button>
+
+        <el-button type="primary" size="default" @click.stop="onObjectAdd">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:plus" />
+            </el-icon>
+          </template>
+          业务对象
+        </el-button>
+      </template>
+    </tool-bar>
+
+    <el-table ref="objectTableRef" v-loading="state.loading" class="list-table" :data="state.objectList" size="small" border stripe highlight-current-row height="100%">
+      <el-table-column type="index" label="序号" header-align="center" align="center" width="70" />
+
+      <el-table-column prop="objectTitle" label="对象名称" header-align="center" align="center" width="200">
+        <template #default="scope">
+          <el-icon>
+            <svg-icon name="uim:box" />
+          </el-icon>
+          <span> &nbsp;&nbsp;{{ scope.row.objectTitle }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="objectCode" label="对象代码" header-align="center" align="center" width="150">
+        <template #default="scope">
+          <span>{{ scope.row.objectCode }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="comment" label="说明" header-align="center" align="left">
+        <template #default="scope">
+          <span>{{ scope.row.comment }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="操作" header-align="center" align="center" width="230">
+        <template #default="scope">
+          <div>
+            <el-button type="primary" size="small" plain @click="onObjectOAM(scope.row)">
+              行为
+            </el-button>
+            <el-button type="warning" size="small" plain @click="onObjectDetails(scope.row)">
+              详情
+            </el-button>
+            <el-button type="danger" size="small" plain @click="onObjectDelete(scope.row)">
+              删除
+            </el-button>
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+    <BizObjectComponent ref="bizObjectRef" @success="getData" />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+</style>

+ 9 - 344
src/views/biz/biz/index.vue

@@ -4,300 +4,29 @@ meta:
 </route>
 
 <script lang="ts" setup>
-import { ElMessage, ElMessageBox } from 'element-plus'
-import BizObjectComponent from '../object/components/Object.vue'
-import BizComponent from './components/Biz.vue'
-import { deleteBizById, getBizByList } from '@/api/biz/bizApi'
-import { deleteObjectById, getObjectByList } from '@/api/biz/bizObjectApi'
-import useSettingsStore from '@/store/modules/settings'
+import LeftBizListComponent from './components/BizList.vue'
+import ObjectListComponent from './components/ObjectList.vue'
+const bizListRef = ref()
+const objectListRef = ref()
 
-const settingsStore = useSettingsStore()
-const router = useRouter()
-const tabbar = useTabbar()
-
-interface TreeNode {
-  label: string
-  isLeaf: boolean
-  bizId: number
-  children?: TreeNode[]
-}
-
-interface Object {
-  bizId: number
-  objectId: number
-  objectTitle: string
-  objectCode: string
-  comment: string
-}
-
-const state = reactive({
-  loading: false,
-  keywords: '',
-  treeData: [] as TreeNode[],
-  curBizId: 0,
-  objectList: [] as Object[],
-  dialogState: 1,
-  search: {
-    keywords: '',
-  },
-})
-
-const leftTreeRef = ref()
-const bizRef = ref()
-const getObjectData = async () => {
-  const curBizId = state.curBizId
-  if (curBizId > 0) {
-    state.loading = true
-    const { data } = await getObjectByList({ bizId: curBizId })
-    state.objectList = data
-    state.loading = false
-  }
-}
-
-const getBizData = async () => {
-  const { data } = await getBizByList('')
-  const treeNodes: TreeNode[] = []
-  data.forEach((item: any) => {
-    return treeNodes.push({
-      label: item.bizTitle,
-      bizId: item.bizId,
-      isLeaf: true,
-    })
-  })
-  state.treeData = treeNodes
-
-  if (data && data.length > 0) {
-    state.curBizId = data[0].bizId
-    nextTick(() => {
-      leftTreeRef.value.setCurrentKey(data[0].bizId)
-    })
-    await getObjectData()
-  }
-}
-
-onMounted(() => {
-  getBizData()
-})
-
-// 业务新增
-const onBizAdd = () => {
-  bizRef.value.showAddModel()
-}
-
-// 业务编辑
-const onBizEdit = (data: { bizId: number }) => {
-  const bizId = data.bizId
-  bizRef.value.showEditModel(bizId)
-}
-
-// 业务删除
-const onBizDelete = (data: any) => {
-  ElMessageBox.confirm(`确认删除「${data.bizTitle}」吗?`, '确认信息').then(async () => {
-    const { msg } = await deleteBizById(data.bizId)
-    ElMessage.success(msg)
-    await getBizData()
-  })
-}
-
-// 业务选择
-const onTreeNodeClick = (node: TreeNode) => {
-  if (node.isLeaf) {
-    state.curBizId = node.bizId
-    getObjectData()
-  }
-}
-
-const bizObjectRef = ref()
-const objectTableRef = ref()
-
-// 检索对象
-const onSearch = () => {
-  getObjectData()
-}
-
-// 新增对象
-const onObjectAdd = () => {
-  const bizId = state.curBizId
-  bizObjectRef.value.showAddModel(bizId)
-}
-
-// 编辑对象
-const onObjectDetails = (row: { bizId: any; objectId: any }) => {
-  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
-    tabbar.open({
-      name: 'bizObjectDetails',
-      params: {
-        bizId: row.bizId,
-        objectId: row.objectId,
-      },
-    })
-  }
-  else {
-    router.push({
-      name: 'bizObjectDetails',
-      params: {
-        bizId: row.bizId,
-        objectId: row.objectId,
-      },
-    })
-  }
-}
-
-const onObjectOAM = (row: any) => {
-  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
-    tabbar.open({
-      name: 'bizObjectOAM',
-      params: {
-        bizId: row.bizId,
-        objectId: row.objectId,
-      },
-    })
-  }
-  else {
-    router.push({
-      name: 'bizObjectOAM',
-      params: {
-        bizId: row.bizId,
-        objectId: row.objectId,
-      },
-    })
-  }
-}
-
-// 删除对象
-const onObjectDelete = (row: any) => {
-  const { bizId, objectId, objectTitle } = row
-  ElMessageBox.confirm(`确认删除「${objectTitle}」吗?`, '确认信息').then(async () => {
-    const { msg } = await deleteObjectById(bizId, objectId)
-    ElMessage.success(msg)
-    await getObjectData()
-  })
+const onItemSelect = (bizId: number) => {
+  objectListRef.value.loadData(bizId)
 }
 </script>
 
 <template>
   <div class="absolute-container">
-    <tool-header title="事务模型">
-      <template #right>
-        <el-button v-waves.float type="primary" @click="onBizAdd">
-          <template #icon>
-            <el-icon>
-              <svg-icon name="i-ep:plus" />
-            </el-icon>
-          </template>
-          业务模型
-        </el-button>
-      </template>
-    </tool-header>
+    <tool-header title="事务模型" />
 
     <div class="page-main">
       <LayoutContainer left-side-width="250px" hide-left-side-toggle>
         <template #leftSide>
-          <el-scrollbar class="tree">
-            <ElTree ref="leftTreeRef" :data="state.treeData" default-expand-all node-key="bizId" @node-click="onTreeNodeClick">
-              <template #default="{ node, data }">
-                <div class="custom-tree-node">
-                  <div class="label" :title="node.label">
-                    <el-icon v-if="data.isLeaf" size="16px" style="margin-right: 5px;">
-                      <svg-icon name="bx:bxs-component" />
-                    </el-icon>
-                    <div class="text">
-                      {{ data.label }}
-                    </div>
-                  </div>
-                  <div v-if="data.isLeaf" class="actions">
-                    <el-button-group>
-                      <el-button type="info" plain size="small" @click.stop="onBizEdit(data)">
-                        <template #icon>
-                          <el-icon>
-                            <svg-icon name="i-ep:edit" />
-                          </el-icon>
-                        </template>
-                      </el-button>
-
-                      <el-button type="danger" plain size="small" @click.stop="onBizDelete(data)">
-                        <template #icon>
-                          <el-icon>
-                            <svg-icon name="i-ep:delete" />
-                          </el-icon>
-                        </template>
-                      </el-button>
-                    </el-button-group>
-                  </div>
-                </div>
-              </template>
-            </ElTree>
-          </el-scrollbar>
+          <LeftBizListComponent ref="bizListRef" @onItemSelect="onItemSelect" />
         </template>
 
-        <div class="container">
-          <tool-bar>
-            <template #right>
-              <el-input v-model="state.search.keywords" placeholder="请输入名称,支持模糊查询" style="padding-right: 10px;" clearable />
-              <el-button type="primary" @click="onSearch">
-                <template #icon>
-                  <el-icon>
-                    <svg-icon name="i-ep:search" />
-                  </el-icon>
-                </template>
-              </el-button>
-
-              <el-button type="primary" size="default" @click.stop="onObjectAdd">
-                <template #icon>
-                  <el-icon>
-                    <svg-icon name="i-ep:plus" />
-                  </el-icon>
-                </template>
-                业务对象
-              </el-button>
-            </template>
-          </tool-bar>
-
-          <el-table ref="objectTableRef" v-loading="state.loading" class="list-table" :data="state.objectList" size="small" border stripe highlight-current-row height="100%">
-            <el-table-column type="index" label="序号" header-align="center" align="center" width="70" />
-
-            <el-table-column prop="objectTitle" label="对象名称" header-align="center" align="center" width="200">
-              <template #default="scope">
-                <el-icon>
-                  <svg-icon name="uim:box" />
-                </el-icon>
-                <span> &nbsp;&nbsp;{{ scope.row.objectTitle }}</span>
-              </template>
-            </el-table-column>
-
-            <el-table-column prop="objectCode" label="对象代码" header-align="center" align="center" width="150">
-              <template #default="scope">
-                <span>{{ scope.row.objectCode }}</span>
-              </template>
-            </el-table-column>
-
-            <el-table-column prop="comment" label="说明" header-align="center" align="left">
-              <template #default="scope">
-                <span>{{ scope.row.comment }}</span>
-              </template>
-            </el-table-column>
-
-            <el-table-column label="操作" header-align="center" align="center" width="230">
-              <template #default="scope">
-                <div>
-                  <el-button type="primary" size="small" plain @click="onObjectOAM(scope.row)">
-                    行为
-                  </el-button>
-                  <el-button type="warning" size="small" plain @click="onObjectDetails(scope.row)">
-                    详情
-                  </el-button>
-                  <el-button type="danger" size="small" plain @click="onObjectDelete(scope.row)">
-                    删除
-                  </el-button>
-                </div>
-              </template>
-            </el-table-column>
-          </el-table>
-        </div>
+        <ObjectListComponent ref="objectListRef" />
       </LayoutContainer>
     </div>
-    <BizComponent ref="bizRef" @success="getBizData" />
-    <BizObjectComponent ref="bizObjectRef" @success="getObjectData" />
   </div>
 </template>
 
@@ -313,70 +42,6 @@ const onObjectDelete = (row: any) => {
     display: flex;
     flex-direction: column;
     height: 100%;
-
-    .btns {
-      display: inline-flex;
-      width: 100%;
-      margin-bottom: var(--container-padding);
-
-      .add {
-        width: 100%;
-      }
-    }
-
-    .tree {
-      flex: 1;
-      overflow-y: auto;
-
-      .el-tree {
-        .el-tree-node__content {
-          height: 40px;
-        }
-
-        .is-current > .el-tree-node__content {
-          background-color: var(--el-color-primary-light-9);
-        }
-
-        .custom-tree-node {
-          flex: 1;
-          position: relative;
-          width: 0;
-          height: 100%;
-          display: flex;
-          flex-direction: column;
-          justify-content: center;
-
-          .label {
-            display: inline-flex;
-            align-items: center;
-            width: calc(100% - 10px);
-            color: var(--el-text-color-primary);
-
-            .text {
-              @include text-overflow;
-            }
-          }
-
-          &:hover {
-            .actions {
-              display: block;
-            }
-          }
-
-          .actions {
-            display: none;
-            position: absolute;
-            right: 10px;
-            top: 50%;
-            transform: translateY(-50%);
-
-            .el-button {
-              padding: 5px 8px;
-            }
-          }
-        }
-      }
-    }
   }
 }
 </style>

+ 0 - 0
src/views/biz/oam/components/RuleSelector.vue → src/views/biz/components/BizRuleSelector.vue


+ 189 - 0
src/views/biz/oam/components/ObjectOAMInfo.vue

@@ -0,0 +1,189 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="BizObjectOAM">
+import { ElMessage, ElMessageBox } from 'element-plus'
+import BizObjectOAMComponent from './ObjectOAM.vue'
+import BizObjectOAMParamsListComponent from '@/views/biz/oam_params/index.vue'
+import { deleteObjectOAMById, getObjectOAMById } from '@/api/biz/bizObjectOAMApi'
+import { oamType, sqlType } from '@/utils/tool'
+const route = useRoute()
+const bizId = parseInt(route.params.bizId.toString())
+const objectId = parseInt(route.params.objectId.toString())
+
+const state = reactive({
+  loading: false,
+  oam: {
+    bizId: 0,
+    objectId: 0,
+    oamId: 0,
+    oamTitle: '',
+    oamCode: '',
+    oamType: 0,
+    oamStatement: '',
+    oamDesc: '',
+    sqlStatement: '',
+    sqlSelect: '',
+    sqlFrom: '',
+    sqlWhere: '',
+    sqlOrder: '',
+    sqlCount: '',
+  },
+  dialogState: 1,
+  search: {
+    oamId: 0,
+    keywords: '',
+  },
+  result: '',
+  actionType: 0,
+})
+
+const getData = async () => {
+  const { oamId } = state.search
+  if (oamId > 0) {
+    state.loading = true
+    const { data } = await getObjectOAMById(bizId, objectId, oamId)
+    state.oam = data
+    state.loading = false
+  }
+}
+
+onMounted(() => {
+  getData()
+})
+
+const bizObjectOAMRef = ref()
+
+const onObjectOAMEdit = () => {
+  const { oamId } = state.search
+  bizObjectOAMRef.value.showEditModel(bizId, objectId, oamId)
+}
+
+const onObjectOAMDelete = (data: { bizId: number; objectId: number; oamId: number; oamTitle: string }) => {
+  const { bizId, objectId, oamId, oamTitle } = data
+  ElMessageBox.confirm(`确认删除「${oamTitle}」吗?`, '确认信息').then(async () => {
+    const { msg } = await deleteObjectOAMById(bizId, objectId, oamId)
+    ElMessage.success(msg)
+  })
+}
+
+defineExpose({
+  loadData(oamId: number) {
+    state.search.oamId = oamId
+    getData()
+  },
+})
+</script>
+
+<template>
+  <div>
+    <el-descriptions
+      :title="state.oam.oamTitle"
+      direction="horizontal"
+      :column="1"
+      size="small"
+      border
+    >
+      <template #extra>
+        <div>
+          <el-button type="primary" @click="onObjectOAMEdit">
+            编辑
+          </el-button>
+          <el-button type="primary" @click="onObjectOAMDelete">
+            删除
+          </el-button>
+        </div>
+      </template>
+
+      <el-descriptions-item
+        label-align="right"
+        label="编码"
+        width="150px"
+      >
+        {{ state.oam.oamCode }}
+      </el-descriptions-item>
+
+      <el-descriptions-item
+        label="行为类型"
+        width="150px"
+        label-align="right"
+      >
+        {{ oamType(state.oam.oamType) }}
+      </el-descriptions-item>
+
+      <el-descriptions-item
+        label-align="right"
+        width="150px"
+        label="操作类型"
+      >
+        {{ sqlType(state.oam.sqlType) }}
+      </el-descriptions-item>
+
+      <el-descriptions-item
+        v-if="state.oam.sqlType === 1"
+        label-align="right"
+        width="150px"
+        label="Sql"
+      >
+        {{ state.oam.sqlStatement }}
+      </el-descriptions-item>
+
+      <el-descriptions-item
+        v-if="state.oam.oamType === 3"
+        label-align="right"
+        width="150px"
+        label="Count"
+      >
+        {{ state.oam.sqlCount }}
+      </el-descriptions-item>
+
+      <el-descriptions-item
+        label-align="right"
+        width="150px"
+        label="说明"
+      >
+        {{ state.oam.oamDesc }}
+      </el-descriptions-item>
+    </el-descriptions>
+    <div v-if="state.oam && state.oam.sqlType === 1" class="container">
+      <BizObjectOAMParamsListComponent
+        ref="bizObjectOAMParamsListRef"
+        :biz-id="state.search.bizId"
+        :object-id="state.search.objectId"
+      />
+    </div>
+    <BizObjectOAMComponent ref="bizObjectOAMRef" @success="getData" />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.question {
+  .answer {
+    margin: 20px 0 0;
+    padding-left: 20px;
+    font-size: 16px;
+    color: var(--el-text-color-secondary);
+
+    li {
+      margin-bottom: 10px;
+      line-height: 1.5;
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+
+    span {
+      color: var(--el-text-color-primary);
+      font-weight: bold;
+    }
+  }
+}
+
+h5{
+  padding: 0;
+  margin: 0;
+}
+</style>

+ 179 - 0
src/views/biz/oam/components/ObjectOAMList.vue

@@ -0,0 +1,179 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="BizObjectOAM">
+import ObjectOAMComponent from './ObjectOAM.vue'
+import { getObjectOAMListByObjectId } from '@/api/biz/bizObjectOAMApi'
+const emit = defineEmits(['onItemSelect'])
+const route = useRoute()
+const bizId = parseInt(route.params.bizId.toString())
+const objectId = parseInt(route.params.objectId.toString())
+interface TreeNode {
+  label: string
+  isLeaf: boolean
+  oamId: number
+  oamCode: string
+  children?: TreeNode[]
+}
+
+const state = reactive({
+  loading: false,
+  curOamId: 0,
+  oamList: [],
+  treeData: [] as TreeNode[],
+  dialogState: 1,
+  search: {
+    oamId: 0,
+    keywords: '',
+  },
+  result: '',
+  actionType: 0,
+})
+
+const leftTreeRef = ref()
+
+const getData = async () => {
+  const { data } = await getObjectOAMListByObjectId(bizId, objectId)
+  state.treeData = []
+  if (data && data.length > 0) {
+    data.forEach((item: any) => {
+      state.treeData.push({
+        label: item.oamTitle,
+        oamId: item.oamId,
+        oamCode: item.oamCode,
+        isLeaf: true,
+      })
+    })
+
+    state.curOamId = data[0].oamId
+    nextTick(() => {
+      leftTreeRef.value.setCurrentKey(state.curOamId)
+      emit('onItemSelect', state.curOamId)
+    })
+  }
+}
+
+onMounted(() => {
+  getData()
+})
+
+// Object OAM选择
+const onTreeNodeClick = async (node: TreeNode) => {
+  if (node.isLeaf) {
+    state.curOamId = node.oamId
+    emit('onItemSelect', state.curOamId)
+  }
+}
+
+const objectOAMRef = ref()
+const onObjectOAMAdd = () => {
+  objectOAMRef.value.showAddModel(bizId, objectId)
+}
+</script>
+
+<template>
+  <div>
+    <el-button-group class="btns">
+      <el-button type="primary" class="add" @click="onObjectOAMAdd()">
+        <template #icon>
+          <el-icon>
+            <svg-icon name="i-ep:plus" />
+          </el-icon>
+        </template>
+        对象行为
+      </el-button>
+      <el-button @click="getData">
+        <template #icon>
+          <el-icon>
+            <svg-icon name="i-ep:refresh" />
+          </el-icon>
+        </template>
+      </el-button>
+    </el-button-group>
+
+    <el-scrollbar class="tree">
+      <ElTree ref="leftTreeRef" :data="state.treeData" default-expand-all node-key="oamId" @node-click="onTreeNodeClick">
+        <template #default="{ node, data }">
+          <div class="custom-tree-node">
+            <div class="label" :title="node.label">
+              <div class="text">
+                <el-icon v-if="data.isLeaf" size="16px" style="margin:0 5px 5px 0;">
+                  <svg-icon name="ant-design:api-outlined" />
+                </el-icon>
+                <span>{{ data.label }}</span>
+              </div>
+              <div class="code">
+                {{ data.oamCode }}
+              </div>
+            </div>
+          </div>
+        </template>
+      </ElTree>
+    </el-scrollbar>
+    <ObjectOAMComponent ref="objectOAMRef" @success="getData" />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.btns {
+  display: inline-flex;
+  width: 100%;
+
+  .add {
+    width: 100%;
+  }
+}
+
+.tree {
+  flex: 1;
+  overflow-y: auto;
+
+  .el-tree {
+    .el-tree-node__content {
+      height: 60px!important;
+    }
+
+    .is-current > .el-tree-node__content {
+      background-color: var(--el-color-primary-light-9)!important;
+    }
+
+    .custom-tree-node {
+      flex: 1;
+      position: relative;
+      width: 0;
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+
+      .label {
+        width: calc(100% - 10px);
+        color: var(--el-text-color-primary);
+        padding: 10px;
+
+        @include text-overflow;
+
+        .el-icon {
+          padding-top: 5px;
+        }
+      }
+
+      .code {
+        padding-left: 20px;
+        width: calc(100% - 10px);
+        color: var(--el-text-color-placeholder);
+
+        @include text-overflow;
+      }
+
+      &:hover {
+        .actions {
+          display: block;
+        }
+      }
+    }
+  }
+}
+</style>

+ 11 - 309
src/views/biz/oam/index.vue

@@ -4,15 +4,12 @@ meta:
 </route>
 
 <script lang="ts" setup name="BizObjectOAM">
-import { ElMessage, ElMessageBox } from 'element-plus'
-import BizObjectOAMParamsListComponent from '../oam_params/index.vue'
-import BizObjectOAMRuleListComponent from '../oam_rule/index.vue'
 import BizObjectOAMMappingListComponent from '../oam_mapping/index.vue'
-import ObjectOAMComponent from './components/objectOAM.vue'
+import BizObjectOAMRuleListComponent from '../oam_rule/index.vue'
+import BizObjectOAMListComponent from './components/ObjectOAMList.vue'
+import BizObjectOAMInfoComponent from './components/ObjectOAMInfo.vue'
 import useSettingsStore from '@/store/modules/settings'
 import { getObjectById } from '@/api/biz/bizObjectApi'
-import { deleteObjectOAMById, getObjectOAMById, getObjectOAMListByObjectId } from '@/api/biz/bizObjectOAMApi'
-import { oamType, sqlType } from '@/utils/tool'
 
 const settingsStore = useSettingsStore()
 const route = useRoute()
@@ -22,41 +19,13 @@ const tabbar = useTabbar()
 const bizId = parseInt(route.params.bizId.toString())
 const objectId = parseInt(route.params.objectId.toString())
 
-interface TreeNode {
-  label: string
-  isLeaf: boolean
-  oamId: number
-  oamCode: string
-  children?: TreeNode[]
-}
-
-interface ObjectOAM {
-  bizId: number
-  objectId: number
-  oamId: number
-  oamTitle: string
-  oamCode: string
-  oamType: number
-  oamStatement: string
-  oamDesc: string
-  sqlStatement: string
-  sqlSelect: string
-  sqlFrom: string
-  sqlWhere: string
-  sqlOrder: string
-  sqlCount: string
-}
-
 const state = reactive({
   loading: false,
   objectTitle: '',
   objectCode: '',
   objectType: 0,
-  keywords: '',
   curOamId: 0,
   oamList: [],
-  treeData: [] as TreeNode[],
-  oam: {} as ObjectOAM,
   dialogState: 1,
   search: {
     bizId,
@@ -67,8 +36,6 @@ const state = reactive({
   actionType: 0,
 })
 
-const leftTreeRef = ref()
-
 const getObjectData = async () => {
   state.loading = true
   const { data } = await getObjectById(bizId, objectId)
@@ -78,84 +45,19 @@ const getObjectData = async () => {
   state.loading = false
 }
 
-const getObjectOAMInfo = async () => {
-  const curOamId = state.curOamId
-  if (curOamId > 0) {
-    state.loading = true
-    const { data } = await getObjectOAMById(bizId, objectId, curOamId)
-    state.oam = data
-    state.loading = false
-  }
-}
-const bizObjectOAMParamsListRef = ref()
+const bizObjectOAMListRef = ref()
+const bizObjectOAMInfoRef = ref()
 const bizObjectOAMRuleListRef = ref()
 const bizObjectOAMMappingListRef = ref()
 
-const getOAMTree = async () => {
-  const { data } = await getObjectOAMListByObjectId(bizId, objectId)
-  state.treeData = []
-  if (data && data.length > 0) {
-    data.forEach((item: any) => {
-      state.treeData.push({
-        label: item.oamTitle,
-        oamId: item.oamId,
-        oamCode: item.oamCode,
-        isLeaf: true,
-      })
-    })
-
-    state.curOamId = data[0].oamId
-    bizObjectOAMParamsListRef.value?.showData(state.curOamId)
-    bizObjectOAMRuleListRef.value?.showData(state.curOamId)
-    bizObjectOAMMappingListRef.value?.showData(state.curOamId)
-    nextTick(() => {
-      leftTreeRef.value.setCurrentKey(data[0].oamId)
-    })
-    await getObjectOAMInfo()
-  }
-}
-
-const getObjectOAMData = async () => {
-  await getObjectOAMInfo()
-  bizObjectOAMParamsListRef.value?.showData(state.curOamId)
-  bizObjectOAMRuleListRef.value?.showData(state.curOamId)
-  bizObjectOAMMappingListRef.value?.showData(state.curOamId)
-}
-
 onMounted(() => {
   getObjectData()
-  getOAMTree()
 })
 
-// Object OAM选择
-const onTreeNodeClick = async (node: TreeNode) => {
-  if (node.isLeaf) {
-    state.curOamId = node.oamId
-    await getObjectOAMData()
-  }
-}
-
-const objectOAMRef = ref()
-const onObjectOAMAdd = () => {
-  objectOAMRef.value.showAddModel(bizId, objectId)
-}
-
-const onObjectOAMEdit = () => {
-  objectOAMRef.value.showEditModel(bizId, objectId, state.curOamId)
-}
-
-const onObjectOAMDelete = (data: { bizId: number; objectId: number; oamId: number; oamTitle: string }) => {
-  const { bizId, objectId, oamId, oamTitle } = data
-  ElMessageBox.confirm(`确认删除「${oamTitle}」吗?`, '确认信息').then(async () => {
-    const { msg } = await deleteObjectOAMById(bizId, objectId, oamId)
-    ElMessage.success(msg)
-    await getOAMTree()
-  })
-}
-
-// 选择对象模型回调
-const onSuccess = () => {
-  getOAMTree()
+const onItemSelect = (oamId: number) => {
+  bizObjectOAMInfoRef.value?.loadData(oamId)
+  bizObjectOAMRuleListRef.value?.loadData(oamId)
+  bizObjectOAMMappingListRef.value?.loadData(oamId)
 }
 
 // 返回列表页
@@ -185,120 +87,13 @@ function goBack() {
     <div class="page-main">
       <LayoutContainer left-side-width="250px" hide-left-side-toggle>
         <template #leftSide>
-          <el-button-group class="btns">
-            <el-button type="primary" class="add" @click="onObjectOAMAdd()">
-              <template #icon>
-                <el-icon>
-                  <svg-icon name="i-ep:plus" />
-                </el-icon>
-              </template>
-              对象行为
-            </el-button>
-            <el-button @click="getObjectOAMData">
-              <template #icon>
-                <el-icon>
-                  <svg-icon name="i-ep:refresh" />
-                </el-icon>
-              </template>
-            </el-button>
-          </el-button-group>
-          <el-input placeholder="请输入关键词筛选" clearable class="search" />
-
-          <el-scrollbar class="tree">
-            <ElTree ref="leftTreeRef" :data="state.treeData" default-expand-all node-key="oamId" @node-click="onTreeNodeClick">
-              <template #default="{ node, data }">
-                <div class="custom-tree-node">
-                  <div class="label" :title="node.label">
-                    <div class="text">
-                      <el-icon v-if="data.isLeaf" size="16px" style="margin:0 5px 5px 0;">
-                        <svg-icon name="ant-design:api-outlined" />
-                      </el-icon>
-                      <span>{{ data.label }}</span>
-                    </div>
-                    <div class="code">
-                      {{ data.oamCode }}
-                    </div>
-                  </div>
-                </div>
-              </template>
-            </ElTree>
-          </el-scrollbar>
+          <BizObjectOAMListComponent ref="bizObjectOAMListRef" :object-id="objectId" :biz-id="bizId" @onItemSelect="onItemSelect" />
         </template>
 
         <div class="container">
           <el-tabs class="demo-tabs">
             <el-tab-pane label="行为定义" name="first">
-              <el-descriptions
-                :title="state.oam.oamTitle"
-                direction="horizontal"
-                :column="1"
-                size="small"
-                border
-              >
-                <template #extra>
-                  <div>
-                    <el-button type="primary" @click="onObjectOAMEdit">
-                      编辑
-                    </el-button>
-                    <el-button type="primary" @click="onObjectOAMDelete">
-                      删除
-                    </el-button>
-                  </div>
-                </template>
-
-                <el-descriptions-item
-                  label-align="right"
-                  label="编码"
-                  width="150px"
-                >
-                  {{ state.oam.oamCode }}
-                </el-descriptions-item>
-
-                <el-descriptions-item
-                  label="行为类型"
-                  width="150px"
-                  label-align="right"
-                >
-                  {{ oamType(state.oam.oamType) }}
-                </el-descriptions-item>
-
-                <el-descriptions-item
-                  label-align="right"
-                  width="150px"
-                  label="操作类型"
-                >
-                  {{ sqlType(state.oam.sqlType) }}
-                </el-descriptions-item>
-
-                <el-descriptions-item
-                  v-if="state.oam.sqlType === 1"
-                  label-align="right"
-                  width="150px"
-                  label="Sql"
-                >
-                  {{ state.oam.sqlStatement }}
-                </el-descriptions-item>
-
-                <el-descriptions-item
-                  v-if="state.oam.oamType === 3"
-                  label-align="right"
-                  width="150px"
-                  label="Count"
-                >
-                  {{ state.oam.sqlCount }}
-                </el-descriptions-item>
-
-                <el-descriptions-item
-                  label-align="right"
-                  width="150px"
-                  label="说明"
-                >
-                  {{ state.oam.oamDesc }}
-                </el-descriptions-item>
-              </el-descriptions>
-              <div v-if="state.oam && state.oam.sqlType === 1" class="container">
-                <BizObjectOAMParamsListComponent ref="bizObjectOAMParamsListRef" :biz-id="bizId" :object-id="objectId" />
-              </div>
+              <BizObjectOAMInfoComponent ref="bizObjectOAMInfoRef" :biz-id="bizId" :object-id="objectId" />
             </el-tab-pane>
 
             <el-tab-pane v-if="state.oam && state.oam.sqlType !== 1" label="业务规则" name="two">
@@ -312,7 +107,6 @@ function goBack() {
         </div>
       </LayoutContainer>
     </div>
-    <ObjectOAMComponent ref="objectOAMRef" @success="getObjectOAMData" />
   </div>
 </template>
 
@@ -346,98 +140,6 @@ function goBack() {
     display: flex;
     flex-direction: column;
     height: 100%;
-
-      .search{
-        margin: 15px 0;
-      }
-
-      .btns {
-      display: inline-flex;
-      width: 100%;
-
-      .add {
-        width: 100%;
-      }
-    }
-
-    .tree {
-      flex: 1;
-      overflow-y: auto;
-
-      .el-tree {
-        .el-tree-node__content {
-          height: 60px;
-        }
-
-        .is-current > .el-tree-node__content {
-          background-color: var(--el-color-primary-light-9);
-        }
-
-        .custom-tree-node {
-          flex: 1;
-          position: relative;
-          width: 0;
-          height: 100%;
-          display: flex;
-          flex-direction: column;
-          justify-content: center;
-
-          .label {
-            width: calc(100% - 10px);
-            color: var(--el-text-color-primary);
-            padding: 10px;
-
-            @include text-overflow;
-
-            .el-icon {
-              padding-top: 5px;
-            }
-          }
-
-          .code {
-            padding-left: 20px;
-            width: calc(100% - 10px);
-            color: var(--el-text-color-placeholder);
-
-            @include text-overflow;
-          }
-
-          &:hover {
-            .actions {
-              display: block;
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-.question {
-  .answer {
-    margin: 20px 0 0;
-    padding-left: 20px;
-    font-size: 16px;
-    color: var(--el-text-color-secondary);
-
-    li {
-      margin-bottom: 10px;
-      line-height: 1.5;
-
-      &:last-child {
-        margin-bottom: 0;
-      }
-    }
-
-    span {
-      color: var(--el-text-color-primary);
-      font-weight: bold;
-    }
   }
 }
-
-h5{
-  padding: 0;
-  margin: 0;
-}
 </style>

+ 1 - 1
src/views/biz/oam_mapping/index.vue

@@ -137,7 +137,7 @@ onMounted(() => {
 })
 
 defineExpose({
-  showData(oamId: number) {
+  loadData(oamId: number) {
     state.conditions.oamId = oamId
     getData()
   },

+ 1 - 1
src/views/biz/oam_params/index.vue

@@ -8,7 +8,7 @@ import type { FormInstance, FormRules } from 'element-plus'
 import { ElMessage } from 'element-plus'
 import { dataType } from '@/utils/tool'
 import { createObjectOAMParams, deleteObjectOAMParamsById, getObjectOAMParamsListByOamId, updateObjectOAMParams } from '@/api/biz/bizObjectOAMParamsApi'
-import RuleSelector from '@/views/biz/oam/components/RuleSelector.vue'
+import RuleSelector from '@/views/biz/components/BizRuleSelector.vue'
 const props = withDefaults(defineProps<{
   bizId: number
   objectId: number

+ 1 - 1
src/views/biz/oam_rule/components/ObjectOAMRule.vue

@@ -7,7 +7,7 @@ meta:
 import type { FormInstance, FormRules } from 'element-plus'
 import { ElMessage } from 'element-plus'
 import { createObjectOAMRule, getObjectOAMRuleById, updateObjectOAMRule } from '@/api/biz/bizObjectOAMRuleApi'
-import RuleSelector from '@/views/biz/oam/components/RuleSelector.vue'
+import RuleSelector from '@/views/biz/components/BizRuleSelector.vue'
 import ObjectAttrSelector from '@/views/biz/rule/components/ObjectAttrSelector.vue'
 const emit = defineEmits(['success'])
 

+ 1 - 1
src/views/biz/oam_rule/index.vue

@@ -135,7 +135,7 @@ onMounted(() => {
 })
 
 defineExpose({
-  showData(oamId: number) {
+  loadData(oamId: number) {
     state.search.oamId = oamId
     getData()
   },

+ 209 - 0
src/views/model/model/components/ModelList.vue

@@ -0,0 +1,209 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="model_object_List">
+import { ElMessage, ElMessageBox } from 'element-plus'
+import ModelComponent from './Model.vue'
+import { deleteModelById, getModelByList } from '@/api/model/modelApi'
+const emit = defineEmits(['onItemSelect'])
+
+interface TreeNode {
+  label: string
+  isLeaf: boolean
+  modelId: number
+  children?: TreeNode[]
+}
+
+const state = reactive({
+  loading: false,
+  keywords: '',
+  treeData: [] as TreeNode[],
+  curModelId: 0,
+  dialogState: 1,
+  search: {
+    keywords: '',
+  },
+})
+
+const leftTreeRef = ref()
+const modelRef = ref()
+
+const getData = async () => {
+  const { data } = await getModelByList('')
+  const treeNodes: TreeNode[] = []
+  data.forEach((item: any) => {
+    return treeNodes.push({
+      label: item.modelTitle,
+      modelId: item.modelId,
+      isLeaf: true,
+    })
+  })
+  state.treeData = treeNodes
+
+  if (data && data.length > 0) {
+    state.curModelId = data[0].modelId
+    nextTick(() => {
+      leftTreeRef.value.setCurrentKey(state.curModelId)
+      emit('onItemSelect', state.curModelId)
+    })
+  }
+}
+
+onMounted(() => {
+  getData()
+})
+
+// 模型新增
+const onModelAdd = () => {
+  modelRef.value.showAddModel()
+}
+
+// 模型编辑
+const onModelEdit = (data: { modelId: number }) => {
+  const modelId = data.modelId
+  modelRef.value.showEditModel(modelId)
+}
+
+// 模型删除
+const onModelDelete = (data: any) => {
+  ElMessageBox.confirm(`确认删除「${data.modelTitle}」吗?`, '确认信息').then(async () => {
+    const { msg } = await deleteModelById(data.modelId)
+    ElMessage.success(msg)
+    await getData()
+  })
+}
+
+// 模型选择
+const onTreeNodeClick = (node: TreeNode) => {
+  if (node.isLeaf) {
+    state.curModelId = node.modelId
+    emit('onItemSelect', state.curModelId)
+  }
+}
+</script>
+
+<template>
+  <div>
+    <el-scrollbar class="tree">
+      <el-button-group class="btns">
+        <el-button type="primary" class="add" @click="onModelAdd()">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:plus" />
+            </el-icon>
+          </template>
+          元数据模型
+        </el-button>
+        <el-button @click="getData">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:refresh" />
+            </el-icon>
+          </template>
+        </el-button>
+      </el-button-group>
+      <ElTree ref="leftTreeRef" :data="state.treeData" default-expand-all node-key="modelId" @node-click="onTreeNodeClick">
+        <template #default="{ node, data }">
+          <div class="custom-tree-node">
+            <div class="label" :title="node.label">
+              <el-icon v-if="data.isLeaf" size="16px" style="margin-right: 5px;">
+                <svg-icon name="bx:bxs-component" />
+              </el-icon>
+              <div class="text">
+                {{ data.label }}
+              </div>
+            </div>
+            <div v-if="data.isLeaf" class="actions">
+              <el-button-group>
+                <el-button type="info" plain size="small" @click.stop="onModelEdit(data)">
+                  <template #icon>
+                    <el-icon>
+                      <svg-icon name="i-ep:edit" />
+                    </el-icon>
+                  </template>
+                </el-button>
+
+                <el-button type="danger" plain size="small" @click.stop="onModelDelete(data)">
+                  <template #icon>
+                    <el-icon>
+                      <svg-icon name="i-ep:delete" />
+                    </el-icon>
+                  </template>
+                </el-button>
+              </el-button-group>
+            </div>
+          </div>
+        </template>
+      </ElTree>
+    </el-scrollbar>
+    <ModelComponent ref="modelRef" @success="getData" />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.btns {
+  display: inline-flex;
+  width: 100%;
+  margin-bottom: var(--container-padding);
+
+  .add {
+    width: 100%;
+  }
+}
+
+.tree {
+  flex: 1;
+  overflow-y: auto;
+
+  .el-tree {
+    .el-tree-node__content {
+      height: 40px!important;
+    }
+
+    .is-current > .el-tree-node__content {
+      background-color: var(--el-color-primary-light-9)!important;
+    }
+
+    .custom-tree-node {
+      flex: 1;
+      position: relative;
+      width: 0;
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+
+      .label {
+        display: inline-flex;
+        align-items: center;
+        width: calc(100% - 10px);
+        color: var(--el-text-color-primary);
+
+        .text {
+          @include text-overflow;
+        }
+      }
+
+      &:hover {
+        .actions {
+          display: block;
+        }
+      }
+
+      .actions {
+        display: none;
+        position: absolute;
+        right: 10px;
+        top: 50%;
+        transform: translateY(-50%);
+
+        .el-button {
+          padding: 5px 8px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 172 - 0
src/views/model/model/components/Object.vue

@@ -0,0 +1,172 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="ModelObject">
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { createObject, getObjectById, updateObject } from '@/api/model/modelObjectApi'
+const emit = defineEmits(['success'])
+
+const state = reactive({
+  title: '',
+  dialogVisible: false,
+  loading: false,
+  formData: {
+    modelId: 0,
+    objectId: 0,
+    objectCode: '',
+    objectTitle: '',
+    comment: '',
+  },
+  actionType: 1,
+})
+
+const formRef = ref<FormInstance>()
+const formRules = ref<FormRules>({
+  objectTitle: [
+    { required: true, message: '请输入标题', trigger: 'blur' },
+  ],
+  objectCode: [
+    { required: true, message: '请输入标题', trigger: 'blur' },
+  ],
+  comment: [
+    { required: false, message: '请输入描述', trigger: 'blur' },
+  ],
+})
+
+// 查询数据
+const getData = async (modelId: number, objectId: number) => {
+  state.loading = true
+  const { data } = await getObjectById(modelId, objectId)
+  state.loading = false
+  state.formData = data
+}
+
+onMounted(() => {
+  nextTick(() => {
+  })
+})
+
+// 保存
+function onSubmit() {
+  formRef.value && formRef.value.validate(async (valid) => {
+    if (valid) {
+      if (state.actionType === 1) {
+        const { msg } = await createObject(state.formData)
+        ElMessage.success(msg)
+        state.dialogVisible = false
+        emit('success')
+      }
+      else {
+        const { msg } = await updateObject(state.formData)
+        ElMessage.success(msg)
+        state.dialogVisible = false
+        emit('success')
+      }
+    }
+  })
+}
+
+function onCancel() {
+  state.dialogVisible = false
+}
+
+function resetFormData() {
+  state.formData = {
+    modelId: 0,
+    objectId: 0,
+    objectCode: '',
+    objectTitle: '',
+    comment: '',
+  }
+}
+
+defineExpose({
+  showAddModel(modelId: number) {
+    resetFormData()
+    state.title = '新增对象'
+    state.actionType = 1
+    state.dialogVisible = true
+    state.formData.modelId = modelId
+  },
+  showEditModel(modelId: number, objectId: number) {
+    resetFormData()
+    state.title = '编辑对象'
+    state.actionType = 2
+    state.dialogVisible = true
+    getData(modelId, objectId)
+  },
+})
+</script>
+
+<template>
+  <el-drawer v-model="state.dialogVisible" :title="state.title" size="30%" direction="rtl">
+    <el-scrollbar>
+      <div class="form-content">
+        <el-form ref="formRef" :model="state.formData" :rules="formRules" label-position="top">
+          <el-form-item label="对象名称" prop="objectTitle">
+            <el-input v-model="state.formData.objectTitle" placeholder="请输入标题" />
+          </el-form-item>
+          <el-form-item label="对象代码" prop="objectCode">
+            <el-input v-model="state.formData.objectCode" placeholder="请输入代码" />
+          </el-form-item>
+          <el-form-item label="简要说明" prop="comment">
+            <el-input v-model="state.formData.comment" type="textarea" rows="10" placeholder="请输入标题" />
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-scrollbar>
+
+    <template #footer>
+      <div style="flex: auto">
+        <el-button type="primary" size="large" @click="onSubmit">
+          提交
+        </el-button>
+        <el-button size="large" @click="onCancel">
+          取消
+        </el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<style lang="scss" scoped>
+.form-right-side {
+  padding: var(--container-padding);
+  border-left: 1px dashed var(--el-disabled-border-color);
+  background-color: var(--g-app-bg);
+  transition: background-color 0.3s;
+
+  :deep(.el-table) {
+    height: 100%;
+    margin-top: 15px;
+
+    .el-table__row {
+      .index {
+        display: inline-block;
+      }
+
+      .delete {
+        display: none;
+      }
+
+      &:hover {
+        .index {
+          display: none;
+        }
+
+        .delete {
+          display: inline-block;
+        }
+      }
+
+      .el-tag.sortable,
+      .el-tag.sortable .el-icon {
+        cursor: s-resize;
+      }
+    }
+  }
+}
+</style>

+ 209 - 0
src/views/model/model/components/ObjectList.vue

@@ -0,0 +1,209 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="model_object_List">
+import { ElMessage, ElMessageBox } from 'element-plus'
+import ObjectComponent from './Object.vue'
+
+import { deleteObjectById, getObjectByList } from '@/api/model/modelObjectApi'
+import useSettingsStore from '@/store/modules/settings'
+
+const settingsStore = useSettingsStore()
+const router = useRouter()
+const tabbar = useTabbar()
+
+interface Object {
+  modelId: number
+  objectId: number
+  objectTitle: string
+  objectCode: string
+  comment: string
+}
+
+const state = reactive({
+  loading: false,
+  objectList: [] as Object[],
+  dialogState: 1,
+  search: {
+    modelId: 0,
+    keywords: '',
+  },
+})
+
+const getData = async () => {
+  const modelId = state.search.modelId
+  if (modelId > 0) {
+    state.loading = true
+    const { data } = await getObjectByList(state.search)
+    state.objectList = data
+    state.loading = false
+  }
+}
+
+onMounted(() => {
+  getData()
+})
+
+const modelObjectTableRef = ref()
+const modelObjectRef = ref()
+
+// 检索对象
+const onSearch = () => {
+  getData()
+}
+
+// 新增对象
+const onObjectAdd = () => {
+  const modelId = state.search.modelId
+  if (modelId > 0) {
+    modelObjectRef.value.showAddModel(modelId)
+  }
+}
+
+// 详情
+const onObjectDetails = (row: { modelId: any; objectId: any }) => {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.open({
+      name: 'modelObjectDetails',
+      params: {
+        modelId: row.modelId,
+        objectId: row.objectId,
+      },
+    })
+  }
+  else {
+    router.push({
+      name: 'modelObjectDetails',
+      params: {
+        modelId: row.modelId,
+        objectId: row.objectId,
+      },
+    })
+  }
+}
+
+const onObjectOAM = (row: any) => {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.open({
+      name: 'modelObjectOAM',
+      params: {
+        modelId: row.modelId,
+        objectId: row.objectId,
+      },
+    })
+  }
+  else {
+    router.push({
+      name: 'modelObjectOAM',
+      params: {
+        modelId: row.modelId,
+        objectId: row.objectId,
+      },
+    })
+  }
+}
+
+// 删除对象
+const onObjectDelete = (row: any) => {
+  const { modelId, objectId, objectTitle } = row
+  ElMessageBox.confirm(`确认删除「${objectTitle}」吗?`, '确认信息').then(async () => {
+    const { msg } = await deleteObjectById(modelId, objectId)
+    ElMessage.success(msg)
+    await getData()
+  })
+}
+
+defineExpose({
+  loadData(modelId: number) {
+    state.search.modelId = modelId
+    getData()
+  },
+})
+</script>
+
+<template>
+  <div class="container">
+    <tool-bar>
+      <template #right>
+        <el-input v-model="state.search.keywords" placeholder="请输入名称,支持模糊查询" style="padding-right: 10px;" clearable />
+        <el-button type="primary" @click="onSearch">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:search" />
+            </el-icon>
+          </template>
+        </el-button>
+
+        <el-button size="default" @click.stop="onObjectAdd">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:plus" />
+            </el-icon>
+          </template>
+          对象
+        </el-button>
+      </template>
+    </tool-bar>
+
+    <el-table ref="modelObjectTableRef" v-loading="state.loading" class="list-table" :data="state.objectList" size="small" border stripe highlight-current-row height="100%">
+      <el-table-column type="index" label="序号" header-align="center" align="center" width="60" />
+
+      <el-table-column prop="objectTitle" label="对象名称" header-align="center" align="center" width="200">
+        <template #default="scope">
+          <div>
+            <el-icon>
+              <svg-icon name="uim:box" />
+            </el-icon>
+            <span>{{ scope.row.objectTitle }}</span>
+          </div>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="objectCode" label="代码" header-align="center" align="center" width="150">
+        <template #default="scope">
+          <span>{{ scope.row.objectCode }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="objectType" label="类型" header-align="center" align="center" width="150">
+        <template #default="scope">
+          <span v-if="scope.row.objectType === 1">实体对象</span>
+          <span v-else>视图对象</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="comment" label="说明" header-align="center" align="left">
+        <template #default="scope">
+          <span>{{ scope.row.comment }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="操作" header-align="center" align="center" width="220">
+        <template #default="scope">
+          <div>
+            <el-button type="primary" size="small" plain @click="onObjectOAM(scope.row)">
+              行为
+            </el-button>
+            <el-button type="warning" size="small" plain @click="onObjectDetails(scope.row)">
+              详情
+            </el-button>
+            <el-button type="danger" size="small" plain @click="onObjectDelete(scope.row)">
+              删除
+            </el-button>
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+    <ObjectComponent ref="modelObjectRef" @success="getData" />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+</style>

+ 10 - 357
src/views/model/model/index.vue

@@ -3,313 +3,30 @@ meta:
   enabled: false
 </route>
 
-<script lang="ts" setup name="model_object_List">
-import { ElMessage, ElMessageBox } from 'element-plus'
-import ModelObjectComponent from '../object/components/ModelObject.vue'
-import ModelComponent from './components/Model.vue'
+<script lang="ts" setup>
+import LeftModelListComponent from './components/ModelList.vue'
+import ObjectListComponent from './components/ObjectList.vue'
+const modelListRef = ref()
+const objectListRef = ref()
 
-import { deleteModelById, getModelByList } from '@/api/model/modelApi'
-import { deleteObjectById, getObjectByList } from '@/api/model/modelObjectApi'
-import useSettingsStore from '@/store/modules/settings'
-
-const settingsStore = useSettingsStore()
-const router = useRouter()
-const tabbar = useTabbar()
-
-interface TreeNode {
-  label: string
-  isLeaf: boolean
-  modelId: number
-  children?: TreeNode[]
-}
-
-interface Object {
-  modelId: number
-  objectId: number
-  objectTitle: string
-  objectCode: string
-  comment: string
-}
-
-const state = reactive({
-  loading: false,
-  keywords: '',
-  treeData: [] as TreeNode[],
-  curModelId: 0,
-  objectList: [] as Object[],
-  dialogState: 1,
-  search: {
-    keywords: '',
-  },
-})
-
-const leftTreeRef = ref()
-const modelRef = ref()
-const getObjectData = async () => {
-  const curModelId = state.curModelId
-  if (curModelId > 0) {
-    state.loading = true
-    const { data } = await getObjectByList({ modelId: curModelId })
-    state.objectList = data
-    state.loading = false
-  }
-}
-
-const getModelData = async () => {
-  const { data } = await getModelByList('')
-  const treeNodes: TreeNode[] = []
-  data.forEach((item: any) => {
-    return treeNodes.push({
-      label: item.modelTitle,
-      modelId: item.modelId,
-      isLeaf: true,
-    })
-  })
-  state.treeData = treeNodes
-
-  if (data && data.length > 0) {
-    state.curModelId = data[0].modelId
-    nextTick(() => {
-      leftTreeRef.value.setCurrentKey(data[0].modelId)
-    })
-    await getObjectData()
-  }
-}
-
-onMounted(() => {
-  getModelData()
-})
-
-// 模型新增
-const onModelAdd = () => {
-  modelRef.value.showAddModel()
-}
-
-// 模型编辑
-const onModelEdit = (data: { modelId: number }) => {
-  const modelId = data.modelId
-  modelRef.value.showEditModel(modelId)
-}
-
-// 模型删除
-const onModelDelete = (data: any) => {
-  ElMessageBox.confirm(`确认删除「${data.modelTitle}」吗?`, '确认信息').then(async () => {
-    const { msg } = await deleteModelById(data.modelId)
-    ElMessage.success(msg)
-    await getModelData()
-  })
-}
-
-// 模型选择
-const onTreeNodeClick = (node: TreeNode) => {
-  if (node.isLeaf) {
-    state.curModelId = node.modelId
-    getObjectData()
-  }
-}
-
-const modelObjectTableRef = ref()
-const modelObjectRef = ref()
-
-// 检索对象
-const onSearch = () => {
-  getObjectData()
-}
-
-// 新增对象
-const onObjectAdd = () => {
-  const modelId = state.curModelId
-  if (modelId > 0) {
-    modelObjectRef.value.showAddModel(modelId)
-  }
-}
-
-// 详情
-const onObjectDetails = (row: { modelId: any; objectId: any }) => {
-  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
-    tabbar.open({
-      name: 'modelObjectDetails',
-      params: {
-        modelId: row.modelId,
-        objectId: row.objectId,
-      },
-    })
-  }
-  else {
-    router.push({
-      name: 'modelObjectDetails',
-      params: {
-        modelId: row.modelId,
-        objectId: row.objectId,
-      },
-    })
-  }
-}
-
-const onObjectOAM = (row: any) => {
-  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
-    tabbar.open({
-      name: 'modelObjectOAM',
-      params: {
-        modelId: row.modelId,
-        objectId: row.objectId,
-      },
-    })
-  }
-  else {
-    router.push({
-      name: 'modelObjectOAM',
-      params: {
-        modelId: row.modelId,
-        objectId: row.objectId,
-      },
-    })
-  }
-}
-
-// 删除对象
-const onObjectDelete = (row: any) => {
-  const { modelId, objectId, objectTitle } = row
-  ElMessageBox.confirm(`确认删除「${objectTitle}」吗?`, '确认信息').then(async () => {
-    const { msg } = await deleteObjectById(modelId, objectId)
-    ElMessage.success(msg)
-    await getObjectData()
-  })
+const onItemSelect = (modelId: number) => {
+  objectListRef.value.loadData(modelId)
 }
 </script>
 
 <template>
   <div class="absolute-container">
-    <tool-header title="数据模型">
-      <template #right>
-        <el-button v-waves.float type="primary" @click="onModelAdd">
-          <template #icon>
-            <el-icon>
-              <svg-icon name="i-ep:plus" />
-            </el-icon>
-          </template>
-          数据模型
-        </el-button>
-      </template>
-    </tool-header>
+    <tool-header title="元数据模型" />
 
     <div class="page-main">
       <LayoutContainer left-side-width="250px" hide-left-side-toggle>
         <template #leftSide>
-          <el-scrollbar class="tree">
-            <ElTree ref="leftTreeRef" :data="state.treeData" default-expand-all node-key="modelId" @node-click="onTreeNodeClick">
-              <template #default="{ node, data }">
-                <div class="custom-tree-node">
-                  <div class="label" :title="node.label">
-                    <el-icon v-if="data.isLeaf" size="16px" style="margin-right: 5px;">
-                      <svg-icon name="bx:bxs-component" />
-                    </el-icon>
-                    <div class="text">
-                      {{ data.label }}
-                    </div>
-                  </div>
-                  <div v-if="data.isLeaf" class="actions">
-                    <el-button-group>
-                      <el-button type="info" plain size="small" @click.stop="onModelEdit(data)">
-                        <template #icon>
-                          <el-icon>
-                            <svg-icon name="i-ep:edit" />
-                          </el-icon>
-                        </template>
-                      </el-button>
-
-                      <el-button type="danger" plain size="small" @click.stop="onModelDelete(data)">
-                        <template #icon>
-                          <el-icon>
-                            <svg-icon name="i-ep:delete" />
-                          </el-icon>
-                        </template>
-                      </el-button>
-                    </el-button-group>
-                  </div>
-                </div>
-              </template>
-            </ElTree>
-          </el-scrollbar>
+          <LeftModelListComponent ref="modelListRef" @onItemSelect="onItemSelect" />
         </template>
 
-        <div class="container">
-          <tool-bar>
-            <template #right>
-              <el-input v-model="state.search.keywords" placeholder="请输入名称,支持模糊查询" style="padding-right: 10px;" clearable />
-              <el-button type="primary" @click="onSearch">
-                <template #icon>
-                  <el-icon>
-                    <svg-icon name="i-ep:search" />
-                  </el-icon>
-                </template>
-              </el-button>
-
-              <el-button size="default" @click.stop="onObjectAdd">
-                <template #icon>
-                  <el-icon>
-                    <svg-icon name="i-ep:plus" />
-                  </el-icon>
-                </template>
-                数据对象
-              </el-button>
-            </template>
-          </tool-bar>
-
-          <el-table ref="modelObjectTableRef" v-loading="state.loading" class="list-table" :data="state.objectList" size="small" border stripe highlight-current-row height="100%">
-            <el-table-column type="index" label="序号" header-align="center" align="center" width="60" />
-
-            <el-table-column prop="objectTitle" label="名称" header-align="center" align="center" width="200">
-              <template #default="scope">
-                <div>
-                  <el-icon>
-                    <svg-icon name="uim:box" />
-                  </el-icon>
-                  <span>{{ scope.row.objectTitle }}</span>
-                </div>
-              </template>
-            </el-table-column>
-
-            <el-table-column prop="objectCode" label="代码" header-align="center" align="center" width="150">
-              <template #default="scope">
-                <span>{{ scope.row.objectCode }}</span>
-              </template>
-            </el-table-column>
-
-            <el-table-column prop="objectType" label="类型" header-align="center" align="center" width="150">
-              <template #default="scope">
-                <span v-if="scope.row.objectType === 1">实体对象</span>
-                <span v-else>视图对象</span>
-              </template>
-            </el-table-column>
-
-            <el-table-column prop="comment" label="说明" header-align="center" align="left">
-              <template #default="scope">
-                <span>{{ scope.row.comment }}</span>
-              </template>
-            </el-table-column>
-
-            <el-table-column label="操作" header-align="center" align="center" width="220">
-              <template #default="scope">
-                <div>
-                  <el-button type="primary" size="small" plain @click="onObjectOAM(scope.row)">
-                    行为
-                  </el-button>
-                  <el-button type="warning" size="small" plain @click="onObjectDetails(scope.row)">
-                    详情
-                  </el-button>
-                  <el-button type="danger" size="small" plain @click="onObjectDelete(scope.row)">
-                    删除
-                  </el-button>
-                </div>
-              </template>
-            </el-table-column>
-          </el-table>
-        </div>
+        <ObjectListComponent ref="objectListRef" />
       </LayoutContainer>
     </div>
-    <ModelComponent ref="modelRef" @success="getModelData" />
-    <ModelObjectComponent ref="modelObjectRef" @success="getObjectData" />
   </div>
 </template>
 
@@ -325,70 +42,6 @@ const onObjectDelete = (row: any) => {
     display: flex;
     flex-direction: column;
     height: 100%;
-
-    .btns {
-      display: inline-flex;
-      width: 100%;
-      margin-bottom: var(--container-padding);
-
-      .add {
-        width: 100%;
-      }
-    }
-
-    .tree {
-      flex: 1;
-      overflow-y: auto;
-
-      .el-tree {
-        .el-tree-node__content {
-          height: 40px;
-        }
-
-        .is-current > .el-tree-node__content {
-          background-color: var(--el-color-primary-light-9);
-        }
-
-        .custom-tree-node {
-          flex: 1;
-          position: relative;
-          width: 0;
-          height: 100%;
-          display: flex;
-          flex-direction: column;
-          justify-content: center;
-
-          .label {
-            display: inline-flex;
-            align-items: center;
-            width: calc(100% - 10px);
-            color: var(--el-text-color-primary);
-
-            .text {
-              @include text-overflow;
-            }
-          }
-
-          &:hover {
-            .actions {
-              display: block;
-            }
-          }
-
-          .actions {
-            display: none;
-            position: absolute;
-            right: 10px;
-            top: 50%;
-            transform: translateY(-50%);
-
-            .el-button {
-              padding: 5px 8px;
-            }
-          }
-        }
-      }
-    }
   }
 }
 </style>