瀏覽代碼

新增接口同步功能
优化确认框延时关闭,避免多次点击确定的问题

zhontai 2 年之前
父節點
當前提交
5100b85a0b

+ 50 - 0
src/api/admin/Api.extend.ts

@@ -0,0 +1,50 @@
+/* eslint-disable */
+/* tslint:disable */
+/*
+ * ---------------------------------------------------------------
+ * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
+ * ##                                                           ##
+ * ## AUTHOR: acacode                                           ##
+ * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
+ * ---------------------------------------------------------------
+ */
+
+import { AxiosResponse } from 'axios'
+import { HttpClient, RequestParams } from './http-client'
+
+export class Api<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
+  /**
+   * No description
+   *
+   * @tags api
+   * @name GetList
+   * @summary 获得swagger resources
+   * @request GET:/swagger-resources
+   * @secure
+   */
+  getSwaggerResources = (params: RequestParams = {}) =>
+    this.request<AxiosResponse, any>({
+      path: `/swagger-resources`,
+      method: 'GET',
+      secure: true,
+      format: 'json',
+      ...params,
+    })
+  /**
+   * No description
+   *
+   * @tags api
+   * @name GetList
+   * @summary 获得swagger json
+   * @request GET:/swagger-resources
+   * @secure
+   */
+  getSwaggerJson = (path: string, params: RequestParams = {}) =>
+    this.request<AxiosResponse, any>({
+      path: path,
+      method: 'GET',
+      secure: true,
+      format: 'json',
+      ...params,
+    })
+}

+ 35 - 0
src/api/admin/File.ts

@@ -0,0 +1,35 @@
+/* eslint-disable */
+/* tslint:disable */
+/*
+ * ---------------------------------------------------------------
+ * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
+ * ##                                                           ##
+ * ## AUTHOR: acacode                                           ##
+ * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
+ * ---------------------------------------------------------------
+ */
+
+import { PageInputFileGetPageDto, ResultOutputPageOutputFileGetPageOutput } from './data-contracts'
+import { ContentType, HttpClient, RequestParams } from './http-client'
+
+export class File<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
+  /**
+   * No description
+   *
+   * @tags file
+   * @name GetPage
+   * @summary 查询文件列表
+   * @request POST:/api/admin/file/get-page
+   * @secure
+   */
+  getPage = (data: PageInputFileGetPageDto, params: RequestParams = {}) =>
+    this.request<ResultOutputPageOutputFileGetPageOutput, any>({
+      path: `/api/admin/file/get-page`,
+      method: 'POST',
+      body: data,
+      secure: true,
+      type: ContentType.Json,
+      format: 'json',
+      ...params,
+    })
+}

+ 76 - 6
src/api/admin/data-contracts.ts

@@ -666,6 +666,31 @@ export type DynamicFilterLogic = 0 | 1
  */
 export type DynamicFilterOperator = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18
 
