Sfoglia il codice sorgente

feat: api服务中心

lvkun996 2 anni fa
parent
commit
4064abc1bc

File diff suppressed because it is too large
+ 1 - 15451
package-lock.json


+ 2 - 1
package.json

@@ -60,7 +60,8 @@
     "less": "^4.0.0",
     "less-loader": "^8.0.0",
     "lint-staged": "^11.1.2",
-    "typescript": "~4.5.5"
+    "typescript": "~4.5.5",
+    "webpack-bundle-analyzer": "^4.9.0"
   },
   "eslintConfig": {
     "root": true,

+ 4 - 3
plugins/build.js

@@ -14,7 +14,7 @@ const r = file.replace(
   'const _routes = [iot, rts, schedule, view, lowcode, user, login]',
   `const _routes = [${args.map((arg, index) => index > 0 ? ` ${arg}` : arg)}]`
 )
-console.log(r)
+
 console.log('修改路由值成功 🌹')
 
 fs.writeFileSync(resolve(rootPath, 'src/router/index.ts'), r, 'utf-8')
@@ -25,7 +25,8 @@ exec('npm run build', (error, stdout, stderr) => {
   if (error) {
     console.error(`执行脚本时出错:${error}`)
     fs.writeFileSync(resolve(rootPath, 'src/router/index.ts'), file, 'utf-8')
+  } else {
+    console.log('打包成功 🎉')
+    fs.writeFileSync(resolve(rootPath, 'src/router/index.ts'), file, 'utf-8')
   }
-  console.log('打包成功 🎉')
-  fs.writeFileSync(resolve(rootPath, 'src/router/index.ts'), file, 'utf-8')
 })

+ 304 - 0
src/api/schedule/apiCenter.ts

@@ -0,0 +1,304 @@
+import request from '@/service/request'
+
+/**
+ * API列表分页查询
+ * */
+export function getApiTableList (params) {
+  return request({
+    url: '/apiCenter/page',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * API列表编辑弹框修改
+ */
+export async function updateApiTableItem (data) {
+  return request({
+    url: '/apiCenter',
+    method: 'PUT',
+    data
+  })
+}
+
+/**
+ * 根据serviceId获取详情
+ * 用appId获取
+ */
+export async function getDetailById (data) {
+  return request({
+    url: `/apiCenter?id=${data.id}&serviceId=${data.serviceId}${data.vid ? ('&vId=' + data.vid) : ''}`,
+    method: 'GET'
+  })
+}
+
+/**
+ * 根据id删除api
+ */
+export function delDataById (id: string) {
+  return request({
+    url: `/apiCenter/${id}`,
+    method: 'DELETE'
+  })
+}
+
+/**
+ * API新增
+ */
+export function addApi (data) {
+  return request({
+    url: '/apiCenter',
+    method: 'POST',
+    data
+  })
+}
+
+/**
+ * 根据serviceId获取api使用情况
+ */
+export function usagListById (apiId) {
+  return request({
+    url: `/apiCenter/usage?apiId=${apiId}`,
+    method: 'GET'
+  })
+}
+
+/**
+ * 根据serviceId获取api使用情况
+ */
+export function copyApiById (params) {
+  return request({
+    url: '/apiCenter/copy',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 根据serviceId获取api使用情况
+ */
+export function saveReqAndRsp (data) {
+  return request({
+    url: '/apiCenter/saveReqAndRsp',
+    method: 'POST',
+    data
+  })
+}
+
+/**
+ * 服务编排批量删除
+ */
+export function delApiCenterBatch (data) {
+  return request({
+    url: '/apiCenter/batchDelete',
+    method: 'POST',
+    data
+  })
+}
+
+/**
+ * API分组列表
+ */
+export function treeGroupList () {
+  return request({
+    url: '/apiCenterGroup/tree',
+    method: 'GET'
+  })
+}
+
+/**
+ * API分组节点详情
+ */
+export function treeGroupNodeInfo (id: string) {
+  return request({
+    url: `/apiCenterGroup/${id}`,
+    method: 'GET'
+  })
+}
+
+/**
+ * API分组添加
+ */
+export function addGroupTree (data) {
+  return request({
+    url: '/apiCenterGroup',
+    method: 'POST',
+    data
+  })
+}
+
+/**
+ * API分组删除
+ */
+export function delTree (id: string) {
+  return request({
+    url: `/apiCenterGroup/${id}`,
+    method: 'DELETE'
+  })
+}
+
+/**
+ * API分组修改
+ */
+export function editorTree (data) {
+  return request({
+    url: '/apiCenterGroup',
+    method: 'PUT',
+    data
+  })
+}
+
+/**
+ * 根据服务ID查询对应版本
+ */
+export function apiCenterRevision (serviceId: string) {
+  return request({
+    url: `/apiCenterRevision?serviceId=${serviceId}`,
+    method: 'GET'
+  })
+}
+
+/**
+ * 版本管理 新增版本
+ * @apiId  API主键 必须
+ * @snapshot 快照号 必须
+ * @version 版本号 必须
+ * @remark 版本说明 非必须
+ */
+export function apiVersion (data) {
+  return request({
+    url: 'apiVersion',
+    method: 'GET',
+    data
+  })
+}
+
+/**
+ * 版本管理分页查询
+ * @apiId API主键
+ * @pageNum 当前页
+ * @pageSize 页数大小
+ * @remark 版本描述
+ */
+export function apiVersionPage (params) {
+  return request({
+    url: '/apiVersion/page',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 启用版本
+ * @id api 版本主键
+ */
+export function enableVersion (id: string) {
+  return request({
+    url: `/apiVersion/enable/${id}`,
+    method: 'PUT'
+  })
+}
+
+/**
+ * 停用版本
+ * @id api 版本主键
+ */
+export function disableVersion (id: string) {
+  return request({
+    url: `/apiVersion/disable/${id}`,
+    method: 'PUT'
+  })
+}
+
+/**
+ * 发布
+ * @id api 版本主键
+ */
+export function disableVersionPush (id: string) {
+  return request({
+    url: `/apiVersion/publish/${id}`,
+    method: 'PUT'
+  })
+}
+
+/**
+ * 复制发布地址
+ * @id api 版本主键
+ */
+export function versionCopyPushPath (id: string) {
+  return request({
+    url: `/apiCenter/getPublishPath/${id}`,
+    method: 'GET'
+  })
+}
+
+/**
+ * 导出源码
+ * id: api的ID
+ * vid: 版本ID
+ */
+export function exportCode (id: string, vid: string) {
+  return request({
+    url: `/apiCode/${id}/${vid}`,
+    method: 'GET',
+    headers: {
+      responseType: 'blob'
+    }
+  })
+}
+
+/**
+ * 查询数据源
+ */
+export function appDsPage (params) {
+  return request({
+    url: '/apiCenter/qryAppDsPage',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 查询模型
+ */
+export function appTableByAppDs (params) {
+  return request({
+    url: '/apiCenter/qryAppTableByAppDs',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 查询模型字段
+ */
+export function modelColumns (params) {
+  return request({
+    url: '/apiCenter/qryModelColumns',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 查询数据类型
+ */
+export function appTableDataType (params) {
+  return request({
+    url: '/apiCenter/qryAppTableDataType',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 查询主表关联的表
+ */
+export function associative (params) {
+  return request({
+    url: '/apiCenter/qryAppTableRelationListByMainTableId',
+    method: 'GET',
+    params
+  })
+}

+ 2 - 4
src/components/CodeMirror/index.tsx

@@ -4,11 +4,9 @@ import { basicSetup } from 'codemirror'
 import { EditorView } from '@codemirror/view'
 import { EditorState, StateEffect } from '@codemirror/state'
 import { javascript } from '@codemirror/lang-javascript'
-// import { sql } from '@codemirror/lang-sql'
+import { sql } from '@codemirror/lang-sql'
 import { useId } from '@/hooks'
 
-const sql = () => {}
-
 export const CodeMirrorTsx = defineComponent({
   name: 'code-mirror-tsx',
   props: {
@@ -46,7 +44,7 @@ export const CodeMirrorTsx = defineComponent({
       if (props.bodyType === 'javascript') {
         extensions.push(javascript())
       } else if (props.bodyType === 'sql') {
-        // extensions.push(sql())
+        extensions.push(sql())
       }
       const editorState = EditorState.create({
         doc: transDoc(),

+ 43 - 0
src/components/InfoAccordion/index.less

@@ -0,0 +1,43 @@
+.info-box {
+  width: 100%;
+  // display: inline;
+}
+
+.icon-box {
+  transition: all 0.3s;
+  color: #8c8c8c;
+}
+
+.title-box {
+  padding-left: 16px;
+  border-left: 4px solid #4169e1;
+  line-height: 14px;
+  cursor: pointer;
+  display: inline-block;
+  margin-bottom: 24px;
+}
+
+.close-contant {
+  opacity: 0;
+  max-height: 0 !important;
+  transition: all 0.3s ease;
+}
+
+.open-contant {
+  opacity: 1;
+  max-height: 4000px !important;
+  transition: all 0.3s ease-in;
+}
+
+.contant-box1 {
+  max-height: 4000px;
+  overflow: hidden;
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.title-text {
+  margin-right: 4.8px;
+  color: #262626;
+}

+ 52 - 0
src/components/InfoAccordion/index.tsx

@@ -0,0 +1,52 @@
+import { defineComponent, ref } from 'vue'
+import { DownOutlined } from '@ant-design/icons-vue'
+import './index.less'
+
+export default defineComponent({
+  name: 'info-accordion',
+  props: {
+    title: {
+      type: String,
+      default: '基本信息'
+    }
+  },
+  emits: {},
+  setup (props, ctx) {
+    const visible = ref<boolean>(true)
+
+    const iconDom = ref<HTMLDivElement>()
+
+    const contentDom = ref<HTMLDivElement>()
+
+    const titleClick = () => {
+      if (visible.value) {
+        contentDom.value?.classList.add('close-contant')
+        contentDom.value?.classList.remove('open-contant')
+        iconDom.value!.style.transform = 'rotate(-90deg)'
+      } else {
+        contentDom.value?.classList.add('open-contant')
+        contentDom.value?.classList.remove('close-contant')
+        iconDom.value!.style.transform = 'rotate(0deg)'
+      }
+
+      visible.value = !visible.value
+    }
+
+    return () => (
+      <div class='info-box'>
+      <div class='title-box' onClick={titleClick}>
+        <span class='title-text' >{props.title}</span>
+        <a-space>
+          <DownOutlined
+            class='icon-box'
+            ref={iconDom}
+          />
+        </a-space>
+      </div>
+      <div class='contant-box' ref={contentDom} >
+        {ctx.slots.default!()}
+      </div>
+    </div>
+    )
+  }
+})

+ 207 - 0
src/pages/schedule/APICenter/index.vue

@@ -0,0 +1,207 @@
+<template>
+<a-card title="API服务中心" >
+  <a-row>
+    <a-col>
+      <a-card title="分组" ></a-card>
+    </a-col>
+    <a-col>
+      <a-row>
+        <a-col>
+          <a-space>
+            <a-button>
+              <a-input-search
+                v-model:value="queryState.searchValue"
+                @search="getAPiList"
+              >
+                <template #addonBefore>
+                  <select-tsx
+                    :request="async () => await searchKeys"
+                    v-model:value="queryState.searchKey"
+                  />
+                </template>
+              </a-input-search>
+            </a-button>
+          </a-space>
+        </a-col>
+        <a-col>
+          <a-space>
+            <a-button>新建API</a-button>
+            <a-button>批量导出</a-button>
+            <a-button>删除</a-button>
+            <a-button>批量删除</a-button>
+          </a-space>
+        </a-col>
+      </a-row>
+    </a-col>
+  </a-row>
+</a-card>
+
+<modal-pro
+  :open="state.visible"
+  height="300px"
+  style="height: 300px"
+  @cencal="state.visible = false"
+  @ok="ok"
+>
+  <a-form  :labelCol="{span: 6}" :wrapperCol="{span: 14}" >
+    <info-accordion title="API" >
+      <a-row>
+        <a-col>
+          <a-form-item label="API标题" v-bind="validateInfos.serviceName"  >
+            <a-input allowClear v-model:value="apiState.serviceName" />
+          </a-form-item>
+        </a-col>
+        <a-col>
+          <a-form-item label="API标识" v-bind="validateInfos.serviceId"  >
+            <a-input allowClear v-model:value="apiState.serviceId" />
+          </a-form-item>
+        </a-col>
+        <a-col>
+          <a-form-item label="API说明" v-bind="validateInfos.serviceDesc"  >
+            <a-input allowClear v-model:value="apiState.serviceDesc" />
+          </a-form-item>
+        </a-col>
+        <a-col>
+          <a-form-item label="请求方法" v-bind="validateInfos.requestMethod"  >
+            <select-tsx :request="async () => await methodKeys"  v-model:value="apiState.requestMethod" />
+          </a-form-item>
+        </a-col>
+        <a-col>
+          <a-form-item label="API类型" v-bind="validateInfos.serviceType"  >
+            <a-radio-group v-model:value="apiState.serviceType" button-style="solid">
+              <a-radio-button :value="11">API</a-radio-button>
+              <a-radio-button :value="12">服务编排</a-radio-button>
+            </a-radio-group>
+          </a-form-item>
+        </a-col>
+        <a-col>
+          <a-form-item label="请求TOKEN" v-bind="validateInfos.permanentToken"  >
+            <a-input v-model:value="apiState.permanentToken" />
+          </a-form-item>
+        </a-col>
+      </a-row>
+    </info-accordion>
+    <info-accordion title="基本信息" v-if="apiState.serviceType === 11">
+
+    </info-accordion>
+    <info-accordion title="节点配置" >
+
+    </info-accordion>
+    </a-form>
+
+</modal-pro>
+</template>
+
+<script setup  lang="ts">
+import { reactive } from 'vue'
+import { SelectTsx } from '@/components/MicroComponents/index'
+import InfoAccordion from '@/components/InfoAccordion/index'
+import { Form } from 'ant-design-vue'
+
+const searchKeys = [
+  {
+    name: '标识',
+    key: '',
+    value: ''
+  },
+  {
+    name: 'API标题',
+    key: '',
+    value: ''
+  }
+]
+
+const methodKeys = [
+  {
+    name: 'get',
+    key: 'GET',
+    value: 'GET'
+  },
+  {
+    name: 'post',
+    key: 'POST',
+    value: 'POST'
+  }
+]
+
+const defaultApiData = {
+  serviceName: '',
+  serviceId: '',
+  serviceDesc: '',
+  requestMethod: '',
+  permanentToken: '',
+  groupKey: '',
+  serviceType: 11,
+  sourceName: '',
+  targetName: '',
+  title: '',
+  url: '',
+  method: 'GET',
+  contentType: 'JSON',
+  retry: 0,
+  authType: 'NONE',
+  basicUsername: '',
+  basicPassword: '',
+  jwtMethod: 'HS256',
+  jwtKey: '',
+  enableCustomInput: false,
+  customInputMerge: false,
+  inputMap: [],
+  enableCustomQuery: false,
+  customQueryMerge: false,
+  queryMap: [],
+  enableCustomHeader: false,
+  customHeaderMerge: false,
+  headerMap: [],
+  isDownload: false,
+  transformMerge: false,
+  enableCustomOutput: false,
+  outputTransform: [],
+  enableResponseAdaptor: false,
+  responseAdaptor: `// 支持ES6,
+ // 仅支持原生js, 不支持导入第三方包
+ // state: 全局根变量
+ // js 代码里面每一行结束 要么添加换行符 要么添加 ;
+  // 外部变量中的数组需要经过JSON.parse()处理,才可使用Map等方法,代码中自定义数组不需要JSON.parse()
+ return responseData;`,
+  enableCustomCa: false,
+  httpsKey: '',
+  httpsCert: '',
+  reqParam: [],
+  respParam: []
+}
+
+const queryState = reactive({
+  page: 1,
+  pageSize: 10,
+  total: 0,
+  searchKey: '',
+  searchValue: ''
+})
+
+const state = reactive({
+  loading: false,
+  visible: false,
+  dataSource: []
+})
+
+const apiState = reactive({ ...defaultApiData })
+
+const useForm = Form.useForm
+
+const { resetFields, validate, validateInfos } = useForm(apiState, reactive({
+
+}))
+
+const ok = () => {
+
+}
+
+const getAPiList = () => {
+
+}
+
+</script>
+
+<style>
+</style>

+ 21 - 9
src/pages/schedule/dataLake/dataTool/index.vue

@@ -1,19 +1,31 @@
 <template>
-<a-card title="数据源工具" >
-  <a-row>
-    <a-col></a-col>
-    <a-col></a-col>
-  </a-row>
-  <a-row>
-    <a-col></a-col>
-    <a-col :span="24" >
-      <code-mirror-tsx  style="width: 100%;" body-type="sql" :number-of-rows="20" />
+<a-card title="数据源工具" style="min-height: 600px;">
+  <a-row justify="space-between" :gutter="[8, 8]" style="min-height: 600px;">
+    <a-col :span="3" >
+      <a-card style="height: 100%;" >
+        <a>数据查询</a>
+      </a-card>
+    </a-col>
+    <a-col :span="21" >
+      <a-card  style="height: 100%;"  >
+        <div>
+        <a-space>
+          <a-button small type="link" :icon="h(RightCircleOutlined)" >执行</a-button>
+        </a-space>
+        </div>
+        <div style="margin-top: 20px;border: 1px solid #c9c9c9;" >
+          <code-mirror-tsx  style="width: 100%;" body-type="sql" :number-of-rows="20" />
+        </div>
+      </a-card>
+
     </a-col>
   </a-row>
 </a-card>
 </template>
 <script lang='ts' setup >
 import { CodeMirrorTsx } from '@/components/CodeMirror/index'
+import { h } from 'vue'
+import { RightCircleOutlined } from '@ant-design/icons-vue'
 </script>
 <style lang='less' scoped >
 </style>

+ 7 - 9
src/router/index.ts

@@ -310,15 +310,13 @@ const schedule = {
           component: () => import('@/pages/schedule/dataLake/dataTool/index.vue')
         }
       ]
+    },
+    {
+      path: '/APICenter',
+      name: '数据服务',
+      icon: 'ApiOutlined',
+      component: () => import('@/pages/schedule/APICenter/index.vue')
     }
-    // {
-    //   path: '/dataService',
-    //   name: '数据服务',
-    //   icon: 'ApiOutlined',
-    //   children: [
-
-    //   ]
-    // }
   ]
 }
 
@@ -373,7 +371,7 @@ const login = {
   component: () => import('@/pages/login/index.vue')
 }
 
-const _routes = [iot, rts, schedule, view, lowcode, user, login] as any
+const _routes = [iot, rts, schedule, view, lowcode, user] as any
 // const _routes = [iot] as any
 
 if (_routes[0].link) {

+ 46 - 0
src/type/schedule.d.ts

@@ -0,0 +1,46 @@
+
+declare namespace SCHEDULE {
+  namespace API {
+    interface Detail {
+      serviceName: string,
+      serviceId: string,
+      serviceDesc: string,
+      requestMethod: string,
+      permanentToken: string,
+      groupKey: string,
+      serviceType: string,
+      sourceName: string,
+      targetName: string,
+      title: string,
+      url: string,
+      method: 'GET' | 'POST' | 'PUT' | 'DELETE',
+      contentType: 'JSON',
+      retry: number,
+      authType: string,
+      basicUsername: string,
+      basicPassword: string,
+      jwtMethod: 'HS256',
+      jwtKey: string,
+      enableCustomInput: boolean,
+      customInputMerge: boolean,
+      inputMap: [],
+      enableCustomQuery: boolean,
+      customQueryMerge: boolean,
+      queryMap: [],
+      enableCustomHeader: boolean,
+      customHeaderMerge: boolean,
+      headerMap: [],
+      isDownload: boolean,
+      transformMerge: boolean,
+      enableCustomOutput: boolean,
+      outputTransform: [],
+      enableResponseAdaptor: boolean,
+      responseAdaptor: string,
+      enableCustomCa: boolean,
+      httpsKey: string,
+      httpsCert: string,
+      reqParam: [],
+      respParam: [],
+    }
+  }
+}

+ 6 - 0
vue.config.js

@@ -2,6 +2,7 @@ const { defineConfig } = require('@vue/cli-service')
 const proxy = require('./config/proxy.ts')
 const path = require('path')
 const { resolve } = require('path')
+const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
 
 module.exports = defineConfig({
   // publicPath: '',
@@ -20,6 +21,11 @@ module.exports = defineConfig({
   chainWebpack: config => {
     config.resolve.alias.set('ThingsUi', resolve(__dirname, '/'))
   },
+  configureWebpack: {
+    plugins: [
+      // new BundleAnalyzerPlugin()
+    ]
+  },
   css: {
     loaderOptions: {
       less: {

Some files were not shown because too many files changed in this diff