houyaf 3 vuotta sitten
vanhempi
commit
acc7b1fa07

+ 6 - 6
src/api/paas/moduleApi.ts

@@ -15,12 +15,12 @@ export function getModuleByList(data: any) {
 
 /**
  * 根据Id获取Module
- * @param modId
+ * @param moduleId
  * @returns
  */
-export function getModuleById(modId: number) {
+export function getModuleById(moduleId: number) {
   return apiRequest({
-    url: `/paas/module/${modId}`,
+    url: `/paas/module/${moduleId}`,
     method: 'GET',
   })
 }
@@ -53,12 +53,12 @@ export function updateModule(data: any) {
 
 /**
  * 删除Module
- * @param modId
+ * @param moduleId
  * @returns
  */
-export function deleteModuleById(modId: number) {
+export function deleteModuleById(moduleId: number) {
   return apiRequest({
-    url: `/paas/module/${modId}`,
+    url: `/paas/module/${moduleId}`,
     method: 'DELETE',
   })
 }

+ 1 - 0
src/network/http/apiRequest.ts

@@ -72,6 +72,7 @@ apiRequest.interceptors.response.use(
       ElMessage.error(response.data.msg)
       if (response.data.code === 401) {
         toLogin()
+        return Promise.reject(response.data)
       }
       else {
         return Promise.reject(response.data)

+ 12 - 0
src/router/modules/model.ts

@@ -36,6 +36,18 @@ const routes: RouteRecordRaw[] = [
           noCache: 'modelObjectEdit',
         },
       },
+      {
+        path: 'model/object/oam/:modelId/:objectId',
+        name: 'modelObjectOAM',
+        component: () => import('@/views/model/oam/index.vue'),
+        meta: {
+          title: '行为定义',
+          sidebar: false,
+          activeMenu: '/model/',
+          cache: true,
+          noCache: 'modelObjectOAM',
+        },
+      },
     ],
   },
 ]

+ 11 - 0
src/utils/tool.ts

@@ -744,3 +744,14 @@ export function apiType(i: string | number) {
   ]
   return strs[i as unknown as keyof typeof strs]
 }
+
+export function oamType(i: string | number) {
+  const strs = [
+    '未知',
+    'DQL(数据查询)',
+    'DML(数据操作)',
+    'DDL(数据定义)',
+    'DCL(数据控制)',
+  ]
+  return strs[i as unknown as keyof typeof strs]
+}

+ 25 - 7
src/views/model/model/index.vue

@@ -169,6 +169,27 @@ 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',
+      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
@@ -277,14 +298,11 @@ const onObjectDelete = (row: any) => {
 
             <el-table-column prop="comment" label="说明" header-align="center" align="left" />
 
-            <el-table-column label="操作" header-align="center" align="center" width="200">
+            <el-table-column label="操作" header-align="center" align="center" width="230">
               <template #default="scope">
-                <el-button type="primary" size="small" plain @click="onObjectEdit(scope.row)">
-                  编辑
-                </el-button>
-                <el-button type="danger" size="small" plain @click="onObjectDelete(scope.row)">
-                  删除
-                </el-button>
+                <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>

+ 179 - 0
src/views/model/oam/components/objectOAM.vue

@@ -0,0 +1,179 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup>
+import type { FormInstance, FormRules } from 'element-plus'
+import { createObjectOAM, getObjectOAMById, updateObjectOAM } from '@/api/model/ObjectOAMApi'
+const emit = defineEmits(['success'])
+
+const formRef = ref<FormInstance>()
+const formRules = ref<FormRules>({
+  oamTitle: [
+    { required: true, message: '请输入标题', trigger: 'blur' },
+  ],
+  oamDesc: [
+    { required: false, message: '请输入描述', trigger: 'blur' },
+  ],
+})
+
+const state = reactive({
+  title: '',
+  dialogVisible: false,
+  loading: false,
+  formData: {
+    modelId: 0,
+    objectId: 0,
+    oamId: 0,
+    oamTitle: '',
+    oamType: 0,
+    sqlType: 0,
+    sqlStatement: '',
+    sqlSelect: '',
+    sqlFrom: '',
+    sqlWhere: '',
+    sqlOrder: '',
+    oamDesc: '',
+  },
+  actionType: 1,
+})
+
+onMounted(() => {})
+
+const getData = async () => {
+  const { modelId, objectId, oamId } = state.formData
+  state.loading = true
+  const { data } = await getObjectOAMById(modelId, objectId, oamId)
+  state.loading = false
+  state.formData = data
+}
+
+function onSubmit() {
+  formRef.value && formRef.value.validate(async (valid) => {
+    if (valid) {
+      if (state.actionType === 1) {
+        await createObjectOAM(state.formData)
+        state.dialogVisible = false
+        emit('success')
+      }
+      else {
+        await updateObjectOAM(state.formData)
+        state.dialogVisible = false
+        emit('success')
+      }
+    }
+  })
+}
+
+function onCancel() {
+  state.dialogVisible = false
+}
+
+function resetFormData() {
+  state.formData = {
+    modelId: 0,
+    objectId: 0,
+    oamId: 0,
+    oamType: 0,
+    oamTitle: '',
+    sqlType: 0,
+    sqlStatement: '',
+    sqlSelect: '',
+    sqlFrom: '',
+    sqlWhere: '',
+    sqlOrder: '',
+    oamDesc: '',
+  }
+}
+
+defineExpose({
+  showAddModel(modelId: number, objectId: number) {
+    resetFormData()
+    state.title = '新增对象行为'
+    state.actionType = 1
+    state.formData.modelId = modelId
+    state.formData.objectId = objectId
+    state.dialogVisible = true
+  },
+  showEditModel(modelId: number, objectId: number, oamId: number) {
+    resetFormData()
+    state.title = '编辑对象行为'
+    state.formData.modelId = modelId
+    state.formData.objectId = objectId
+    state.formData.oamId = oamId
+    state.actionType = 2
+    state.dialogVisible = true
+    getData()
+  },
+
+})
+</script>
+
+<template>
+  <div>
+    <el-dialog v-model="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" :model="state.formData" :rules="formRules" label-width="120px" label-suffix=":">
+          <el-form-item label="行为名称" prop="oamTitle">
+            <el-input v-model="state.formData.oamTitle" placeholder="请输入标题" />
+          </el-form-item>
+
+          <el-form-item label="类型" prop="oamType">
+            <el-radio-group v-model="state.formData.oamType">
+              <el-radio :label="1">基于Pk查询</el-radio>
+              <el-radio :label="2">多笔查询</el-radio>
+              <el-radio :label="3">分页查询</el-radio>
+              <el-radio :label="4">新增</el-radio>
+              <el-radio :label="5">修改</el-radio>
+              <el-radio :label="6">删除</el-radio>
+              <el-radio :label="7">非Pk单笔查询</el-radio>
+            </el-radio-group>
+          </el-form-item>
+
+          <el-form-item label="类型" prop="sqlType">
+            <el-radio-group v-model="state.formData.sqlType">
+              <el-radio :label="1">DQL(数据查询)</el-radio>
+              <el-radio :label="2">DML(数据操纵)</el-radio>
+              <el-radio :label="3">DDL(数据定义)</el-radio>
+              <el-radio :label="4">DCL(数据控制)</el-radio>
+            </el-radio-group>
+          </el-form-item>
+
+          <el-form-item label="SQL" prop="sqlStatement">
+            <el-input v-model="state.formData.sqlStatement" type="textarea" rows="3" placeholder="请输入SQL" />
+          </el-form-item>
+
+          <el-form-item label="Select" prop="sqlSelect">
+            <el-input v-model="state.formData.sqlSelect" type="textarea" rows="3" placeholder="请输入SQL" />
+          </el-form-item>
+
+          <el-form-item label="From" prop="sqlFrom">
+            <el-input v-model="state.formData.sqlFrom" type="textarea" rows="3" placeholder="请输入SQL" />
+          </el-form-item>
+
+          <el-form-item label="Where" prop="sqlWhere">
+            <el-input v-model="state.formData.sqlWhere" type="textarea" rows="3" placeholder="请输入SQL" />
+          </el-form-item>
+
+          <el-form-item label="Order" prop="sqlOrder">
+            <el-input v-model="state.formData.sqlOrder" type="textarea" rows="3" placeholder="请输入SQL" />
+          </el-form-item>
+
+          <el-form-item label="简要说明" prop="oamDesc">
+            <el-input v-model="state.formData.oamDesc" type="textarea" rows="3" 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>

+ 380 - 0
src/views/model/oam/index.vue

@@ -0,0 +1,380 @@
+<route lang="yaml">
+meta:
+  enabled: false
+</route>
+
+<script lang="ts" setup name="PagesExampleTable">
+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 { oamType } from '@/utils/tool'
+
+const settingsStore = useSettingsStore()
+const route = useRoute()
+const router = useRouter()
+const tabbar = useTabbar()
+
+const modelId = parseInt(route.params.modelId.toString())
+const objectId = parseInt(route.params.objectId.toString())
+
+interface TreeNode {
+  label: string
+  isLeaf: boolean
+  oamId: number
+  children?: TreeNode[]
+}
+
+interface ObjectOAM {
+  modelId: number
+  objectId: number
+  oamId: number
+  oamTitle: string
+  oamCode: string
+  oamType: number
+  oamStatement: string
+  oamDesc: string
+}
+
+const state = reactive({
+  loading: false,
+  objectTitle: '',
+  objectCode: '',
+  objectType: 0,
+  keywords: '',
+  curOamId: 0,
+  oamList: [],
+  oams: [] as TreeNode[],
+  oam: {} as ObjectOAM,
+  dialogState: 1,
+  search: {
+    modelId,
+    objectId,
+    keywords: '',
+  },
+  params: '',
+  result: '',
+})
+
+const leftTreeRef = ref()
+
+const getObjectData = async () => {
+  state.loading = true
+  const { data } = await getObjectById(modelId, objectId)
+  state.objectTitle = data.objectTitle
+  state.objectCode = data.objectCode
+  state.objectType = data.objectType
+  state.loading = false
+}
+
+const getObjectOAMData = async () => {
+  const curOamId = state.curOamId
+  if (curOamId > 0) {
+    state.loading = true
+    const { data } = await getObjectOAMById(modelId, objectId, curOamId)
+    state.oam = data
+    state.loading = false
+  }
+}
+
+const getOAMTree = async () => {
+  const { data } = await getObjectOAMByList(state.search)
+  const children: TreeNode[] = []
+  data.forEach((item: any) => {
+    return children.push({
+      label: item.oamTitle,
+      oamId: item.oamId,
+      isLeaf: true,
+    })
+  })
+  state.oams = [
+    {
+      label: '对象行为',
+      isLeaf: false,
+      oamId: -1,
+      children,
+    },
+  ]
+
+  if (data && data.length > 0) {
+    state.curOamId = data[0].oamId
+    nextTick(() => {
+      leftTreeRef.value.setCurrentKey(data[0].oamId)
+    })
+    await getObjectOAMData()
+  }
+}
+
+onMounted(() => {
+  getObjectData()
+  getOAMTree()
+})
+
+const formRef = ref<FormInstance>()
+
+// Object OAM选择
+const onTreeNodeClick = (node: TreeNode) => {
+  if (node.isLeaf) {
+    state.curOamId = node.oamId
+    getObjectOAMData()
+  }
+}
+
+const objectOAMRef = ref()
+const onAdd = () => {
+  window.console.log(modelId)
+  window.console.log(objectId)
+  objectOAMRef.value.showAddModel(modelId, objectId)
+}
+
+const onEdit = () => {
+  objectOAMRef.value.showEditModel(modelId, objectId, state.curOamId)
+}
+
+const onDelete = (data: { modelId: number; objectId: number; oamId: number; oamTitle: string }) => {
+  const { modelId, objectId, oamId, oamTitle } = data
+  ElMessageBox.confirm(`确认删除「${oamTitle}」吗?`, '确认信息').then(async () => {
+    await deleteObjectOAMById(modelId, objectId, oamId)
+    await getOAMTree()
+    ElMessage.success({
+      message: '删除成功',
+      center: true,
+    })
+  })
+}
+
+// 选择对象模型回调
+const onSuccess = () => {
+  getOAMTree()
+}
+
+// 返回列表页
+function goBack() {
+  if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
+    tabbar.close({ name: 'modelList' })
+  }
+  else {
+    router.push({ name: 'modelList' })
+  }
+}
+</script>
+
+<template>
+  <div class="absolute-container">
+    <page-header :title="state.objectTitle" :content="state.objectCode">
+      <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 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">
+              <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 class="code">
+                      {{ oamType(data.oamType) }}
+                    </div>
+                  </div>
+                </div>
+              </template>
+            </ElTree>
+          </el-scrollbar>
+        </template>
+
+        <div class="form">
+          <tool-header>
+            <template #right>
+              <el-button type="primary" @click="onAdd">
+                添加
+              </el-button>
+
+              <el-button type="primary" @click="onEdit">
+                编辑
+              </el-button>
+            </template>
+          </tool-header>
+          <page-main title="SQL">
+            <div class="question">
+              <ol class="answer">
+                <li><span>Sql</span><br>{{ state.oam.sqlStatement  }}</li>
+                <li><span>Select</span><br>{{ state.oam.sqlSelect  }}</li>
+                <li><span>From </span><br>{{ state.oam.sqlFrom  }}</li>
+                <li><span>Where</span><br>{{ state.oam.sqlWhere  }}</li>
+                <li><span>Order</span><br>{{ state.oam.sqlOrder  }}</li>
+                <li><span>说明</span><br>{{ state.oam.oamDesc  }}</li>
+              </ol>
+            </div>
+          </page-main>
+        </div>
+      </LayoutContainer>
+    </div>
+    <ObjectOAMComponent ref="objectOAMRef" @success="getOAMTree" />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.absolute-container {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+
+  .page-header {
+    margin-bottom: 0;
+  }
+
+  .page-main {
+    // 让 page-main 的高度自适应
+    flex: 1;
+    overflow: auto;
+    display: flex;
+    flex-direction: column;
+
+    .flex-container {
+      position: static;
+    }
+  }
+}
+
+.flex-container {
+  :deep(.left-side) {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+
+    .btns {
+      display: inline-flex;
+      width: 100%;
+
+      .add {
+        width: 100%;
+      }
+    }
+
+    .search {
+      margin: 15px 0;
+    }
+
+    .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);
+
+            @include text-overflow;
+          }
+
+          .code {
+            width: calc(100% - 10px);
+            color: var(--el-text-color-placeholder);
+
+            @include text-overflow;
+          }
+
+          &:hover {
+            .actions {
+              display: block;
+            }
+          }
+
+          .actions {
+            display: none;
+            position: absolute;
+            right: 10px;
+            top: 50%;
+            transform: translateY(-50%);
+
+            .el-button {
+              padding: 5px 8px;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+:deep(.main) {
+  display: flex;
+  justify-content: center;
+}
+
+.container {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+
+  .empty {
+    text-align: center;
+    font-size: 32px;
+    color: var(--el-text-color-placeholder);
+  }
+
+  .el-table {
+    margin: 15px 0;
+  }
+}
+
+.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;
+    }
+  }
+}
+</style>

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

