GateWayRouteModal.vue 9.96 KB
<template>
  <a-drawer
    :title="title"
    :maskClosable="true"
    width="45%"
    placement="right"
    v-if="visible"
    :closable="true"
    @close="handleCancel"
    :visible="visible"
    style="overflow: auto;padding-bottom: 53px;"
  >
    <a-form-model ref="form" :layout="layout" :label-col="labelCol" :wrapper-col="wrapperCol" :model="router">
      <a-form-model-item :label="$t('monitor.routerId')">
        <a-input v-model="router.routerId" :placeholder="$t('monitor.routerId')" />
      </a-form-model-item>
      <a-form-model-item :label="$t('monitor.routerName')">
        <a-input v-model="router.name" :placeholder="$t('monitor.routerName')" />
      </a-form-model-item>
      <a-form-model-item :label="$t('monitor.routerURI')">
        <a-input v-model="router.uri" :placeholder="$t('monitor.routerURI')" />
      </a-form-model-item>
      <a-form-model-item :label="$t('monitor.status')" prop="status">
        <a-switch default-checked v-model="router.status" />
      </a-form-model-item>
      <a-form-model-item prop="predicates" :label="$t('monitor.routingCondition')">
        <div v-for="(item, index) in router.predicates" :key="index">
          <a-divider>{{ item.name }}
            <a-icon type="delete" size="22" @click="removePredicate(router, index)" />
          </a-divider>
          <div>
            <template v-for="(tag, index) in item.args">
              <a-input
                v-if="index == currentTagIndex"
                ref="input"
                type="text"
                size="small"
                :style="{ width: '190px' }"
                :value="tag"
                @change="handleInputChange"
                @blur="handleInputEditConfirm(item, tag, index)"
                @keyup.enter="handleInputEditConfirm(item, tag, index)"
                :key="index"
              />
              <a-tag
                v-else
                :key="tag"
                :closable="true"
                @close="() => removeTag(item, tag)"
                @click="editTag(tag, index)"
              >
                {{ tag }}
              </a-tag>
            </template>
            <a-input
              v-if="inputVisible && index == currentNameIndex"
              ref="input"
              type="text"
              size="small"
              :style="{ width: '100px' }"
              :value="inputValue"
              @change="handleInputChange"
              @blur="handleInputConfirm(item)"
              @keyup.enter="handleInputConfirm(item)"
            />
            <a-tag v-else style="background: #fff; borderStyle: dashed;" @click="showInput(item, index)">
              <a-icon type="plus" /> {{ $t('button.search') }}{{ item.name }}
            </a-tag>
          </div>
        </div>
        <p class="btn" style="padding-top: 10px">
          <a-dropdown>
            <a-menu slot="overlay" @click="predicatesHandleMenuClick">
              <a-menu-item :key="item" v-for="item in tagArray">{{ item }}</a-menu-item>
            </a-menu>
            <a-button type="dashed" style="margin-left: 8px;width:100%"> {{ $t('monitor.addRoutingCondition') }} <a-icon type="down" /> </a-button>
          </a-dropdown>
        </p>
      </a-form-model-item>
      <a-form-model-item prop="predicates" :label="$t('monitor.filter')">
        <div v-for="(item, index) in router.filters" :key="index">
          <a-divider>{{ item.name }}
            <a-icon type="delete" size="22" @click="removeFilter(router, index)" />
          </a-divider>
          <div v-for="(tag, index) in item.args" :key="tag.key">
            <a-input v-model="tag.key" placeholder="参数键" style="width: 45%; margin-right: 8px" />
            <a-input v-model="tag.value" placeholder="参数值" style="width: 40%; margin-right: 8px" />
            <a-icon class="dynamic-delete-button" type="minus-circle-o" @click="removeFilterParams(item, index)" />
          </div>
          <a-button type="dashed" style="margin-left:28%;width: 30%" size="small" @click="addFilterParams(item)">
            <a-icon type="plus" /> {{ $t('monitor.addParameters') }} </a-button>
        </div>
        <p class="btn" style="padding-top: 10px">
          <a-dropdown>
            <a-menu slot="overlay" @click="filterHandleMenuClick">
              <a-menu-item :key="item.key" :name="item.name" v-for="item in filterArray">{{ item.name }}</a-menu-item>
            </a-menu>
            <a-button type="dashed" style="margin-left: 8px;width:100%"> {{ $t('monitor.addFilter') }} <a-icon type="down" /> </a-button>
          </a-dropdown>
        </p>
      </a-form-model-item>
      <a-row :style="{ textAlign: 'right' }" class="drawer-bootom-button">
        <a-button :style="{ marginRight: '8px' }" @click="handleCancel"> {{ $t('button.close') }} </a-button>
        <a-button @click="handleSubmit" type="primary"> {{ $t('button.ok') }} </a-button>
      </a-row>
    </a-form-model>
  </a-drawer>
</template>
<script>
import { postAction } from '@/api/manage'
import { translateResultMessage } from '@/api/api'

