houyaf 3 rokov pred
rodič
commit
d81f3c67b7
54 zmenil súbory, kde vykonal 1782 pridanie a 476 odobranie
  1. 0 0
      src/api/api/apiApi.ts
  2. 0 0
      src/api/api/apiGatewayApi.ts
  3. 0 0
      src/api/api/apiLogApi.ts
  4. 0 0
      src/api/api/apiModuleApi.ts
  5. 0 0
      src/api/api/apiTransUnitApi.ts
  6. 75 0
      src/api/biz/bizApi.ts
  7. 79 0
      src/api/biz/bizObjectApi.ts
  8. 68 0
      src/api/biz/bizObjectAttrApi.ts
  9. 0 0
      src/api/biz/bizObjectMappingApi.ts
  10. 68 0
      src/api/biz/bizObjectOAMApi.ts
  11. 28 0
      src/api/biz/bizObjectRuleApi.ts
  12. 64 0
      src/api/biz/bizRuleApi.ts
  13. 0 0
      src/api/database/dataApi.ts
  14. 0 0
      src/api/database/dbApi.ts
  15. 0 0
      src/api/database/dbTypeApi.ts
  16. 0 0
      src/api/model/modelObjectApi.ts
  17. 0 0
      src/api/model/modelObjectAttrApi.ts
  18. 0 0
      src/api/model/modelObjectOAMApi.ts
  19. 28 0
      src/api/model/modelObjectRuleApi.ts
  20. 14 14
      src/router/modules/api.ts
  21. 77 0
      src/router/modules/biz.ts
  22. 8 8
      src/router/modules/daas.ts
  23. 8 8
      src/router/modules/model.ts
  24. 0 51
      src/router/modules/rule.ts
  25. 1 1
      src/router/modules/system.ts
  26. 10 10
      src/router/routes.ts
  27. 1 1
      src/settings.ts
  28. 1 1
      src/views/api/api/components/Api.vue
  29. 1 1
      src/views/api/api/components/Module.vue
  30. 2 2
      src/views/api/api/index.vue
  31. 3 3
      src/views/api/log/index.vue
  32. 0 0
      src/views/biz/attr/index.vue
  33. 0 0
      src/views/biz/cat/index.vue
  34. 0 0
      src/views/biz/oam/index.vue
  35. 114 0
      src/views/biz/object/components/Biz.vue
  36. 344 0
      src/views/biz/object/components/BizObject.vue
  37. 52 52
      src/views/biz/object/index.vue
  38. 0 0
      src/views/biz/rule/index.vue
  39. 0 0
      src/views/database/database/components/model_data.vue
  40. 1 1
      src/views/database/database/components/sql_data.vue
  41. 1 1
      src/views/database/database/components/table_data.vue
  42. 0 1
      src/views/database/database/index.vue
  43. 1 1
      src/views/database/database_access/components/DBType.vue
  44. 1 1
      src/views/database/database_access/index.vue
  45. 1 1
      src/views/database/database_type/components/DbType.vue
  46. 1 1
      src/views/database/database_type/index.vue
  47. 408 0
      src/views/model/attr/index.vue
  48. 1 1
      src/views/model/oam/components/objectOAM.vue
  49. 5 5
      src/views/model/oam/index.vue
  50. 0 0
      src/views/model/object/components/Model.vue
  51. 1 1
      src/views/model/object/components/ModelObject.vue
  52. 282 296
      src/views/model/object/index.vue
  53. 20 6
      src/views/paas/atu/components/ModelObjectSelector.vue
  54. 13 8
      src/views/paas/atu/index.vue

+ 0 - 0
src/api/paas/apiApi.ts → src/api/api/apiApi.ts


+ 0 - 0
src/api/paas/apiGatewayApi.ts → src/api/api/apiGatewayApi.ts


+ 0 - 0
src/api/paas/apiReqApi.ts → src/api/api/apiLogApi.ts


+ 0 - 0
src/api/paas/moduleApi.ts → src/api/api/apiModuleApi.ts


+ 0 - 0
src/api/paas/apiTransUnitApi.ts → src/api/api/apiTransUnitApi.ts


+ 75 - 0
src/api/biz/bizApi.ts

@@ -0,0 +1,75 @@
+import apiRequest from '@/network/http/apiRequest'
+
+/**
+ * 获取Model列表
+ * @param data
+ * @returns
+ */
+export function getBizByList(data: any) {
+  return apiRequest({
+    url: '/model',
+    method: 'GET',
+    params: data,
+  })
+}
+
+/**
+ * 根据Id获取Biz
+ * @param bizId
+ * @returns
+ */
+export function getBizById(bizId: number) {
+  return apiRequest({
+    url: `/biz/${bizId}`,
+    method: 'GET',
+  })
+}
+
+/**
+ * 获取模型树视图
+ * @returns
+ */
+export function getBizData() {
+  return apiRequest({
+    url: '/biz/data',
+    method: 'GET',
+  })
+}
+
+/**
+ * 添加Model
+ * @param data
+ * @returns
+ */
+export function createBiz(data: any) {
+  return apiRequest({
+    url: '/biz/add',
+    method: 'POST',
+    data,
+  })
+}
+
+/**
+ * 更新Model
+ * @param data
+ * @returns
+ */
+export function updateBiz(data: any) {
+  return apiRequest({
+    url: '/biz/update',
+    method: 'PUT',
+    data,
+  })
+}
+
+/**
+ * 删除Biz
+ * @para bizId
+ * @returns
+ */
+export function deleteBizById(bizId: number) {
+  return apiRequest({
+    url: `/biz/${bizId}`,
+    method: 'DELETE',
+  })
+}

+ 79 - 0
src/api/biz/bizObjectApi.ts

@@ -0,0 +1,79 @@
+import apiRequest from '@/network/http/apiRequest'
+
+/**
+ * 获取Object分页
+ * @param data
+ * @returns
+ */
+export function getObjectByPage(data: any) {
+  return apiRequest({
+    url: '/biz/object/page',
+    method: 'GET',
+    params: data,
+  })
+}
+
+/**
+ * 获取Object列表
+ * @param data
+ * @returns
+ */
+export function getObjectByList(data: any) {
+  return apiRequest({
+    url: '/biz/object',
+    method: 'GET',
+    params: data,
+  })
+}
+
+/**
+ * 根据Id获取Biz Object
+ * @param bizId
+ * @param objectId
+ * @returns
+ */
+export function getObjectById(bizId: number, objectId: number) {
+  return apiRequest({
+    url: `/biz/object/${bizId}/${objectId}`,
+    method: 'GET',
+  })
+}
+
+/**
+ * 添加Object
+ * @param data
+ * @returns
+ */
+export function createObject(data: any) {
+  return apiRequest({
+    url: '/biz/object/add',
+    method: 'POST',
+    data,
+  })
+}
+
+/**
+ * 更新Object
+ * @param data
+ * @returns
+ */
+export function updateObject(data: any) {
+  return apiRequest({
+    url: '/biz/object/update',
+    method: 'PUT',
+    data,
+  })
+}
+
+/**
+ * 删除Object
+ * @param bizId
+ * @param objectId
+ * @returns
+ */
+export function deleteObjectById(bizId: number, objectId: number) {
+  return apiRequest({
+    url: `/biz/object/${bizId}/${objectId}`,
+    method: 'DELETE',
+  })
+}

+ 68 - 0
src/api/biz/bizObjectAttrApi.ts

@@ -0,0 +1,68 @@
+import apiRequest from '@/network/http/apiRequest'
+
+/**
+ * 获取ObjectAttr列表
+ * @param data
+ * @returns
+ */
+export function getObjectAttrByList(data: any) {
+  return apiRequest({
+    url: '/biz/object/attribute',
+    method: 'GET',
+    params: data,
+  })
+}
+
+/**
+ * 根据Id获取ObjectAttr
+ * @param bizId
+ * @param objectId
+ * @param attrId
+ * @returns
+ */
+export function getObjectAttrById(bizId: number, objectId: number, attrId: number) {
+  return apiRequest({
+    url: `/biz/object/attribute/${bizId}/${objectId}/${attrId}`,
+    method: 'GET',
+  })
+}
+
+/**
+ * 添加ObjectAttr
+ * @param data
+ * @returns
+ */
+export function createObjectAttr(data: any) {
+  return apiRequest({
+    url: '/biz/object/attribute/add',
+    method: 'POST',
+    data,
+  })
+}
+
+/**
+ * 更新ObjectAttr
+ * @param data
+ * @returns
+ */
+export function updateObjectAttr(data: any) {
+  return apiRequest({
+    url: '/biz/object/attribute/update',
+    method: 'PUT',
+    data,
+  })
+}
+
+/**
+ * 删除ObjectAttr
+ * @param bizId
+ * @param objectId
+ * @param attrId
+ * @returns
+ */
+export function deleteObjectAttrById(bizId: number, objectId: number, attrId: number) {
+  return apiRequest({
+    url: `/biz/object/attribute/${bizId}/${objectId}/${attrId}`,
+    method: 'DELETE',
+  })
+}

+ 0 - 0
src/views/rule/rule/index.vue → src/api/biz/bizObjectMappingApi.ts


+ 68 - 0
src/api/biz/bizObjectOAMApi.ts

@@ -0,0 +1,68 @@
+import apiRequest from '@/network/http/apiRequest'
+
+/**
+ * 获取ObjectOAM列表
+ * @param data
+ * @returns
+ */
+export function getObjectOAMByList(data: any) {
+  return apiRequest({
+    url: '/biz/object/oam',
+    method: 'GET',
+    params: data,
+  })
+}
+
+/**
+ * 根据Id获取ObjectOAM
+ * @param bizId
+ * @param objectId
+ * @param oamId
+ * @returns
+ */
+export function getObjectOAMById(bizId: number, objectId: number, oamId: number) {
+  return apiRequest({
+    url: `/biz/object/oam/${bizId}/${objectId}/${oamId}`,
+    method: 'GET',
+  })
+}
+
+/**
+ * 添加ObjectOAM
+ * @param data
+ * @returns
+ */
+export function createObjectOAM(data: any) {
+  return apiRequest({
+    url: '/biz/object/oam/add',
+    method: 'POST',
+    data,
+  })
+}
+
+/**
+ * 更新ObjectOAM
+ * @param data
+ * @returns
+ */
+export function updateObjectOAM(data: any) {
+  return apiRequest({
+    url: '/biz/object/oam/update',
+    method: 'PUT',
+    data,
+  })
+}
+
+/**
+ * 删除ObjectOAM
+ * @param bizId
+ * @param objectId
+ * @param oamId
+ * @returns
+ */
+export function deleteObjectOAMById(bizId: number, objectId: number, oamId: number) {
+  return apiRequest({
+    url: `/biz/object/oam/${bizId}/${objectId}/${oamId}`,
+    method: 'DELETE',
+  })
+}

