zhaoke 3 سال پیش
والد
کامیت
5d5e8caf3e
29فایلهای تغییر یافته به همراه3827 افزوده شده و 9 حذف شده
  1. 202 0
      src/api/gat-interface.js
  2. 33 0
      src/api/gateway.js
  3. BIN
      src/assets/gateway/pic_empty.png
  4. BIN
      src/assets/gateway/pic_empty@2x.png
  5. 79 0
      src/components/deletepopup/deletepopup.scss
  6. 49 0
      src/components/deletepopup/index.vue
  7. 2 7
      src/layout/components/NavRightSide/index.vue
  8. 3 2
      src/router/index.js
  9. 47 0
      src/router/routes/routes-file-six.js
  10. 315 0
      src/views/gateway/circuit-break/index.vue
  11. 115 0
      src/views/gateway/components/NormalCard/index.vue
  12. 356 0
      src/views/gateway/document/index.vue
  13. 82 0
      src/views/gateway/index.vue
  14. 134 0
      src/views/gateway/interface-add/Interfaceadd/Interfaceadd.scss
  15. 92 0
      src/views/gateway/interface-add/Interfaceadd/index.vue
  16. 309 0
      src/views/gateway/interface-add/Interfaceconfiguration/Interfaceconfiguration.scss
  17. 264 0
      src/views/gateway/interface-add/Interfaceconfiguration/index.vue
  18. 197 0
      src/views/gateway/interface-add/Interfaceparameter/Interfaceparameter.scss
  19. 172 0
      src/views/gateway/interface-add/Interfaceparameter/index.vue
  20. 157 0
      src/views/gateway/interface-add/associatedserver/associatedserver.scss
  21. 159 0
      src/views/gateway/interface-add/associatedserver/index.vue
  22. 69 0
      src/views/gateway/interface-add/index.vue
  23. 156 0
      src/views/gateway/interface-add/serverconfiguration/index.vue
  24. 160 0
      src/views/gateway/interface-add/serverconfiguration/serverconfiguration.scss
  25. 110 0
      src/views/gateway/interface-add/testpop/index.vue
  26. 92 0
      src/views/gateway/interface-add/theserverpop/index.vue
  27. 134 0
      src/views/gateway/interface-add/theserverpop/theserverpop.scss
  28. 107 0
      src/views/gateway/interface/index.vue
  29. 232 0
      src/views/gateway/limit/index.vue

+ 202 - 0
src/api/gat-interface.js

@@ -0,0 +1,202 @@
+import request from '@/utils/request'
+
+/**
+ * 
+ * BServer
+ */
+//分页获取所有业务服务器信息
+export function gateWayBServerGetList (params) {
+  return request({
+    url: '/api/BServer/GateWayBServerGetList',
+    method: 'post',
+    params
+  })
+}
+
+//根据ID获取业务服务器信息
+export function gateWayBServerGetById (params) {
+  return request({
+    url: '/api/BServer/GateWayBServerGetById',
+    method: 'post',
+    params
+  })
+}
+
+//删除业务服务器信息
+export function gateWayBServerDeleteById (params) {
+  return request({
+    url: '/api/BServer/GateWayBServerDeleteById',
+    method: 'post',
+    params
+  })
+}
+
+//新增/更新业务服务器信息
+export function gateWayBServerEdit (params) {
+  return request({
+    url: '/api/BServer/GateWayBServerEdit',
+    method: 'post',
+    params
+  })
+}
+
+//更新业务服务器状态信息
+export function gateWayBServerStatusEdit (params) {
+  return request({
+    url: '/api/BServer/GateWayBServerStatusEdit',
+    method: 'post',
+    params
+  })
+}
+
+//根据业务服务ID获取所有关联的业务服务器信息
+export function gateWayRelationBServerGetByBusiness (params) {
+  return request({
+    url: '/api/BServer/GateWayRelationBServerGetByBusiness',
+    method: 'post',
+    params
+  })
+}
+
+//根据业务服务ID获取所有关联和未关联的业务服务器信息
+export function gateWayBServerGetByBusiness (params) {
+  return request({
+    url: '/api/BServer/GateWayBServerGetByBusiness',
+    method: 'post',
+    params
+  })
+}
+
+//以业务服务器为主批量关联业务服务及业务服务器信息
+export function gateWayBusinessBServerRelationByBServer (params) {
+  return request({
+    url: '/api/BServer/GateWayBusinessBServerRelationByBServer',
+    method: 'post',
+    params
+  })
+}
+
+/**
+ * 
+ * Business
+ */
+//
+export function asyncTest (params) {
+  return request({
+    url: '/api/Business/AsyncTest',
+    method: 'post',
+    params
+  })
+}
+
+//API文档列表查询(searchType字段无效)
+export function gateWayApiDocumentList (params) {
+  return request({
+    url: '/api/Business/GateWayApiDocumentList',
+    method: 'post',
+    params
+  })
+}
+
+//分页获取业务服务列表信息
+export function gateWayBusinessGetList (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessGetList',
+    method: 'post',
+    params
+  })
+}
+
+//根据ID获取WebApi业务服务信息
+export function gateWayBusinessGetById (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessGetById',
+    method: 'post',
+    params
+  })
+}
+
+//根据ID获取WebApi业务服务所有信息
+export function gateWayBusinessAllGetById (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessAllGetById',
+    method: 'post',
+    params
+  })
+}
+
+//删除业务服务信息
+export function gateWayBusinessDeleteById (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessDeleteById',
+    method: 'post',
+    params
+  })
+}
+
+//新增/修改业务服务
+export function gateWayBusinessAllEdit (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessAllEdit',
+    method: 'post',
+    params
+  })
+}
+
+//更新业务服务状态信息
+export function gateWayBusinessStatusEdit (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessStatusEdit',
+    method: 'post',
+    params
+  })
+}
+
+//根据业务服务器ID获取所有关联业务服务信息
+export function gateWayRelBusinessGetByBServer (params) {
+  return request({
+    url: '/api/Business/GateWayRelBusinessGetByBServer',
+    method: 'post',
+    params
+  })
+}
+
+//根据业务服务器ID获取所有关联和未关联的业务服务信息
+export function gateWayBusinessGetByBServer (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessGetByBServer',
+    method: 'post',
+    params
+  })
+}
+
+//以业务服务为主批量关联业务服务及业务服务器信息
+export function gateWayBusinessBServerRelationByBusiness (params) {
+  return request({
+    url: '/api/Business/GateWayBusinessBServerRelationByBusiness',
+    method: 'post',
+    params
+  })
+}
+
+/**
+ *
+ * Parameter
+ */
+//根据请求ID、请求参数类型以及请求类型获取参数列表
+export function parameterGetListAll (params) {
+  return request({
+    url: '/api/Parameter/ParameterGetListAll',
+    method: 'post',
+    params
+  })
+}
+
+//更新指定请求的参数
+export function parameterEditByBusinessId (params) {
+  return request({
+    url: '/api/Parameter/ParameterEditByBusinessId',
+    method: 'post',
+    params
+  })
+}

+ 33 - 0
src/api/gateway.js

@@ -0,0 +1,33 @@
+import request from '@/utils/request'
+
+export function getGatewayInterfaceList(params) {
+  return request({
+    url: '/vue-admin-template/gateway/interface/list',
+    method: 'get',
+    params
+  })
+}
+
+export function getGatewayLimitList(params) {
+  return request({
+    url: '/vue-admin-template/gateway/limit/list',
+    method: 'get',
+    params
+  })
+}
+
+export function getGatewayCircuitBreakList(params) {
+  return request({
+    url: '/vue-admin-template/gateway/circuit-break/list',
+    method: 'get',
+    params
+  })
+}
+
+export function getGatewayDocumentList(params) {
+  return request({
+    url: '/vue-admin-template/gateway/document/list',
+    method: 'get',
+    params
+  })
+}

BIN
src/assets/gateway/pic_empty.png


BIN
src/assets/gateway/pic_empty@2x.png


+ 79 - 0
src/components/deletepopup/deletepopup.scss

@@ -0,0 +1,79 @@
+.bf-deletepopup{
+    .el-dialog__header{
+        display: none;
+    }
+    .el-dialog{
+        border-radius: 20px;
+    }
+    .el-dialog__body{
+        padding: 0;
+        background: #ebeff6;
+        box-shadow: 0px 6px 10px 0px rgba(0, 0, 0, 0.3);
+        border-radius: 20px;
+        padding: 0 48px 0 48px;
+        >.deletepopup_header{
+            width: 100%;
+            height: 118px;
+            display: flex;
+            >.left{
+                width: 100%;
+                height: 100%;
+                display: flex;
+                align-items: center;
+                >p{
+                    font-size: 24px;
+                    font-family: Microsoft YaHei;
+                    font-weight: bold;
+                    color: #303133;
+                }
+            }
+        }
+        >.deletepopup_cont{
+            width: 100%;
+            height: 111px;
+            display: flex;
+            align-items: center;
+            font-size: 16px;
+            font-family: Microsoft YaHei;
+            font-weight: 400;
+            color: #303133;
+        }
+        >.footer{
+            width: 100%;
+            height: 57px;
+            display: flex;
+            align-items: flex-start;
+            justify-content: flex-end;
+            >.delebut{
+                // padding: 0 24px 0 24px;
+                height: 32px;
+                // background: #F56C6C;
+                // border-radius: 16px;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #FFFFFF;
+                margin-right: 16px;
+                // cursor: pointer;
+            }
+            >.elebut{
+                // padding: 0 24px 0 24px;
+                height: 32px;
+                // background: #FFFFFF;
+                // border: 1px solid #E4E8F0;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // border-radius: 16px;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // cursor: pointer;
+            }
+        }
+    }
+}

+ 49 - 0
src/components/deletepopup/index.vue

@@ -0,0 +1,49 @@
+<template>
+    <div class="bf-deletepopup">
+        <el-dialog
+        title=""
+        :visible.sync="dialogVisibledele"
+        :modal-append-to-body="false"
+        :before-close="handleClose"
+        :width="isWidth">
+            <div class="deletepopup_header">
+                <div class="left">
+                    <p>删除接口参数配置</p>
+                </div>
+            </div>
+            <div class="deletepopup_cont">
+                是否确定要删除该接口参数配置
+            </div>
+            <div class="footer">
+                <!-- <div class="delebut">删除</div> -->
+                <Bfbutton :butName='butName' class="delebut"  :type = '7'/>
+                <Bfbutton :butName='butNames' class="elebut" @click.native="handleClose"  :type = '8'/>
+                <!-- <div class="elebut" @click="handleClose">取消</div> -->
+            </div>
+        </el-dialog>
+    </div>
+</template>
+<script>
+import Bfbutton from '../../components/bfbutton/index.vue'
+import './deletepopup.scss'
+export default {
+    props: ['dialogVisibledele'],
+    data () {
+        return {
+            isWidth: '31.5%',
+            butName: '删除',
+            butNames: '取消'
+        }
+    },
+    methods: {
+        handleClose () {
+            this.$emit('delepop')
+        }
+    },
+    components: {
+        Bfbutton
+    }
+}
+</script>
+<style lang="scss">
+</style>

+ 2 - 7
src/layout/components/NavRightSide/index.vue

@@ -1,12 +1,7 @@
 <template>
   <div class="nav-right-side">
     <div class="nav-right-side-menu">
-      <div
-        v-for="({ text }, index) in navItems"
-        :key="text"
-        :class="['nav-right-side-item', { 'active': index === activeIndex }]"
-        @click="_.debounce(clickHandler, 300)(index)"
-      >{{ text }}</div>
+      <div v-for="({ text }, index) in navItems" :key="text" :class="['nav-right-side-item', { 'active': index === activeIndex }]" @click="clickHandler(index)">{{ text }}</div>
     </div>
   </div>
 </template>
