houyaf 3 năm trước cách đây
mục cha
commit
a27312ad96

+ 1 - 1
plop-templates/module/detail.hbs

@@ -1,5 +1,5 @@
 <script lang="ts" setup name="{{ properCase componentName }}">
-import DetailForm from './components/DetailForm/index.vue'
+import DetailForm from './components/DetailForm/Api.vue'
 import eventBus from '@/utils/eventBus'
 import useSettingsStore from '@/log/modules/settings'
 

+ 1 - 1
plop-templates/module/list.hbs

@@ -1,6 +1,6 @@
 <script lang="ts" setup name="{{ properCase componentName }}">
 import { ElMessage, ElMessageBox } from 'element-plus'
-import FormMode from './components/FormMode/index.vue'
+import FormMode from './components/FormMode/Api.vue'
 import eventBus from '@/utils/eventBus'
 import apiRequest from '@/apiRequest'
 import useSettingsStore from '@/log/modules/settings'

+ 1 - 1
plop-templates/module/mode.hbs

@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import DetailForm from '../DetailForm/index.vue'
+import DetailForm from '../DetailForm/Api.vue'
 
 const props = defineProps({
   ...DetailForm.props,

+ 4 - 4
src/api/paas/apiReqApi.ts

@@ -5,7 +5,7 @@ import apiRequest from '@/network/http/apiRequest'
  * @param data
  * @returns
  */
-export function getApiRequestByPage(data: any) {
+export function getApiReqByPage(data: any) {
   return apiRequest({
     url: '/paas/api/request/page',
     method: 'GET',
@@ -18,7 +18,7 @@ export function getApiRequestByPage(data: any) {
  * @param data
  * @returns
  */
-export function getApiRequestByList(data: any) {
+export function getApiReqByList(data: any) {
   return apiRequest({
     url: '/paas/api/request',
     method: 'GET',
@@ -31,7 +31,7 @@ export function getApiRequestByList(data: any) {
  * @param reqId
  * @returns
  */
-export function getApiRequestById(reqId: number) {
+export function getApiReqById(reqId: number) {
   return apiRequest({
     url: `/paas/api/request/${reqId}`,
     method: 'GET',
@@ -43,7 +43,7 @@ export function getApiRequestById(reqId: number) {
  * @param reqId
  * @returns
  */
-export function deleteApiRequestById(reqId: number) {
+export function deleteApiReqById(reqId: number) {
   return apiRequest({
     url: `/paas/api/request/${reqId}`,
     method: 'DELETE',

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

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

+ 6 - 6
src/router/modules/paas.ts

@@ -27,10 +27,10 @@ const routes: RouteRecordRaw[] = [
     ],
   },
   {
-    path: '/paas/log',
+    path: '/paas/req',
     component: Layout,
-    redirect: '/paas/log/index',
-    name: 'paas_log',
+    redirect: '/paas/req/index',
+    name: 'paas_req',
     meta: {
       title: '调用日志',
       icon: 'bx:bxs-component',
@@ -38,13 +38,13 @@ const routes: RouteRecordRaw[] = [
     children: [
       {
         path: 'index',
-        name: 'paas_log_index',
-        component: () => import('@/views/paas/log/index.vue'),
+        name: 'paas_req_index',
+        component: () => import('@/views/paas/req/index.vue'),
         meta: {
           title: '调用日志',
           sidebar: false,
           breadcrumb: false,
-          activeMenu: '/paas/log',
+          activeMenu: '/paas/req',
         },
       },
     ],

+ 17 - 24
src/views/paas/api/components/Api/index.vue → src/views/paas/api/components/Api.vue

@@ -1,23 +1,13 @@
 <route lang="yaml">
 meta:
   enabled: false
-    </route>
+</route>
 
 <script lang="ts" setup>
 import type { FormInstance, FormRules } from 'element-plus'
 import { createApi, getApiById, updateApi } from '@/api/paas/apiApi'
 const emit = defineEmits(['success'])
 
-const formRef = ref<FormInstance>()
-const formRules = ref<FormRules>({
-  apiTitle: [
-    { required: true, message: '请输入标题', trigger: 'blur' },
-  ],
-  apiDesc: [
-    { required: false, message: '请输入描述', trigger: 'blur' },
-  ],
-})
-
 const state = reactive({
   title: '',
   dialogVisible: false,
@@ -34,14 +24,24 @@ const state = reactive({
   actionType: 1,
 })
 
+const formRef = ref<FormInstance>()
+const formRules = ref<FormRules>({
+  apiTitle: [
+    { required: true, message: '请输入标题', trigger: 'blur' },
+  ],
+  apiDesc: [
+    { required: false, message: '请输入描述', trigger: 'blur' },
+  ],
+})
+
 const getData = async (modId: number, apiId: number) => {
   state.loading = true
   const { data } = await getApiById(modId, apiId)
-  state.loading = false
   state.formData = data
+  state.loading = false
 }
 
-function onSubmit() {
+const onSubmit = () => {
   formRef.value && formRef.value.validate(async (valid) => {
     if (valid) {
       if (state.actionType === 1) {
@@ -58,7 +58,7 @@ function onSubmit() {
   })
 }
 
-function onCancel() {
+const onCancel = () => {
   state.dialogVisible = false
 }
 
@@ -102,22 +102,15 @@ defineExpose({
           <el-form-item label="标题" prop="apiTitle">
             <el-input v-model="state.formData.apiTitle" placeholder="请输入标题" />
           </el-form-item>
+
           <el-form-item label="编码" prop="apiCode">
             <el-input v-model="state.formData.apiCode" placeholder="请输入编码" />
           </el-form-item>
+
           <el-form-item label="参数">
             <el-input v-model="state.formData.apiParams" placeholder="请输入参数" />
           </el-form-item>
-          <el-form-item label="状态" prop="apiTitle">
-            <el-switch
-              v-model="state.formData.status"
-              :active-value="0"
-              :inactive-value="1"
-              inline-prompt
-              active-text="启用"
-              inactive-text="禁用"
-            />
-          </el-form-item>
+
           <el-form-item label="简要说明" prop="apiDesc">
             <el-input v-model="state.formData.apiDesc" type="textarea" rows="10" placeholder="请输入标题" />
           </el-form-item>

+ 4 - 5
src/views/paas/api/components/Module/index.vue → src/views/paas/api/components/Module.vue

@@ -1,7 +1,7 @@
 <route lang="yaml">
 meta:
   enabled: false
-  </route>
+</route>
 
 <script lang="ts" setup>
 import type { FormInstance, FormRules } from 'element-plus'
@@ -36,11 +36,11 @@ onMounted(() => {})
 const getData = async (modId: number) => {
   state.loading = true
   const { data } = await getModuleById(modId)
-  state.loading = false
   state.formData = data
+  state.loading = false
 }
 
-function onSubmit() {
+const onSubmit = () => {
   formRef.value && formRef.value.validate(async (valid) => {
     if (valid) {
       if (state.actionType === 1) {
@@ -77,14 +77,13 @@ defineExpose({
     state.actionType = 1
     state.dialogVisible = true
   },
-  showEditModule(modId: any) {
+  showEditModule(modId: number) {
     resetFormData()
     state.title = '编辑API模块'
     state.actionType = 2
     state.dialogVisible = true
     getData(modId)
   },
-
 })
 </script>
 

+ 92 - 89
src/views/paas/api/index.vue

@@ -1,12 +1,12 @@
 <route lang="yaml">
 meta:
   enabled: false
-    </route>
+</route>
 
 <script lang="ts" setup>
 import { ElMessage, ElMessageBox } from 'element-plus'
-import PSModule from './components/Module/index.vue'
-import PSApi from './components/Api/index.vue'
+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'
 
@@ -17,20 +17,21 @@ interface TreeNode {
   children?: TreeNode[]
 }
 
-interface Object {
-  modId: number
-  objectId: number
-  objectTitle: string
-  objectCode: string
-  comment: string
+interface Api {
+  apiId: number
+  apiTitle: string
+  apiCode: string
+  apiDesc: string
+  apiParams: string
+  status: number
 }
 
 const state = reactive({
   loading: false,
   keywords: '',
-  Modules: [] as TreeNode[],
+  modules: [] as TreeNode[],
   curModuleId: 0,
-  objectList: [] as Object[],
+  apiList: [] as Api[],
   dialogState: 1,
   search: {
     keywords: '',
@@ -44,7 +45,7 @@ const getApiData = async () => {
   if (curModuleId > 0) {
     state.loading = true
     const { data } = await getApiByList({ modId: curModuleId })
-    state.objectList = data
+    state.apiList = data
     state.loading = false
   }
 }
@@ -59,7 +60,7 @@ const getModuleData = async () => {
       isLeaf: true,
     })
   })
-  state.Modules = [
+  state.modules = [
     {
       label: 'API模块列表',
       isLeaf: false,
@@ -76,18 +77,19 @@ const getModuleData = async () => {
     await getApiData()
   }
 }
-// 模新增
+// 模新增
 const onModuleAdd = () => {
   ModuleRef.value.showAddModule()
 }
 
-// 模型编辑
-const onModuleEdit = (data: { ModuleId: number }) => {
-  const ModuleId = data.ModuleId
-  ModuleRef.value.showEditModule(ModuleId)
+// 模块编辑
+const onModuleEdit = (data: { ModId: number }) => {
+  window.console.log(data)
+  const modId = data.ModId
+  ModuleRef.value.showEditModule(modId)
 }
 
-// 模删除
+// 模删除
 const onModuleDelete = (data: any) => {
   ElMessageBox.confirm(`确认删除「${data.modTitle}」吗?`, '确认信息').then(async () => {
     await deleteModuleById(data.modId)
@@ -99,7 +101,11 @@ const onModuleDelete = (data: any) => {
   })
 }
 
-// 模型选择
+onMounted(() => {
+  getModuleData()
+})
+
+// 模块选择
 const onTreeNodeClick = (node: TreeNode) => {
   if (node.isLeaf) {
     state.curModuleId = node.modId
@@ -107,7 +113,7 @@ const onTreeNodeClick = (node: TreeNode) => {
   }
 }
 
-const objectTableRef = ref()
+const apiTableRef = ref()
 const apiRef = ref()
 
 // 检索对象
@@ -146,10 +152,6 @@ async function onChangeStatus(row: { modId: number;apiId: number; status: number
     center: true,
   })
 }
-
-onMounted(() => {
-  getModuleData()
-})
 </script>
 
 <template>
@@ -171,7 +173,7 @@ onMounted(() => {
       <LayoutContainer left-side-width="300px" hide-left-side-toggle>
         <template #leftSide>
           <el-scrollbar class="tree">
-            <ElTree ref="leftTreeRef" :data="state.Modules" default-expand-all node-key="modId" @node-click="onTreeNodeClick">
+            <ElTree ref="leftTreeRef" :data="state.modules" default-expand-all node-key="modId" @node-click="onTreeNodeClick">
               <template #default="{ node, data }">
                 <div class="custom-tree-node">
                   <div class="label" :title="node.label">
@@ -229,22 +231,23 @@ onMounted(() => {
             </template>
           </tool-bar>
 
-          <el-table ref="objectTableRef" v-loading="state.loading" class="list-table" :data="state.objectList" border stripe highlight-current-row height="100%">
+          <el-table ref="apiTableRef" v-loading="state.loading" class="list-table" :data="state.apiList" border stripe highlight-current-row height="100%">
             <el-table-column type="index" label="序号" header-align="center" align="center" width="70" />
 
             <el-table-column prop="apiTitle" label="名称" header-align="center" align="center" width="200" />
 
             <el-table-column prop="apiCode" label="代码" header-align="center" align="center" width="150" />
             <el-table-column prop="status" label="status" header-align="center" align="center" width="150">
-              <template #default="{ row }">
+              <template #default="scope">
                 <el-switch
-                  v-model="row.status"
+                  v-model="scope.row.status"
                   :active-value="1"
                   :inactive-value="0"
+                  :loading="scope.row.loading"
                   inline-prompt
                   active-text="启用"
                   inactive-text="禁用"
-                  @change="(status) => onChangeStatus(row)"
+                  @change="(status) => onChangeStatus(scope.row)"
                 />
               </template>
             </el-table-column>
@@ -270,82 +273,82 @@ onMounted(() => {
   </div>
 </template>
 
-    <style lang="scss" scoped>
-    .container {
-      height: 100%;
+<style lang="scss" scoped>
+  .container {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .absolute-container {
+    :deep(.left-side) {
       display: flex;
       flex-direction: column;
-    }
+      height: 100%;
 
-    .absolute-container {
-      :deep(.left-side) {
-        display: flex;
-        flex-direction: column;
-        height: 100%;
+      .btns {
+        display: inline-flex;
+        width: 100%;
+        margin-bottom: var(--container-padding);
 
-        .btns {
-          display: inline-flex;
+        .add {
           width: 100%;
-          margin-bottom: var(--container-padding);
-
-          .add {
-            width: 100%;
-          }
         }
+      }
 
-        .tree {
-          flex: 1;
-          overflow-y: auto;
+      .tree {
+        flex: 1;
+        overflow-y: auto;
 
-          .el-tree {
-            .el-tree-node__content {
-              height: 40px;
-            }
+        .el-tree {
+          .el-tree-node__content {
+            height: 40px;
+          }
 
-            .is-current > .el-tree-node__content {
-              background-color: var(--el-color-primary-light-9);
-            }
+          .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;
-                }
+          .custom-tree-node {
+            flex: 1;
+            position: relative;
+            width: 0;
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+
+            .label {
+              display: inline-flex;
+              align-items: center;
+              width: calc(100% - 10px);
+              color: var(--el-text-color-primary);
+
+              .text {
+                @include text-overflow;
               }
+            }
 
-              &:hover {
-                .actions {
-                  display: block;
-                }
+            &:hover {
+              .actions {
+                display: block;
               }
+            }
 
-              .actions {
-                display: none;
-                position: absolute;
-                right: 10px;
-                top: 50%;
-                transform: translateY(-50%);
-
-                .el-button {
-                  padding: 5px 8px;
-                }
+            .actions {
+              display: none;
+              position: absolute;
+              right: 10px;
+              top: 50%;
+              transform: translateY(-50%);
+
+              .el-button {
+                padding: 5px 8px;
               }
             }
           }
         }
       }
     }
-    </style>
+  }
+</style>

+ 0 - 571
src/views/paas/log/components/DetailForm/index.vue

@@ -1,571 +0,0 @@
-<script lang="ts" setup>
-import Sortable from 'sortablejs'
-import type { FormInstance, FormRules } from 'element-plus'
-import { ElMessage } from 'element-plus'
-// import api from '@/api'
-
-const props = withDefaults(
-  defineProps<{
-    id?: string | number
-    parentId?: string | number
-  }>(),
-  {
-    id: '',
-    parentId: '',
-  },
-)
-
-const emits = defineEmits(['onSubmit'])
-
-const loading = ref(false)
-const formRef = ref<FormInstance>()
-const form = ref({
-  id: props.id,
-  parentId: props.parentId,
-  path: '',
-  redirect: '',
-  name: '',
-  component: '',
-  meta: {
-    title: '',
-    icon: '',
-    activeIcon: '',
-    defaultOpened: false,
-    permanent: false,
-    auth: [] as string[],
-    sidebar: true,
-    breadcrumb: true,
-    activeMenu: '',
-    cache: [] as string[] | boolean,
-    noCache: [] as string[],
-    badge: '',
-    link: '',
-    iframe: '',
-    copyright: false,
-    paddingBottom: '0px',
-  },
-  auths: [] as {
-    name: string
-    value: string
-  }[],
-})
-const formRules = ref<FormRules>({
-  'path': [
-    { required: true, message: '请输入路由地址', trigger: 'blur' },
-  ],
-  'meta.title': [
-    { required: true, message: '请输入显示名称', trigger: 'blur' },
-  ],
-})
-
-onMounted(() => {
-  if (form.value.id !== '') {
-    getInfo()
-  }
-})
-
-function getInfo() {
-  loading.value = true
-}
-
-// 鉴权标识
-const inputAuth = ref('')
-const inputAuthVisible = ref(false)
-const InputAuthRef = ref()
-const onInputAuthClose = (tag: string) => {
-  form.value.meta.auth.splice(form.value.meta.auth.indexOf(tag), 1)
-}
-
-const onInputAuthShow = () => {
-  inputAuthVisible.value = true
-  nextTick(() => {
-    InputAuthRef.value!.input!.focus()
-  })
-}
-
-const onInputAuthConfirm = () => {
-  if (inputAuth.value) {
-    if (!form.value.meta.auth.includes(inputAuth.value)) {
-      form.value.meta.auth.push(inputAuth.value)
-    }
-    else {
-      ElMessage.warning('标识已存在')
-    }
-  }
-  inputAuthVisible.value = false
-  inputAuth.value = ''
-}
-
-// 缓存规则
-const inputCache = ref('')
-const inputCacheVisible = ref(false)
-const InputCacheRef = ref()
-const onInputCacheClose = (tag: string) => {
-  typeof form.value.meta.cache === 'object' && form.value.meta.cache.splice(form.value.meta.cache.indexOf(tag), 1)
-}
-const onInputCacheShow = () => {
-  inputCacheVisible.value = true
-  nextTick(() => {
-    InputCacheRef.value!.input!.focus()
-  })
-}
-const onInputCacheConfirm = () => {
-  if (inputCache.value && typeof form.value.meta.cache === 'object') {
-    if (!form.value.meta.cache.includes(inputCache.value)) {
-      form.value.meta.cache.push(inputCache.value)
-    }
-    else {
-      ElMessage.warning('规则已存在')
-    }
-  }
-  inputCacheVisible.value = false
-  inputCache.value = ''
-}
-
-// 不缓存规则
-const inputNoCache = ref('')
-const inputNoCacheVisible = ref(false)
-const InputNoCacheRef = ref()
-const onInputNoCacheClose = (tag: string) => {
-  form.value.meta.noCache.splice(form.value.meta.noCache.indexOf(tag), 1)
-}
-const onInputNoCacheShow = () => {
-  inputNoCacheVisible.value = true
-  nextTick(() => {
-    InputNoCacheRef.value!.input!.focus()
-  })
-}
-const onInputNoCacheConfirm = () => {
-  if (inputNoCache.value) {
-    if (!form.value.meta.noCache.includes(inputNoCache.value)) {
-      form.value.meta.noCache.push(inputNoCache.value)
-    }
-    else {
-      ElMessage.warning('规则已存在')
-    }
-  }
-  inputNoCacheVisible.value = false
-  inputNoCache.value = ''
-}
-
-const authsTableRef = ref()
-const authsTableKey = ref(0)
-onMounted(() => {
-  onAuthDarg()
-})
-function onAuthAdd() {
-  form.value.auths.push({
-    name: '',
-    value: '',
-  })
-  nextTick(() => {
-    authsTableRef.value.setScrollTop(form.value.auths.length * 50)
-  })
-}
-function onAuthDelete(index: number) {
-  form.value.auths.splice(index, 1)
-}
-function onAuthDarg() {
-  const tbody = authsTableRef.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 = form.value.auths.splice(oldIndex, 1)[0]
-      form.value.auths.splice(newIndex, 0, currRow)
-      authsTableKey.value += 1
-      nextTick(() => onAuthDarg())
-    },
-  })
-}
-
-function onSubmit() {
-  if (form.value.id === '') {
-    formRef.value && formRef.value.validate((valid) => {
-      if (valid) { /* empty */ }
-    })
-  }
-  else {
-    formRef.value && formRef.value.validate((valid) => {
-      if (valid) { /* empty */ }
-    })
-  }
-}
-</script>
-
-<template>
-  <div v-loading="loading" class="form">
-    <div class="top-side">
-      <el-form ref="formRef" :model="form" :rules="formRules" label-position="top">
-        <div class="form-left-side">
-          <el-scrollbar>
-            <page-header v-if="!!form.parentId" title="基础配置" content="标准路由配置,包含 path/redirect/name/component" />
-            <el-row v-if="!!form.parentId" :gutter="30" style="padding: 20px;">
-              <el-col :xl="12" :lg="24">
-                <el-form-item label="路由地址" prop="path">
-                  <el-input v-model="form.path" clearable placeholder="请输入路由地址" />
-                </el-form-item>
-              </el-col>
-              <el-col :xl="12" :lg="24">
-                <el-form-item label="重定向" prop="redirect">
-                  <el-input v-model="form.redirect" clearable placeholder="请输入重定向地址" />
-                </el-form-item>
-              </el-col>
-              <el-col :xl="12" :lg="24">
-                <el-form-item prop="name">
-                  <template #label>
-                    路由命名
-                    <span class="label-tip">即 name ,系统唯一</span>
-                  </template>
-                  <el-input v-model="form.name" clearable placeholder="请输入路由命名" />
-                </el-form-item>
-              </el-col>
-              <el-col :xl="12" :lg="24">
-                <el-form-item prop="component">
-                  <template #label>
-                    组件路径
-                    <span class="label-tip">
-                      顶级路由请设置“<el-link type="primary" :underline="false" @click.prevent="form.component = 'Layout'">Layout</el-link>”,中间层级路由无需设置
-                    </span>
-                  </template>
-                  <el-input v-model="form.component" clearable placeholder="请输入完整组件路径">
-                    <template v-if="form.component !== 'Layout'" #prepend>
-                      /src/views/
-                    </template>
-                  </el-input>
-                </el-form-item>
-              </el-col>
-            </el-row>
-            <page-header title="扩展配置">
-              <template #content>
-                <div style="display: flex;">
-                  框架扩展配置,详细配置介绍请查看<el-link type="primary" href="https://hooray.gitee.io/fantastic-admin/guide/router.html#%E5%AF%BC%E8%88%AA%E9%85%8D%E7%BD%AE" target="_blank">
-                    框架文档
-                  </el-link>
-                </div>
-              </template>
-            </page-header>
-            <el-row :gutter="30" style="padding: 20px;">
-              <el-col :xl="12" :lg="24">
-                <el-form-item label="显示名称" prop="meta.title">
-                  <el-input v-model="form.meta.title" clearable placeholder="请输入显示名称" />
-                </el-form-item>
-              </el-col>
-              <el-col :xl="12" :lg="24">
-                <el-form-item prop="meta.auth">
-                  <template #label>
-                    鉴权标识
-                    <el-tooltip content="当设置多个标识时,只要命中其中一个则鉴权通过" placement="top">
-                      <el-icon>
-                        <svg-icon name="i-ri:question-line" />
-                      </el-icon>
-                    </el-tooltip>
-                  </template>
-                  <el-space>
-                    <el-tag v-for="item in (form.meta.auth as string[])" :key="item" size="large" closable :disable-transitions="false" @close="onInputAuthClose(item)">
-                      {{ item }}
-                    </el-tag>
-                    <el-input v-if="inputAuthVisible" ref="InputAuthRef" v-model="inputAuth" style="width: 200px;" @keyup.enter="onInputAuthConfirm" @blur="onInputAuthConfirm" />
-                    <el-button v-else @click="onInputAuthShow">
-                      新增
-                    </el-button>
-                  </el-space>
-                </el-form-item>
-              </el-col>
-              <el-col :xl="12" :lg="24">
-                <el-form-item label="默认图标" prop="meta.icon">
-                  <icon-picker v-model="form.meta.icon" />
-                </el-form-item>
-              </el-col>
-              <el-col :xl="12" :lg="24">
-                <el-form-item label="激活图标" prop="meta.activeIcon">
-                  <icon-picker v-model="form.meta.activeIcon" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item label="默认展开" prop="meta.defaultOpened">
-                  <el-switch v-model="form.meta.defaultOpened" inline-prompt active-text="是" inactive-text="否" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.permanent">
-                  <template #label>
-                    常驻标签页
-                    <span class="label-tip">请勿在带有参数的路由地址上开启该设置</span>
-                  </template>
-                  <el-switch v-model="form.meta.permanent" inline-prompt active-text="是" inactive-text="否" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item label="在导航显示" prop="meta.sidebar">
-                  <el-switch v-model="form.meta.sidebar" inline-prompt active-text="显示" inactive-text="隐藏" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item label="在面包屑显示" prop="meta.breadcrumb">
-                  <el-switch v-model="form.meta.breadcrumb" inline-prompt active-text="显示" inactive-text="隐藏" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.cache">
-                  <template #label>
-                    缓存规则
-                    <el-tooltip content="当跳转到设置的路由时,则会对当前路由进行缓存" placement="top">
-                      <el-icon>
-                        <svg-icon name="i-ri:question-line" />
-                      </el-icon>
-                    </el-tooltip>
-                    <span v-show="typeof form.meta.cache === 'object'" class="label-tip">切换为<el-link type="primary" :underline="false" @click.prevent="form.meta.cache = true">始终缓存</el-link></span>
-                    <span v-show="typeof form.meta.cache === 'boolean'" class="label-tip">切换为<el-link type="primary" :underline="false" @click.prevent="form.meta.cache = []">规则模式</el-link></span>
-                  </template>
-                  <el-space v-show="typeof form.meta.cache === 'object'">
-                    <el-tag v-for="item in (form.meta.cache as string[])" :key="item" size="large" closable :disable-transitions="false" @close="onInputCacheClose(item)">
-                      {{ item }}
-                    </el-tag>
-                    <el-input v-if="inputCacheVisible" ref="InputCacheRef" v-model="inputCache" style="width: 200px;" @keyup.enter="onInputCacheConfirm" @blur="onInputCacheConfirm" />
-                    <el-button v-else @click="onInputCacheShow">
-                      新增
-                    </el-button>
-                  </el-space>
-                  <div v-show="typeof form.meta.cache === 'boolean'">
-                    始终缓存
-                  </div>
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.noCache">
-                  <template #label>
-                    不缓存规则
-                    <el-tooltip content="当跳转到设置的路由时,则会对当前路由取消缓存" placement="top">
-                      <el-icon>
-                        <svg-icon name="i-ri:question-line" />
-                      </el-icon>
-                    </el-tooltip>
-                    <span class="label-tip">当缓存规则为“始终缓存”时生效</span>
-                  </template>
-                  <el-space>
-                    <el-tag v-for="item in (form.meta.noCache as string[])" :key="item" size="large" closable :disable-transitions="false" @close="onInputNoCacheClose(item)">
-                      {{ item }}
-                    </el-tag>
-                    <el-input v-if="inputNoCacheVisible" ref="InputNoCacheRef" v-model="inputNoCache" style="width: 200px;" @keyup.enter="onInputNoCacheConfirm" @blur="onInputNoCacheConfirm" />
-                    <el-button v-else @click="onInputNoCacheShow">
-                      新增
-                    </el-button>
-                  </el-space>
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.activeMenu">
-                  <template #label>
-                    高亮导航
-                    <span class="label-tip">如果子路由不在导航显示,则需要设置高亮的上级路由地址</span>
-                  </template>
-                  <el-input v-model="form.meta.activeMenu" clearable placeholder="请输入高亮导航的完整路由地址" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.badge">
-                  <template #label>
-                    徽标
-                    <span class="label-tip">不宜设置太长,建议控制在4个字符内</span>
-                  </template>
-                  <el-input v-model="form.meta.badge" clearable placeholder="请输入徽标显示内容" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.link">
-                  <template #label>
-                    访问外链
-                    <span class="label-tip">请设置 http/https 开头的完整外链地址</span>
-                  </template>
-                  <el-input v-model="form.meta.link" clearable placeholder="请输入网址" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.iframe">
-                  <template #label>
-                    内嵌网页
-                    <span class="label-tip">请勿与外链同时设置,同时设置时,本设置会失效</span>
-                  </template>
-                  <el-input v-model="form.meta.iframe" clearable placeholder="请输入网址" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item label="底部版权" prop="meta.copyright">
-                  <el-switch v-model="form.meta.copyright" inline-prompt active-text="显示" inactive-text="隐藏" />
-                </el-form-item>
-              </el-col>
-              <el-col v-if="!!form.parentId" :xl="12" :lg="24">
-                <el-form-item prop="meta.paddingBottom">
-                  <template #label>
-                    底部填充高度
-                    <span class="label-tip">请设置有效的长度单位,例如:px/em/rem等</span>
-                  </template>
-                  <el-input v-model="form.meta.paddingBottom" clearable placeholder="请输入显示名称" />
-                </el-form-item>
-              </el-col>
-            </el-row>
-          </el-scrollbar>
-        </div>
-        <div class="form-right-side">
-          <page-header title="权限池">
-            <template #content>
-              <p>设置导航所具备的所有权限,权限池内的权限会用于角色管理</p>
-              <p style="margin-bottom: 0;">
-                通常只在最子级导航上进行设置
-              </p>
-            </template>
-          </page-header>
-          <el-table ref="authsTableRef" :key="authsTableKey" :data="form.auths" border stripe highlight-current-row>
-            <el-table-column width="60" align="center" fixed>
-              <template #header>
-                <el-button type="primary" size="small" plain circle @click="onAuthAdd">
-                  <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="onAuthDelete(scope.$index)">
-                  <template #icon>
-                    <el-icon>
-                      <svg-icon name="i-ep:delete" />
-                    </el-icon>
-                  </template>
-                </el-button>
-              </template>
-            </el-table-column>
-            <el-table-column width="80" align="center" fixed>
-              <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-column label="名称">
-              <template #default="scope">
-                <el-input v-model="scope.row.name" />
-              </template>
-            </el-table-column>
-            <el-table-column label="标识">
-              <template #default="scope">
-                <el-input v-model="scope.row.value" />
-              </template>
-            </el-table-column>
-          </el-table>
-        </div>
-      </el-form>
-    </div>
-    <div class="bottom-side">
-      <el-button type="primary" @click="onSubmit">
-        提交
-      </el-button>
-    </div>
-  </div>
-</template>
-
-<style lang="scss" scoped>
-.form {
-  flex: 1;
-  position: relative;
-  width: 100%;
-  overflow: auto;
-  display: flex;
-  flex-direction: column;
-
-  .top-side {
-    flex: 1;
-    height: 0;
-    display: flex;
-
-    .el-form {
-      flex: 1;
-      display: flex;
-    }
-
-    .page-header {
-      background-color: var(--el-disabled-bg-color);
-      margin-bottom: 0;
-    }
-
-    .form-left-side {
-      flex: 1;
-      padding: var(--container-padding);
-      background-color: var(--g-app-bg);
-      transition: background-color 0.3s;
-      overflow: auto;
-
-      .label-tip {
-        display: inline-flex;
-        margin-left: 10px;
-        color: var(--el-text-color-disabled);
-      }
-
-      :deep(.el-scrollbar__view) {
-        overflow-x: hidden;
-      }
-    }
-
-    .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;
-          }
-        }
-      }
-    }
-  }
-
-  .bottom-side {
-    padding: var(--container-padding);
-    border-top: 1px dashed var(--el-disabled-border-color);
-    background-color: var(--g-app-bg);
-    transition: background-color 0.3s;
-    display: flex;
-    justify-content: center;
-  }
-}
-</style>

+ 0 - 121
src/views/paas/log/index.vue

@@ -1,121 +0,0 @@
-<script lang="ts" setup>
-import { ElMessage, ElMessageBox } from 'element-plus'
-import { deleteApiRequestById, getApiRequestByPage } from '@/api/paas/apiReqApi'
-const { pagination, getParams, onSizeChange, onCurrentChange } = usePagination()
-
-interface TreeNode {
-  label: string
-  groupId: number
-  children?: TreeNode[]
-}
-const state = reactive({
-  loading: false,
-  curGroupId: 0,
-  menu: [] as TreeNode[],
-  userList: [],
-  search: {
-    keywords: '',
-  },
-})
-
-// 查询日志列表
-const getLogData = async () => {
-  const params = getParams()
-  params.keywords = state.search.keywords
-  state.loading = true
-  const { data } = await getApiRequestByPage(params)
-  state.loading = false
-  state.userList = data
-  state.loading = false
-}
-// 每页数量切换
-function sizeChange(size: number) {
-  onSizeChange(size).then(() => getLogData())
-}
-
-// 当前页码切换(翻页)
-function currentChange(page = 1) {
-  onCurrentChange(page).then(() => getLogData())
-}
-// 查询
-const onSearch = () => {
-  getLogData()
-}
-
-// 删除日志
-const onLogDelete = async (data: { logTitle: any; logId: number }) => {
-  ElMessageBox.confirm(`确认删除「${data.logTitle}」吗?`, '确认信息').then(async () => {
-    await deleteApiRequestById(data.logId)
-    await getLogData()
-    ElMessage.success({
-      message: '删除成功',
-      center: true,
-    })
-  })
-}
-
-onMounted(() => {
-  getLogData()
-})
-</script>
-
-<template>
-  <div class="absolute-container">
-    <page-header title="日志管理" content="日志调用管理" />
-    <div class="page-main">
-      <LayoutContainer left-side-width="300px" hide-left-side-toggle>
-        <template #leftSide>
-          <el-scrollbar class="tree">
-            <ElTree ref="menuRef" :data="state.menu" default-expand-all>
-              <template #default="{ data }">
-                <div class="custom-tree-node">
-                  <div class="label" :title="data.meta.title">
-                    <el-icon v-if="data.meta.icon" size="16px" style="margin-right: 5px;">
-                      <svg-icon :name="data.meta.icon" />
-                    </el-icon>
-                    <div class="text">
-                      {{ data.meta.title }}
-                    </div>
-                  </div>
-                </div>
-              </template>
-            </ElTree>
-          </el-scrollbar>
-        </template>
-        <div class="container">
-          <tool-bar>
-            <template #right>
-              <el-input v-model="state.search.keywords" placeholder="请输入名称,支持模糊查询" style="padding-right: 10px;" clearable />
-              <el-button type="primary" @click="onSearch">
-                <template #icon>
-                  <el-icon>
-                    <svg-icon name="i-ep:search" />
-                  </el-icon>
-                </template>
-              </el-button>
-            </template>
-          </tool-bar>
-
-          <el-table ref="accountTableRef" v-loading="state.loading" class="list-table" :data="state.userList" border stripe highlight-current-row>
-            <el-table-column type="index" align="center" label="序号" width="60" />
-            <el-table-column align="center" width="100" label="接口名称" prop="ip" />
-            <el-table-column align="center" label="调用者IP" prop="ip" />
-            <el-table-column align="center" label="创建时间" prop="createTime" />
-            <el-table-column align="center" label="调用次数" prop="time" />
-            <el-table-column label="操作" header-align="center" align="center" width="220">
-              <template #default="scope">
-                <el-button v-if="scope.row.isFixed !== 1" size="small" type="danger" @click="onLogDelete(scope.row)">
-                  删除
-                </el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-          <el-pagination :current-page="pagination.page" :total="pagination.total" :page-size="pagination.size" :page-sizes="pagination.sizes" :layout="pagination.layout" :hide-on-single-page="false" class="pagination" background @current-change="currentChange" @size-change="sizeChange" />
-        </div>
-      </LayoutContainer>
-    </div>
-  </div>
-</template>
-
-<style lang="scss" scoped>
-</style>

+ 247 - 0
src/views/paas/req/index.vue

@@ -0,0 +1,247 @@
+<script lang="ts" setup>
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { deleteApiReqById, getApiReqByPage } from '@/api/paas/apiReqApi'
+import { getModuleByList } from '@/api/paas/moduleApi'
+const { pagination, getParams, onSizeChange, onCurrentChange } = usePagination()
+
+interface TreeNode {
+  label: string
+  isLeaf: boolean
+  modId: number
+  children?: TreeNode[]
+}
+
+const state = reactive({
+  loading: false,
+  curModuleId: 0,
+  modules: [] as TreeNode[],
+  reqList: [],
+  search: {
+    keywords: '',
+  },
+})
+
+const leftTreeRef = ref()
+const ModuleRef = ref()
+
+// 查询日志列表
+const getReqData = async () => {
+  const params = getParams()
+  params.modId = state.curModuleId
+  params.keywords = state.search.keywords
+  state.loading = true
+  const { data } = await getApiReqByPage(params)
+  state.reqList = data.data
+  state.loading = false
+}
+
+const getModuleData = async () => {
+  const { data } = await getModuleByList('')
+  const children: TreeNode[] = []
+  data.forEach((item: any) => {
+    return children.push({
+      label: item.modTitle,
+      modId: item.modId,
+      isLeaf: true,
+    })
+  })
+  state.modules = [
+    {
+      label: 'API模块列表',
+      isLeaf: false,
+      modId: -1,
+      children,
+    },
+  ]
+
+  if (data && data.length > 0) {
+    state.curModuleId = data[0].modId
+    nextTick(() => {
+      leftTreeRef.value.setCurrentKey(data[0].modId)
+    })
+    await getReqData()
+  }
+}
+
+// 每页数量切换
+function sizeChange(size: number) {
+  onSizeChange(size).then(() => getReqData())
+}
+
+// 当前页码切换(翻页)
+function currentChange(page = 1) {
+  onCurrentChange(page).then(() => getReqData())
+}
+// 查询
+const onSearch = () => {
+  getReqData()
+}
+
+onMounted(() => {
+  getModuleData()
+})
+
+// 模块选择
+const onTreeNodeClick = (node: TreeNode) => {
+  if (node.isLeaf) {
+    state.curModuleId = node.modId
+    getReqData()
+  }
+}
+
+// 删除日志
+const onReqDel = async (data: { apiTitle: any; reqId: number }) => {
+  ElMessageBox.confirm('确认删除吗?', '确认信息').then(async () => {
+    await deleteApiReqById(data.reqId)
+    await getReqData()
+    ElMessage.success({
+      message: '删除成功',
+      center: true,
+    })
+  })
+}
+</script>
+
+<template>
+  <div class="absolute-container">
+    <page-header title="日志管理" content="日志调用管理" />
+    <div class="page-main">
+      <LayoutContainer left-side-width="300px" hide-left-side-toggle>
+        <template #leftSide>
+          <el-scrollbar class="tree">
+            <ElTree ref="leftTreeRef" :data="state.modules" default-expand-all node-key="modId" @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">
+                  </div>
+                </div>
+              </template>
+            </ElTree>
+          </el-scrollbar>
+        </template>
+
+        <div class="container">
+          <tool-bar>
+            <template #right>
+              <el-input v-model="state.search.keywords" placeholder="请输入名称,支持模糊查询" style="padding-right: 10px;" clearable />
+              <el-button type="primary" @click="onSearch">
+                <template #icon>
+                  <el-icon>
+                    <svg-icon name="i-ep:search" />
+                  </el-icon>
+                </template>
+              </el-button>
+            </template>
+          </tool-bar>
+
+          <el-table ref="apiReqTableRef" v-loading="state.loading" class="list-table" :data="state.reqList" border stripe highlight-current-row>
+            <el-table-column type="index" align="center" label="序号" width="60" />
+
+            <el-table-column align="center" width="100" label="接口名称" prop="apiTitle" />
+
+            <el-table-column align="center" label="调用者IP" prop="appTitle" />
+
+            <el-table-column align="center" label="创建时间" prop="reqTime" />
+
+            <el-table-column label="操作" header-align="center" align="center" width="220">
+              <template #default="scope">
+                <el-button v-if="scope.row.isFixed !== 1" size="small" type="danger" @click="onReqDel(scope.row)">
+                  删除
+                </el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <el-pagination :current-page="pagination.page" :total="pagination.total" :page-size="pagination.size" :page-sizes="pagination.sizes" :layout="pagination.layout" :hide-on-single-page="false" class="pagination" background @current-change="currentChange" @size-change="sizeChange" />
+        </div>
+      </LayoutContainer>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+
+.absolute-container {
+  :deep(.left-side) {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+
+    .btns {
+      display: inline-flex;
+      width: 100%;
+      margin-bottom: var(--container-padding);
+
+      .add {
+        width: 100%;
+      }
+    }
+
+    .tree {
+      flex: 1;
+      overflow-y: auto;
+
+      .el-tree {
+        .el-tree-node__content {
+          height: 40px;
+        }
+
+        .is-current > .el-tree-node__content {
+          background-color: var(--el-color-primary-light-9);
+        }
+
+        .custom-tree-node {
+          flex: 1;
+          position: relative;
+          width: 0;
+          height: 100%;
+          display: flex;
+          flex-direction: column;
+          justify-content: center;
+
+          .label {
+            display: inline-flex;
+            align-items: center;
+            width: calc(100% - 10px);
+            color: var(--el-text-color-primary);
+
+            .text {
+              @include text-overflow;
+            }
+          }
+
+          &:hover {
+            .actions {
+              display: block;
+            }
+          }
+
+          .actions {
+            display: none;
+            position: absolute;
+            right: 10px;
+            top: 50%;
+            transform: translateY(-50%);
+
+            .el-button {
+              padding: 5px 8px;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>