+ 28 - 0
src/api/biz/bizObjectRuleApi.ts

@@ -0,0 +1,28 @@
+import apiRequest from '@/network/http/apiRequest'
+
+/**
+ * 添加ObjectOAM
+ * @param data
+ * @returns
+ */
+export function createObjectRole(data: any) {
+  return apiRequest({
+    url: '/biz/object/rule/add',
+    method: 'POST',
+    data,
+  })
+}
+
+/**
+ * 删除ObjectOAM
+ * @param bizId
+ * @param objectId
+ * @param oamId
+ * @returns
+ */
+export function deleteObjectRuleById(bizId: number, objectId: number, ruleId: number) {
+  return apiRequest({
+    url: `/biz/object/rule/${bizId}/${objectId}/${ruleId}`,
+    method: 'DELETE',
+  })
+}

+ 64 - 0
src/api/biz/bizRuleApi.ts

@@ -0,0 +1,64 @@
+import apiRequest from '@/network/http/apiRequest'
+
+/**
+ * 获取Model列表
+ * @param data
+ * @returns
+ */
+export function getBizRuleByList(data: any) {
+  return apiRequest({
+    url: '/biz/rule',
+    method: 'GET',
+    params: data,
+  })
+}
+
+/**
+ * 根据Id获取BizRule
+ * @param ruleId
+ * @returns
+ */
+export function getBizRuleById(ruleId: number) {
+  return apiRequest({
+    url: `/biz/rule/${ruleId}`,
+    method: 'GET',
+  })
+}
+
+/**
+ * 添加BizRule
+ * @param data
+ * @returns
+ */
+export function createBizRule(data: any) {
+  return apiRequest({
+    url: '/biz/rule/add',
+    method: 'POST',
+    data,
+  })
+}
+
+/**
+ * 更新Model
+ * @param data
+ * @returns
+ */
+export function updateBizRule(data: any) {
+  return apiRequest({
+    url: '/biz/rule/update',
+    method: 'PUT',
+    data,
+  })
+}
+
+/**
+ * 删除BizRule
+ * @para bizId
+ * @returns
+ */
+export function deleteBizRuleById(ruleId: number) {
+  return apiRequest({
+    url: `/biz/rule/${ruleId}`,
+    method: 'DELETE',
+  })
+}

+ 0 - 0
src/api/daas/dataApi.ts → src/api/database/dataApi.ts


+ 0 - 0
src/api/daas/dbApi.ts → src/api/database/dbApi.ts


+ 0 - 0
src/api/daas/dbTypeApi.ts → src/api/database/dbTypeApi.ts


+ 0 - 0
src/api/model/objectApi.ts → src/api/model/modelObjectApi.ts


+ 0 - 0
src/api/model/objectAttrApi.ts → src/api/model/modelObjectAttrApi.ts


+ 0 - 0
src/api/model/ObjectOAMApi.ts → src/api/model/modelObjectOAMApi.ts


+ 28 - 0
src/api/model/modelObjectRuleApi.ts

@@ -0,0 +1,28 @@
+import apiRequest from '@/network/http/apiRequest'
+
+/**
+ * 添加ObjectOAM
+ * @param data
+ * @returns
+ */
+export function createObjectRole(data: any) {
+  return apiRequest({
+    url: '/model/object/rule/add',
+    method: 'POST',
+    data,
+  })
+}
+
+/**
+ * 删除ObjectOAM
+ * @param modelId
+ * @param objectId
+ * @param ruleId
+ * @returns
+ */
+export function deleteObjectRuleById(modelId: number, objectId: number, ruleId: number) {
+  return apiRequest({
+    url: `/model/object/rule/${modelId}/${objectId}/${ruleId}`,
+    method: 'DELETE',
+  })
+}

+ 14 - 14
src/router/modules/paas.ts → src/router/modules/api.ts

