0
点赞
收藏
分享

微信扫一扫

【动态表单,动态新增输入框,下拉框】

<template>

  <div id="detail">

    <DetailNavbar />

    <div class="app-container">

      <el-tabs v-model="activeName" @tab-click="handleClick">

        <el-tab-pane label="接口" name="interface">接口</el-tab-pane>

        <el-tab-pane label="数据管理" name="data">

          <el-form ref="dataForm" :model="dataForm" :rules="dataRules" label-width="100px" label-position="left">

            <el-form-item>

              <h3>数据导入</h3>

            </el-form-item>

            <el-form-item>

              Swagger

            </el-form-item>

            <el-form-item>

              <el-select ref="groupId" v-model="dataForm.groupId" style="width: 26%" placeholder="请选择所属分组">

                <el-option

                  v-for="item in groupOptions"

                  :key="item.id"

                  :value="item.id"

                  :label="item.name"

                />

              </el-select>

            </el-form-item>

            <el-form-item>

              开启url导入

              <el-tooltip class="item" effect="light" content="swagger url导入" placement="top">

                <i class="el-icon-question" />

              </el-tooltip>:

              <el-switch

                v-model="enableUrlImport"

                style="margin-left: 20px;"

                @change="changeEnable"

              />

            </el-form-item>

            <el-form-item>

              <el-upload

                v-show="!enableUrlImport"

                style="width: 360px"

                drag

                action=""

                :on-change="readFile"

              >

                <i class="el-icon-upload" />

                <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>

                <div slot="tip" class="el-upload__tip">只能上传Swagger文件,且不超过500kb</div>

              </el-upload>

              <el-input v-show="enableUrlImport" ref="url" v-model="dataForm.url" style="width: 26%" placeholder="http://demo.swagger.io/avatar-service/v2/api-docs" />

            </el-form-item>

            <el-form-item v-show="enableUrlImport">

              <el-button type="primary" @click="importSwagger">上传</el-button>

            </el-form-item>

          </el-form>

        </el-tab-pane>

        <el-tab-pane label="成员管理" name="members">成员管理</el-tab-pane>

        <el-tab-pane label="设置" name="setting">

          <div class="app-container">

            <el-tabs v-model="settingActiveName" type="card" @tab-click="settingHandleClick">

              <el-tab-pane label="项目配置" name="projectSetting">

                <el-form ref="projectForm" :model="projectForm" :rules="projectRules" label-width="250px" label-position="right">

                  <el-form-item prop="id" label="项目ID">

                    {{ projectForm.id }}

                  </el-form-item>

                  <el-form-item prop="name" label="项目名称">

                    <el-input ref="name" v-model="projectForm.name" style="width: 95%" placeholder="请输入项目名称" />

                  </el-form-item>

                  <el-form-item ref="groupId" prop="groupId" label="所属分组">

                    <el-select v-model="projectForm.groupId" style="width: 95%" placeholder="请选择所属分组">

                      <el-option

                        v-for="item in groupOptions"

                        :key="item.id"

                        :value="item.id"

                        :label="item.name"

                      />

                    </el-select>

                  </el-form-item>

                  <el-form-item prop="path" label="基本路径">

                    <label slot="label">

                      基本路径

                      <el-tooltip class="item" effect="light" content="接口基本路径,为空是根路径" placement="top">

                        <i class="el-icon-question" />

                      </el-tooltip>

                    </label>

                    <el-input ref="path" v-model="projectForm.path" style="width: 95%" placeholder="请输入基本路径" />

                  </el-form-item>

                  <el-form-item prop="description" label="描述">

                    <el-input

                      ref="description"

                      v-model="projectForm.description"

                      :autosize="{ minRows: 2, maxRows: 4}"

                      type="textarea"

                      style="width: 95%"

                      placeholder="请输入描述"

                    />

                  </el-form-item>

                  <el-form-item prop="access" label="权限">

                    <el-radio v-model="projectForm.access" label="1">

                      <i class="el-icon-lock" style="font-weight: 700; color: #5d5d5d;" />

                      <span style="font-weight: 700; color: #5d5d5d;">私有</span>

                    </el-radio>

                    <br>

                    <span style="margin-left: 24px; color: #919191">只有组长和项目开发者可以索引并查看项目信息</span>

                  </el-form-item>

                  <el-form-item>

                    <el-button type="primary" @click="submitForm('projectForm')">保存</el-button>

                    <div style="margin-top: 50px;">

                      <h2><i class="el-icon-warning">危险操作</i></h2>

                    </div>

                    <el-button type="danger" plain @click="deleteProject()">删除</el-button>

                  </el-form-item>

                </el-form>

              </el-tab-pane>

              <el-tab-pane label="环境配置" name="envSetting">

                <el-tabs v-model="editableTabsValue" type="card" editable @tab-click="tabClick" @edit="handleTabsEdit">

                  <el-tab-pane

                    v-for="item in enviromentList"

                    :key="item.id"

                    :label="item.title"

                    :name="item.name"

                  >

                    <el-form ref="dynamicValidateForm" :model="dynamicValidateForm" label-width="100px" class="demo-dynamic">

                      <el-form-item label="环境名称">

                        <el-input v-model="item.title" />

                      </el-form-item>

                      <el-form-item label="环境域名">

                        <el-select v-model="item.firstHost" style="width: 9%">

                          <el-option

                            v-for="host in hostOptions"

                            :key="host.key"

                            :value="host.value"

                            :label="host.label"

                          />

                        </el-select>

                        <el-input v-model="item.lastHost" style="width: 90%" />

                      </el-form-item>

                      <div style="margin-left: 40px; margin-bottom: -25px;">Header</div>

                      <el-form-item v-for="(header, index) in dynamicValidateForm.header" :key="header.key" :prop="'header.' + index + '.value'">

                        <el-select v-model="names[index]" allow-create filterable clearable placeholder="请输入header名称">

                          <el-option v-for="option in options" :key="option.key" :label="option.label" :value="option.value" />

                        </el-select>

                        <el-input v-model="values[index]" placeholder="请输入参数内容" style="width: 30%;" clearable />

                        <el-button @click.prevent="removeDomain(header)">删除</el-button>

                      </el-form-item>

                      <el-form-item>

                        <el-button @click="addHeader">新增属性</el-button>

                      </el-form-item>

                      <div style="margin-left: 40px; margin-bottom: -25px;">Cookie</div>

                      <el-form-item v-for="(cookie, index) in dynamicValidateForm.cookies" :key="cookie.key" :prop="'cookie.' + index + '.value'">

                        <el-input v-model="cookieNames[index]" placeholder="请输入cookie Name" style="width: 30%;" clearable />

                        <el-input v-model="cookieValues[index]" placeholder="请输入参数内容" style="width: 30%;" clearable />

                        <el-button @click.prevent="removeCookie(cookie)">删除</el-button>

                      </el-form-item>

                      <el-form-item>

                        <el-button @click="addCookie">新增属性</el-button>

                      </el-form-item>

                      <el-form-item>

                        <el-button @click="saveEnv">保存</el-button>

                      </el-form-item>

                    </el-form>

                  </el-tab-pane>

                </el-tabs>

              </el-tab-pane>

            </el-tabs>

          </div>

        </el-tab-pane>

      </el-tabs>

    </div>

  </div>