+export interface FileGetPageDto {
+  /** 文件名 */
+  fileName?: string | null
+}
+
+export interface FileGetPageOutput {
+  /** Invalid=0,Minio=1,Aliyun=2,QCloud=3,Qiniu=4,HuaweiCloud=5 */
+  provider?: OSSProvider
+  /** 存储桶名称 */
+  bucketName?: string | null
+  /**
+   * 文件Guid
+   * @format uuid
+   */
+  fileGuid?: string
+  /** 文件名 */
+  fileName?: string | null
+  /** 文件扩展名 */
+  extension?: string | null
+  /** 文件大小格式化 */
+  sizeFormat?: string | null
+  /** 链接地址 */
+  linkUrl?: string | null
+}
+
 export interface LogGetPageDto {
   /** 创建者 */
   createdUserName?: string | null
@@ -744,6 +769,12 @@ export interface LoginLogListOutput {
   createdTime?: string | null
 }
 
+/**
+ * Invalid=0,Minio=1,Aliyun=2,QCloud=3,Qiniu=4,HuaweiCloud=5
+ * @format int32
+ */
+export type OSSProvider = 0 | 1 | 2 | 3 | 4 | 5
+
 /** 添加 */
 export interface OprationLogAddInput {
   /** 姓名 */
@@ -1060,6 +1091,22 @@ export interface PageInputDictionaryTypeGetPageDto {
   filter?: DictionaryTypeGetPageDto
 }
 
+/** 分页信息输入 */
+export interface PageInputFileGetPageDto {
+  /**
+   * 当前页标
+   * @format int32
+   */
+  currentPage?: number
+  /**
+   * 每页大小
+   * @format int32
+   */
+  pageSize?: number
+  dynamicFilter?: DynamicFilterInfo
+  filter?: FileGetPageDto
+}
+
 /** 分页信息输入 */
 export interface PageInputLogGetPageDto {
   /**
@@ -1190,6 +1237,17 @@ export interface PageOutputDictionaryTypeListOutput {
   list?: DictionaryTypeListOutput[] | null
 }
 
+/** 分页信息输出 */
+export interface PageOutputFileGetPageOutput {
+  /**
+   * 数据总数
+   * @format int64
+   */
+  total?: number
+  /** 数据 */
+  list?: FileGetPageOutput[] | null
+}
+
 /** 分页信息输出 */
 export interface PageOutputLoginLogListOutput {
   /**
@@ -2174,6 +2232,18 @@ export interface ResultOutputPageOutputDictionaryTypeListOutput {
   data?: PageOutputDictionaryTypeListOutput
 }
 
+/** 结果输出 */
+export interface ResultOutputPageOutputFileGetPageOutput {
+  /** 是否成功标记 */
+  success?: boolean
+  /** 编码 */
+  code?: string | null
+  /** 消息 */
+  msg?: string | null
+  /** 分页信息输出 */
+  data?: PageOutputFileGetPageOutput
+}
+
 /** 结果输出 */
 export interface ResultOutputPageOutputLoginLogListOutput {
   /** 是否成功标记 */
@@ -2391,7 +2461,7 @@ export interface RoleAddInput {
   name?: string | null
   /** 编码 */
   code?: string | null
-  /** 角色类型:Group=1,Menu=2 */
+  /** 角色类型:Group=1,Role=2 */
   type?: RoleType
   /** 数据范围:All=1,DeptWithChild=2,Dept=3,Self=4,Custom=5 */
   dataScope?: DataScope
@@ -2474,7 +2544,7 @@ export interface RoleEntity {
   name?: string | null
   /** 编码 */
   code?: string | null
-  /** 角色类型:Group=1,Menu=2 */
+  /** 角色类型:Group=1,Role=2 */
   type?: RoleType
   /** 数据范围:All=1,DeptWithChild=2,Dept=3,Self=4,Custom=5 */
   dataScope?: DataScope
@@ -2510,7 +2580,7 @@ export interface RoleGetListOutput {
   name?: string | null
   /** 编码 */
   code?: string | null
-  /** 角色类型:Group=1,Menu=2 */
+  /** 角色类型:Group=1,Role=2 */
   type?: RoleType
   /**
    * 排序
@@ -2531,7 +2601,7 @@ export interface RoleGetOutput {
   name?: string | null
   /** 编码 */
   code?: string | null
-  /** 角色类型:Group=1,Menu=2 */
+  /** 角色类型:Group=1,Role=2 */
   type?: RoleType
   /** 数据范围:All=1,DeptWithChild=2,Dept=3,Self=4,Custom=5 */
   dataScope?: DataScope
@@ -2593,7 +2663,7 @@ export interface RoleSetDataScopeInput {
 }
 
 /**
- * 角色类型:Group=1,Menu=2
+ * 角色类型:Group=1,Role=2
  * @format int32
  */
 export type RoleType = 1 | 2
@@ -2609,7 +2679,7 @@ export interface RoleUpdateInput {
   name?: string | null
   /** 编码 */
   code?: string | null
-  /** 角色类型:Group=1,Menu=2 */
+  /** 角色类型:Group=1,Role=2 */
   type?: RoleType
   /** 数据范围:All=1,DeptWithChild=2,Dept=3,Self=4,Custom=5 */
   dataScope?: DataScope

+ 70 - 2
src/views/admin/api/index.vue

@@ -10,6 +10,11 @@
             <el-form-item>
               <el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
               <el-button v-auth="'api:admin:api:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
+              <el-popconfirm title="确定要同步接口" hide-icon width="180" hide-after="0" @confirm="onSync">
+                <template #reference>
+                  <el-button v-auth="'api:admin:api:sync'" :loading="state.syncLoading" type="primary" icon="ele-Refresh"> 同步 </el-button>
+                </template>
+              </el-popconfirm>
             </el-form-item>
           </el-form>
         </el-card>
@@ -52,8 +57,9 @@
 import { ref, reactive, onMounted, getCurrentInstance, onUnmounted, defineAsyncComponent } from 'vue'
 import { ApiListOutput } from '/@/api/admin/data-contracts'
 import { Api as ApiApi } from '/@/api/admin/Api'
+import { Api as ApiExtApi } from '/@/api/admin/Api.extend'
 import { listToTree } from '/@/utils/tree'
-import { cloneDeep } from 'lodash-es'
+import { cloneDeep, isArray } from 'lodash-es'
 import eventBus from '/@/utils/mitt'
 
 // 引入组件
@@ -65,6 +71,7 @@ const apiFormRef = ref()
 
 const state = reactive({
   loading: false,
+  syncLoading: false,
   apiFormTitle: '',
   filterModel: {
     name: '',
@@ -109,13 +116,74 @@ const onEdit = (row: ApiListOutput) => {
 
 const onDelete = (row: ApiListOutput) => {
   proxy.$modal
-    .confirmDelete(`确定要删除接口【${row.label}】?`)
+    .confirmDelete(`确定要删除接口【${row.label}】?`, { type: 'info' })
     .then(async () => {
       await new ApiApi().delete({ id: row.id }, { loading: true })
       onQuery()
     })
     .catch(() => {})
 }
+
+const syncApi = async (url: string) => {
+  const res = await new ApiExtApi().getSwaggerJson(url, { showErrorMessage: false })
+  if (!res) {
+    return
+  }
+
+  const tags = res.tags
+  const paths = res.paths
+
+  const apis = []
+  // tags
+  if (tags && tags.length > 0) {
+    tags.forEach((t: any) => {
+      apis[apis.length] = {
+        label: t.description,
+        path: t.name,
+      }
+    })
+  }
+  // paths
+  if (paths) {
+    for (const [key, value] of Object.entries(paths)) {
+      const keys = Object.keys(value as any)
+      const values = Object.values(value as any)
+      const v = values && values.length > 0 ? values[0] : ({} as any)
+      const parentPath = v.tags && v.tags.length > 0 ? v.tags[0] : ''
+      apis[apis.length] = {
+        label: v.summary,
+        path: key,
+        parentPath,
+        httpMethods: keys.join(','),
+      }
+    }
+  }
+
+  return await new ApiApi().sync({ apis })
+}
+
+const onSync = async () => {
+  state.syncLoading = true
+  const resSwaggerResources = await new ApiExtApi().getSwaggerResources({ showErrorMessage: false }).catch(() => {
+    state.syncLoading = false
+  })
+  if (isArray(resSwaggerResources) && (resSwaggerResources?.length as number) > 0) {
+    for (let index = 0, len = resSwaggerResources.length, last = len - 1; index < len; index++) {
+      const swaggerResource = resSwaggerResources[index]
+      const resSyncApi = await syncApi(swaggerResource.url)
+      if (index === last) {
+        state.syncLoading = false
+        if (resSyncApi?.success) {
+          proxy.$modal.msgSuccess('同步成功')
+        } else {
+          proxy.$modal.msgError('同步失败')
+        }
+      }
+    }
+  } else {
+    state.syncLoading = false
+  }
+}
 </script>
 
 <script lang="ts">

+ 98 - 0
src/views/admin/file/index.vue

@@ -0,0 +1,98 @@
+<template>
+  <div style="padding: 0px 0px 8px 8px">
+    <el-card shadow="never" :body-style="{ paddingBottom: '0' }" style="margin-top: 8px">
+      <el-form :model="state.filterModel" :inline="true">
+        <el-form-item prop="name">
+          <el-input v-model="state.filterModel.fileName" placeholder="文件名" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <el-card shadow="never" style="margin-top: 8px">
+      <el-table v-loading="state.loading" :data="state.fileListData" row-key="id" style="width: 100%">
+        <el-table-column prop="fileName" label="文件名" min-width="120" show-overflow-tooltip />
+        <el-table-column prop="createdTime" label="更新时间" :formatter="formatterTime" width="120" />
+        <el-table-column label="操作" width="180" fixed="right" header-align="center" align="center">
+          <!-- <template #default="{ row }">
+            
+          </template> -->
+        </el-table-column>
+      </el-table>
+      <div class="my-flex my-flex-end" style="margin-top: 20px">
+        <el-pagination
+          v-model:currentPage="state.pageInput.currentPage"
+          v-model:page-size="state.pageInput.pageSize"
+          :total="state.total"
+          :page-sizes="[10, 20, 50, 100]"
+          small
+          background
+          @size-change="onSizeChange"
+          @current-change="onCurrentChange"
+          layout="total, sizes, prev, pager, next, jumper"
+        />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { reactive, onMounted } from 'vue'
+import { PageInputFileGetPageDto, FileGetPageOutput } from '/@/api/admin/data-contracts'
+import { File as FileApi } from '/@/api/admin/File'
+import dayjs from 'dayjs'
+
+const state = reactive({
+  loading: false,
+  fileFormTitle: '',
+  filterModel: {
+    fileName: '',
+  },
+  total: 0,
+  pageInput: {
+    currentPage: 1,
+    pageSize: 20,
+  } as PageInputFileGetPageDto,
+  fileListData: [] as Array<FileGetPageOutput>,
+  fileLogsTitle: '',
+})
+
+onMounted(() => {
+  onQuery()
+})
+
+const formatterTime = (row: any, column: any, cellValue: any) => {
+  return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
+}
+
+const onQuery = async () => {
+  state.loading = true
+  const res = await new FileApi().getPage({ ...state.pageInput, filter: state.filterModel })
+
+  state.fileListData = res?.data?.list ?? []
+  state.total = res.data?.total ?? 0
+  state.loading = false
+}
+
+const onSizeChange = (val: number) => {
+  state.pageInput.pageSize = val
+  onQuery()
+}
+
+const onCurrentChange = (val: number) => {
+  state.pageInput.currentPage = val
+  onQuery()
+}
+</script>
+
+<script lang="ts">
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+  name: 'admin/file',
+})
+</script>
+
+<style scoped lang="scss"></style>

+ 1 - 1
src/views/admin/personal/index.vue

@@ -79,7 +79,7 @@
               </el-col>
               <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
                 <el-form-item>
-                  <el-popconfirm title="确定要更新个人信息吗?" hide-icon width="180" @confirm="onUpdateBasic">
+                  <el-popconfirm title="确定要更新个人信息吗?" hide-icon hide-after="0" width="180" @confirm="onUpdateBasic">
                     <template #reference>
                       <el-button :loading="state.updateLoading" type="primary">
                         <el-icon>

+ 3 - 1
src/views/admin/task/index.vue

@@ -32,7 +32,9 @@
         <el-table-column prop="lastRunTime" label="最后运行时间" :formatter="formatterTime" width="120" />
         <el-table-column label="操作" width="180" fixed="right" header-align="center" align="center">
           <template #default="{ row }">
-            <el-button v-auth="" icon="ele-Tickets" size="small" text type="primary" @click="onShowLogs(row)">日志</el-button>
+            <el-button v-auth="'api:admin:task-log:get-page'" icon="ele-Tickets" size="small" text type="primary" @click="onShowLogs(row)"
+              >日志</el-button
+            >
             <el-button
               v-if="row.status === 1 || row.status === 'Paused'"
               v-auth="'api:admin:task:pause'"