@@ -4,24 +4,24 @@ const Layout = () => import('@/layouts/index.vue')
 
 const routes: RouteRecordRaw[] = [
   {
-    path: '/paas/api',
+    path: '/api',
     component: Layout,
-    redirect: '/paas/api/index',
-    name: 'paas_api',
+    redirect: '/api/index',
+    name: 'api',
     meta: {
-      title: 'API接口',
+      title: 'API管理',
       icon: 'ri:function-line',
     },
     children: [
       {
         path: 'index',
-        name: 'paas_api_index',
-        component: () => import('@/views/paas/api/index.vue'),
+        name: 'api_index',
+        component: () => import('@/views/api/api/index.vue'),
         meta: {
           title: 'API接口',
           sidebar: false,
           breadcrumb: false,
-          activeMenu: '/paas/api',
+          activeMenu: '/api',
         },
       },
       {
@@ -31,7 +31,7 @@ const routes: RouteRecordRaw[] = [
         meta: {
           title: 'Api事务配置',
           sidebar: false,
-          activeMenu: '/paas/api',
+          activeMenu: '/api',
           cache: true,
           noCache: 'apiTrans',
         },
@@ -39,10 +39,10 @@ const routes: RouteRecordRaw[] = [
     ],
   },
   {
-    path: '/paas/req',
+    path: '/api/log',
     component: Layout,
-    redirect: '/paas/req/index',
-    name: 'paas_req',
+    redirect: '/api/log/index',
+    name: 'api_log',
     meta: {
       title: '调用日志',
       icon: 'bx:bxs-component',
@@ -50,13 +50,13 @@ const routes: RouteRecordRaw[] = [
     children: [
       {
         path: 'index',
-        name: 'paas_req_index',
-        component: () => import('@/views/paas/req/index.vue'),
+        name: 'api_log_index',
+        component: () => import('@/views/api/log/index.vue'),
         meta: {
           title: '调用日志',
           sidebar: false,
           breadcrumb: false,
-          activeMenu: '/paas/req',
+          activeMenu: '/api/log',
         },
       },
     ],

+ 77 - 0
src/router/modules/biz.ts

@@ -0,0 +1,77 @@
+import type { RouteRecordRaw } from 'vue-router'
+
+const Layout = () => import('@/layouts/index.vue')
+
+const routes: RouteRecordRaw[] = [
+  {
+    path: '/biz/object',
+    component: Layout,
+    redirect: '/biz/object/index',
+    name: 'biz_object',
+    meta: {
+      title: '业务对象',
+      icon: 'ri:function-line',
+    },
+    children: [
+      {
+        path: 'index',
+        name: 'biz_object_index',
+        component: () => import('@/views/biz/object/index.vue'),
+        meta: {
+          title: '业务对象',
+          sidebar: false,
+          breadcrumb: false,
+          activeMenu: '/biz/object',
+        },
+      },
+      {
+        path: '/attr/:bizId/:objectId',
+        name: 'bizObjectEdit',
+        component: () => import('@/views/biz/attr/index.vue'),
+        meta: {
+          title: '对象编辑',
+          sidebar: false,
+          activeMenu: '/biz/object',
+          cache: true,
+          noCache: 'bizObjectEdit',
+        },
+      },
+      {
+        path: '/oam/:bizId/:objectId',
+        name: 'bizObjectOAM',
+        component: () => import('@/views/biz/oam/index.vue'),
+        meta: {
+          title: '行为定义',
+          sidebar: false,
+          activeMenu: '/biz/object',
+          cache: true,
+          noCache: 'bizObjectOAM',
+        },
+      },
+    ],
+  },
+  {
+    path: '/biz/rule',
+    component: Layout,
+    redirect: '/biz/rule/index',
+    name: 'rule',
+    meta: {
+      title: '业务规则',
+      icon: 'ep:element-plus',
+    },
+    children: [
+      {
+        path: 'index',
+        name: 'ruleList',
+        component: () => import('@/views/biz/rule/index.vue'),
+        meta: {
+          title: '业务规则',
+          sidebar: false,
+          breadcrumb: false,
+          activeMenu: '/biz/rule',
+        },
+      },
+    ],
+  },
+]
+export default routes

+ 8 - 8
src/router/modules/daas.ts

@@ -4,9 +4,9 @@ const Layout = () => import('@/layouts/index.vue')
 
 const routes: RouteRecordRaw[] = [
   {
-    path: '/daas/data',
+    path: '/database/data',
     component: Layout,
-    redirect: '/daas/data/database',
+    redirect: '/database/data/database',
     name: 'daas_data',
     meta: {
       title: '数据仓库',
@@ -16,20 +16,20 @@ const routes: RouteRecordRaw[] = [
       {
         path: 'database',
         name: 'daas_data_index',
-        component: () => import('@/views/daas/database/index.vue'),
+        component: () => import('@/views/database/database/index.vue'),
         meta: {
           title: '数据仓库',
           sidebar: false,
           breadcrumb: false,
-          activeMenu: '/daas/data',
+          activeMenu: '/database/data',
         },
       },
     ],
   },
   {
-    path: '/daas/data/database-access',
+    path: '/database/data/database-access',
     component: Layout,
-    redirect: '/daas/data/database-access/index',
+    redirect: '/database/data/database-access/index',
     name: 'databaseAccess',
     meta: {
       title: '数据库接入',
@@ -39,11 +39,11 @@ const routes: RouteRecordRaw[] = [
       {
         path: 'index',
         name: 'database_access',
-        component: () => import('@/views/daas/database_access/index.vue'),
+        component: () => import('@/views/database/database_access/index.vue'),
         meta: {
           title: '数据库接入',
           sidebar: false,
-          activeMenu: '/daas/data/database-access',
+          activeMenu: '/database/data/database-access',
         },
       },
     ],

+ 8 - 8
src/router/modules/model.ts

@@ -4,30 +4,30 @@ const Layout = () => import('@/layouts/index.vue')
 
 const routes: RouteRecordRaw[] = [
   {
-    path: '/model/object',
+    path: '/model/attr',
     component: Layout,
-    redirect: '/model/object/index',
+    redirect: '/model/attr/index',
     name: 'model',
     meta: {
-      title: '对象定义',
+      title: '模型管理',
       icon: 'ep:coin',
     },
     children: [
       {
         path: 'index',
         name: 'modelList',
-        component: () => import('@/views/model/model/index.vue'),
+        component: () => import('@/views/model/object/index.vue'),
         meta: {
           title: '对象定义',
           sidebar: false,
           breadcrumb: false,
-          activeMenu: '/model/object',
+          activeMenu: '/model/attr',
         },
       },
       {
-        path: 'model/object/:modelId/:objectId',
+        path: 'model/attr/:modelId/:objectId',
         name: 'modelObjectEdit',
-        component: () => import('@/views/model/object/index.vue'),
+        component: () => import('@/views/model/attr/index.vue'),
         meta: {
           title: '对象编辑',
           sidebar: false,
@@ -37,7 +37,7 @@ const routes: RouteRecordRaw[] = [
         },
       },
       {
-        path: 'model/object/oam/:modelId/:objectId',
+        path: 'model/attr/oam/:modelId/:objectId',
         name: 'modelObjectOAM',
         component: () => import('@/views/model/oam/index.vue'),
         meta: {

+ 0 - 51
src/router/modules/rule.ts

@@ -1,51 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router'
-
-const Layout = () => import('@/layouts/index.vue')
-
-const routes: RouteRecordRaw[] = [
-  {
-    path: '/rule',
-    component: Layout,
-    redirect: '/rule/index',
-    name: 'rule',
-    meta: {
-      title: '业务规则',
-      icon: 'ep:element-plus',
-    },
-    children: [
-      {
-        path: 'index',
-        name: 'ruleList',
-        component: () => import('@/views/model/model/index.vue'),
-        meta: {
-          title: '业务规则',
-          sidebar: false,
-          breadcrumb: false,
-          activeMenu: '/model/object',
-        },
-      },
-    ],
-  },
-  {
-    path: '/rule/cat',
-    component: Layout,
-    redirect: '/rule/cat/index',
-    name: 'ruleCat',
-    meta: {
-      title: '规则类别',
-      icon: 'ic:twotone-double-arrow',
-    },
-    children: [
-      {
-        path: 'index',
-        name: 'ruleCatIndex',
-        component: () => import('@/views/rule/cat/index.vue'),
-        meta: {
-          title: '规则类别',
-          sidebar: false,
-        },
-      },
-    ],
-  },
-]
-export default routes

+ 1 - 1
src/router/modules/system.ts

@@ -116,7 +116,7 @@ const routes: RouteRecordRaw[] = [
       {
         path: 'database_type',
         name: 'database_type',
-        component: () => import('@/views/daas/database_type/index.vue'),
+        component: () => import('@/views/database/database_type/index.vue'),
         meta: {
           title: '数据库类型',
         },

+ 10 - 10
src/router/routes.ts

@@ -3,9 +3,9 @@ import generatedRoutes from 'virtual:generated-pages'
 import type { RouteRecordRaw } from 'vue-router'
 import SystemEntries from './modules/system'
 import DaaSEntries from './modules/daas'
-import PaaSEntries from './modules/paas'
+import ApiEntries from './modules/api'
 import ModelEntries from './modules/model'
-import RuleEntries from './modules/rule'
+import BizEntries from './modules/biz'
 import AppCenterEntries from '@/router/modules/app.center'
 import type { Route } from '#/global'
 import useSettingsStore from '@/store/modules/settings'
@@ -107,29 +107,29 @@ const asyncRoutes: Route.recordMainRaw[] = [
   },
   {
     meta: {
-      title: '规则',
-      icon: 'ep:element-plus',
+      title: '数据',
+      icon: 'ep:coin',
     },
     children: [
-      ...RuleEntries,
+      ...DaaSEntries,
     ],
   },
   {
     meta: {
-      title: '数据',
-      icon: 'ep:coin',
+      title: '规则',
+      icon: 'ep:element-plus',
     },
     children: [
-      ...DaaSEntries,
+      ...BizEntries,
     ],
   },
   {
     meta: {
-      title: '业务',
+      title: 'API',
       icon: 'ep:cpu',
     },
     children: [
-      ...PaaSEntries,
+      ...ApiEntries,
     ],
   },
   {

+ 1 - 1
src/settings.ts

@@ -54,7 +54,7 @@ const globalSettings: Settings.all = {
     switchTabbarAndToolbar: true,
   },
   tabbar: {
-    enable: true,
+    enable: false,
     enableIcon: true,
     enableHotkeys: true,
     style: 'card',

+ 1 - 1
src/views/paas/api/components/Api.vue → src/views/api/api/components/Api.vue

@@ -5,7 +5,7 @@ meta:
 
 <script lang="ts" setup>
 import type { FormInstance, FormRules } from 'element-plus'
-import { createApi, getApiById, updateApi } from '@/api/paas/apiApi'
+import { createApi, getApiById, updateApi } from '@/api/api/apiApi'
 const emit = defineEmits(['success'])
 
 const state = reactive({

+ 1 - 1
src/views/paas/api/components/Module.vue → src/views/api/api/components/Module.vue

@@ -5,7 +5,7 @@ meta:
 
 <script lang="ts" setup>
 import type { FormInstance, FormRules } from 'element-plus'
-import { createModule, getModuleById, updateModule } from '@/api/paas/moduleApi'
+import { createModule, getModuleById, updateModule } from '@/api/api/apiModuleApi'
 const emit = defineEmits(['success'])
 
 const formRef = ref<FormInstance>()

+ 2 - 2
src/views/paas/api/index.vue → src/views/api/api/index.vue

@@ -7,8 +7,8 @@ meta:
 import { ElMessage, ElMessageBox } from 'element-plus'
 import PSModule from './components/Module.vue'
 import PSApi from './components/Api.vue'
-import { deleteApiById, getApiByList, updateApiStatus } from '@/api/paas/apiApi'
-import { deleteModuleById, getModuleByList } from '@/api/paas/moduleApi'
+import { deleteApiById, getApiByList, updateApiStatus } from '@/api/api/apiApi'
+import { deleteModuleById, getModuleByList } from '@/api/api/apiModuleApi'
 import useSettingsStore from '@/store/modules/settings'
 import { apiType } from '@/utils/tool'
 

+ 3 - 3
src/views/paas/req/index.vue → src/views/api/log/index.vue

@@ -1,7 +1,7 @@
 <script lang="ts" setup>
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { deleteApiReqById, getApiReqByPage } from '@/api/paas/apiReqApi'
-import { getModuleByList } from '@/api/paas/moduleApi'
+import { deleteApiReqById, getApiReqByPage } from '@/api/api/apiLogApi'
+import { getModuleByList } from '@/api/api/apiModuleApi'
 const { pagination, getParams, onSizeChange, onCurrentChange } = usePagination()
 
 interface TreeNode {
@@ -104,7 +104,7 @@ const onReqDel = async (data: { apiTitle: any; reqId: number }) => {
 
 <template>
   <div class="absolute-container">
-    <page-header title="日志管理" content="日志调用管理" />
+    <page-header title="Api日志管理" content="Api日志管理" />
     <div class="page-main">
       <LayoutContainer left-side-width="300px" hide-left-side-toggle>
         <template #leftSide>

+ 0 - 0
src/views/biz/attr/index.vue


+ 0 - 0
src/views/rule/cat/index.vue → src/views/biz/cat/index.vue


+ 0 - 0
src/views/biz/oam/index.vue


+ 114 - 0
src/views/biz/object/components/Biz.vue

@@ -0,0 +1,114 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup>
+import type { FormInstance, FormRules } from 'element-plus'
+import { createBiz, getBizById, updateBiz } from '@/api/biz/bizApi'
+const emit = defineEmits(['success'])
+
+const formRef = ref<FormInstance>()
+const formRules = ref<FormRules>({
+  bizTitle: [
+    { required: true, message: '请输入标题', trigger: 'blur' },
+  ],
+  bizDesc: [
+    { required: false, message: '请输入描述', trigger: 'blur' },
+  ],
+})
+
+const state = reactive({
+  title: '',
+  dialogVisible: false,
+  loading: false,
+  formData: {
+    bizId: 1,
+    bizTitle: '',
+    bizDesc: '',
+  },
+  actionType: 1,
+})
+
+onMounted(() => {})
+
+const getData = async (bizId: number) => {
+  state.loading = true
+  const { data } = await getBizById(bizId)
+  state.loading = false
+  state.formData = data
+}
+
+function onSubmit() {
+  formRef.value && formRef.value.validate(async (valid) => {
+    if (valid) {
+      if (state.actionType === 1) {
+        await createBiz(state.formData)
+        state.dialogVisible = false
+        emit('success')
+      }
+      else {
+        await updateBiz(state.formData)
+        state.dialogVisible = false
+        emit('success')
+      }
+    }
+  })
+}
+
+function onCancel() {
+  state.dialogVisible = false
+}
+
+function resetFormData() {
+  state.formData = {
+    bizId: -1,
+    bizTitle: '',
+    bizDesc: '',
+  }
+}
+
+defineExpose({
+  showAddModel() {
+    resetFormData()
+    state.title = '新增模型'
+    state.actionType = 1
+    state.dialogVisible = true
+  },
+  showEditModel(bizId: any) {
+    resetFormData()
+    state.title = '编辑模型'
+    state.actionType = 2
+    state.dialogVisible = true
+    getData(bizId)
+  },
+
+})
+</script>
+
+<template>
+  <div>
+    <el-dialog v-biz="state.dialogVisible" :title="state.title" width="600px" :close-on-click-modal="false" append-to-body destroy-on-close>
+      <div v-loading="state.loading">
+        <el-form ref="formRef" :biz="state.formData" :rules="formRules" label-width="120px" label-suffix=":">
+          <el-form-item label="业务名称" prop="bizTitle">
+            <el-input v-biz="state.formData.bizTitle" placeholder="请输入标题" />
+          </el-form-item>
+
+          <el-form-item label="简要说明" prop="bizDesc">
+            <el-input v-biz="state.formData.bizDesc" type="textarea" rows="10" placeholder="请输入标题" />
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <template #footer>
+        <el-button size="large" @click="onCancel">
+          取消
+        </el-button>
+        <el-button type="primary" size="large" @click="onSubmit">
+          保存
+        </el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>

+ 344 - 0
src/views/biz/object/components/BizObject.vue

@@ -0,0 +1,344 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup>
+import Sortable from 'sortablejs'
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { createObject, getObjectById, updateObject } from '@/api/biz/bizObjectApi'
+const emit = defineEmits(['success'])
+
+interface ObjectAttr {
+  attrId: number
+  attrTitle: string
+  attrCode: string
+  attrType: number
+  attrLength: number
+  attrDecimals: number
+  isNotNull: number
+  isFixed: number
+  comment: string
+  isPKey: number
+  sortNo: number
+}
+
+const dataType = [
+  { dataType: 1, dataName: '整数' },
+  { dataType: 2, dataName: '字符串' },
+  { dataType: 3, dataName: '小数' }]
+
+const state = reactive({
+  title: '',
+  dialogVisible: false,
+  loading: false,
+  formData: {
+    bizId: 0,
+    objectId: 0,
+    objectCode: '',
+    objectTitle: '',
+    comment: '',
+    attrs: [] as ObjectAttr[],
+  },
+  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 (bizId: number, objectId: number) => {
+  state.loading = true
+  const { data } = await getObjectById(bizId, objectId)
+  state.loading = false
+  state.formData = data
+}
+
+const attrsTableRef = ref()
+const attrsTableKey = ref(0)
+function onAttrAdd() {
+  state.formData.attrs.push({
+    attrId: 0,
+    attrTitle: '', // 名称
+    attrCode: '', // 代码
+    attrType: 0, // 类型
+    attrLength: 0, // 长度
+    attrDecimals: 0, // 小数位数
+    isNotNull: 0, // 是否为空
+    isFixed: 0, // 是否锁定
+    isPKey: 0, // 主键
+    comment: '', // 注释
+    sortNo: 0,
+  })
+  nextTick(() => {
+    attrsTableRef.value.setScrollTop(state.formData.attrs.length * 50)
+  })
+}
+
+// 删除属性
+function onAttrDelete(index: number) {
+  state.formData.attrs.splice(index, 1)
+}
+
+function onAttrDrag() {
+  const tbody = attrsTableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
+  Sortable.create(tbody, {
+    handle: '.sortable',
+    animation: 300,
+    ghostClass: 'ghost',
+    onEnd: ({ newIndex, oldIndex }) => {
+      if (newIndex === undefined || oldIndex === undefined) {
+        return
+      }
+      const currRow = state.formData.attrs.splice(oldIndex, 1)[0]
+      state.formData.attrs.splice(newIndex, 0, currRow)
+      attrsTableKey.value += 1
+      nextTick(() => onAttrDrag())
+    },
+  })
+}
+
+onMounted(() => {
+  nextTick(() => {
+    onAttrDrag()
+  })
+})
+
+// 保存
+function onSubmit() {
+  formRef.value && formRef.value.validate(async (valid) => {
+    if (valid) {
+      state.formData.attrs.forEach((item, index) => item.sortNo = index)
+      if (state.actionType === 1) {
+        await createObject(state.formData)
+        state.dialogVisible = false
+        ElMessage.success('新增成功')
+        emit('success')
+      }
+      else {
+        await updateObject(state.formData)
+        state.dialogVisible = false
+        ElMessage.success('修改成功')
+        emit('success')
+      }
+    }
+  })
+}
+
+function onCancel() {
+  state.dialogVisible = false
+}
+
+function resetFormData() {
+  state.formData = {
+    bizId: 0,
+    objectId: 0,
+    objectCode: '',
+    objectTitle: '',
+    comment: '',
+    attrs: [],
+  }
+}
+
+defineExpose({
+  showAddModel(bizId: number) {
+    resetFormData()
+    state.title = '新增对象'
+    state.actionType = 1
+    state.dialogVisible = true
+    state.formData.bizId = bizId
+  },
+  showEditModel(bizId: number, objectId: number) {
+    resetFormData()
+    state.title = '编辑对象'
+    state.actionType = 2
+    state.dialogVisible = true
+    getData(bizId, objectId)
+  },
+
+})
+</script>
+
+<template>
+  <div v-show="state.dialogVisible">
+    <el-drawer :model-value="true" :title="state.title" size="80%" direction="ltr">
+      <template #default>
+        <el-row :gutter="20" class="container">
+          <el-col :span="7" :xs="24" class="form-left-side">
+            <h2>基本信息</h2>
+            <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>
+          </el-col>
+          <el-col :span="17" :xs="24" class="form-right-side">
+            <h2>属性</h2>
+            <el-table ref="attrsTableRef" :key="attrsTableKey" :data="state.formData.attrs" border stripe highlight-current-row>
+              <el-table-column width="60" align="center" fixed>
+                <template #header>
+                  <el-button type="primary" size="small" plain circle @click="onAttrAdd">
+                    <template #icon>
+                      <el-icon>
+                        <svg-icon name="i-ep:plus" />
+                      </el-icon>
+                    </template>
+                  </el-button>
+                </template>
+
+                <template #default="scope">
+                  <span class="index">{{ scope.$index + 1 }}</span>
+                  <el-button type="danger" size="small" plain circle class="delete" @click="onAttrDelete(scope.$index)">
+                    <template #icon>
+                      <el-icon>
+                        <svg-icon name="i-ep:delete" />
+                      </el-icon>
+                    </template>
+                  </el-button>
+                </template>
+              </el-table-column>
+
+              <el-table-column label="名称" width="150">
+                <template #default="scope">
+                  <el-input v-model="scope.row.attrTitle" />
+                </template>
+              </el-table-column>
+
+              <el-table-column label="代码" width="120">
+                <template #default="scope">
+                  <el-input v-model="scope.row.attrCode" />
+                </template>
+              </el-table-column>
+
+              <el-table-column label="类型" width="120">
+                <template #default="scope">
+                  <el-select v-model="scope.row.attrType">
+                    <el-option
+                      v-for="item in dataType"
+                      :key="item.dataType"
+                      :value="item.dataType"
+                      :label="item.dataName"
+                    />
+                  </el-select>
+                </template>
+              </el-table-column>
+
+              <el-table-column label="长度" width="90">
+                <template #default="scope">
+                  <el-input v-model="scope.row.attrLength" />
+                </template>
+              </el-table-column>
+
+              <el-table-column label="小数位数" width="90">
+                <template #default="scope">
+                  <el-input v-model="scope.row.attrDecimals" />
+                </template>
+              </el-table-column>
+
+              <el-table-column label="是否为空" width="90">
+                <template #default="scope">
+                  <el-checkbox v-model="scope.row.isNotNull" :true-label="1" :false-label="0">
+                    {{ scope.row.isNotNull === 1 ? '是' : '否' }}
+                  </el-checkbox>
+                </template>
+              </el-table-column>
+
+              <el-table-column label="注释" width="120">
+                <template #default="scope">
+                  <el-input v-model="scope.row.comment" />
+                </template>
+              </el-table-column>
+
+              <el-table-column width="80" align="center">
+                <template #header>
+                  排序
+                </template>
+                <template #default>
+                  <el-tag type="info" class="sortable">
+                    <el-icon>
+                      <svg-icon name="i-ep:d-caret" />
+                    </el-icon>
+                  </el-tag>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-col>
+        </el-row>
+      </template>
+
+      <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>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+    .form-right-side {
+      // display: flex;
+      // flex-direction: column;
+      // width: 500px;
+      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>

+ 52 - 52
src/views/model/model/index.vue → src/views/biz/object/index.vue

@@ -5,10 +5,10 @@ meta:
 
 <script lang="ts" setup>
 import { ElMessage, ElMessageBox } from 'element-plus'
-import DSModel from './components/Model.vue'
-import DSObject from './components/object.vue'
-import { deleteModelById, getModelByList } from '@/api/model/modelApi'
-import { deleteObjectById, getObjectByList } from '@/api/model/objectApi'
+import Biz from './components/Biz.vue'
+import BizObject from './components/BizObject.vue'
+import { deleteBizById, getBizByList } from '@/api/biz/bizApi'
+import { deleteObjectById, getObjectByList } from '@/api/biz/bizObjectApi'
 import useSettingsStore from '@/store/modules/settings'
 
 const settingsStore = useSettingsStore()
@@ -18,12 +18,12 @@ const tabbar = useTabbar()
 interface TreeNode {
   label: string
   isLeaf: boolean
-  modelId: number
+  bizId: number
   children?: TreeNode[]
 }
 
 interface Object {
-  modelId: number
+  bizId: number
   objectId: number
   objectTitle: string
   objectCode: string
@@ -33,8 +33,8 @@ interface Object {
 const state = reactive({
   loading: false,
   keywords: '',
-  models: [] as TreeNode[],
-  curModelId: 0,
+  treeData: [] as TreeNode[],
+  curBizId: 0,
   objectList: [] as Object[],
   dialogState: 1,
   search: {
@@ -43,65 +43,65 @@ const state = reactive({
 })
 
 const leftTreeRef = ref()
-const modelRef = ref()
+const bizRef = ref()
 const getObjectData = async () => {
-  const curModelId = state.curModelId
-  if (curModelId > 0) {
+  const curBizId = state.curBizId
+  if (curBizId > 0) {
     state.loading = true
-    const { data } = await getObjectByList({ modelId: curModelId })
+    const { data } = await getObjectByList({ modelId: curBizId })
     state.objectList = data
     state.loading = false
   }
 }
 
-const getModelData = async () => {
-  const { data } = await getModelByList('')
+const getBizData = async () => {
+  const { data } = await getBizByList('')
   const children: TreeNode[] = []
   data.forEach((item: any) => {
     return children.push({
-      label: item.modelTitle,
-      modelId: item.modelId,
+      label: item.bizTitle,
+      bizId: item.bizId,
       isLeaf: true,
     })
   })
-  state.models = [
+  state.treeData = [
     {
       label: '模型库',
       isLeaf: false,
-      modelId: -1,
+      bizId: -1,
       children,
     },
   ]
 
   if (data && data.length > 0) {
-    state.curModelId = data[0].modelId
+    state.curBizId = data[0].bizId
     nextTick(() => {
-      leftTreeRef.value.setCurrentKey(data[0].modelId)
+      leftTreeRef.value.setCurrentKey(data[0].bizId)
     })
     await getObjectData()
   }
 }
 
 onMounted(() => {
-  getModelData()
+  getBizData()
 })
 
 // 模型新增
-const onModelAdd = () => {
-  modelRef.value.showAddModel()
+const onBizAdd = () => {
+  bizRef.value.showAddBiz()
 }
 
 // 模型编辑
-const onModelEdit = (data: { modelId: number }) => {
-  const modelId = data.modelId
-  modelRef.value.showEditModel(modelId)
+const onBizEdit = (data: { bizId: number }) => {
+  const bizId = data.bizId
+  bizRef.value.showEditBiz(bizId)
 }
 
 // 模型删除
-const onModelDelete = (data: any) => {
-  ElMessageBox.confirm(`确认删除「${data.modelTitle}」吗?`, '确认信息').then(async () => {
-    await deleteModelById(data.modelId)
-    await getModelData()
+const onBizDelete = (data: any) => {
+  ElMessageBox.confirm(`确认删除「${data.bizTitle}」吗?`, '确认信息').then(async () => {
+    await deleteBizById(data.bizId)
+    await getBizData()
     ElMessage.success({
       message: '删除成功',
       center: true,
@@ -112,7 +112,7 @@ const onModelDelete = (data: any) => {
 // 模型选择
 const onTreeNodeClick = (node: TreeNode) => {
   if (node.isLeaf) {
-    state.curModelId = node.modelId
+    state.curBizId = node.bizId
     getObjectData()
   }
 }
@@ -129,18 +129,18 @@ const onSearch = () => {
 const onObjectAdd = () => {
   if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
     tabbar.open({
-      name: 'modelObjectEdit',
+      name: 'bizObjectEdit',
       params: {
-        modelId: state.curModelId,
+        modelId: state.curBizId,
         objectId: 0,
       },
     })
   }
   else {
     router.push({
-      name: 'modelObjectEdit',
+      name: 'bizObjectEdit',
       params: {
-        modelId: state.curModelId,
+        modelId: state.curBizId,
         objectId: 0,
       },
     })
@@ -148,21 +148,21 @@ const onObjectAdd = () => {
 }
 
 // 编辑对象
-const onObjectEdit = (row: { modelId: any; objectId: any }) => {
+const onObjectEdit = (row: { bizId: any; objectId: any }) => {
   if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
     tabbar.open({
-      name: 'modelObjectEdit',
+      name: 'bizObjectEdit',
       params: {
-        modelId: row.modelId,
+        bizId: row.bizId,
         objectId: row.objectId,
       },
     })
   }
   else {
     router.push({
-      name: 'modelObjectEdit',
+      name: 'bizObjectEdit',
       params: {
-        modelId: row.modelId,
+        bizId: row.bizId,
         objectId: row.objectId,
       },
     })
@@ -172,18 +172,18 @@ const onObjectEdit = (row: { modelId: any; objectId: any }) => {
 const onObjectOAM = (row: any) => {
   if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
     tabbar.open({
-      name: 'modelObjectOAM',
+      name: 'bizObjectOAM',
       params: {
-        modelId: row.modelId,
+        bizId: row.bizId,
         objectId: row.objectId,
       },
     })
   }
   else {
     router.push({
-      name: 'modelObjectOAM',
+      name: 'bizObjectOAM',
       params: {
-        modelId: row.modelId,
+        bizId: row.bizId,
         objectId: row.objectId,
       },
     })
@@ -192,9 +192,9 @@ const onObjectOAM = (row: any) => {
 
 // 删除对象
 const onObjectDelete = (row: any) => {
-  const { modelId, objectId, objectTitle } = row
+  const { bizId, objectId, objectTitle } = row
   ElMessageBox.confirm(`确认删除「${objectTitle}」吗?`, '确认信息').then(async () => {
-    await deleteObjectById(modelId, objectId)
+    await deleteObjectById(bizId, objectId)
     await getObjectData()
     ElMessage.success({
       message: '删除成功',
@@ -208,7 +208,7 @@ const onObjectDelete = (row: any) => {
   <div class="absolute-container">
     <tool-header title="数据模型">
       <template #right>
-        <el-button plain @click="onModelAdd">
+        <el-button plain @click="onBizAdd">
           <template #icon>
             <el-icon>
               <svg-icon name="i-ep:plus" />
@@ -222,7 +222,7 @@ const onObjectDelete = (row: any) => {
       <LayoutContainer left-side-width="300px" hide-left-side-toggle>
         <template #leftSide>
           <el-scrollbar class="tree">
-            <ElTree ref="leftTreeRef" :data="state.models" default-expand-all node-key="modelId" @node-click="onTreeNodeClick">
+            <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">
@@ -235,7 +235,7 @@ const onObjectDelete = (row: any) => {
                   </div>
                   <div v-if="data.isLeaf" class="actions">
                     <el-button-group>
-                      <el-button type="info" plain size="small" @click.stop="onModelEdit(data)">
+                      <el-button type="info" plain size="small" @click.stop="onBizEdit(data)">
                         <template #icon>
                           <el-icon>
                             <svg-icon name="i-ep:edit" />
@@ -243,7 +243,7 @@ const onObjectDelete = (row: any) => {
                         </template>
                       </el-button>
 
-                      <el-button type="danger" plain size="small" @click.stop="onModelDelete(data)">
+                      <el-button type="danger" plain size="small" @click.stop="onBizDelete(data)">
                         <template #icon>
                           <el-icon>
                             <svg-icon name="i-ep:delete" />
@@ -308,8 +308,8 @@ const onObjectDelete = (row: any) => {
         </div>
       </LayoutContainer>
     </div>
-    <DSModel ref="modelRef" @success="getModelData" />
-    <DSObject ref="objectRef" @success="getObjectData" />
+    <Biz ref="modelRef" @success="getBizData" />
+    <BizObject ref="objectRef" @success="getObjectData" />
   </div>
 </template>
 

+ 0 - 0
src/views/biz/rule/index.vue


+ 0 - 0
src/views/daas/database/components/model_data.vue → src/views/database/database/components/model_data.vue


+ 1 - 1
src/views/daas/database/components/sql_data.vue → src/views/database/database/components/sql_data.vue

@@ -1,6 +1,6 @@
 <script lang="ts" setup name="sql_data">
 import { cloneDeep } from 'lodash-es'
-import { getTableByList, getTableFieldsByList } from '@/api/daas/dbApi'
+import { getTableByList, getTableFieldsByList } from '@/api/database/dbApi'
 
 const state = reactive({
   layoutMode: 'table',

+ 1 - 1
src/views/daas/database/components/table_data.vue → src/views/database/database/components/table_data.vue

@@ -1,5 +1,5 @@
 <script lang="ts" setup name="table_data">
-import { getTableByList, getTableFieldsByList } from '@/api/daas/dbApi'
+import { getTableByList, getTableFieldsByList } from '@/api/database/dbApi'
 
 interface TreeNode {
   label: string

+ 0 - 1
src/views/daas/database/index.vue → src/views/database/database/index.vue

@@ -4,7 +4,6 @@ meta:
 </route>
 
 <script lang="ts" setup>
-
 const state = reactive({
   layoutMode: 'model',
 })

+ 1 - 1
src/views/daas/database_access/components/DBType.vue → src/views/database/database_access/components/DBType.vue

@@ -6,7 +6,7 @@ meta:
 <script lang="ts" setup>
 import { ElMessage } from 'element-plus'
 import type { FormInstance, FormRules } from 'element-plus'
-import { createDbType, getDbTypeById, updateDbType } from '@/api/daas/dbTypeApi'
+import { createDbType, getDbTypeById, updateDbType } from '@/api/database/dbTypeApi'
 const emit = defineEmits(['success'])
 
 const formRef = ref<FormInstance>()

+ 1 - 1
src/views/daas/database_access/index.vue → src/views/database/database_access/index.vue

@@ -1,7 +1,7 @@
 <script lang="ts" setup name="DBTypeIndex">
 import { ElMessage, ElMessageBox } from 'element-plus'
 import DBType from './components/DBType.vue'
-import { deleteDbTypeById, getDbTypeByList } from '@/api/daas/dbTypeApi'
+import { deleteDbTypeById, getDbTypeByList } from '@/api/database/dbTypeApi'
 
 const state = reactive({
   loading: false,

+ 1 - 1
src/views/daas/database_type/components/DbType.vue → src/views/database/database_type/components/DbType.vue

@@ -6,7 +6,7 @@ meta:
 <script lang="ts" setup>
 import { ElMessage } from 'element-plus'
 import type { FormInstance, FormRules } from 'element-plus'
-import { createDbType, getDbTypeById, updateDbType } from '@/api/daas/dbTypeApi'
+import { createDbType, getDbTypeById, updateDbType } from '@/api/database/dbTypeApi'
 const emit = defineEmits(['success'])
 
 const formRef = ref<FormInstance>()

+ 1 - 1
src/views/daas/database_type/index.vue → src/views/database/database_type/index.vue

@@ -1,7 +1,7 @@
 <script lang="ts" setup name="DbTypeIndex">
 import { ElMessage, ElMessageBox } from 'element-plus'
 import DbType from './components/DbType.vue'
-import { deleteDbTypeById, getDbTypeByList } from '@/api/daas/dbTypeApi'
+import { deleteDbTypeById, getDbTypeByList } from '@/api/database/dbTypeApi'
 
 const state = reactive({
   loading: false,

+ 408 - 0
src/views/model/attr/index.vue

@@ -0,0 +1,408 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="daasObjectEdit">
+import Sortable from 'sortablejs'
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { createObject, getObjectById, updateObject } from '@/api/model/modelObjectApi'
+import useSettingsStore from '@/store/modules/settings'
+
+const settingsStore = useSettingsStore()
+const route = useRoute()
+const modelId = parseInt(route.params.modelId.toString())
+const objectId = parseInt(route.params.objectId.toString())
+const router = useRouter()
+const tabbar = useTabbar()
+
+interface ObjectAttr {
+  attrId: number
+  attrTitle: string
+  attrCode: string
+  attrType: number
+  attrLength: number
+  attrDecimals: number
+  isNotNull: number
+  isFixed: number
+  comment: string
+  isPKey: number
+  sortNo: number
+}
+
+const dataType = [
+  { dataType: 1, dataName: '整数' },
+  { dataType: 2, dataName: '字符串' },
+  { dataType: 3, dataName: '小数' }]
+
+// 数据
+const state = reactive({
+  title: '',
+  dialogVisible: false,
+  loading: false,
+  search: {
+    keywords: '',
+  },
+  formData: {
+    modelId,
+    objectId,
+    objectType: 1,
+    objectCode: '',
+    objectTitle: '',
+    comment: '',
+    attrs: [] as ObjectAttr[],
+  },
+  actionType: 1,
+})
+
+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' },
+  ],
+})
+
+// 查询数据
+const getData = async () => {
+  state.loading = true
+  const { data } = await getObjectById(modelId, objectId)
+  state.loading = false
+  state.formData = data
+}
+
+const attrsTableRef = ref()
+const attrsTableKey = ref(0)
+function onAttrAdd() {
+  state.formData.attrs.push({
+    attrId: 0,
+    attrTitle: '', // 名称
+    attrCode: '', // 代码
+    attrType: 0, // 类型
+    attrLength: 0, // 长度
+    attrDecimals: 0, // 小数位数
+    isNotNull: 0, // 是否为空
+    isFixed: 0, // 是否锁定
+    isPKey: 0, // 主键
+    comment: '', // 注释
+    sortNo: 0,
+  })
+  nextTick(() => {
+    attrsTableRef.value.setScrollTop(state.formData.attrs.length * 50)
+  })
+}
+
+// 删除属性
+function onAttrDelete(index: number) {
+  state.formData.attrs.splice(index, 1)
+}
+
+function onAttrDrag() {
+  const tbody = attrsTableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
+  Sortable.create(tbody, {
+    handle: '.sortable',
+    animation: 300,
+    ghostClass: 'ghost',
+    onEnd: ({ newIndex, oldIndex }) => {
+      if (newIndex === undefined || oldIndex === undefined) {
+        return
+      }
+      const currRow = state.formData.attrs.splice(oldIndex, 1)[0]
+      state.formData.attrs.splice(newIndex, 0, currRow)
+      attrsTableKey.value += 1
+      nextTick(() => onAttrDrag())
+    },
+  })
+}
+
+onMounted(() => {
+  if (objectId <= 0) {
+    state.title = '新增对象'
+    state.actionType = 1
+  }
+  else {
+    state.title = '编辑对象'
+    state.actionType = 2
+    getData()
+  }
+
+  nextTick(() => {
+    onAttrDrag()
+  })
+})
+
+// 保存
+function onSubmit() {
+  formRef.value && formRef.value.validate(async (valid) => {
+    if (valid) {
+      state.formData.attrs.forEach((item, index) => item.sortNo = index)
+      if (state.actionType === 1) {
+        await createObject(state.formData)
+        state.dialogVisible = false
+        ElMessage.success('新增成功')
+      }
+      else {
+        await updateObject(state.formData)
+        state.dialogVisible = false
+        ElMessage.success('修改成功')
+      }
+      goBack()
+    }
+  })
+}
+
+function onCancel() {
+  goBack()
+}
+
+// 返回列表页
+function goBack() {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.close({ name: 'model' })
+  }
+  else {
+    router.push({ name: 'model' })
+  }
+}
+</script>
+
+<template>
+  <div class="absolute-container">
+    <page-header title="对象" content="创建元数据对象。">
+      <el-button size="default" round @click="goBack">
+        <template #icon>
+          <el-icon>
+            <svg-icon name="i-ep:arrow-left" />
+          </el-icon>
+        </template>
+        返回
+      </el-button>
+    </page-header>
+
+    <div class="page-main">
+      <LayoutContainer hide-left-side-toggle>
+        <template #leftSide>
+          <h2>基本信息</h2>
+          <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>
+
+        <div class="container">
+          <tool-bar>
+            <template #left>
+              <h2>属性</h2>
+            </template>
+            <template #right>
+              <el-input v-model="state.search.keywords" placeholder="请输入关键词筛选字典项" clearable style="width: 200px;" />
+              <el-button style="margin-left:10px" @click="getData">
+                <template #icon>
+                  <el-icon>
+                    <svg-icon name="i-ep:search" />
+                  </el-icon>
+                </template>
+              </el-button>
+
+              <el-button type="primary" @click="onAttrAdd">
+                <template #icon>
+                  <el-icon>
+                    <svg-icon name="i-ep:plus" />
+                  </el-icon>
+                </template>
+              </el-button>
+            </template>
+          </tool-bar>
+
+          <el-table ref="attrsTableRef" :key="attrsTableKey" :data="state.formData.attrs" class="list-table" border stripe highlight-current-row>
+            <el-table-column width="60" align="center" fixed>
+              <template #header>
+                <el-button type="primary" size="small" plain circle @click="onAttrAdd">
+                  <template #icon>
+                    <el-icon>
+                      <svg-icon name="i-ep:plus" />
+                    </el-icon>
+                  </template>
+                </el-button>
+              </template>
+
+              <template #default="scope">
+                <span class="index">{{ scope.$index + 1 }}</span>
+                <el-button type="danger" size="small" plain circle class="delete" @click="onAttrDelete(scope.$index)">
+                  <template #icon>
+                    <el-icon>
+                      <svg-icon name="i-ep:delete" />
+                    </el-icon>
+                  </template>
+                </el-button>
+              </template>
+            </el-table-column>
+
+            <el-table-column label="名称" width="150">
+              <template #default="scope">
+                <el-input v-model="scope.row.attrTitle" />
+              </template>
+            </el-table-column>
+
+            <el-table-column label="代码" width="120">
+              <template #default="scope">
+                <el-input v-model="scope.row.attrCode" />
+              </template>
+            </el-table-column>
+
+            <el-table-column label="类型" width="120">
+              <template #default="scope">
+                <el-select v-model="scope.row.attrType">
+                  <el-option
+                    v-for="item in dataType"
+                    :key="item.dataType"
+                    :value="item.dataType"
+                    :label="item.dataName"
+                  />
+                </el-select>
+              </template>
+            </el-table-column>
+
+            <el-table-column label="长度" width="90">
+              <template #default="scope">
+                <el-input v-model="scope.row.attrLength" />
+              </template>
+            </el-table-column>
+
+            <el-table-column label="小数位数" width="90">
+              <template #default="scope">
+                <el-input v-model="scope.row.attrDecimals" />
+              </template>
+            </el-table-column>
+
+            <el-table-column label="是否为空" width="90">
+              <template #default="scope">
+                <el-checkbox v-model="scope.row.isNotNull" :true-label="1" :false-label="0">
+                  {{ scope.row.isNotNull === 1 ? '是' : '否' }}
+                </el-checkbox>
+              </template>
+            </el-table-column>
+
+            <el-table-column label="主键" width="70">
+              <template #default="scope">
+                <el-checkbox v-model="scope.row.isPKey" :true-label="1" :false-label="0">
+                  {{ scope.row.isPKey === 1 ? '是' : '否' }}
+                </el-checkbox>
+              </template>
+            </el-table-column>
+
+            <el-table-column label="注释">
+              <template #default="scope">
+                <el-input v-model="scope.row.comment" />
+              </template>
+            </el-table-column>
+
+            <el-table-column width="80" align="center">
+              <template #header>
+                排序
+              </template>
+              <template #default>
+                <el-tag type="info" class="sortable">
+                  <el-icon>
+                    <svg-icon name="i-ep:d-caret" />
+                  </el-icon>
+                </el-tag>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </LayoutContainer>
+    </div>
+
+    <fixed-action-bar>
+      <el-button type="primary" size="large" @click="onSubmit">
+        保存
+      </el-button>
+      <el-button size="large" @click="onCancel">
+        取消
+      </el-button>
+    </fixed-action-bar>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.page-header {
+  margin-bottom: 0;
+}
+
+.page-main {
+  :deep(.left-side) {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    .form-el-scrollbar{
+      flex: 1;
+    }
+  }
+  :deep(.el-table) {
+        height: 100%;
+
+        .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;
+          }
+        }
+      }
+  h2{
+    padding: 0;
+    margin: 0;
+  }
+}
+</style>

+ 1 - 1
src/views/model/oam/components/objectOAM.vue

@@ -5,7 +5,7 @@ meta:
 
 <script lang="ts" setup>
 import type { FormInstance, FormRules } from 'element-plus'
-import { createObjectOAM, getObjectOAMById, updateObjectOAM } from '@/api/model/ObjectOAMApi'
+import { createObjectOAM, getObjectOAMById, updateObjectOAM } from '@/api/model/modelObjectOAMApi'
 const emit = defineEmits(['success'])
 
 const formRef = ref<FormInstance>()

+ 5 - 5
src/views/model/oam/index.vue

@@ -8,8 +8,8 @@ import type { FormInstance } from 'element-plus'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import ObjectOAMComponent from './components/objectOAM.vue'
 import useSettingsStore from '@/store/modules/settings'
-import { getObjectById } from '@/api/model/objectApi'
-import { deleteObjectOAMById, getObjectOAMById, getObjectOAMByList } from '@/api/model/ObjectOAMApi'
+import { getObjectById } from '@/api/model/modelObjectApi'
+import { deleteObjectOAMById, getObjectOAMById, getObjectOAMByList } from '@/api/model/modelObjectOAMApi'
 import { oamType } from '@/utils/tool'
 
 const settingsStore = useSettingsStore()
@@ -52,7 +52,7 @@ const state = reactive({
   keywords: '',
   curOamId: 0,
   oamList: [],
-  oams: [] as TreeNode[],
+  treeData: [] as TreeNode[],
   oam: {} as ObjectOAM,
   dialogState: 1,
   search: {
@@ -95,7 +95,7 @@ const getOAMTree = async () => {
       isLeaf: true,
     })
   })
-  state.oams = [
+  state.treeData = [
     {
       label: '对象行为',
       isLeaf: false,
@@ -183,7 +183,7 @@ function goBack() {
       <LayoutContainer left-side-width="300px" hide-left-side-toggle>
         <template #leftSide>
           <el-scrollbar class="tree">
-            <ElTree ref="leftTreeRef" :data="state.oams" default-expand-all node-key="oamId" @node-click="onTreeNodeClick">
+            <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">

+ 0 - 0
src/views/model/model/components/Model.vue → src/views/model/object/components/Model.vue


+ 1 - 1
src/views/model/model/components/Object.vue → src/views/model/object/components/ModelObject.vue

@@ -7,7 +7,7 @@ meta:
 import Sortable from 'sortablejs'
 import type { FormInstance, FormRules } from 'element-plus'
 import { ElMessage } from 'element-plus'
-import { createObject, getObjectById, updateObject } from '@/api/model/objectApi'
+import { createObject, getObjectById, updateObject } from '@/api/model/modelObjectApi'
 const emit = defineEmits(['success'])
 
 interface ObjectAttr {

+ 282 - 296
src/views/model/object/index.vue

@@ -3,233 +3,266 @@ meta:
   enabled: false
 </route>
 
-<script lang="ts" setup name="daasObjectEdit">
-import Sortable from 'sortablejs'
-import type { FormInstance, FormRules } from 'element-plus'
-import { ElMessage } from 'element-plus'
-import { createObject, getObjectById, updateObject } from '@/api/model/objectApi'
+<script lang="ts" setup>
+import { ElMessage, ElMessageBox } from 'element-plus'
+import Model from './components/Model.vue'
+import ModelObject from './components/ModelObject.vue'
+import { deleteModelById, getModelByList } from '@/api/model/modelApi'
+import { deleteObjectById, getObjectByList } from '@/api/model/modelObjectApi'
 import useSettingsStore from '@/store/modules/settings'
 
 const settingsStore = useSettingsStore()
-const route = useRoute()
-const modelId = parseInt(route.params.modelId.toString())
-const objectId = parseInt(route.params.objectId.toString())
 const router = useRouter()
 const tabbar = useTabbar()
 
-interface ObjectAttr {
-  attrId: number
-  attrTitle: string
-  attrCode: string
-  attrType: number
-  attrLength: number
-  attrDecimals: number
-  isNotNull: number
-  isFixed: number
-  comment: string
-  isPKey: number
-  sortNo: number
+interface TreeNode {
+  label: string
+  isLeaf: boolean
+  modelId: number
+  children?: TreeNode[]
 }
 
-const dataType = [
-  { dataType: 1, dataName: '整数' },
-  { dataType: 2, dataName: '字符串' },
-  { dataType: 3, dataName: '小数' }]
+interface Object {
+  modelId: number
+  objectId: number
+  objectTitle: string
+  objectCode: string
+  comment: string
+}
 
-// 数据
 const state = reactive({
-  title: '',
-  dialogVisible: false,
   loading: false,
+  keywords: '',
+  treeData: [] as TreeNode[],
+  curModelId: 0,
+  objectList: [] as Object[],
+  dialogState: 1,
   search: {
     keywords: '',
   },
-  formData: {
-    modelId,
-    objectId,
-    objectType: 1,
-    objectCode: '',
-    objectTitle: '',
-    comment: '',
-    attrs: [] as ObjectAttr[],
-  },
-  actionType: 1,
 })
 
-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' },
-  ],
+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 children: TreeNode[] = []
+  data.forEach((item: any) => {
+    return children.push({
+      label: item.modelTitle,
+      modelId: item.modelId,
+      isLeaf: true,
+    })
+  })
+  state.treeData = [
+    {
+      label: '模型库',
+      isLeaf: false,
+      modelId: -1,
+      children,
+    },
+  ]
+
+  if (data && data.length > 0) {
+    state.curModelId = data[0].modelId
+    nextTick(() => {
+      leftTreeRef.value.setCurrentKey(data[0].modelId)
+    })
+    await getObjectData()
+  }
+}
+
+onMounted(() => {
+  getModelData()
 })
 
-// 查询数据
-const getData = async () => {
-  state.loading = true
-  const { data } = await getObjectById(modelId, objectId)
-  state.loading = false
-  state.formData = data
+// 模型新增
+const onModelAdd = () => {
+  modelRef.value.showAddModel()
 }
 
-const attrsTableRef = ref()
-const attrsTableKey = ref(0)
-function onAttrAdd() {
-  state.formData.attrs.push({
-    attrId: 0,
-    attrTitle: '', // 名称
-    attrCode: '', // 代码
-    attrType: 0, // 类型
-    attrLength: 0, // 长度
-    attrDecimals: 0, // 小数位数
-    isNotNull: 0, // 是否为空
-    isFixed: 0, // 是否锁定
-    isPKey: 0, // 主键
-    comment: '', // 注释
-    sortNo: 0,
-  })
-  nextTick(() => {
-    attrsTableRef.value.setScrollTop(state.formData.attrs.length * 50)
+// 模型编辑
+const onModelEdit = (data: { modelId: number }) => {
+  const modelId = data.modelId
+  modelRef.value.showEditModel(modelId)
+}
+
+// 模型删除
+const onModelDelete = (data: any) => {
+  ElMessageBox.confirm(`确认删除「${data.modelTitle}」吗?`, '确认信息').then(async () => {
+    await deleteModelById(data.modelId)
+    await getModelData()
+    ElMessage.success({
+      message: '删除成功',
+      center: true,
+    })
   })
 }
 
-// 删除属性
-function onAttrDelete(index: number) {
-  state.formData.attrs.splice(index, 1)
+// 模型选择
+const onTreeNodeClick = (node: TreeNode) => {
+  if (node.isLeaf) {
+    state.curModelId = node.modelId
+    getObjectData()
+  }
 }
 
-function onAttrDrag() {
-  const tbody = attrsTableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
-  Sortable.create(tbody, {
-    handle: '.sortable',
-    animation: 300,
-    ghostClass: 'ghost',
-    onEnd: ({ newIndex, oldIndex }) => {
-      if (newIndex === undefined || oldIndex === undefined) {
-        return
-      }
-      const currRow = state.formData.attrs.splice(oldIndex, 1)[0]
-      state.formData.attrs.splice(newIndex, 0, currRow)
-      attrsTableKey.value += 1
-      nextTick(() => onAttrDrag())
-    },
-  })
+const objectTableRef = ref()
+const objectRef = ref()
+
+// 检索对象
+const onSearch = () => {
+  getObjectData()
 }
 
-onMounted(() => {
-  if (objectId <= 0) {
-    state.title = '新增对象'
-    state.actionType = 1
+// 新增对象
+const onObjectAdd = () => {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.open({
+      name: 'modelObjectEdit',
+      params: {
+        modelId: state.curModelId,
+        objectId: 0,
+      },
+    })
   }
   else {
-    state.title = '编辑对象'
-    state.actionType = 2
-    getData()
+    router.push({
+      name: 'modelObjectEdit',
+      params: {
+        modelId: state.curModelId,
+        objectId: 0,
+      },
+    })
   }
-
-  nextTick(() => {
-    onAttrDrag()
-  })
-})
-
-// 保存
-function onSubmit() {
-  formRef.value && formRef.value.validate(async (valid) => {
-    if (valid) {
-      state.formData.attrs.forEach((item, index) => item.sortNo = index)
-      if (state.actionType === 1) {
-        await createObject(state.formData)
-        state.dialogVisible = false
-        ElMessage.success('新增成功')
-      }
-      else {
-        await updateObject(state.formData)
-        state.dialogVisible = false
-        ElMessage.success('修改成功')
-      }
-      goBack()
-    }
-  })
 }
 
-function onCancel() {
-  goBack()
+// 编辑对象
+const onObjectEdit = (row: { modelId: any; objectId: any }) => {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.open({
+      name: 'modelObjectEdit',
+      params: {
+        modelId: row.modelId,
+        objectId: row.objectId,
+      },
+    })
+  }
+  else {
+    router.push({
+      name: 'modelObjectEdit',
+      params: {
+        modelId: row.modelId,
+        objectId: row.objectId,
+      },
+    })
+  }
 }
 
-// 返回列表页
-function goBack() {
+const onObjectOAM = (row: any) => {
   if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
-    tabbar.close({ name: 'model' })
+    tabbar.open({
+      name: 'modelObjectOAM',
+      params: {
+        modelId: row.modelId,
+        objectId: row.objectId,
+      },
+    })
   }
   else {
-    router.push({ name: 'model' })
+    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 () => {
+    await deleteObjectById(modelId, objectId)
+    await getObjectData()
+    ElMessage.success({
+      message: '删除成功',
+      center: true,
+    })
+  })
+}
 </script>
 
 <template>
   <div class="absolute-container">
-    <page-header title="对象" content="创建元数据对象。">
-      <el-button size="default" round @click="goBack">
-        <template #icon>
-          <el-icon>
-            <svg-icon name="i-ep:arrow-left" />
-          </el-icon>
-        </template>
-        返回
-      </el-button>
-    </page-header>
-
+    <tool-header title="数据模型">
+      <template #right>
+        <el-button plain @click="onModelAdd">
+          <template #icon>
+            <el-icon>
+              <svg-icon name="i-ep:plus" />
+            </el-icon>
+          </template>
+          新增模型
+        </el-button>
+      </template>
+    </tool-header>
     <div class="page-main">
-      <LayoutContainer hide-left-side-toggle>
+      <LayoutContainer left-side-width="300px" hide-left-side-toggle>
         <template #leftSide>
-          <h2>基本信息</h2>
-          <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 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="uim:box" />
+                    </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>
         </template>
 
         <div class="container">
           <tool-bar>
-            <template #left>
-              <h2>属性</h2>
-            </template>
             <template #right>
-              <el-input v-model="state.search.keywords" placeholder="请输入关键词筛选字典项" clearable style="width: 200px;" />
-              <el-button style="margin-left:10px" @click="getData">
+              <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" />
@@ -237,172 +270,125 @@ function goBack() {
                 </template>
               </el-button>
 
-              <el-button type="primary" @click="onAttrAdd">
+              <el-button plain 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="attrsTableRef" :key="attrsTableKey" :data="state.formData.attrs" class="list-table" border stripe highlight-current-row>
-            <el-table-column width="60" align="center" fixed>
-              <template #header>
-                <el-button type="primary" size="small" plain circle @click="onAttrAdd">
-                  <template #icon>
-                    <el-icon>
-                      <svg-icon name="i-ep:plus" />
-                    </el-icon>
-                  </template>
-                </el-button>
-              </template>
+          <el-table ref="objectTableRef" v-loading="state.loading" class="list-table" :data="state.objectList" border stripe highlight-current-row height="100%">
+            <el-table-column type="index" label="序号" header-align="center" align="center" width="70" />
 
-              <template #default="scope">
-                <span class="index">{{ scope.$index + 1 }}</span>
-                <el-button type="danger" size="small" plain circle class="delete" @click="onAttrDelete(scope.$index)">
-                  <template #icon>
-                    <el-icon>
-                      <svg-icon name="i-ep:delete" />
-                    </el-icon>
-                  </template>
-                </el-button>
-              </template>
-            </el-table-column>
+            <el-table-column prop="objectTitle" label="名称" header-align="center" align="center" width="200" />
 
-            <el-table-column label="名称" width="150">
-              <template #default="scope">
-                <el-input v-model="scope.row.attrTitle" />
-              </template>
-            </el-table-column>
-
-            <el-table-column label="代码" width="120">
-              <template #default="scope">
-                <el-input v-model="scope.row.attrCode" />
-              </template>
-            </el-table-column>
-
-            <el-table-column label="类型" width="120">
-              <template #default="scope">
-                <el-select v-model="scope.row.attrType">
-                  <el-option
-                    v-for="item in dataType"
-                    :key="item.dataType"
-                    :value="item.dataType"
-                    :label="item.dataName"
-                  />
-                </el-select>
-              </template>
-            </el-table-column>
-
-            <el-table-column label="长度" width="90">
-              <template #default="scope">
-                <el-input v-model="scope.row.attrLength" />
-              </template>
-            </el-table-column>
-
-            <el-table-column label="小数位数" width="90">
-              <template #default="scope">
-                <el-input v-model="scope.row.attrDecimals" />
-              </template>
-            </el-table-column>
+            <el-table-column prop="objectCode" label="代码" header-align="center" align="center" width="150" />
 
-            <el-table-column label="是否为空" width="90">
+            <el-table-column prop="objectType" label="类型" header-align="center" align="center" width="150">
               <template #default="scope">
-                <el-checkbox v-model="scope.row.isNotNull" :true-label="1" :false-label="0">
-                  {{ scope.row.isNotNull === 1 ? '是' : '否' }}
-                </el-checkbox>
+                <span v-if="scope.row.objectType === 1">实体对象</span>
+                <span v-else>视图对象</span>
               </template>
             </el-table-column>
 
-            <el-table-column label="主键" width="70">
-              <template #default="scope">
-                <el-checkbox v-model="scope.row.isPKey" :true-label="1" :false-label="0">
-                  {{ scope.row.isPKey === 1 ? '是' : '否' }}
-                </el-checkbox>
-              </template>
-            </el-table-column>
+            <el-table-column prop="comment" label="说明" header-align="center" align="left" />
 
-            <el-table-column label="注释">
+            <el-table-column label="操作" header-align="center" align="center" width="230">
               <template #default="scope">
-                <el-input v-model="scope.row.comment" />
-              </template>
-            </el-table-column>
-
-            <el-table-column width="80" align="center">
-              <template #header>
-                排序
-              </template>
-              <template #default>
-                <el-tag type="info" class="sortable">
-                  <el-icon>
-                    <svg-icon name="i-ep:d-caret" />
-                  </el-icon>
-                </el-tag>
+                <el-button type="primary" size="small" plain @click="onObjectOAM(scope.row)">行为</el-button>
+                <el-button type="warning" size="small" plain @click="onObjectEdit(scope.row)">编辑</el-button>
+                <el-button type="danger" size="small" plain @click="onObjectDelete(scope.row)">删除</el-button>
               </template>
             </el-table-column>
           </el-table>
         </div>
       </LayoutContainer>
     </div>
-
-    <fixed-action-bar>
-      <el-button type="primary" size="large" @click="onSubmit">
-        保存
-      </el-button>
-      <el-button size="large" @click="onCancel">
-        取消
-      </el-button>
-    </fixed-action-bar>
+    <Model ref="modelRef" @success="getModelData" />
+    <ModelObject ref="objectRef" @success="getObjectData" />
   </div>
 </template>
 
 <style lang="scss" scoped>
-.page-header {
-  margin-bottom: 0;
+.container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
 }
 
-.page-main {
+.absolute-container {
   :deep(.left-side) {
     display: flex;
     flex-direction: column;
     height: 100%;
-    .form-el-scrollbar{
-      flex: 1;
+
+    .btns {
+      display: inline-flex;
+      width: 100%;
+      margin-bottom: var(--container-padding);
+
+      .add {
+        width: 100%;
+      }
     }
-  }
-  :deep(.el-table) {
-        height: 100%;
 
-        .el-table__row {
-          .index {
-            display: inline-block;
-          }
+    .tree {
+      flex: 1;
+      overflow-y: auto;
 
-          .delete {
-            display: none;
-          }
+      .el-tree {
+        .el-tree-node__content {
+          height: 40px;
+        }
 
-          &:hover {
-            .index {
-              display: none;
+        .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;
             }
+          }
 
-            .delete {
-              display: inline-block;
+          &:hover {
+            .actions {
+              display: block;
             }
           }
 
-          .el-tag.sortable,
-          .el-tag.sortable .el-icon {
-            cursor: s-resize;
+          .actions {
+            display: none;
+            position: absolute;
+            right: 10px;
+            top: 50%;
+            transform: translateY(-50%);
+
+            .el-button {
+              padding: 5px 8px;
+            }
           }
         }
       }
-  h2{
-    padding: 0;
-    margin: 0;
+    }
   }
 }
 </style>

+ 20 - 6
src/views/paas/atu/components/ModelObjectSelector.vue

@@ -5,8 +5,9 @@ meta:
 
 <script lang="ts" setup>
 import { getModelByList } from '@/api/model/modelApi'
-import { getObjectByList } from '@/api/model/objectApi'
-import { getObjectOAMByList } from '@/api/model/objectOAMApi'
+import { getObjectByList } from '@/api/model/modelObjectApi'
+import { getObjectOAMByList } from '@/api/model/modelObjectOAMApi'
+import { createAtu } from '@/api/api/apiTransUnitApi'
 
 interface TreeNode {
   label: string
@@ -112,7 +113,6 @@ const onTreeNodeClick = (node: TreeNode) => {
 }
 
 const objectTableRef = ref()
-
 const dialogVisible = ref(false)
 const onObjectSel = async (row: { objectId: any }) => {
   state.curObjectId = row.objectId
@@ -125,9 +125,16 @@ const onObjectOAMSel = async (row: { modelId: any; objectId: any; oamId: any })
   state.formData.objectId = row.objectId
   state.formData.oamId = row.oamId
   state.objectOAMDetail = row
-  // await createAtu(state.formData)
-  // emit('onSuccess')
-  // dialogVisible.value = false
+}
+
+const onSave = async () => {
+  await createAtu(state.formData)
+  emit('onSuccess')
+  dialogVisible.value = false
+}
+
+const onCancel = () => {
+  dialogVisible.value = false
 }
 
 // 点击选择
@@ -214,6 +221,13 @@ defineExpose({
             </li>
           </ul>
           <el-Empty v-else />
+
+          <el-button type="success" @click="onSave">
+            保存
+          </el-button>
+          <el-button type="info" @click="onCancel">
+            取消
+          </el-button>
         </el-card>
       </el-col>
     </el-row>

+ 13 - 8
src/views/paas/atu/index.vue

@@ -8,9 +8,9 @@ import type { FormInstance } from 'element-plus'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import ModelObjectSelector from './components/ModelObjectSelector.vue'
 import useSettingsStore from '@/store/modules/settings'
-import { getApiById } from '@/api/paas/apiApi'
-import { deleteAtuById, generateParamsByCode, getAtuByList } from '@/api/paas/apiTransUnitApi'
-import { createX, deleteX, getX, patchX, updateX } from '@/api/paas/apiGatewayApi'
+import { getApiById } from '@/api/api/apiApi'
+import { deleteAtuById, generateParamsByCode, getAtuByList } from '@/api/api/apiTransUnitApi'
+import { createX, deleteX, getX, patchX, updateX } from '@/api/api/apiGatewayApi'
 
 const settingsStore = useSettingsStore()
 const route = useRoute()
@@ -87,19 +87,24 @@ const onExecute = async () => {
     const apiCode = state.apiCode
     const params = JSON.parse(state.params)
     if (apiType === 1) {
-      await getX(apiCode, params)
+      const { data } = await getX(apiCode, params)
+      state.result = JSON.stringify(data)
     }
     else if (apiType === 2) {
-      await createX(apiCode, params)
+      const { data } = await createX(apiCode, params)
+      state.result = JSON.stringify(data)
     }
     else if (apiType === 3) {
-      await updateX(apiCode, params)
+      const { data } = await updateX(apiCode, params)
+      state.result = JSON.stringify(data)
     }
     else if (apiType === 4) {
-      await patchX(apiCode, params)
+      const { data } = await patchX(apiCode, params)
+      state.result = JSON.stringify(data)
     }
     else if (apiType === 5) {
-      await deleteX(apiCode, params)
+      const { data } = await deleteX(apiCode, params)
+      state.result = JSON.stringify(data)
     }
   }
   catch (err) {