export default {
  name: 'GateWayRouteModal',
  components: {},
  data() {
    return {
      layout: 'horizontal',
      labelCol: { span: 3 },
      wrapperCol: { span: 14 },
      currentNameIndex: 0,
      currentTagIndex: -1,
      predicates: {},
      filterArray: [
        { key: 0, name: this.$t('monitor.fusibleLink'), },
        { key: 1, name: this.$t('monitor.restrictionFilters'), }
      ],
      tagArray: ['Path', 'Host', 'Cookie', 'Header', 'Method', 'Query', 'After', 'Before', 'Between', 'RemoteAddr'],
      inputVisible: false,
      inputValue: '',
      url: {
        update: '/sys/gatewayRoute/updateAll',
        clear: '/sys/gatewayRoute/clearRedis'
      },
      router: this.getRouter(),
      title: this.$t('monitor.routingEditor'),
      visible: false,
      loading: false
    }
  },
  methods: {
    getRouter() {
      return {
        routerId: '',
        name: '',
        uri: '',
        predicates: [],
        filters: []
      }
    },
    show(router) {
      if (router) {
        router.status = Boolean(router.status)
        this.router = router
      } else {
        this.router = this.getRouter()
        this.inputValue = ''
      }
      this.visible = true
      this.currentTagIndex = -1
      this.currentNameIndex = -1
    },
    close() {
      this.reset()
      this.$emit('close')
      this.$refs['form'].resetFields()
      this.visible = false
    },
    //删除路由条件配置项
    removeTag(item, removedTag) {
      const tags = item.args.filter(tag => tag !== removedTag)
      item.args = tags
    },
    //添加路由选项
    predicatesHandleMenuClick(e) {
      this.router.predicates.push({
        args: [],
        name: e.key
      })
    },
    editTag(tag, index) {
      this.currentTagIndex = index
    },
    //显示输入框
    showInput(item, index) {
      this.inputVisible = true
      this.currentNameIndex = index
    },
    //路由选项输入框失去焦点事件
    handleInputChange(e) {
      this.inputValue = e.target.value
    },
    //删除路由条件
    removePredicate(item, index) {
      item.predicates.splice(index, 1)
    },
    //删除过滤器参数
    removeFilterParams(item, index) {
      item.args.splice(index, 1)
    },
    //删除过滤器
    removeFilter(item, index) {
      item.filters.splice(index, 1)
    },
    //添加过滤器参数
    addFilterParams(item) {
      item.args.push({
        key: 'key' + item.args.length + 1,
        value: ''
      })
    },
    //过滤器添加事件
    filterHandleMenuClick(e) {
      if (e.key == 0) {
        this.router.filters.push({
          args: [
            {
              key: 'name',
              value: 'default'
            },
            {
              key: 'fallbackUri',
              value: 'forward:/fallback'
            }
          ],
          name: 'Hystrix',
          title: this.filterArray[0].name
        })
      }
      if (e.key == 1) {
        this.router.filters.push({
          args: [
            {
              key: 'key-resolver',
              value: '#{@ipKeyResolver}'
            },
            {
              key: 'redis-rate-limiter.replenishRate',
              value: 20
            },
            {
              key: 'redis-rate-limiter.burstCapacity',
              value: 20
            }
          ],
          name: 'RequestRateLimiter',
          title: this.filterArray[1].name
        })
      }
    },
    //输入框确认
    handleInputConfirm(item) {
      const inputValue = this.inputValue
      let tags = item.args
      if (inputValue && tags.indexOf(inputValue) === -1) {
        item.args = [...tags, inputValue]
      }
      console.log(tags)
      Object.assign(this, {
        tags,
        inputVisible: false,
        inputValue: ''
      })
      this.currentTagIndex = -1
    },
    //输入框确认
    handleInputEditConfirm(item, tag, index) {
      if (this.inputValue) {
        const inputValue = this.inputValue
        item.args[index] = inputValue
      }
      this.currentTagIndex = -1
    },
    reset() {
      this.expandedKeysss = []
      this.checkedKeys = []
      this.defaultCheckedKeys = []
      this.loading = false
    },
    //关闭弹窗
    handleCancel() {
      this.close()
    },
    //提交路由
    handleSubmit() {
      let { predicates, filters, ...other } = this.router
      let router = other
      router.predicates = JSON.stringify(this.router.predicates)
      router.filters = JSON.stringify(this.router.filters)
      postAction(this.url.update, {
        router
      }).then(res => {
        if (res.success) {
          this.close()
          this.$emit('ok')
          this.$message.success(translateResultMessage(res, res.message))
        } else {
          this.$message.error(translateResultMessage(res, res.message))
        }
      })
    }
  }
}
</script>
<style lang="less" scoped>
.drawer-bootom-button {
  position: absolute;
  bottom: 0;
  width: 100%;
  border-top: 1px solid #e8e8e8;
  padding: 10px 16px;
  text-align: right;
  left: 0;
  background: #fff;
  border-radius: 0 0 2px 2px;
}
</style>