@@ -34,7 +29,7 @@ export default {
     }
   },
   methods: {
-    clickHandler(index) {
+    clickHandler (index) {
       if (this.activeIndex !== index) {
         this.$emit('selection-changed', index)
       }

+ 3 - 2
src/router/index.js

@@ -17,6 +17,7 @@ import routesFour from './routes/routes-file-four'
 import routesTwo from './routes/routes-file-two'
 import routesThree from './routes/routes-file-three'
 import routesFive from './routes/routes-file-five'
+import routesFileSix from './routes/routes-file-six'
 /**
  * Note: sub-menu only appear when route children.length >= 1
  * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
@@ -65,9 +66,9 @@ export const constantRoutes = [
 // 插入路由
 export const asyncRoutes = []
 if (PLATFROM_CONFIG.doesJobShow) {
-  routesPush([...routesOne, ...routesTwo, ...routesThree, ...routesFour, ...routesFive], asyncRoutes)
+  routesPush([...routesOne, ...routesTwo, ...routesThree, ...routesFour, ...routesFive, ...routesFileSix], asyncRoutes)
 } else {
-  routesPush([...routesOne, ...routesTwo, ...routesFour, ...routesFive], asyncRoutes)
+  routesPush([...routesOne, ...routesTwo, ...routesFour, ...routesFive, ...routesFileSix], asyncRoutes)
 }
 asyncRoutes.push({ path: '/', component: () => import('@/views/noPower'), hidden: true })
 asyncRoutes.push({ path: '*', component: () => import('@/views/404'), hidden: true })

+ 47 - 0
src/router/routes/routes-file-six.js

@@ -0,0 +1,47 @@
+import Layout from '@/layout'
+
+const gatewayRoutes = {
+  path: '/gateway',
+  component: Layout,
+  children: [{
+    path: '/gateway',
+    name: 'Gateway',
+    component: () => import('@/views/gateway/index'),
+    redirect: '/gateway/interface',
+    meta: { title: 'API网关', icon: 'dashboard', imgstyle: 'ic_home_nav_defaul.png', imgstyleup: 'ic_home_nav_check.png' },
+    children: [
+      {
+        path: '/gateway/interface',
+        name: 'GatewayInterface',
+        component: () => import('@/views/gateway/interface'),
+        meta: { title: '接口配置' }
+      },
+      {
+        path: '/gateway/interface-add',
+        name: 'GateWayInterfaceAdd',
+        component: () => import('@/views/gateway/interface-add'),
+        meta: { title: '新增接口配置', withoutNav: true }
+      },
+      {
+        path: '/gateway/limit',
+        name: 'GatewayLimit',
+        component: () => import('@/views/gateway/limit'),
+        meta: { title: '限流配置' }
+      },
+      {
+        path: '/gateway/circuit-break',
+        name: 'GatewayCircuitBreak',
+        component: () => import('@/views/gateway/circuit-break'),
+        meta: { title: '熔断配置' }
+      },
+      {
+        path: '/gateway/document',
+        name: 'GatewayDocument',
+        component: () => import('@/views/gateway/document'),
+        meta: { title: 'API文档' }
+      }
+    ]
+  }]
+}
+
+export default [gatewayRoutes]

+ 315 - 0
src/views/gateway/circuit-break/index.vue

@@ -0,0 +1,315 @@
+<template>
+  <div class="gateway-circuit-break">
+    <div class="gateway-circuit-break-head">
+      <Search placeholder="请输入您要搜索的内容" :isSlot="true">
+        <button class="btnAdd" @click="dialogAddShow = true">新增</button>
+      </Search>
+    </div>
+    <div class="gateway-circuit-break-content">
+      <template v-if="circuitBreakList.length">
+        <el-row :gutter="24">
+          <el-col
+            v-for="(
+              {
+                id,
+                name,
+                circuitBreakDuration,
+                timeoutPeriod,
+                circuitBreakStandard,
+                interfaceBinding,
+              },
+              index
+            ) in circuitBreakList"
+            :key="id"
+            :xs="24"
+            :md="12"
+            :lg="6"
+            :xl="6"
+          >
+            <NormalCard
+              :title="name"
+              :flag.sync="circuitBreakList[index].flag"
+              @close-click="removeCard(index)"
+            >
+              <template #default>
+                <el-row :gutter="16">
+                  <el-col :span="7" class="card-content-left"
+                    >熔断时间:</el-col
+                  >
+                  <el-col :span="5" class="card-content-right">{{
+                    circuitBreakDuration
+                  }}</el-col>
+                  <el-col :span="7" class="card-content-left"
+                    >接口关联:</el-col
+                  >
+                  <el-col :span="5" class="card-content-right">{{
+                    interfaceBinding
+                  }}</el-col>
+                  <el-col :span="7" class="card-content-left"
+                    >超时时间:</el-col
+                  >
+                  <el-col :span="17" class="card-content-right">{{
+                    timeoutPeriod
+                  }}</el-col>
+                  <el-col :span="7" class="card-content-left"
+                    >熔断标准:</el-col
+                  >
+                  <el-col :span="17" class="card-content-right">{{
+                    circuitBreakStandard
+                  }}</el-col>
+                </el-row>
+              </template>
+            </NormalCard>
+          </el-col>
+        </el-row>
+      </template>
+      <template v-else>
+        <el-empty description="暂无数据" />
+      </template>
+    </div>
+    <Dialog
+      :flag="dialogAddShow"
+      width="630px"
+      @close-dialog="dialogAddShow = false"
+    >
+      <div class="dialog-add-title">新增熔断配置</div>
+      <div class="dialog-add-content">
+        <el-form :model="circuitBreakAddForm" label-width="auto">
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="熔断时间">
+                <el-input
+                  v-model="circuitBreakAddForm.circuitBreakDuration"
+                  placeholder="请输入熔断时间"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="服务超时时间">
+                <el-input
+                  v-model="circuitBreakAddForm.timeoutPeriod"
+                  placeholder="请输入服务超时时间"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="达成熔断标准">
+                <el-input
+                  v-model="circuitBreakAddForm.circuitBreakStandard"
+                  placeholder="请输入次数(次)"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="认定错误状态码">
+                <el-input
+                  v-model="circuitBreakAddForm.errorCode"
+                  placeholder="请输入状态码"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="是否启用">
+                <el-radio-group v-model="circuitBreakAddForm.enable">
+                  <el-radio :label="true">是</el-radio>
+                  <el-radio :label="false">否</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-form-item label="熔断规则描述">
+            <el-input
+              v-model="circuitBreakAddForm.description"
+              placeholder="请输入描述"
+            />
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="dialog-add-bottom fc">
+        <el-button
+          size="medium"
+          type="primary"
+          @click="dialogAddShow = false"
+          class="r24 blubtn"
+          >提交</el-button
+        >
+        <el-button size="medium" class="wbtn" @click="dialogAddShow = false"
+          >取消</el-button
+        >
+      </div>
+    </Dialog>
+    <Dialog :flag="dialogVisible">
+      <div class="closeDialog">
+        <div class="title">删除熔断配置</div>
+        <div class="content">是否确定要删除{{ deleteUserName }}?</div>
+        <div class="foot right t30">
+          <el-button size="medium" type="danger" class="r24" @click="del()"
+            >删除</el-button
+          >
+
+          <el-button size="medium" @click="dialogVisible = false"
+            >取消</el-button
+          >
+        </div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Search from "@/layout/components/Search";
+import NormalCard from "../components/NormalCard";
+import Dialog from "@/layout/components/Dialog";
+import { getGatewayCircuitBreakList } from "@/api/gateway";
+
+export default {
+  name: "GatewayLimit",
+  components: {
+    Search,
+    NormalCard,
+    Dialog,
+  },
+  data() {
+    return {
+      circuitBreakList: [
+        {
+          id: 0,
+          name: "熔断规则名称",
+          circuitBreakDuration: 2,
+          timeoutPeriod: 2,
+          circuitBreakStandard: 3,
+          interfaceBinding: 2,
+          flag: true,
+        },
+        {
+          id: 1,
+          name: "熔断规则名称",
+          circuitBreakDuration: 2,
+          timeoutPeriod: 2,
+          circuitBreakStandard: 3,
+          interfaceBinding: 2,
+          flag: true,
+        },
+        {
+          id: 2,
+          name: "熔断规则名称",
+          circuitBreakDuration: 2,
+          timeoutPeriod: 2,
+          circuitBreakStandard: 3,
+          interfaceBinding: 2,
+          flag: true,
+        },
+        {
+          id: 3,
+          name: "熔断规则名称",
+          circuitBreakDuration: 2,
+          timeoutPeriod: 2,
+          circuitBreakStandard: 3,
+          interfaceBinding: 2,
+          flag: true,
+        },
+      ],
+      circuitBreakAddForm: {
+        circuitBreakDuration: "",
+        timeoutPeriod: "",
+        circuitBreakStandard: "",
+        errorCode: "",
+        enable: true,
+        description: "",
+      },
+      dialogAddShow: false,
+      deleteUserName: "",
+      dialogVisible: false,
+    };
+  },
+  created() {
+    this.fetchData();
+  },
+  methods: {
+    fetchData() {
+      this.listLoading = true;
+      getGatewayCircuitBreakList().then((response) => {
+        this.circuitBreakList.push(...response.data.items);
+        this.listLoading = false;
+      });
+    },
+    //删除-弹窗
+    removeCard(index) {
+      this.dialogVisible = true;
+      // this.circuitBreakList.splice(index, 1);
+    },
+    //删除-接口
+    del() {},
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.gateway-circuit-break-head {
+  display: flex;
+  justify-content: flex-end;
+}
+::v-deep .el-radio__input.is-checked .el-radio__inner {
+  border-color: #6f80bc;
+  background: #6f80bc;
+}
+::v-deep .el-radio__input.is-checked + .el-radio__label {
+  color: #303133;
+}
+::v-deep .el-button--primary {
+  border-color: #6f80bc;
+}
+.gateway-circuit-break-content {
+  margin-top: 32px;
+  height: calc(100vh - 224px);
+  overflow-x: hidden;
+  overflow-y: auto;
+
+  & > .el-row > .el-col {
+    margin-bottom: 24px;
+  }
+
+  ::v-deep .normal-card .card-content {
+    & > .el-row > .el-col {
+      margin-bottom: 24px;
+
+      &:nth-last-child(1),
+      &:nth-last-child(2) {
+        margin-bottom: 0;
+      }
+    }
+
+    .card-content-left {
+      word-break: keep-all;
+    }
+
+    .card-content-right {
+      color: #909399;
+      word-break: keep-all;
+    }
+  }
+}
+
+.dialog-add-title {
+  font-size: 24px;
+  font-weight: bold;
+  color: #303133;
+}
+
+.dialog-add-content {
+  margin-top: 48px;
+  font-size: 14px;
+  font-weight: 400;
+  color: #303133;
+
+  ::v-deep .el-input .el-input__inner {
+    background-color: #f5f7fa;
+    border: 1px solid #dcdfe6;
+    border-radius: 8px;
+  }
+}
+
+.dialog-add-bottom {
+  margin-top: 48px;
+}
+</style>

+ 115 - 0
src/views/gateway/components/NormalCard/index.vue

@@ -0,0 +1,115 @@
+<template>
+  <div :class="['normal-card', { disabled: !flag }]">
+    <div class="card-head">
+      <div class="card-title">{{ title }}</div>
+      <div class="card-close">
+        <i class="icon el-icon-close" @click="closeClickHandler" />
+      </div>
+    </div>
+    <div class="card-content">
+      <slot />
+    </div>
+    <div class="card-switch">
+      <p :class="flag ? 'start_up' : 'close'">{{ flag ? "开启" : "关闭" }}</p>
+      <el-switch
+        :value="flag"
+        active-color="#6F81BC"
+        @change="switchChangeHandler"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "InterfaceCard",
+  props: {
+    title: {
+      type: String,
+      default: "名称",
+    },
+    description: {
+      type: String,
+      default: "描述",
+    },
+    protocol: {
+      type: String,
+      default: "协议",
+    },
+    flag: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  methods: {
+    switchChangeHandler(val) {
+      this.$emit("update:flag", val);
+    },
+    closeClickHandler() {
+      this.$emit("close-click");
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.normal-card {
+  position: relative;
+  padding: 32px;
+  width: 100%;
+  min-width: 318px;
+  background: #ffffff;
+  box-shadow: 0px 6px 7px 0px rgba(0, 0, 0, 0.06);
+  border-radius: 16px;
+  .start_up {
+    font-size: 12px;
+    font-family: Microsoft YaHei;
+    font-weight: 400;
+    color: #6f81bc;
+    display: flex;
+    justify-content: flex-end;
+    margin-bottom: 7px;
+  }
+  .close {
+    font-size: 12px;
+    font-family: Microsoft YaHei;
+    font-weight: 400;
+    color: #303133;
+    display: flex;
+    justify-content: flex-end;
+    margin-bottom: 7px;
+  }
+  // &.disabled ::v-deep div {
+  //   text-decoration: line-through;
+  // }
+
+  .card-head {
+    display: flex;
+    justify-content: space-between;
+
+    .card-title {
+      font-size: 18px;
+      font-family: Microsoft YaHei;
+      font-weight: bold;
+      color: #303133;
+    }
+
+    .card-close {
+      width: 11px;
+      height: 11px;
+      color: #303133;
+      cursor: pointer;
+    }
+  }
+
+  .card-content {
+    margin-top: 41px;
+  }
+
+  .card-switch {
+    position: absolute;
+    right: 32px;
+    bottom: 28px;
+  }
+}
+</style>

+ 356 - 0
src/views/gateway/document/index.vue

@@ -0,0 +1,356 @@
+<template>
+  <div class="gateway-document">
+    <div class="gateway-document-head">
+      <Search placeholder="请输入您要搜索的内容" />
+    </div>
+    <div class="gateway-document-content">
+      <el-collapse
+        v-model="activeName"
+        accordion
+        @change="showParams = '入参'"
+      >
+        <el-collapse-item
+          v-for="{id, name, protocol, type, time, method, description, params } in documentList"
+          :key="id"
+          :name="name"
+        >
+          <template #title>
+            <el-row
+              :gutter="24"
+              class="item-head"
+            >
+              <el-col
+                :span="1"
+                :class="['icon', activeName === name ? 'el-icon-arrow-up' : 'el-icon-arrow-down']"
+              />
+              <el-col :span="4">{{ id }}</el-col>
+              <el-col
+                :span="1"
+                class="icon el-icon-copy-document"
+              />
+              <el-col :span="6">{{ name }}</el-col>
+              <el-col :span="4">{{ protocol }}</el-col>
+              <el-col :span="8">{{ type }}</el-col>
+            </el-row>
+          </template>
+          <div class="item-title">基本信息</div>
+          <el-row
+            :gutter="20"
+            class="item-content"
+          >
+            <el-col :span="8">
+              <span class="item-content-left">名称:</span>
+              <span class="item-content-right">{{ name }}</span>
+            </el-col>
+            <el-col :span="8">
+              <span class="item-content-left">ID:</span>
+              <span class="item-content-right">{{ id }}</span>
+            </el-col>
+            <el-col :span="8">
+              <span class="item-content-left">时间:</span>
+              <span class="item-content-right">{{ time }}</span>
+            </el-col>
+            <el-col :span="8">
+              <span class="item-content-left">协议:</span>
+              <span class="item-content-right">{{ protocol }}</span>
+            </el-col>
+            <el-col :span="8">
+              <span class="item-content-left">请求方式:</span>
+              <span class="item-content-right">{{ type }}</span>
+            </el-col>
+            <el-col :span="8">
+              <span class="item-content-left">方法:</span>
+              <span class="item-content-right">{{ method }}</span>
+            </el-col>
+            <el-col :span="8">
+              <span class="item-content-left">描述:</span>
+              <span class="item-content-right">{{ description }}</span>
+            </el-col>
+          </el-row>
+          <div class="item-content-params-tabs">
+            <div class="item-title">接口参数</div>
+            <el-radio-group
+              v-model="showParams"
+              fill="#5C6789"
+              size="small"
+            >
+              <el-radio-button label="入参" />
+              <el-radio-button label="出参" />
+            </el-radio-group>
+          </div>
+          <el-table
+            v-show="showParams === '入参'"
+            :data="params.input"
+            height="253"
+          >
+            <template #empty>
+              <img
+                src="@/assets/gateway/pic_empty.png"
+                alt="暂无数据"
+              >
+              <p>暂无数据</p>
+            </template>
+            <el-table-column
+              prop="name"
+              label="名称"
+            />
+            <el-table-column
+              prop="type"
+              label="类型"
+            />
+            <el-table-column
+              prop="length"
+              label="长度"
+            />
+            <el-table-column
+              prop="default"
+              label="默认值"
+            />
+            <el-table-column
+              prop="reference"
+              label="参考值"
+            />
+            <el-table-column
+              prop="required"
+              label="是否必填"
+            >
+              <template slot-scope="scope">{{ scope.row.required ? '是' : '否' }}</template>
+            </el-table-column>
+            <el-table-column
+              prop="superior"
+              label="上级参数"
+            >
+              <template slot-scope="scope">{{ scope.row.superior ? scope.row.superior : '无' }}</template>
+            </el-table-column>
+            <el-table-column
+              prop="description"
+              label="描述"
+            />
+          </el-table>
+          <el-table
+            v-show="showParams === '出参'"
+            :data="params.output"
+            height="253"
+          >
+            <template #empty>
+              <img
+                src="@/assets/gateway/pic_empty.png"
+                alt="暂无数据"
+              >
+              <p>暂无数据</p>
+            </template>
+            <el-table-column
+              prop="name"
+              label="名称"
+            />
+            <el-table-column
+              prop="type"
+              label="类型"
+            />
+            <el-table-column
+              prop="length"
+              label="长度"
+            />
+            <el-table-column
+              prop="default"
+              label="默认值"
+            />
+            <el-table-column
+              prop="reference"
+              label="参考值"
+            />
+            <!-- <el-table-column
+              prop="required"
+              label="是否必填"
+            /> -->
+            <el-table-column
+              prop="superior"
+              label="上级参数"
+            >
+              <template slot-scope="scope">{{ scope.row.superior ? scope.row.superior : '无' }}</template>
+            </el-table-column>
+            <el-table-column
+              prop="description"
+              label="描述"
+            />
+          </el-table>
+        </el-collapse-item>
+      </el-collapse>
+    </div>
+  </div>
+</template>
+
+<script>
+import Search from '@/layout/components/Search'
+import { getGatewayDocumentList } from '@/api/gateway'
+
+export default {
+  components: {
+    Search
+  },
+  data() {
+    return {
+      documentList: [
+        {
+          id: 265912187337728,
+          name: '/api/msgTemplateSetting/stopstart',
+          protocol: 'http',
+          type: 'post',
+          time: '2021/10/10 12:30:30',
+          method: '/api/msgTemplateSetting/stopstart',
+          description: '/api/msgTemplateSetting/stopstart',
+          params: {
+            input: [
+              // {
+              //   name: '参数1',
+              //   type: 'string',
+              //   length: 10,
+              //   default: '1234567890',
+              //   reference: '1234567890',
+              //   required: true,
+              //   superior: '',
+              //   description: '1234567890'
+              // }
+            ],
+            output: [
+              {
+                name: '参数1',
+                type: 'string',
+                length: 10,
+                default: '1234567890',
+                reference: '1234567890',
+                superior: '',
+                description: '1234567890'
+              }
+            ]
+          }
+        }
+      ],
+      activeName: '',
+      showParams: '入参'
+    }
+  },
+  created() {
+    this.fetchData()
+  },
+  methods: {
+    fetchData() {
+      this.listLoading = true
+      getGatewayDocumentList().then(response => {
+        this.documentList.push(...response.data.items)
+        this.listLoading = false
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.gateway-document-head {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.gateway-document-content {
+  margin-top: 32px;
+  padding: 32px;
+  height: calc(100vh - 224px);
+  overflow: auto;
+  display: flex;
+  flex-wrap: wrap;
+  background: #fff;
+  box-shadow: 0px 6px 7px 0px rgba(0, 0, 0, 0.06);
+  border-radius: 16px;
+
+  ::v-deep .el-collapse {
+    flex: 1;
+    border: none;
+
+    .el-collapse-item {
+      margin-bottom: 25px;
+
+      .el-collapse-item__header {
+        background-color: #5c6789;
+        height: 48px;
+        border-radius: 6px;
+        color: #fff;
+        border: none;
+
+        &.is-active {
+          background: linear-gradient(0deg, #777dba, #6983be);
+          border-radius: 6px 6px 0 0;
+        }
+
+        .el-collapse-item__arrow {
+          display: none;
+        }
+
+        .item-head {
+          padding: 0 24px;
+          width: 100%;
+
+          & > .el-col {
+            font-weight: 400;
+            line-height: 48px;
+          }
+        }
+      }
+
+      .el-collapse-item__content {
+        background-color: #f5f7fa;
+        padding: 48px 48px 0;
+
+        .item-title {
+          font-size: 18px;
+          font-weight: bold;
+          color: #303133;
+        }
+
+        .item-content {
+          margin-top: 48px;
+
+          .item-content-left {
+            margin-right: 15px;
+            font-weight: 400;
+            color: #303133;
+          }
+
+          .item-content-right {
+            font-weight: 400;
+            color: #909399;
+          }
+        }
+
+        .item-content-params-tabs {
+          margin-top: 48px;
+          display: flex;
+          justify-content: flex-start;
+
+          .item-title {
+            margin-right: 35px;
+          }
+        }
+
+        .el-table {
+          margin-top: 14px;
+
+          .el-table__header-wrapper {
+            height: 48px;
+            border-radius: 6px;
+
+            .el-table__cell {
+              color: #fff;
+              background-color: #5c6789;
+              border: none;
+            }
+          }
+
+          .el-table__empty-text {
+            line-height: 0;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 82 - 0
src/views/gateway/index.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="gateway">
+    <div :class="['gateway-left', {'without-right-nav': $route.path.includes('interface-add')}]">
+      <div class="gateway-content">
+        <router-view />
+      </div>
+    </div>
+    <div v-if="!$route.meta.withoutNav" class="gateway-right">
+      <GatewayNav :nav-items="navItems" :active-index="activeIndex" @selection-changed="selectedHandler" />
+    </div>
+  </div>
+</template>
+
+<script>
+import GatewayNav from '@/layout/components/NavRightSide'
+
+export default {
+  name: 'Gateway',
+  components: { GatewayNav },
+  data () {
+    return {
+      navItems: [
+        {
+          text: '接口配置',
+          path: 'interface'
+        },
+        {
+          text: '限流配置',
+          path: 'limit'
+        },
+        {
+          text: '熔断配置',
+          path: 'circuit-break'
+        },
+        {
+          text: 'API文档',
+          path: 'document'
+        }
+      ],
+      activeIndex: 0
+    }
+  },
+  created () {
+    const index = this.navItems.findIndex(item => this.$route.path.includes(item.path))
+    if (index > -1) {
+      this.activeIndex = index
+    }
+  },
+  methods: {
+    selectedHandler (index) {
+      console.log(index)
+      this.$router.push(this.navItems[index].path)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.gateway {
+  transform: none;
+  font-family: MicroSoft Yahei;
+  font-size: 16px;
+
+  .gateway-left {
+    padding: 32px 42px 0 0;
+    margin-right: 20.1vw;
+
+    &.without-right-nav {
+      margin-right: 0;
+    }
+  }
+
+  .gateway-right {
+    position: fixed;
+    top: 112px;
+    right: 0;
+    bottom: 0;
+    width: 20.1vw;
+    background: #fff;
+  }
+}
+</style>

+ 134 - 0
src/views/gateway/interface-add/Interfaceadd/Interfaceadd.scss

@@ -0,0 +1,134 @@
+.bf-Interfaceadd{
+    .el-dialog__header{
+        display: none;
+    }
+    .el-dialog{
+        border-radius: 20px;
+    }
+    .el-dialog__body{
+        padding: 0;
+        background: #ebeff6;
+        box-shadow: 0px 6px 10px 0px rgba(0, 0, 0, 0.3);
+        border-radius: 20px;
+        padding: 0 48px 0 48px;
+        >.Interfaceadd_header{
+            width: 100%;
+            height: 120px;
+            display: flex;
+            >.left{
+                width: 100%;
+                height: 100%;
+                display: flex;
+                align-items: center;
+                >p{
+                    font-size: 24px;
+                    font-family: Microsoft YaHei;
+                    font-weight: bold;
+                    color: #303133;
+                }
+            }
+        }
+        >.planbute{
+            width: 100%;
+            padding: 0 50px 0 50px;
+            height: 32px;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            margin-bottom: 24px;
+            >p{
+                font-size: 14px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #303133;
+                margin-top: 0;
+                margin-bottom: 0;
+                white-space:nowrap;
+                text-overflow:ellipsis;
+                margin-right: 16px;
+            }
+            >.el-input{
+                width: 200px;
+                height: 32px;
+                background: #F5F7FA;
+                border-radius: 8px;
+                >.el-input__inner{
+                    width: 100%;
+                    height: 100%;
+                    background: #F5F7FA;
+                    border: 1px solid #DCDFE6;
+                    border-radius: 8px;
+                }
+            }
+        }
+        >.planbutelast{
+            width: 100%;
+            padding: 0 50px 0 50px;
+            height: 32px;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            margin-bottom: 16px;
+            >p{
+                font-size: 14px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #303133;
+                margin-top: 0;
+                margin-bottom: 0;
+                white-space:nowrap;
+                text-overflow:ellipsis;
+                margin-right: 16px;
+            }
+            >.el-input{
+                width: 200px;
+                height: 32px;
+                background: #F5F7FA;
+                border-radius: 8px;
+                >.el-input__inner{
+                    width: 100%;
+                    height: 100%;
+                    background: #F5F7FA;
+                    border: 1px solid #DCDFE6;
+                    border-radius: 8px;
+                }
+            }
+        }
+        >.isfooterup{
+            width: 100%;
+            height: 128px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            >.but{
+                // padding: 0 24px 0 24px;
+                height: 32px;
+                // background: #303133;
+                // border-radius: 16px;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #FFFFFF;
+                margin-right: 16px;
+                // cursor: pointer;
+            }
+            >.buts{
+                // padding: 0 24px 0 24px;
+                height: 32px;           
+                // background: #FFFFFF;
+                // border-radius: 16px;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // cursor: pointer;
+            }
+        }
+    }
+}

+ 92 - 0
src/views/gateway/interface-add/Interfaceadd/index.vue

@@ -0,0 +1,92 @@
+<template>
+  <div class="bf-Interfaceadd">
+    <el-dialog
+      title=""
+      :visible.sync="dialogVisibleadd"
+      :modal-append-to-body="false"
+      :before-close="handleClose"
+      :width="isWidth"
+    >
+      <div class="Interfaceadd_header">
+        <div class="left">
+          <p>调用规则管理</p>
+        </div>
+      </div>
+      <div class="planbute">
+        <p>参数名</p>
+        <el-input
+          v-model="input"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="planbute">
+        <p>默认值</p>
+        <el-input
+          v-model="input2"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="planbute">
+        <p>数据类型</p>
+        <el-input
+          v-model="input3"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="planbutelast">
+        <p>参数位置</p>
+        <el-input
+          v-model="input4"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="isfooterup">
+        <!-- <div class="but">提交</div>
+                <div class="buts" @click="handleClose">取消</div> -->
+        <Bfbutton
+          :but-name="butName"
+          class="but"
+          :type="9"
+        />
+        <Bfbutton
+          :but-name="butNames"
+          class="buts"
+          :type="8"
+          @click.native="handleClose"
+        />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import './Interfaceadd.scss'
+import Bfbutton from '@/components/bfbutton/index.vue'
+export default {
+  components: {
+    Bfbutton
+  },
+  props: {
+    dialogVisibleadd: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      isWidth: '25%',
+      butName: '提交',
+      butNames: '取消',
+      input: '',
+      input2: '',
+      input3: '',
+      input4: ''
+    }
+  },
+  methods: {
+    handleClose() {
+      this.$emit('newAdd')
+    }
+  }
+}
+</script>
+<style lang="scss">
+</style>

+ 309 - 0
src/views/gateway/interface-add/Interfaceconfiguration/Interfaceconfiguration.scss

@@ -0,0 +1,309 @@
+.bf-Interfaceconfiguration{
+    // width: 98.7%;
+    height: 500px;
+    background: #FFFFFF;
+    box-shadow: 0px 6px 7px 0px rgba(0, 0, 0, 0.06);
+    border-radius: 16px;
+    padding-bottom: 64px;
+    // padding: 0 32px 0 32px;
+    >.configure_header{
+        width: 100%;
+        height: 88px;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: 16px;
+        padding: 0 32px 0 32px;
+        >p{
+            font-size: 24px;
+            font-family: Microsoft YaHei;
+            font-weight: bold;
+            color: #303133;
+            margin-top: 0;
+            margin-bottom: 0;
+        }
+        >.right{
+            height: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            >.but{
+                height: 32px;
+                margin-left: 24px;
+            }
+        }
+    }
+    >.Interface_drop{
+        width: 100%;
+        height: 33px;
+        display: flex;
+        align-items: center;
+        padding: 0 32px 0 32px;
+        >.attribute{
+            height: 100%;
+            display: flex;
+            align-items: center;
+            margin-right: 64px;
+            >p{
+                font-size: 14px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #303133;
+                display: inline;
+                white-space:nowrap;
+                text-overflow:ellipsis;
+                margin-top: 0;
+                margin-bottom: 0;
+                margin-right: 16px;
+            }
+            >.el-input{
+                width: 280px;
+                height: 32px;
+                background: #F5F7FA;
+                border-radius: 8px;
+                >.el-input__inner{
+                    width: 100%;
+                    height: 100%;
+                    background: #F5F7FA;
+                    border: 1px solid #DCDFE6;
+                    border-radius: 8px;
+                }
+            }
+        }
+        >.source{
+            height: 100%;
+            display: flex;
+            align-items: center;
+            margin-right: 64px;
+            >p{
+                font-size: 14px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #303133;
+                display: inline;
+                white-space:nowrap;
+                text-overflow:ellipsis;
+                margin-top: 0;
+                margin-bottom: 0;
+                margin-right: 16px;
+            }
+            >.el-select{
+                width: 160px;
+                height: 32px;
+                background: #F5F7FA;
+                border-radius: 8px;
+                .el-input__icon{
+                    line-height:33px
+                }
+                >.el-input{
+                    width: 100%;
+                    height: 100%;
+                    background: #F5F7FA;
+                    border-radius: 8px;
+                    >.el-input__inner{
+                        width: 100%;
+                        height: 100%;
+                        background: #F5F7FA;
+                        border: 1px solid #DCDFE6;
+                        border-radius: 8px;
+                    }
+                }
+            }
+        }
+    }
+    >.agreement{
+        width: 100%;
+        height: 33px;
+        display: flex;
+        align-items: center;
+        margin-top: 16px;
+        padding: 0 32px 0 32px;
+        >p{
+            font-size: 14px;
+            font-family: Microsoft YaHei;
+            font-weight: 400;
+            color: #303133;
+            margin-top: 0;
+            margin-bottom: 0;
+            margin-right: 62px;
+        }
+        .el-radio{
+            width: 120px;
+            margin-right: 0;
+        }
+        .el-radio__label{
+            color: #303133;
+        }
+        
+        .el-radio__input.is-checked + .el-radio__label {
+            color: #303133 !important;
+        }
+        .el-radio__input.is-checked .el-radio__inner {
+            background: #235395 !important;
+            border-color: #235395 !important;
+        }
+        .el-radio__inner{
+            width: 16px;
+            height: 16px;
+        }
+        .el-radio__inner::after{
+            width: 6px;
+            height: 6px;
+        }
+    }
+    >.boder{
+        width: 100%;
+        height: 1px;
+        background: #F5F7FA;
+        margin-top: 32px;
+    }
+    >.displaytitle{
+        width: 100%;
+        height: 81px;
+        display: flex;
+        align-items: center;
+        padding: 0 32px 0 32px;
+        >.displaytitle_cont{
+            border-right: 2px solid #C0C4CC;
+            padding-right: 30px;
+            padding-left: 32px;
+            >.upChild{
+                font-size: 16px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #909399;
+            }
+            >.upChilder{
+                font-size: 16px;
+                font-family: Microsoft YaHei;
+                font-weight: bold;
+                color: #5F82B2;
+            }
+        }
+        .displaytitle_cont:nth-child(1){
+            padding-left: 0;
+        }
+        .displaytitle_cont:last-child{
+            border-right: none;
+        }
+    }
+    >.request_path{
+        width: 100%;
+        height: 33px;
+        display: flex;
+        align-items: center;
+        margin-top: 10px;
+        padding: 0 32px 0 32px;
+        >.attribute{
+            height: 100%;
+            display: flex;
+            align-items: center;
+            margin-right: 64px;
+            >p{
+                font-size: 14px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #303133;
+                display: inline;
+                white-space:nowrap;
+                text-overflow:ellipsis;
+                margin-top: 0;
+                margin-bottom: 0;
+                margin-right: 16px;
+            }
+            >.el-input{
+                width: 280px;
+                height: 32px;
+                background: #F5F7FA;
+                border-radius: 8px;
+                >.el-input__inner{
+                    width: 100%;
+                    height: 100%;
+                    background: #F5F7FA;
+                    border: 1px solid #DCDFE6;
+                    border-radius: 8px;
+                }
+            }
+        }
+    }
+    >.request_type{
+        width: 100%;
+        height: 16px;
+        display: flex;
+        align-items: center;
+        margin-top: 34px;
+        padding: 0 32px 0 32px;
+        >p{
+            font-size: 14px;
+            font-family: Microsoft YaHei;
+            font-weight: 400;
+            color: #303133;
+            margin-top: 0;
+            margin-bottom: 0;
+            margin-right: 62px;
+        }
+        .el-radio{
+            // width: 120px;
+            margin-right:56px;
+        }
+        .el-radio__label{
+            color: #303133;
+        }
+        
+        .el-radio__input.is-checked + .el-radio__label {
+            color: #303133 !important;
+        }
+        .el-radio__input.is-checked .el-radio__inner {
+            background: #235395 !important;
+            border-color: #235395 !important;
+        }
+        .el-radio__inner{
+            width: 16px;
+            height: 16px;
+        }
+        .el-radio__inner::after{
+            width: 6px;
+            height: 6px;
+        }
+    }
+    >.data_type{
+        width: 100%;
+        height: 16px;
+        display: flex;
+        align-items: center;
+        margin-top: 34px;
+        padding: 0 32px 0 32px;
+        >p{
+            font-size: 14px;
+            font-family: Microsoft YaHei;
+            font-weight: 400;
+            color: #303133;
+            margin-top: 0;
+            margin-bottom: 0;
+            margin-right: 35px;
+        }
+        .el-radio{
+            // width: 120px;
+            margin-right:56px;
+        }
+        .el-radio__label{
+            color: #303133;
+        }
+        
+        .el-radio__input.is-checked + .el-radio__label {
+            color: #303133 !important;
+        }
+        .el-radio__input.is-checked .el-radio__inner {
+            background: #235395 !important;
+            border-color: #235395 !important;
+        }
+        .el-radio__inner{
+            width: 16px;
+            height: 16px;
+        }
+        .el-radio__inner::after{
+            width: 6px;
+            height: 6px;
+        }
+    }
+}

+ 264 - 0
src/views/gateway/interface-add/Interfaceconfiguration/index.vue

@@ -0,0 +1,264 @@
+<template>
+  <div class="bf-Interfaceconfiguration">
+    <div class="configure_header">
+      <p>接口配置</p>
+      <div class="right">
+        <Bfbutton
+          class="but"
+          :but-name="butCancel"
+          :type="8"
+          @click.native="$router.back()"
+        />
+        <Bfbutton
+          class="but"
+          :but-name="butReset"
+          :type="8"
+        />
+        <Bfbutton
+          class="but"
+          :but-name="butTest"
+          :type="8"
+          @click.native="tsetUp"
+        />
+        <Bfbutton
+          class="but"
+          :but-name="butPreser"
+          :type="9"
+        />
+      </div>
+    </div>
+    <div class="Interface_drop">
+      <div class="attribute">
+        <p>属性方式</p>
+        <el-input
+          v-model="input"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="source">
+        <p>关联源数据</p>
+        <el-select
+          v-model="value"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in options"
+            :key="item.id"
+            :label="item.label"
+            :value="item.label"
+          />
+        </el-select>
+      </div>
+      <div class="source">
+        <p>关联元数据</p>
+        <el-select
+          v-model="value"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in options"
+            :key="item.id"
+            :label="item.label"
+            :value="item.label"
+          />
+        </el-select>
+      </div>
+      <div class="source">
+        <p>调用规则</p>
+        <el-select
+          v-model="value"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in options"
+            :key="item.id"
+            :label="item.label"
+            :value="item.label"
+          />
+        </el-select>
+      </div>
+    </div>
+    <div class="agreement">
+      <p>协议类型</p>
+      <el-radio
+        v-for="(item,index) in optioner"
+        :key="index"
+        v-model="radio"
+        :label="item.id"
+        @change="onChange(index)"
+      >{{ item.label }}</el-radio>
+    </div>
+    <div class="boder" />
+    <div class="displaytitle">
+      <div
+        v-for="(item,index) in optioner"
+        :key="index"
+        class="displaytitle_cont"
+      >
+        <div :class="active === index ? 'upChilder' : 'upChild'">{{ item.label }}</div>
+      </div>
+    </div>
+    <div class="request_path">
+      <div class="attribute">
+        <p>请求路径</p>
+        <el-input
+          v-model="inputpath"
+          placeholder="请输入内容"
+        />
+      </div>
+    </div>
+    <div class="request_type">
+      <p>请求类型</p>
+      <el-radio
+        v-for="(item,index) in optiontype"
+        :key="index"
+        v-model="radios"
+        :label="item.id"
+      >{{ item.label }}</el-radio>
+    </div>
+    <div class="data_type">
+      <p>请求数据类型</p>
+      <el-radio
+        v-for="(item,index) in optionDateType"
+        :key="index"
+        v-model="radiotype"
+        :label="item.id"
+      >{{ item.label }}</el-radio>
+    </div>
+    <Testpop
+      :dialog-visibletest="dialogVisibletest"
+      @testClose="testClose"
+    />
+  </div>
+</template>
+<script>
+import './Interfaceconfiguration.scss'
+import Bfbutton from '@/components/bfbutton/index.vue'
+import Testpop from '../testpop/index.vue'
+export default {
+  components: {
+    Bfbutton,
+    Testpop
+  },
+  data() {
+    return {
+      input: '',
+      inputpath: '',
+      value: '',
+      radio: 1,
+      radios: 1,
+      radiotype: 1,
+      active: 0,
+      dialogVisibletest: false,
+      options: [
+        {
+          label: '选项一',
+          id: 1
+        },
+        {
+          label: '选项二',
+          id: 2
+        },
+        {
+          label: '选项三',
+          id: 3
+        }
+      ],
+      optioner: [
+        {
+          label: 'http/https',
+          id: 1
+        },
+        {
+          label: 'MQ',
+          id: 2
+        },
+        {
+          label: 'FTP',
+          id: 3
+        },
+        {
+          label: '脚本',
+          id: 4
+        },
+        {
+          label: '自定义',
+          id: 5
+        }
+      ],
+      optiontype: [
+        {
+          label: 'POST',
+          id: 1
+        },
+        {
+          label: 'GET',
+          id: 2
+        },
+        {
+          label: 'HEAD',
+          id: 3
+        },
+        {
+          label: 'PUT',
+          id: 4
+        },
+        {
+          label: 'DELETE',
+          id: 5
+        },
+        {
+          label: 'OPTIONS',
+          id: 6
+        },
+        {
+          label: 'TRACE',
+          id: 7
+        },
+        {
+          label: 'CONNECT',
+          id: 8
+        }
+      ],
+      optionDateType: [
+        {
+          label: 'application/json',
+          id: 1
+        },
+        {
+          label: 'application/text',
+          id: 2
+        },
+        {
+          label: 'multipart/form-data',
+          id: 3
+        },
+        {
+          label: 'application/x-www-form-urlencoded',
+          id: 4
+        }
+      ],
+      butCancel: '取消',
+      butReset: '重置',
+      butTest: '测试',
+      butPreser: '保存'
+    }
+  },
+  methods: {
+    onChange(index) {
+      // console.log(item)
+      this.active = index
+    },
+    // 打开弹窗
+    tsetUp() {
+      this.dialogVisibletest = !this.dialogVisibletest
+    },
+    // 弹窗取消
+    testClose() {
+      this.dialogVisibletest = false
+    }
+  }
+}
+</script>
+<style lang="scss">
+</style>

+ 197 - 0
src/views/gateway/interface-add/Interfaceparameter/Interfaceparameter.scss

@@ -0,0 +1,197 @@
+.bf-Interfaceparameter{
+    // width: 98.7%;
+    height: 540px;
+    background: #FFFFFF;
+    box-shadow: 0px 6px 7px 0px rgba(0, 0, 0, 0.06);
+    border-radius: 16px;
+    margin-top: 24px;
+    >.Interfaceparameter_header{
+        width: 100%;
+        height: 88px;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: 16px;
+        padding: 0 32px 0 32px;
+        >.left{
+            width: 50%;
+            height: 100%;
+            display: flex;
+            align-items: center;
+            >p{
+                font-size: 24px;
+                font-family: Microsoft YaHei;
+                font-weight: bold;
+                color: #303133;
+                margin-top: 0;
+                margin-bottom: 0;
+            }
+            >.parameter{
+                width: 156px;
+                height: 36px;
+                background: #F5F7FA;
+                border-radius: 4px;
+                margin-left: 80px;
+                display: flex;
+                align-items: center;
+                justify-content: space-around;
+                >.child{
+                    width: 72px;
+                    height: 30px;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    font-size: 16px;
+                    font-family: Microsoft YaHei;
+                    font-weight: 400;
+                    color: #606266;
+                    cursor: pointer;
+                }
+                >.childer{
+                    width: 72px;
+                    height: 30px;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    font-size: 16px;
+                    font-family: Microsoft YaHei;
+                    font-weight: 400;
+                    color: #606266;
+                    background: #FFFFFF;
+                    cursor: pointer;
+                }
+            }
+        }
+        >.right{
+            width: 50%;
+            height: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            >.imports{
+                height: 32px;
+                // padding: 0 47px 0 47px;
+                // height: 32px;
+                // border: 1px solid #E4E8F0;
+                // border-radius: 16px;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // cursor: pointer;
+                margin-right: 16px;
+            }
+            >.newadd{
+                height: 32px;
+                // padding: 0 47px 0 47px;
+                // height: 32px;
+                // border: 1px solid #E4E8F0;
+                // border-radius: 16px;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // cursor: pointer;
+            }
+        }
+    }
+    >.listheader{
+        width: 100%;
+        height: 64px;
+        border-radius: 8px;
+        padding: 0 32px 0 32px;
+        >ul{
+            width: 100%;
+            height: 100%;
+            display: flex;
+            background: #4A678E;
+            border-top-left-radius: 8px;
+            border-top-right-radius: 8px;
+            >li{
+                width: 25%;
+                height: 100%;
+                display: flex;
+                align-items: center;
+                justify-content: flex-start;
+                font-size: 16px;
+                font-family: Microsoft YaHei;
+                font-weight: bold;
+                color: #FFFFFF;
+                padding-left: 47px;
+            }
+        }
+    }
+    >.content{
+        width: 100%;
+        height: 320px;
+        padding: 0 32px 0 32px;
+        border-bottom-left-radius: 8px;
+        border-bottom-right-radius: 8px;
+        >.el-scrollbar{
+            border-bottom-left-radius: 8px;
+            border-bottom-right-radius: 8px;
+            >.el-scrollbar__wrap{
+                overflow-x: hidden;
+                ul{
+                    width: 100%;
+                    height: 64px;
+                    display: flex;
+                    margin: 0;
+                    >li{
+                        width: 25%;
+                        height: 100%;
+                        display: flex;
+                        align-items: center;
+                        justify-content: flex-start;
+                        font-size: 16px;
+                        font-family: Microsoft YaHei;
+                        font-weight: 400;
+                        color: #303133;
+                        padding-left: 47px;
+                        >.edit{
+                            // padding: 0 16px 0 16px;
+                            height: 32px;
+                            // background: #303133;
+                            // border-radius: 16px;
+                            // display: flex;
+                            // align-items: center;
+                            // justify-content: center;
+                            // font-size: 16px;
+                            // font-family: Microsoft YaHei;
+                            // font-weight: 400;
+                            // color: #FFFFFF;
+                            margin-right: 41px;
+                            // cursor: pointer;
+                        }
+                        >.deleter{
+                            // padding: 0 16px 0 16px;
+                            height: 32px;
+                            // border: 1px solid #F56C6C;
+                            // border-radius: 16px;
+                            // display: flex;
+                            // align-items: center;
+                            // justify-content: center;
+                            // font-size: 16px;
+                            // font-family: Microsoft YaHei;
+                            // font-weight: 400;
+                            // color: #F56C6C;
+                            // cursor: pointer;
+                        }
+                    }
+                }
+                ul:nth-child(odd){
+                    background: #f6f7fb;
+                }
+                ul:nth-child(even){
+                    background: #E3E8EF;
+                }
+            }
+        }
+    }
+}

+ 172 - 0
src/views/gateway/interface-add/Interfaceparameter/index.vue

@@ -0,0 +1,172 @@
+<template>
+  <div class="bf-Interfaceparameter">
+    <div class="Interfaceparameter_header">
+      <div class="left">
+        <p>接口参数配置</p>
+        <div class="parameter">
+          <div
+            v-for="(item,index) in option"
+            :key="index"
+            :class="active === index ? 'childer' : 'child'"
+            @click="upClick(index)"
+          >{{ item.name }}</div>
+        </div>
+      </div>
+      <div class="right">
+        <Bfbutton
+          :but-name="butName"
+          class="imports"
+          :type="4"
+        />
+        <!-- <div class="imports">导入</div> -->
+        <Bfbutton
+          :but-name="butNames"
+          :type="10"
+          class="newadd"
+          @click.native="newAdd"
+        />
+        <!-- <div class="newadd" @click="newAdd">新增</div> -->
+      </div>
+    </div>
+    <div class="listheader">
+      <ul>
+        <li
+          v-for="(item,index) in listHeader"
+          :key="index"
+        >{{ item.name }}</li>
+      </ul>
+    </div>
+    <div class="content">
+      <el-scrollbar style="height:100%">
+        <ul
+          v-for="(item,index) in list"
+          :key="index"
+        >
+          <li>{{ item.name }}</li>
+          <li>{{ item.value1 }}</li>
+          <li>{{ item.value2 }}</li>
+          <li>{{ item.value3 }}</li>
+          <li>
+            <!-- <div class="edit">编辑</div> -->
+            <Bfbutton
+              class="edit"
+              :but-name="butNameer"
+              :type="5"
+            />
+            <Bfbutton
+              :but-name="butNameers"
+              :type="6"
+              class="deleter"
+              @click.native="eledele"
+            />
+            <!-- <div class="deleter" @click="eledele">删除</div> -->
+          </li>
+        </ul>
+      </el-scrollbar>
+    </div>
+    <Deletepopup
+      :dialog-visibledele="dialogVisibledele"
+      @delepop="delepop"
+    />
+  </div>
+</template>
+<script>
+import './Interfaceparameter.scss'
+import Deletepopup from '@/components/deletepopup/index.vue'
+import Bfbutton from '@/components/bfbutton/index.vue'
+export default {
+  components: {
+    Deletepopup,
+    Bfbutton
+  },
+  data() {
+    return {
+      active: 0,
+      butName: '导入',
+      butNames: '新增',
+      butNameer: '编辑',
+      butNameers: '删除',
+      option: [
+        {
+          name: '入参'
+        },
+        {
+          name: '出参'
+        }
+      ],
+      listHeader: [
+        {
+          name: '参数名'
+        },
+        {
+          name: '默认值'
+        },
+        {
+          name: '数据类型'
+        },
+        {
+          name: '参数位置'
+        },
+        {
+          name: '操作'
+        }
+      ],
+      list: [
+        {
+          name: 'name',
+          value1: '张三',
+          value2: 'string',
+          value3: 'body'
+        },
+        {
+          name: 'name',
+          value1: '张三',
+          value2: 'string',
+          value3: 'body'
+        },
+        {
+          name: 'name',
+          value1: '张三',
+          value2: 'string',
+          value3: 'body'
+        },
+        {
+          name: 'name',
+          value1: '张三',
+          value2: 'string',
+          value3: 'body'
+        },
+        {
+          name: 'name',
+          value1: '张三',
+          value2: 'string',
+          value3: 'body'
+        },
+        {
+          name: 'name',
+          value1: '张三',
+          value2: 'string',
+          value3: 'body'
+        }
+      ],
+      dialogVisibledele: false
+    }
+  },
+  methods: {
+    upClick(index) {
+      this.active = index
+    },
+    newAdd() {
+      this.$emit('newAdd')
+    },
+    eledele() {
+      this.dialogVisibledele = !this.dialogVisibledele
+    },
+    delepop() {
+      this.dialogVisibledele = !this.dialogVisibledele
+    }
+  }
+}
+</script>
+<style lang="scss">
+</style>

+ 157 - 0
src/views/gateway/interface-add/associatedserver/associatedserver.scss

@@ -0,0 +1,157 @@
+.bf-associatedserver{
+    .el-dialog{
+        border-radius: 20px;
+    }
+    .el-dialog__header{
+        display: none;
+    }
+    .el-dialog__body{
+        padding: 0;
+        background: #F5F7FA;
+        box-shadow: 0px 6px 10px 0px rgba(0, 0, 0, 0.3);
+        border-radius: 20px;
+        padding: 0 48px 0 48px;
+        >.associatedserver_header{
+            width: 100%;
+            height: 120px;
+            display: flex;
+            >.left{
+                width: 100%;
+                height: 100%;
+                display: flex;
+                align-items: center;
+                >p{
+                    font-size: 24px;
+                    font-family: Microsoft YaHei;
+                    font-weight: bold;
+                    color: #303133;
+                }
+            }
+        }
+        >.associatedserver_content{
+            width: 100%;
+            height: 408px;
+            display: flex;
+            flex-wrap: wrap;
+            >.el-scrollbar{
+                >.el-scrollbar__wrap{
+                    overflow-x: hidden;
+                    >.el-scrollbar__view{
+                        // display: flex;
+                        // justify-content: space-between;
+                        // flex-wrap: wrap;
+                        .Server_card{
+                            width: 224px;
+                            height: 120px;
+                            background: #FFFFFF;
+                            box-shadow: 0px 6px 7px 0px rgba(0, 0, 0, 0.06);
+                            border-radius: 8px;
+                            float: left;
+                            margin-right: 14px;
+                            margin-bottom: 16px;
+                            padding: 0 16px 0 16px;
+                            >.Server_header{
+                                width: 100%;
+                                height: 48px;
+                                display: flex;
+                                align-items: center;
+                                justify-content: space-between;
+                                margin-bottom: 8px;
+                                >p{
+                                    font-size: 16px;
+                                    font-family: Microsoft YaHei;
+                                    font-weight: bold;
+                                    color: #303133;
+                                }
+                                .el-radio{
+                                    // width: 117px;
+                                    margin-right: 0;
+                                    // margin-bottom: 34px;
+                                }
+                                .el-radio__label{
+                                    color: #303133;
+                                    display: none;
+                                }
+                                
+                                .el-radio__input.is-checked + .el-radio__label {
+                                    color: #303133 !important;
+                                }
+                                .el-radio__input.is-checked .el-radio__inner {
+                                    background: #235395 !important;
+                                    border-color: #235395 !important;
+                                }
+                                .el-radio__inner{
+                                    width: 16px;
+                                    height: 16px;
+                                }
+                                .el-radio__inner::after{
+                                    width: 6px;
+                                    height: 6px;
+                                }
+                            }
+                            >.Server_content{
+                                width: 100%;
+                                height: 12px;
+                                display: flex;
+                                align-items: center;
+                                justify-content: space-between;
+                                margin-bottom: 16px;
+                                >p{
+                                    font-size: 14px;
+                                    font-family: Microsoft YaHei;
+                                    font-weight: 400;
+                                    color: #303133;
+                                }
+                                >span{
+                                    font-size: 14px;
+                                    font-family: Microsoft YaHei;
+                                    font-weight: 400;
+                                    color: #909399;
+                                }
+                            }
+                        }
+                        .Server_card:nth-child(4n){
+                            margin-right: 0;
+                        }
+                    }
+                }
+            }
+        }
+        >.isfooterup{
+            width: 100%;
+            height: 128px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            >.but{
+                // padding: 0 24px 0 24px;
+                height: 32px;
+                // background: #303133;
+                // border-radius: 16px;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #FFFFFF;
+                margin-right: 16px;
+                // cursor: pointer;
+            }
+            >.buts{
+                // padding: 0 24px 0 24px;
+                height: 32px;           
+                // background: #FFFFFF;
+                // border-radius: 16px;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // cursor: pointer;
+            }
+        }
+    }
+}

+ 159 - 0
src/views/gateway/interface-add/associatedserver/index.vue

@@ -0,0 +1,159 @@
+<template>
+  <div class="bf-associatedserver">
+    <el-dialog
+      title=""
+      :visible.sync="dialogVisibleass"
+      :modal-append-to-body="false"
+      :before-close="handleClose"
+      :width="isWidth"
+    >
+      <div class="associatedserver_header">
+        <div class="left">
+          <p>关联服务器</p>
+        </div>
+      </div>
+      <div class="associatedserver_content">
+        <el-scrollbar style="height:100%">
+          <div
+            v-for="(item,index) in optioner"
+            :key="index"
+            class="Server_card"
+          >
+            <div class="Server_header">
+              <p>{{ item.label }}</p>
+              <el-radio
+                v-model="radio"
+                :label="item.id"
+              />
+            </div>
+            <div class="Server_content">
+              <p>地址</p>
+              <span>{{ item.address }}</span>
+            </div>
+            <div class="Server_content">
+              <p>端口号</p>
+              <span>{{ item.port }}</span>
+            </div>
+          </div>
+        </el-scrollbar>
+        <!-- <el-radio v-model="radio" :label="item.id" v-for="(item,index) in optioner" :key="index">{{item.label}}</el-radio> -->
+      </div>
+      <div class="isfooterup">
+        <Bfbutton
+          :but-name="butName"
+          class="but"
+          :type="9"
+        />
+        <Bfbutton
+          :but-name="butNames"
+          :type="8"
+          class="buts"
+          @click.native="handleClose"
+        />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import './associatedserver.scss'
+import Bfbutton from '@/components/bfbutton/index.vue'
+export default {
+  components: {
+    Bfbutton
+  },
+  props: {
+    dialogVisibleass: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      isWidth: '54.5%',
+      butName: '提交',
+      butNames: '取消',
+      radio: 1,
+      optioner: [
+        {
+          label: '服务器名称',
+          id: 1,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 2,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 3,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 4,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 5,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 6,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 7,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 8,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 9,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 10,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 11,
+          address: '192.168.192.192',
+          port: '8080'
+        },
+        {
+          label: '服务器名称',
+          id: 12,
+          address: '192.168.192.192',
+          port: '8080'
+        }
+      ]
+    }
+  },
+  methods: {
+    handleClose() {
+      this.$emit('assAdd')
+    }
+  }
+}
+</script>
+<style lang="scss">
+</style>

+ 69 - 0
src/views/gateway/interface-add/index.vue

@@ -0,0 +1,69 @@
+<template>
+  <div class="newDatagovernanceadd">
+    <!-- 接口配置 -->
+    <Interfaceconfiguration />
+    <!-- 接口参数配置 -->
+    <Interfaceparameter @new-add="newAdd" />
+    <!-- 服务器配置 -->
+    <Serverconfiguration
+      @serve-add="serveAdd"
+      @ass-add="assAdd"
+    />
+    <!-- 接口参数新增弹窗 -->
+    <Interfaceadd
+      :dialog-visibleadd="dialogVisibleadd"
+      @new-add="newAdd"
+    />
+    <!-- 服务器新增 -->
+    <Theserverpop
+      :dialog-visibleserve="dialogVisibleserve"
+      @serve-add="serveAdd"
+    />
+    <!-- 关联服务器 -->
+    <Associatedserver
+      :dialog-visibleass="dialogVisibleass"
+      @ass-add="assAdd"
+    />
+  </div>
+</template>
+<script>
+import Interfaceconfiguration from './Interfaceconfiguration/index.vue'
+import Interfaceparameter from './Interfaceparameter/index.vue'
+import Serverconfiguration from './serverconfiguration/index.vue'
+import Interfaceadd from './Interfaceadd/index.vue'
+import Theserverpop from './theserverpop/index.vue'
+import Associatedserver from './associatedserver/index.vue'
+export default {
+  components: {
+    Interfaceconfiguration,
+    Interfaceparameter,
+    Serverconfiguration,
+    Interfaceadd,
+    Theserverpop,
+    Associatedserver
+  },
+  data() {
+    return {
+      dialogVisibleadd: false,
+      dialogVisibleserve: false,
+      dialogVisibleass: false
+    }
+  },
+  methods: {
+    newAdd() {
+      this.dialogVisibleadd = !this.dialogVisibleadd
+    },
+    serveAdd() {
+      this.dialogVisibleserve = !this.dialogVisibleserve
+    },
+    assAdd() {
+      this.dialogVisibleass = !this.dialogVisibleass
+    }
+  }
+}
+</script>
+<style lang="scss">
+.newDatagovernanceadd {
+  margin: 30px 0 30px 15px;
+}
+</style>

+ 156 - 0
src/views/gateway/interface-add/serverconfiguration/index.vue

@@ -0,0 +1,156 @@
+<template>
+  <div class="bf-serverconfiguration">
+    <div class="serverconfiguration_header">
+      <div class="left">
+        <p>服务器配置</p>
+      </div>
+      <div class="right">
+        <!-- <div class="relation_server" @click="newAss">关联服务器</div>
+                <div class="add_server" @click="newServe">新增服务器</div> -->
+        <Bfbutton
+          :but-name="butName"
+          :type="4"
+          class="relation_server"
+          @click.native="newAss"
+        />
+        <Bfbutton
+          :but-name="butNames"
+          :type="10"
+          class="add_server"
+          @click.native="newServe"
+        />
+      </div>
+    </div>
+    <div class="listheader">
+      <ul>
+        <li
+          v-for="(item,index) in listHeader"
+          :key="index"
+        >{{ item.name }}</li>
+      </ul>
+    </div>
+    <div class="content">
+      <el-scrollbar style="height:100%">
+        <ul
+          v-for="(item,index) in list"
+          :key="index"
+        >
+          <li>{{ item.name }}</li>
+          <li>{{ item.value1 }}</li>
+          <li>{{ item.value2 }}</li>
+          <li>{{ item.value3 }}</li>
+          <li>
+            <!-- <div class="edit">编辑</div>
+                        <div class="deleter"  @click="eledele">删除</div> -->
+            <Bfbutton
+              class="edit"
+              :but-name="butNameer"
+              :type="5"
+            />
+            <Bfbutton
+              class="deleter"
+              :but-name="butNameers"
+              :type="6"
+              @click.native="eledele"
+            />
+          </li>
+        </ul>
+      </el-scrollbar>
+    </div>
+    <Deletepopup
+      :dialog-visibledele="dialogVisibledele"
+      @delepop="delepop"
+    />
+  </div>
+</template>
+<script>
+import './serverconfiguration.scss'
+import Deletepopup from '@/components/deletepopup/index.vue'
+import Bfbutton from '@/components/bfbutton/index.vue'
+export default {
+  components: {
+    Deletepopup,
+    Bfbutton
+  },
+  data() {
+    return {
+      butName: '关联服务器',
+      butNames: '新增服务器',
+      butNameer: '编辑',
+      butNameers: '删除',
+      listHeader: [
+        {
+          name: '服务器名称'
+        },
+        {
+          name: '地址'
+        },
+        {
+          name: '端口号'
+        },
+        {
+          name: '描述'
+        },
+        {
+          name: '操作'
+        }
+      ],
+      list: [
+        {
+          name: '192.168.0.0.1',
+          value1: '8080',
+          value2: 'XXX服务器',
+          value3: 'XXX服务器用于XX服务部署'
+        },
+        {
+          name: '192.168.0.0.1',
+          value1: '8080',
+          value2: 'XXX服务器',
+          value3: 'XXX服务器用于XX服务部署'
+        },
+        {
+          name: '192.168.0.0.1',
+          value1: '8080',
+          value2: 'XXX服务器',
+          value3: 'XXX服务器用于XX服务部署'
+        },
+        {
+          name: '192.168.0.0.1',
+          value1: '8080',
+          value2: 'XXX服务器',
+          value3: 'XXX服务器用于XX服务部署'
+        },
+        {
+          name: '192.168.0.0.1',
+          value1: '8080',
+          value2: 'XXX服务器',
+          value3: 'XXX服务器用于XX服务部署'
+        },
+        {
+          name: '192.168.0.0.1',
+          value1: '8080',
+          value2: 'XXX服务器',
+          value3: 'XXX服务器用于XX服务部署'
+        }
+      ],
+      dialogVisibledele: false
+    }
+  },
+  methods: {
+    newServe() {
+      this.$emit('serveAdd')
+    },
+    newAss() {
+      this.$emit('assAdd')
+    },
+    eledele() {
+      this.dialogVisibledele = !this.dialogVisibledele
+    },
+    delepop() {
+      this.dialogVisibledele = !this.dialogVisibledele
+    }
+  }
+}
+</script>
+<style lang="scss">
+</style>

+ 160 - 0
src/views/gateway/interface-add/serverconfiguration/serverconfiguration.scss

@@ -0,0 +1,160 @@
+.bf-serverconfiguration{
+    // width: 98.7%;
+    height: 540px;
+    background: #FFFFFF;
+    box-shadow: 0px 6px 7px 0px rgba(0, 0, 0, 0.06);
+    border-radius: 16px;
+    margin-top: 24px;
+    >.serverconfiguration_header{
+        width: 100%;
+        height: 88px;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: 16px;
+        padding: 0 32px 0 32px;
+        >.left{
+            width: 50%;
+            height: 100%;
+            display: flex;
+            align-items: center;
+            >p{
+                font-size: 24px;
+                font-family: Microsoft YaHei;
+                font-weight: bold;
+                color: #303133;
+                margin-top: 0;
+                margin-bottom: 0;
+            }
+        }
+        >.right{
+            width: 50%;
+            height: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            >.relation_server{
+                height: 32px;
+                // border: 1px solid #E4E8F0;
+                // border-radius: 16px;
+                // padding: 0 23px 0 23px;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // cursor: pointer;
+                margin-right: 16px;
+            }
+            >.add_server{
+                height: 32px;
+                // border: 1px solid #E4E8F0;
+                // border-radius: 16px;
+                // padding: 0 23px 0 23px;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // cursor: pointer;
+            }
+        }
+    }
+    >.listheader{
+        width: 100%;
+        height: 64px;
+        border-radius: 8px;
+        padding: 0 32px 0 32px;
+        >ul{
+            width: 100%;
+            height: 100%;
+            display: flex;
+            background: #4A678E;
+            border-top-left-radius: 8px;
+            border-top-right-radius: 8px;
+            >li{
+                width: 25%;
+                height: 100%;
+                display: flex;
+                align-items: center;
+                justify-content: flex-start;
+                font-size: 16px;
+                font-family: Microsoft YaHei;
+                font-weight: bold;
+                color: #FFFFFF;
+                padding-left: 47px;
+            }
+        }
+    }
+    >.content{
+        width: 100%;
+        height: 320px;
+        padding: 0 32px 0 32px;
+        border-bottom-left-radius: 8px;
+        border-bottom-right-radius: 8px;
+        >.el-scrollbar{
+            border-bottom-left-radius: 8px;
+            border-bottom-right-radius: 8px;
+            >.el-scrollbar__wrap{
+                overflow-x: hidden;
+                ul{
+                    width: 100%;
+                    height: 64px;
+                    display: flex;
+                    margin: 0;
+                    >li{
+                        width: 25%;
+                        height: 100%;
+                        display: flex;
+                        align-items: center;
+                        justify-content: flex-start;
+                        font-size: 16px;
+                        font-family: Microsoft YaHei;
+                        font-weight: 400;
+                        color: #303133;
+                        padding-left: 47px;
+                        >.edit{
+                            // padding: 0 16px 0 16px;
+                            height: 32px;
+                            // background: #303133;
+                            // border-radius: 16px;
+                            // display: flex;
+                            // align-items: center;
+                            // justify-content: center;
+                            // font-size: 16px;
+                            // font-family: Microsoft YaHei;
+                            // font-weight: 400;
+                            // color: #FFFFFF;
+                            margin-right: 41px;
+                            // cursor: pointer;
+                        }
+                        >.deleter{
+                            // padding: 0 16px 0 16px;
+                            height: 32px;
+                            // border: 1px solid #F56C6C;
+                            // border-radius: 16px;
+                            // display: flex;
+                            // align-items: center;
+                            // justify-content: center;
+                            // font-size: 16px;
+                            // font-family: Microsoft YaHei;
+                            // font-weight: 400;
+                            // color: #F56C6C;
+                            // cursor: pointer;
+                        }
+                    }
+                }
+                ul:nth-child(odd){
+                    background: #f6f7fb;
+                }
+                ul:nth-child(even){
+                    background: #E3E8EF;
+                }
+            }
+        }
+    }
+}

+ 110 - 0
src/views/gateway/interface-add/testpop/index.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="bf-testpop">
+    <el-dialog
+      title=""
+      :visible.sync="dialogVisibletest"
+      :modal-append-to-body="false"
+      :before-close="handleClose"
+      :width="isWidth"
+    >
+      <div class="planningpop_header">
+        <div class="left">
+          <p>接口配置测试</p>
+        </div>
+      </div>
+      <div class="planningpop_content">
+        <el-input
+          v-model="textarea"
+          type="textarea"
+          :rows="7"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="footer">
+        <Bfbutton
+          class="but"
+          :but-name="butCancel"
+          :type="9"
+          @click.native="handleClose"
+        />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import Bfbutton from '@/components/bfbutton/index.vue'
+export default {
+  components: {
+    Bfbutton
+  },
+  props: {
+    dialogVisibletest: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      isWidth: '33%',
+      textarea: '',
+      butCancel: '确定'
+    }
+  },
+  methods: {
+    handleClose() {
+      this.$emit('testClose')
+    }
+  }
+}
+</script>
+<style lang="scss">
+.bf-testpop {
+  .el-dialog__header {
+    display: none;
+  }
+  .el-dialog {
+    border-radius: 20px;
+    .el-dialog__body {
+      // display: flex;
+      padding: 0;
+      background: #ffffff;
+      box-shadow: 0px 6px 10px 0px rgba(0, 0, 0, 0.3);
+      border-radius: 20px;
+      padding: 0 48px 0 48px;
+      > .planningpop_header {
+        width: 100%;
+        height: 120px;
+        display: flex;
+        > .left {
+          width: 50%;
+          height: 100%;
+          display: flex;
+          align-items: center;
+          > p {
+            font-size: 24px;
+            font-family: Microsoft YaHei;
+            font-weight: bold;
+            color: #303133;
+          }
+        }
+      }
+      > .planningpop_content {
+        .el-textarea__inner {
+          resize: none;
+          background: #f5f7fa;
+          border: 1px solid #dcdfe6;
+        }
+      }
+      > .footer {
+        width: 100%;
+        height: 88px;
+        display: flex;
+        align-items: center;
+        justify-content: flex-end;
+        > .but {
+          height: 32px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 92 - 0
src/views/gateway/interface-add/theserverpop/index.vue

@@ -0,0 +1,92 @@
+<template>
+  <div class="bf-theserverpop">
+    <el-dialog
+      title=""
+      :visible.sync="dialogVisibleserve"
+      :modal-append-to-body="false"
+      :before-close="handleClose"
+      :width="isWidth"
+    >
+      <div class="theserverpop_header">
+        <div class="left">
+          <p>服务器新增</p>
+        </div>
+      </div>
+      <div class="planbute">
+        <p>服务器名称</p>
+        <el-input
+          v-model="input"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="planbute">
+        <p>地址</p>
+        <el-input
+          v-model="input2"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="planbute">
+        <p>端口号</p>
+        <el-input
+          v-model="input3"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="planbutelast">
+        <p>描述</p>
+        <el-input
+          v-model="input4"
+          placeholder="请输入内容"
+        />
+      </div>
+      <div class="isfooterup">
+        <!-- <div class="but">提交</div>
+                <div class="buts" @click="handleClose">取消</div> -->
+        <Bfbutton
+          :but-name="butName"
+          :type="9"
+          class="but"
+        />
+        <Bfbutton
+          :but-name="butNames"
+          :type="8"
+          class="buts"
+          @click.native="handleClose"
+        />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import './theserverpop.scss'
+import Bfbutton from '@/components/bfbutton/index.vue'
+export default {
+  components: {
+    Bfbutton
+  },
+  props: {
+    dialogVisibleserve: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      isWidth: '25%',
+      butName: '提交',
+      butNames: '取消',
+      input: '',
+      input2: '',
+      input3: '',
+      input4: ''
+    }
+  },
+  methods: {
+    handleClose() {
+      this.$emit('serveAdd')
+    }
+  }
+}
+</script>
+<style lang="scss">
+</style>

+ 134 - 0
src/views/gateway/interface-add/theserverpop/theserverpop.scss

@@ -0,0 +1,134 @@
+.bf-theserverpop{
+    .el-dialog{
+        border-radius: 20px;
+    }
+    .el-dialog__header{
+        display: none;
+    }
+    .el-dialog__body{
+        padding: 0;
+        background: #F5F7FA;
+        box-shadow: 0px 6px 10px 0px rgba(0, 0, 0, 0.3);
+        border-radius: 20px;
+        padding: 0 48px 0 48px;
+        >.theserverpop_header{
+            width: 100%;
+            height: 120px;
+            display: flex;
+            >.left{
+                width: 100%;
+                height: 100%;
+                display: flex;
+                align-items: center;
+                >p{
+                    font-size: 24px;
+                    font-family: Microsoft YaHei;
+                    font-weight: bold;
+                    color: #303133;
+                }
+            }
+        }
+        >.planbute{
+            width: 100%;
+            padding: 0 50px 0 50px;
+            height: 32px;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            margin-bottom: 24px;
+            >p{
+                font-size: 14px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #303133;
+                margin-top: 0;
+                margin-bottom: 0;
+                white-space:nowrap;
+                text-overflow:ellipsis;
+                margin-right: 16px;
+            }
+            >.el-input{
+                width: 200px;
+                height: 32px;
+                background: #F5F7FA;
+                border-radius: 8px;
+                >.el-input__inner{
+                    width: 100%;
+                    height: 100%;
+                    background: #F5F7FA;
+                    border: 1px solid #DCDFE6;
+                    border-radius: 8px;
+                }
+            }
+        }
+        >.planbutelast{
+            width: 100%;
+            padding: 0 50px 0 50px;
+            height: 32px;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            margin-bottom: 16px;
+            >p{
+                font-size: 14px;
+                font-family: Microsoft YaHei;
+                font-weight: 400;
+                color: #303133;
+                margin-top: 0;
+                margin-bottom: 0;
+                white-space:nowrap;
+                text-overflow:ellipsis;
+                margin-right: 16px;
+            }
+            >.el-input{
+                width: 200px;
+                height: 32px;
+                background: #F5F7FA;
+                border-radius: 8px;
+                >.el-input__inner{
+                    width: 100%;
+                    height: 100%;
+                    background: #F5F7FA;
+                    border: 1px solid #DCDFE6;
+                    border-radius: 8px;
+                }
+            }
+        }
+        >.isfooterup{
+            width: 100%;
+            height: 128px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            >.but{
+                // padding: 0 24px 0 24px;
+                height: 32px;
+                // background: #303133;
+                // border-radius: 16px;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #FFFFFF;
+                margin-right: 16px;
+                // cursor: pointer;
+            }
+            >.buts{
+                // padding: 0 24px 0 24px;
+                height: 32px;           
+                // background: #FFFFFF;
+                // border-radius: 16px;
+                // display: flex;
+                // align-items: center;
+                // justify-content: center;
+                // font-size: 16px;
+                // font-family: Microsoft YaHei;
+                // font-weight: bold;
+                // color: #303133;
+                // cursor: pointer;
+            }
+        }
+    }
+}

+ 107 - 0
src/views/gateway/interface/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="gateway-interface">
+    <div class="gateway-interface-head">
+      <Search placeholder="请输入您要搜索的内容">
+        <button class="btnAdd" @click="$router.push('interface-add')">新增</button>
+      </Search>
+    </div>
+    <div class="gateway-interface-content">
+      <template v-if="interfaceList.length">
+        <el-row :gutter="24">
+          <el-col v-for="({ id, name, description, protocol }, index) in interfaceList" :key="id" :xs="24" :md="12" :lg="8" :xl="6">
+            <NormalCard :title="name" :flag.sync="interfaceList[index].flag" @close-click="removeCard(index)">
+              <template #default>
+                <el-row :gutter="25">
+                  <el-col :span="6" class="card-content-left">描述:</el-col>
+                  <el-col :span="18" class="card-content-right">{{ description }}</el-col>
+                  <el-col :span="6" class="card-content-left">协议:</el-col>
+                  <el-col :span="18" class="card-content-right">{{ protocol }}</el-col>
+                </el-row>
+              </template>
+            </NormalCard>
+          </el-col>
+        </el-row>
+      </template>
+      <template v-else>
+        <el-empty description="暂无数据" />
+      </template>
+    </div>
+  </div>
+</template>
+
+<script>
+import Search from '@/layout/components/Search'
+import NormalCard from '../components/NormalCard'
+import { getGatewayInterfaceList } from '@/api/gateway'
+
+export default {
+  name: 'GatewayInterface',
+  components: {
+    Search,
+    NormalCard
+  },
+  data () {
+    return {
+      interfaceList: [
+        {
+          id: 0,
+          name: '名称',
+          description: '/api/msgTemplateSetting/stopstart',
+          protocol: 'http',
+          flag: true
+        }
+      ]
+    }
+  },
+  created () {
+    this.fetchData()
+  },
+  methods: {
+    fetchData () {
+      this.listLoading = true
+      getGatewayInterfaceList().then(response => {
+        this.interfaceList.push(...response.data.items)
+        this.listLoading = false
+      })
+    },
+    removeCard (index) {
+      this.interfaceList.splice(index, 1)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.gateway-interface-head {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.gateway-interface-content {
+  margin-top: 32px;
+  height: calc(100vh - 224px);
+  overflow-x: hidden;
+  overflow-y: auto;
+
+  & > .el-row > .el-col {
+    margin-bottom: 24px;
+  }
+
+  ::v-deep .normal-card .card-content {
+    & > .el-row > .el-col:nth-child(2) {
+      margin-bottom: 24px;
+      height: 41px;
+      line-height: 24px;
+    }
+
+    .card-content-left {
+      word-break: keep-all;
+    }
+
+    .card-content-right {
+      color: #909399;
+      word-break: break-all;
+    }
+  }
+}
+</style>

+ 232 - 0
src/views/gateway/limit/index.vue

@@ -0,0 +1,232 @@
+<template>
+  <div class="gateway-limit">
+    <div class="gateway-limit-head">
+      <Search placeholder="请输入您要搜索的内容" :isSlot="true">
+        <button class="btnAdd" @click="dialogAddShow = true">新增</button>
+      </Search>
+    </div>
+    <div class="gateway-limit-content">
+      <template v-if="limitList.length">
+        <el-row :gutter="24">
+          <el-col
+            v-for="(
+              { id, name, visitTimes, visitDuration, inBlacklist }, index
+            ) in limitList"
+            :key="id"
+            :xs="24"
+            :md="12"
+            :lg="6"
+            :xl="6"
+          >
+            <NormalCard
+              :title="name"
+              :flag.sync="limitList[index].flag"
+              @close-click="removeCard(index)"
+            >
+              <el-row :gutter="16">
+                <el-col :span="12" class="card-content-left"
+                  >IP访问单位次数:</el-col
+                >
+                <el-col :span="12" class="card-content-right">{{
+                  visitTimes
+                }}</el-col>
+                <el-col :span="12" class="card-content-left"
+                  >IP访问单位时间:</el-col
+                >
+                <el-col :span="12" class="card-content-right">{{
+                  visitDuration
+                }}</el-col>
+                <el-col :span="12" class="card-content-left"
+                  >是否加入黑名单:</el-col
+                >
+                <el-col :span="12" class="card-content-right">{{
+                  inBlacklist ? "是" : "否"
+                }}</el-col>
+              </el-row>
+            </NormalCard>
+          </el-col>
+        </el-row>
+      </template>
+      <template v-else>
+        <el-empty description="暂无数据" />
+      </template>
+    </div>
+    <Dialog
+      :flag="dialogAddShow"
+      width="630px"
+      @close-dialog="dialogAddShow = false"
+    >
+      <div class="dialog-add-title">新增限流配置</div>
+      <div class="dialog-add-content">
+        <el-form :model="limitAddForm" label-width="auto">
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="IP单位访问时间">
+                <el-input
+                  v-model="limitAddForm.visitDuration"
+                  placeholder="请输入访问时间"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="IP访问单位次数">
+                <el-input
+                  v-model="limitAddForm.visitTimes"
+                  placeholder="请输入访问次数"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="是否加入黑名单">
+                <el-radio-group v-model="limitAddForm.inBlacklist">
+                  <el-radio :label="true">是</el-radio>
+                  <el-radio :label="false">否</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="是否启用">
+                <el-radio-group v-model="limitAddForm.enable">
+                  <el-radio :label="true">是</el-radio>
+                  <el-radio :label="false">否</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-form-item label="限流规则描述">
+            <el-input
+              v-model="limitAddForm.description"
+              placeholder="请输入描述"
+            />
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="dialog-add-bottom center">
+        <el-button size="medium" type="primary" @click="dialogAddShow = false"
+          >提交</el-button
+        >
+        <el-button
+          size="medium"
+          class="btn-cancel"
+          @click="dialogAddShow = false"
+          >取消</el-button
+        >
+      </div>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Search from "@/layout/components/Search";
+import NormalCard from "../components/NormalCard";
+import Dialog from "@/layout/components/Dialog";
+import { getGatewayLimitList } from "@/api/gateway";
+
+export default {
+  name: "GatewayLimit",
+  components: {
+    Search,
+    NormalCard,
+    Dialog,
+  },
+  data() {
+    return {
+      limitList: [
+        {
+          id: 0,
+          name: "访问规则名称",
+          visitTimes: 21090,
+          visitDuration: 21,
+          inBlackList: true,
+          flag: true,
+        },
+      ],
+      limitAddForm: {
+        visitTimes: "",
+        visitDuration: "",
+        inBlacklist: true,
+        enable: true,
+        description: "",
+      },
+      dialogAddShow: false,
+    };
+  },
+  created() {
+    this.fetchData();
+  },
+  methods: {
+    fetchData() {
+      this.listLoading = true;
+      getGatewayLimitList().then((response) => {
+        this.limitList.push(...response.data.items);
+        console.log(this.limitList);
+        this.listLoading = false;
+      });
+    },
+    removeCard(index) {
+      this.limitList.splice(index, 1);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.gateway-limit-head {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.gateway-limit-content {
+  margin-top: 32px;
+  height: calc(100vh - 224px);
+  overflow-x: hidden;
+  overflow-y: auto;
+
+  & > .el-row > .el-col {
+    margin-bottom: 24px;
+  }
+
+  ::v-deep .normal-card .card-content {
+    & > .el-row > .el-col {
+      margin-top: 21px;
+
+      &:nth-child(1),
+      &:nth-child(2) {
+        margin-top: 0;
+      }
+    }
+
+    .card-content-left {
+      word-break: keep-all;
+    }
+
+    .card-content-right {
+      color: #909399;
+      word-break: break-all;
+    }
+  }
+}
+
+.dialog-add-title {
+  font-size: 24px;
+  font-weight: bold;
+  color: #303133;
+}
+
+.dialog-add-content {
+  margin-top: 48px;
+  font-size: 14px;
+  font-weight: 400;
+  color: #303133;
+
+  ::v-deep .el-input .el-input__inner {
+    background-color: #f5f7fa;
+    border: 1px solid #dcdfe6;
+    border-radius: 8px;
+  }
+}
+
+.dialog-add-bottom {
+  margin-top: 48px;
+}
+</style>