</template>

<script>

import DetailNavbar from '@/views/components/DetailNavbar'

import { getProject, getEnvironmentList, addEnvironment, updateEnvironment, deleteEnvironment, importSwagger } from '@/api/project-manager'

import { getGroupList, updateProject, deleteProject } from '@/api/group-manager'

import { deepClone } from '@/utils'

import { trimStr } from '@/utils/validate'

const HTTP_REQUEST_HEADER = ['Accept', 'Accept-Charset', 'Accept-Encoding', 'Accept-Language', 'Accept-Datetime', 'Authorization', 'Cache-Control', 'Connection', 'Cookie', 'Content-Disposition', 'Content-Length', 'Content-MD5', 'Content-Type', 'Date', 'Expect', 'From', 'Host', 'If-Match', 'If-Modified-Since', 'If-None-Match', 'If-Range', 'If-Unmodified-Since', 'Max-Forwards', 'Origin', 'Pragma', 'Proxy-Authorization', 'Range', 'Referer', 'TE', 'User-Agent', 'Upgrade', 'Via', 'Warning', 'X-Requested-With', 'DNT', 'X-Forwarded-For', 'X-Forwarded-Host', 'X-Forwarded-Proto', 'Front-End-Https', 'X-Http-Method-Override', 'X-ATT-DeviceId', 'X-Wap-Profile', 'Proxy-Connection', 'X-UIDH', 'X-Csrf-Token']

const state = {

  result: [],

  currentKey: -2

}