@@ -6,6 +6,7 @@ meta:
 <script lang="ts" setup>
 import { getModelByList } from '@/api/model/modelApi'
 import { getObjectByList } from '@/api/model/objectApi'
+import { getObjectOAMByList } from '@/api/model/objectOAMApi'
 import { createAtu } from '@/api/paas/apiTransUnitApi'
 
 interface TreeNode {
@@ -31,7 +32,9 @@ const state = reactive({
   title: '',
   models: [] as TreeNode[],
   curModelId: 0,
+  curObjectId: 0,
   objectList: [] as Object[],
+  objectOAMList: [] as Object[],
   dialogState: 1,
   search: {
     apiId: 0,
@@ -42,11 +45,22 @@ const state = reactive({
     apiId: 0,
     modelId: 0,
     objectId: 0,
-    objectOamType: 1,
+    oamId: 1,
   },
 })
 
 const leftTreeRef = ref()
+const getObjectOAMData = async () => {
+  const curModelId = state.curModelId
+  const curObjectId = state.curObjectId
+  if (curModelId > 0 && curObjectId > 0) {
+    state.loading = true
+    const { data } = await getObjectOAMByList({ modelId: curModelId })
+    state.objectOAMList = data
+    state.loading = false
+  }
+}
+
 const getObjectData = async () => {
   const curModelId = state.curModelId
   if (curModelId > 0) {
@@ -99,13 +113,20 @@ const onTreeNodeClick = (node: TreeNode) => {
 
 const objectTableRef = ref()
 
-const drawerModel = ref(false)
-const onObjectSel = async (row: { modelId: any; objectId: any }) => {
+const dialogVisible = ref(false)
+const onObjectSel = async (row: { objectId: any }) => {
+  state.curObjectId = row.objectId
+  await getObjectOAMData()
+}
+
+const objectOAMTableRef = ref()
+const onObjectOAMSel = async (row: { modelId: any; objectId: any; oamId: any }) => {
   state.formData.modelId = row.modelId
   state.formData.objectId = row.objectId
+  state.formData.oamId = row.oamId
   await createAtu(state.formData)
   emit('onSuccess')
-  drawerModel.value = false
+  dialogVisible.value = false
 }
 
 // 点击选择
@@ -114,13 +135,13 @@ defineExpose({
     state.search.apiId = apiId
     state.formData.moduleId = moduleId
     state.formData.apiId = apiId
-    drawerModel.value = true
+    dialogVisible.value = true
   },
 })
 </script>
 
 <template>
-  <el-drawer v-model="drawerModel" :title="state.title" size="55%">
+  <el-drawer v-model="dialogVisible" :title="state.title" size="55%">
     <div class="absolute-container">
       <div class="page-main">
         <LayoutContainer left-side-width="200px" hide-left-side-toggle>
@@ -163,6 +184,22 @@ defineExpose({
               </el-table-column>
             </el-table>
           </div>
+
+          <template #rightSide >
+            <el-table ref="objectOAMTableRef" v-loading="state.loading" class="list-table" :data="state.objectOAMList" border stripe highlight-current-row height="100%">
+              <el-table-column type="index" label="序号" header-align="center" align="center" width="70" />
+              <el-table-column prop="oamTitle" label="名称" header-align="center" align="center" minwidth="200" />
+              <el-table-column prop="oamType" label="类型" header-align="center" align="center" minwidth="150" />
+              <el-table-column prop="oamDesc" label="说明" header-align="center" align="left" />
+              <el-table-column label="操作" header-align="center" align="center" width="100">
+                <template #default="scope">
+                  <el-button type="primary" size="small" plain @click="onObjectOAMSel(scope.row)">
+                    选择
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </template>
         </LayoutContainer>
       </div>
     </div>

+ 1 - 1
src/views/paas/atu/index.vue

@@ -158,7 +158,7 @@ function goBack() {
 
             <el-table-column prop="objectTitle" label="对象" header-align="center" align="center" min-width="150px" />
 
-            <el-table-column prop="objectOamType" label="行为" header-align="center" align="center" />
+            <el-table-column prop="oamTitle" label="行为" header-align="center" align="center" />
 
             <el-table-column label="操作" width="140" align="center" fixed="right">
               <template #default="scope">