export default {

  components: {

    DetailNavbar

  },

  data() {

    const validateName = (rule, value, callback) => {

      const name = value && trimStr(value)

      if (name === '' || name === undefined) {

        callback(new Error('不能为空'))

      } else if (name.length > 64) {

        callback(new Error('不能超过64个字符'))

      } else {

        callback()

      }

    }

    const validateDescription = (rule, value, callback) => {

      const description = value && trimStr(value)

      if (description && description.length > 512) {

        callback(new Error('不能超过512个字符'))

      } else {

        callback()

      }

    }

    return {

      groupId: '',

      itemId: '',

      activeName: 'interface',

      settingActiveName: 'projectSetting',

      groupOptions: [],

      defaultProject: {},

      projectForm: {

        id: '',

        name: '',

        groupId: '',

        path: '',

        description: '',

        access: '1'

      },

      projectRules: {

        name: [{ required: true, trigger: 'blur', validator: validateName }],

        groupId: [{ required: true, trigger: 'blur' }],

        path: [{ required: false, trigger: 'blur' }],

        description: [{ required: false, trigger: 'blur', validator: validateDescription }],

        access: [{ required: true }]

      },

      enviromentList: [],

      currentEnv: {},

      editableTabsValue: '',

      options: [],

      tabIndex: 1,

      dynamicValidateForm: {

        header: [

          {

            value: ''

          }

        ],

        cookies: [

          {

            value: ''

          }

        ]

      },

      names: [],

      values: [],

      cookieNames: [],

      cookieValues: [],

      hostOptions: [

        {

          value: 'http://',

          label: 'http://'

        },

        {

          value: 'https://',

          label: 'https://'

        }

      ],

      dataRules: {

        groupId: [{ required: true, trigger: 'blur' }],

        jsonStr: [{ required: true, trigger: 'blur' }],

        url: [{ required: true, trigger: 'blur' }]

      },

      dataForm: {

        groupId: '',

        itemId: '',

        jsonStr: '',

        url: ''

      },

      enableUrlImport: false

    }

  },

  created() {

    this.groupId = this.$route.query.groupId

    const path = this.$route.path

    const params = path && path.split('\/')

    if (params.length) {

      this.itemId = params[2]

      this.activeIndex = params[3]

    }

    this.initOptions()

  },

  methods: {

    initImportData() {

      getGroupList().then(response => {

        this.groupOptions = response.result

      })

      this.dataForm.itemId = this.itemId

      this.dataForm.groupId = this.groupId

    },

    changeEnable(state) {

      this.enableUrlImport = state

    },

    importSwagger() {

      this.$refs.dataForm.validate((valid) => {

        if (valid) {

          if (this.enableUrlImport) {

            this.dataForm.jsonStr = ''

          } else {

            this.dataForm.url = ''

          }

          importSwagger(this.dataForm).then(response => {

            if (response) {

              this.$message({

                type: 'success',

                message: '导入成功!'

              })

            }

          })

        } else {

          return false

        }

      })

    },

    readFile(file) {

      const index = file.name.split('.')

      if (index[1] === 'json') {

        this.dataForm.jsonStr = ''

        const reader = new FileReader()

        reader.readAsText(file.raw)

        reader.onload = (e) => {

          // 读取文件内容

          const cont = e.target.result

          // 接下来可对文件内容进行处理

          this.dataForm.jsonStr += cont

        }

        if (trimStr(this.dataForm.jsonStr) !== '' ) {

          this.importSwagger()

        }

      } else {

        this.$message({

          type: 'error',

          message: '只支持Swagger json文件!'

        })

      }

    },

    initProject() {

      getGroupList().then(response => {

        this.groupOptions = response.result

      })

      this.getProject()

    },

    getProject() {

      getProject(this.itemId).then(response => {

        this.projectForm = deepClone(response.result)

        this.projectForm.access = '1'

        this.defaultProject = response.result

      })

    },

    submitForm(formName) {

      this.$refs[formName].validate(async(valid) => {

        if (valid) {

          await updateProject(this.projectForm).then(async(response) => {

            if (response) {

              this.$message({

                type: 'success',

                message: '修改成功!'

              })

            }

          })

        } else {

          return false

        }

      })

    },

    deleteProject() {

      this.$confirm('确定要删除项目:' + this.defaultProject.name + '吗?', 'Warning', {

        confirmButtonText: '确定',

        cancelButtonText: '取消',

        type: 'warning'

      })

        .then(async() => {

          const response = await deleteProject(this.itemId)

          if (response) {

            this.$router.push({ path: '/dashboard' })

            this.$message({

              type: 'success',

              message: '删除成功!'

            })

          }

        })

        .catch(err => { console.error(err) })

    },

    initOptions() {

      this.options = []

      for (let i = 0; i < HTTP_REQUEST_HEADER.length; i++) {

        const option = {

          value: HTTP_REQUEST_HEADER[i],

          label: HTTP_REQUEST_HEADER[i]

        }

        this.options.push(option)

      }

    },

    handleClick(tab, event) {

      let route = ''

      this.activeName = tab.name

      const path = this.$route.path

      const params = path && path.split('\/')

      if (params.length) {

        this.itemId = params[2]

        route = { path: '/projectDetail/' + this.itemId + '/' + this.activeName, query: { groupId: this.groupId }}

        if (this.activeName === 'setting') {

          this.initProject()

        } else if (this.activeName === 'data') {

          this.initImportData()

        }

      }

      this.$router.push(route)

    },

    settingHandleClick(tab, event) {

      if (tab.name === 'envSetting') {

        this.initEnvironment()

      } else {

        this.initProject()

      }

    },

    envHandleClick(key, data) {

      this.currentEnv = data

      this.currentKey = key

      this.initEnvParams()

    },

    initState(curdata) {

      const newValue = {}

      newValue['result'] = [].concat(curdata)

      this.setState(newValue, newValue['result'][0], 0)

    },

    setState(result, currentEnv, currentKey) {

      this.result = result

      this.currentKey = currentKey

      this.currentEnv = currentEnv

      this.initEnvParams()

    },

    initEnvironment() {

      getEnvironmentList(this.itemId).then(response => {

        this.enviromentList = response.result || []

        if (this.enviromentList && this.enviromentList.length) {

          for (const enviroment of this.enviromentList) {

            // 新增title属性显示页签

            this.$set(enviroment, 'title', enviroment.name)

            if (enviroment.host) {

              const hosts = enviroment.host.split(':\/\/')

              if (hosts.length === 2) {

                this.$set(enviroment, 'firstHost', hosts[0] + '://')

                this.$set(enviroment, 'lastHost', hosts[1])

              } else {

                this.$set(enviroment, 'firstHost', 'http://')

                this.$set(enviroment, 'lastHost', enviroment.host)

              }

            }

          }

          this.editableTabsValue = this.enviromentList[0].title

          this.currentEnv = this.enviromentList[0]

          this.initEnvParams()

          this.initState(this.enviromentList)

          this.envHandleClick(0, this.enviromentList[0])

        } else {

          // 没有环境配置时,默认新增

          this.handleTabsEdit(null, 'add')

        }

      })

    },

    initEnvParams() {

      this.dynamicValidateForm.header = [{ value: '', key: '' }]

      this.names = []

      this.values = []

      const header = this.currentEnv && this.currentEnv.header

      for (const key in header) {

        if (key && header[key]) {

          this.dynamicValidateForm.header.push({

            value: header[key],

            key: key

          })

          this.names.push(key)

          this.values.push(header[key])

        }

      }

      this.dynamicValidateForm.cookies = [{ value: '', key: '' }]

      this.cookieNames = []

      this.cookieValues = []

      const cookies = this.currentEnv && this.currentEnv.cookies

      for (const key in cookies) {

        if (key && cookies[key]) {

          this.dynamicValidateForm.cookies.push({

            value: cookies[key],

            key: key

          })

          this.cookieNames.push(key)

          this.cookieValues.push(cookies[key])

        }

      }

    },

    addEnvParams(name, data) {

      // 增加新环境变量项

      const newValue = {}

      data = { name: '', firstHost: 'http://', lastHost: '', header: {}, cookies: {}}

      newValue[name] = [].concat(data, state[name])

      this.setState(newValue)

      this.envHandleClick(0, data)

    },

    tabClick(tab, event) {

      this.envHandleClick(tab.index, this.enviromentList[tab.index])

    },

    handleTabsEdit(targetName, action) {

      if (action === 'add') {

        this.addEnvParams('result')

        const newTabName = 'local' + new Date().getTime() + ''

        this.enviromentList.push({

          name: newTabName,

          title: newTabName,

          firstHost: 'http://',

          lastHost: '',

          header: {},

          cookies: {}

        })

        this.editableTabsValue = newTabName

        this.currentEnv = this.enviromentList[this.enviromentList.length - 1]

      }

      if (action === 'remove') {

        // 删除页签

        this.$confirm('确定要删除环境:' + targetName + '吗?', 'Warning', {

          confirmButtonText: '确定',

          cancelButtonText: '取消',

          type: 'warning'

        })

          .then(async() => {

            const tabs = this.enviromentList

            let activeName = this.editableTabsValue

            if (activeName === targetName) {

              tabs.forEach((tab, index) => {

                if (tab.name === targetName) {

                  const nextTab = tabs[index + 1] || tabs[index - 1]

                  if (nextTab) {

                    activeName = nextTab.name

                  }

                }

              })

            }

            this.editableTabsValue = activeName

            this.enviromentList = tabs.filter(tab => tab.name !== targetName)

            if (this.currentEnv && this.currentEnv.id) {

              const queryParam = { itemId: this.itemId }

              const response = await deleteEnvironment(queryParam, this.currentEnv.id)

              if (response) {

                this.$message({

                  type: 'success',

                  message: '删除成功!'

                })

                this.initEnvironment()

              }

            } else {

              this.$message({

                type: 'success',

                message: '删除成功!'

              })

            }

          })

          .catch(err => { console.error(err) })

      }

    },

    removeDomain(item) {

      var index = this.dynamicValidateForm.header.indexOf(item)

      if (index !== -1) {

        this.dynamicValidateForm.header.splice(index, 1)

        this.names.splice(index, 1)

        this.values.splice(index, 1)

      }

    },

    addHeader() {

      this.dynamicValidateForm.header.push({

        value: '',

        key: Date.now()

      })

    },

    removeCookie(item) {

      var index = this.dynamicValidateForm.cookies.indexOf(item)

      if (index !== -1) {

        this.dynamicValidateForm.cookies.splice(index, 1)

        this.cookieNames.splice(index, 1)

        this.cookieValues.splice(index, 1)

      }

    },

    addCookie() {

      this.dynamicValidateForm.cookies.push({

        value: '',

        key: Date.now()

      })

    },

    saveEnv() {

      if (trimStr(this.currentEnv.title) === '') {

        this.$message({

          type: 'error',

          message: '请输入环境名称!'

        })

        return false

      }

      if (trimStr(this.currentEnv.lastHost) === '') {

        this.$message({

          type: 'error',

          message: '请输入环境域名!'

        })

        return false

      }

      const arryKey = [...this.names, ...this.cookieNames]

      const arrySet = new Set(arryKey)

      if (arryKey.length !== arrySet.size) {

        this.$message({

          type: 'error',

          message: '存在重复key,请检查重新输入'

        })

        return false

      }

      if (this.names.length !== this.values.length) {

        this.$message({

          type: 'error',

          message: 'Header 属性必需成对出现且不能为空,请检查重新输入'

        })

        return false

      } else {

        for (let i = 0; i < this.names.length; i++) {

          if (trimStr(this.names[i]) === '' || trimStr(this.values[i]) === '') {

            this.$message({

              type: 'error',

              message: 'Header 属性必需成对出现且不能为空,请检查重新输入'

            })

            return false

          }

        }

      }

      if (this.cookieNames.length !== this.cookieValues.length) {

        this.$message({

          type: 'error',

          message: 'Cookie 属性必需成对出现且不能为空,请检查重新输入'

        })

        return false

      } else {

        for (let i = 0; i < this.cookieNames.length; i++) {

          if (trimStr(this.cookieNames[i]) !== '') {

            if (trimStr(this.cookieValues[i]) === '') {

              this.$message({

                type: 'error',

                message: 'Cookie 属性必需成对出现且不能为空,请检查重新输入'

              })

              return false

            }

          }

        }

      }

      const header = {}

      for (let i = 0; i < this.names.length; i++) {

        if (trimStr(this.names[i]) !== '') {

          const headerKey = trimStr(this.names[i])

          const headValue = trimStr(this.values[i])

          header[headerKey] = headValue

        }

      }

      const cookies = {}

      for (let i = 0; i < this.cookieNames.length; i++) {

        if (trimStr(this.cookieNames[i]) !== '') {

          const cookieKey = trimStr(this.cookieNames[i])

          const cookieValue = trimStr(this.cookieValues[i])

          cookies[cookieKey] = cookieValue

        }

      }

      let params = {

        host: this.currentEnv.firstHost + this.currentEnv.lastHost,

        name: this.currentEnv.title,

        cookies: cookies,

        header: header

      }

      const queryParam = { itemId: this.itemId }

      if (this.currentEnv.id) {

        params = Object.assign(params,

          {

            id: this.currentEnv.id

          })

        updateEnvironment(queryParam, params).then(response => {

          if (response) {

            this.$message({

              type: 'success',

              message: '修改成功!'

            })

            this.initEnvironment()

          }

        })

      } else {

        addEnvironment(queryParam, params).then(response => {

          if (response) {

            this.$message({

              type: 'success',

              message: '新增环境成功!'

            })

            this.initEnvironment()

          }

        })

      }

    }

  }

}

</script>

<style lang="scss" scoped>

</style>

举报

相关推荐

0 条评论