边缘计算平台EdgeGallery前端源码分析02-开发者平台

news/2024/5/19 14:54:23 标签: 边缘计算, 前端, 人工智能

1 集成工具

首页主要由两部分组成 插件 和 上传

1.1 插件

插件页面由一个table表格组成并且可以根据插件名称和插件语言,进行筛选。

代码路径 developer\developer-fe\src\pages\plugin\List.vue

(1)table表格

<el-table
  :data="searchListData"  // 表格数据来源
  style="width: 100%"
  header-cell-class-name="headerStyle"
>
  <el-table-column
    :label="$t('workspace.icon')"
    width="280"
  >

searchListData为table表格的数据来源

页面挂载时,会调用getPluginListData方法,获取table表格展示需要的数据

getPluginListData () {
  Plugin.getPluginListApi(this.limitSize, this.offsetPage, this.inputPluginName, this.selectCodeLanguage).then(res => {
    this.searchListData = res.data.results
    this.listTotal = res.data.total
    this.dataLoading = false
  }).catch(err => {
    console.log(err)
    setTimeout(() => {
      this.dataLoading = false
    }, 2000)
  })
},
// getPluginListApi为发送请求的方法

getPluginListApi: function (limitSize, offsetPage, inputPluginName, selectCodeLanguage) {
    return Get('mec/developer/v1/plugins/?pluginType=1&limit=' + limitSize + '&offset=' + offsetPage + '&pluginName=' + inputPluginName + '&codeLanguage=' + selectCodeLanguage)
  },

(2)查询

用户可根据插件名称和插件语言,查询相关的内容。

点击查询按钮后,会调用searchPluginList方法,该方法会调用getPluginListData方法(上面分析过)请求数据

searchPluginList () {
  sessionStorage.setItem('currentPage', 1)
  this.getPluginListData() // 请求数据
},

1.2 上传

代码路径  developer\developer-fe\src\pages\plugin\Upload.vue

点击立即上传按钮,会调用submitTrue函数,该函数首先会进行上传前的参数校验,校验通过后,调用onSubmit函数

submitTrue () {
      this.uploadBtnLoading = true
      let pluginName = this.form.pluginName
      let nameRule = pluginName.match(/^\S.{0,29}$/g)
      let codeLanguage = this.form.codeLanguage
      let pluginType = this.form.pluginType
      let plugFileList = this.plugFileList.length
      let logoFileList = this.logoFileList.length || this.defaultIconFile.length
      let apiFileList = this.apiFileList.length
      let version = this.form.version
      let versionRule = version.match(/^[\w\\-][\w\\-\s.]{0,9}$/g)
      let introduction = this.form.introduction
      let introductionRule = introduction.match(/^(?!\s)(?![0-9]+$)[\S.\s\n\r]{1,1024}$/g)
      if (!pluginName) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.pluginNameEmpty')
        })
        this.uploadBtnLoading = false
      } else if (!nameRule) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.pluginNameRule')
        })
        this.uploadBtnLoading = false
      } else if (!codeLanguage) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.pluginFunEmpty')
        })
        this.uploadBtnLoading = false
      } else if (!pluginType) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.plugTypeEmpty')
        })
        this.uploadBtnLoading = false
      } else if (!plugFileList) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.pluginFileEmpty')
        })
        this.uploadBtnLoading = false
      } else if (!logoFileList) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.logoEmpty')
        })
        this.uploadBtnLoading = false
      } else if (!apiFileList) {
        this.$message({
          type: 'warning',
          message: this.$t('system.pleaseUpload') + this.$t('system.guideFileId')
        })
        this.uploadBtnLoading = false
      } else if (!version) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.versionEmpty')
        })
        this.uploadBtnLoading = false
      } else if (!versionRule) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.versionRule')
        })
        this.uploadBtnLoading = false
      } else if (!introduction) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.descriptionEmpty')
        })
        this.uploadBtnLoading = false
      } else if (!introductionRule) {
        this.$message({
          type: 'warning',
          message: this.$t('promptMessage.introductionRule')
        })
        this.uploadBtnLoading = false
      } else {
        this.onSubmit()  // 校验通过后,调用onSubmit函数
      }
    },
 onSubmit () {
  let formdata = new FormData()
  Object.keys(this.form).forEach(item => {
    formdata.append(item, this.form[item])
  })
  formdata.append('pluginFile', this.plugFileList[0])
  formdata.append('logoFile', this.form.appIcon.length > 0 ? this.form.appIcon[0] : this.defaultIconFile[0])
  formdata.append('apiFile', this.apiFileList[0])  //数据组装
  Plugin.uploadPluginApi(formdata).then(res => {  // 发送请求
    this.$message({
      message: this.$t('promptMessage.uploadSuccess'),
      type: 'success'
    })
    this.$router.push('/mecDeveloper/plugin/list')
  }).catch(err => {
    if (err.response.data.code === 403) {
      this.$message.error(this.$t('promptMessage.guestPrompt'))
    } else {
      this.$message.error(this.$t('promptMessage.uploadFailure'))
    }
    this.uploadBtnLoading = false
  })
},
  // 上传插件的接口
  uploadPluginApi: function (params) {
    return Post('mec/developer/v1/plugins/', params)
  },

2 工具箱

2.1 应用编辑

代码路径  developer\developer-fe\src\pages\toolBox\applicationEditor\Index.vue

工具箱页面由table表格组成

<el-table
    v-loading="loading"
    row-key="hostId"
    :data="allListData"  // table表格数据
    class="tableStyle"
  >
    <el-table-column
      prop="name"
      :label="$t('system.name')"
      min-width="10%"
    />

页面挂载时,会调用getListData 方法,获取table表格展示需要的数据

getListData () {
    // 请求接口
  applicationEditorApi.getReleasedPackage({ name: this.enterQuery, limit: this.limitSize, offset: this.offsetPage }).then(res => {
    this.allListData = res.data.results || []
    this.listTotal = res.data.total
    if (this.allListData) {
      this.allListData.forEach(item => {
        item.synchronizeDate = common.formatDate(item.synchronizeDate)
        this.changeIndustry(item)
        this.changeType(item)
      })
    }
  }).catch(() => {
    this.loading = false
  })
},

请求接口

getReleasedPackage: function (params) {
    return Get('mec/developer/v2/released-packages', params)
  },

应用编辑模块搜索时根据名称进行搜索,搜索会调用searchListData函数,该函数会调用getListData函数(上面分析过),将输入框输入的内容作为参数传递给接口

searchListData () {  //搜索触发该函数
  sessionStorage.setItem('currentPage', 1)
  this.getListData()  
},
getListData () {  // 发送请求  name: this.enterQuery,这个字段表示搜索名称
  applicationEditorApi.getReleasedPackage({ name: this.enterQuery, limit: this.limitSize, offset: this.offsetPage }).then(res => {
    this.allListData = res.data.results || []
    this.listTotal = res.data.total
    if (this.allListData) {
      this.allListData.forEach(item => {
        item.synchronizeDate = common.formatDate(item.synchronizeDate)
        this.changeIndustry(item)
        this.changeType(item)
      })
    }
  }).catch(() => {
    this.loading = false
  })
},

(2)选择应用

选择应用按钮点击后,会出现弹窗组件

弹窗组件代码路径  developer\developer-fe\src\pages\toolBox\applicationEditor\SelectApplicationDlg.vue

该弹窗组件由table表格组成

<el-table
  row-key="hostId"
  :data="allAppData"  //table表格数据
  class="tableStyle"
  @selection-change="handleSelectionChange"
>
  <el-table-column
    type="selection"
    width="55"
  />

页面挂载时,会调用getAppData方法,获取table表格展示需要的数据

getAppData () {
  let _searchCondition = {
    types: [],
    affinity: [],
    industry: [],
    showType: ['public', 'inner-public'],
    workloadType: [],
    userId: '',
    queryCtrl: {
      appName: '',
      status: ['Published'],
      offset: this.offsetPage,
      limit: this.limitSize,
      sortItem: 'createTime',
      sortType: 'desc'
    }
  }  // 数据组装
  applicationEditorApi.getAppData(_searchCondition).then((res) => {
    this.allAppData = res.data.results
    this.listTotal = res.data.total
  })
},

请求接口

getAppData: function (params) {
    return Post('mec/appstore/v2/apps/action/query', params, 'appstore')
  },

点击确定,会调用confirm函数,请求相应的接口,提交数据

confirm () {
  let params = []
  this.syncParams.forEach(item => {
    let _obj = {
      appId: '',
      packageId: ''
    }
    _obj.appId = item.appId
    _obj.packageId = item.packageId
    params.push(_obj)
  })  //数据组装
  applicationEditorApi.syncApplication(params).then(res => {  // 提交数据
    this.syncParams = []   
    this.$emit('getListData')
    this.closeDlg()
  }).catch((error) => {
    let defaultMsg = this.$t('toolBox.appEditor.syncFailed')
    commonUtil.showTipMsg(this.language, error, defaultMsg)
    this.closeDlg()
  })
}

提交数据的接口

  syncApplication: function (params) {
    return Post('mec/developer/v2/released-packages', params)
  },

3 工作空间

工作空间展示项目并且可以进行项目的创建

入口文件代码路径 developer\developer-fe\src\pages\workspace\Index.vue
table表格组件代码路径 developer\developer-fe\src\pages\workspace\ProjectList.vue

(1)table表格展示项目

<el-table
  v-loading="dataLoading"
  :data="allListData"  //表格数据来源
  :row-style="{marginBottom:'10px'}"
  style="width: 100%"
  class="tableStyle"
  :class="{'tableStyle_en':language=='en'}"
>
  <el-table-column
    prop="iconUrl"
    :label="$t('workspace.icon')"
    min-width="9.7%"
  >

页面初始化调用getProjectListData方法,该方法请求后端接口数据

getProjectListData () {
  const qs = { projectName: this.enterQuery, limit: this.limitSize, offset: this.offsetPage }
  Workspace.getProjectListApi(this.userId, qs).then(res => {  //调用接口
    if (res.data) {
      this.allListData = res.data.results || []
      this.listTotal = res.data.total
      if (this.pageData.length > 0) {
        this.pageData.sort(function (a, b) {
          return a.createDate < b.createDate ? 1 : -1
        })
      }
      let newItem = this.pageData.forEach((item, index) => {
        item.index = index + 1
        return newItem
      })
      this.pageData.forEach(item => {
        this.getIcon(item.iconFileId)
      })
      this.dataLoading = false
    }
  }).catch(err => {
    console.log(err)
    setTimeout(() => {
      this.dataLoading = false
    }, 2000)
  })
},

请求接口

  getProjectListApi: function (userId, params) {
    return Get('mec/developer/v1/projects/?userId=' + userId, params)
  },

(2)项目创建

1)应用集成项目

代码路径 developer\developer-fe\src\pages\workspace\AppDetail.vue

a)基本信息

代码路径 developer\developer-fe\src\pages\workspace\NewProjectFirst.vue

点击确定后,会调用 emitStepData方法,将form表单数据传递给父组件

// Pass the parameters to parent component
emitStepData () {
  this.$emit('getFormData', { data: this.form, step: 'first' })
},

接收数据,存储在allFormData对象中

getFormData ({ data, step }) {
  this.allFormData[step] = data
},

b)部署调测

1 文件导入

代码路径  developer\developer-fe\src\pages\workspace\ConfigYaml.vue

2 可视化配置

代码路径 developer\developer-fe\src\pages\workspace\ConfigVisual.vue

点击保存配置会调用saveConfig函数,发送请求给后端

 saveConfig () {
      let isSaveConfig = this.checkPodDataRequired() && this.checkServiceDataRequired()
      if (isSaveConfig) {
        let podArr = []
        let serviceArr = []
        if (this.ifSaveConfig) {
          this.deleteDataShow(podArr, serviceArr)
        }
        this.configData.deployYamls = []
        let podDataTemp = JSON.parse(JSON.stringify(this.podData))
        podDataTemp.forEach(podItem => {
          podItem.metadata.labels.app = podItem.metadata.name
          podItem.spec.containers.forEach(containersItem => {
            containersItem.image = '{{.Values.imagelocation.domainname}}/{{.Values.imagelocation.project}}/' + containersItem.image
            if (containersItem.command !== '' || containersItem.command !== null) {
              let str = containersItem.command
              let arr = str.split(' ')
              let str2 = JSON.stringify(arr)
              let str3 = str2.replace(/"/g, '\\"')
              containersItem.command = str3
            }
          })
          this.configData.deployYamls.push(podItem)
        })
        this.serviceData.forEach(serviceItem => {
          serviceItem.metadata.labels.svc = serviceItem.metadata.name
          serviceItem.spec.selector.app = serviceItem.metadata.name
          this.configData.deployYamls.push(serviceItem)
        })
        let params = JSON.stringify(this.configData.deployYamls)
        Workspace.postConfigVisualApi(this.projectId, this.userId, params, 'config').then(res => {
          this.$eg_messagebox(this.$t('workspace.visualConfig.saveConfigSuccess'), 'success')
          this.dialogVisible = true
          this.appYamlFileId = res.data.fileId
          this.markdownSource = '```yaml\r\n' + res.data.content + '\r\n```'
          this.viewConfigFileBtn = true
          this.$emit('getConfigVisual', this.appYamlFileId)
          this.submitData(this.appYamlFileId)
          this.setApiHeight()
        }).catch(() => {
          this.$eg_messagebox(this.$t('workspace.visualConfig.saveConfigFail'), 'error')
          this.appYamlFileId = ''
          this.markdownSource = ''
        })
      }
    },

请求接口

  postConfigVisualApi: function (projectId, userId, params, configType) {
    return Post('mec/developer/v1/deploy/' + projectId + '/action/save-yaml?userId=' + userId + '&configType=' + configType, params)
  },

3 应用发布

代码路径   developer\developer-fe\src\pages\workspace\AppRelease.vue

点击保存配置按钮,会调用saveConfig函数

    saveConfig () {
      let trafficDataTemp = JSON.parse(JSON.stringify(this.trafficListData))
      trafficDataTemp.forEach(item => {
        item.trafficFilter.forEach(subItem => {
          subItem.dstAddress = this.strToArray(subItem.dstAddress)
          subItem.dstPort = this.strToArray(subItem.dstPort)
          subItem.dstTunnelPort = this.strToArray(subItem.dstTunnelPort)
          subItem.protocol = this.strToArray(subItem.protocol)
          subItem.srcAddress = this.strToArray(subItem.srcAddress)
          subItem.srcPort = this.strToArray(subItem.srcPort)
          subItem.srcTunnelAddress = this.strToArray(subItem.srcTunnelAddress)
          subItem.srcTunnelPort = this.strToArray(subItem.srcTunnelPort)
          subItem.tag = this.strToArray(subItem.tag)
          subItem.tgtTunnelAddress = this.strToArray(subItem.tgtTunnelAddress)
        })
      })
      let appPublishConfigTemp = JSON.parse(JSON.stringify(this.appPublishListData))
      appPublishConfigTemp.forEach(item => {
        item.dnsRulesList = this.strToArray(item.dnsRulesList)
        item.trafficRulesList = this.strToArray(item.trafficRulesList)
      })
      this.trafficAllData.capabilitiesDetail.appTrafficRule = trafficDataTemp
      this.trafficAllData.capabilitiesDetail.appDNSRule = this.dnsListData
      this.trafficAllData.capabilitiesDetail.serviceDetails = appPublishConfigTemp
      this.trafficAllData.appInstanceId = sessionStorage.getItem('csarId')
      if (this.projectDetailData.appInstanceId || this.vmRelease) {
        this.getReleaseConfig(this.trafficAllData)   //发送请求
        this.isRelease = false
      } else {
        this.$eg_messagebox(this.$t('promptMessage.notDeploy'), 'warning')
        this.isRelease = true
      }
    },
    // Manually click the Save Rules button
    getReleaseConfig (params) {
      Workspace.getReleaseConfigApi(this.projectId).then(res => {  //请求
        let releaseId = res.data.releaseId
        this.trafficAllData.atpTest = res.data.atpTest
        Workspace.saveRuleConfig(this.projectId, params, releaseId).then(() => {
          this.$eg_messagebox(this.$t('promptMessage.saveRuleSuccess'), 'success')
          this.getReleaseConfigList()
        }).catch(() => {
          this.$eg_messagebox(this.$t('promptMessage.saveRuleFail'), 'error')
        })
      })
    },

请求接口

  getReleaseConfigApi (projectId) {
    return Get('mec/developer/v1/releaseconfig/' + projectId + '/action/release-config')
  },

4 系统

4.1 沙箱管理

代码路径 developer\developer-fe\src\pages\system\HostList.vue

(1)table表格展示

<el-table
    v-loading="loading"
    row-key="id"
    :data="allListData"  //table表格数据
    class="tableStyle"
  >
    <el-table-column
      prop="name"
      :label="$t('system.name')"
      min-width="10%"
    />
getListData () {
  this.loading = true
  System.getHosts({ name: this.enterQuery, vimType: '', architecture: '', limit: this.limitSize, offset: this.offsetPage }).then(res => {
    this.allListData = res.data.results || []  //数据来源
    this.listTotal = res.data.total
  }).finally(() => {
    this.loading = false
  })
},
接口
  getHosts: function (params) {
    return Get('mec/developer/v2/mephosts', params)
  },

(2)新增沙箱环境

点击按钮,调用handleShowForm函数,获取数据

handleShowForm (v) {
  this.form = JSON.parse(JSON.stringify(v))
  System.getFileInfo(this.form.configId).then(res => {
    if (res && res.data) {
      this.configId_file_list.length = 0
      let obj = { name: res.data.fileName }
      this.configId_file_list.push(obj)
    }
  })
  delete this.form.userName
  if (this.form.vimType === 'K8S') {
    this.showOther = false
  } else {
    this.showOther = true
  }
  this.configId_file_list = []
  this.visible = true
  this.$nextTick(() => {
    this.$refs.form.clearValidate()
  })
},

获取数据接口

  getFileInfo: function (fileId) {
    return Get('mec/developer/v2/upload-files/' + fileId)
  }

点击确认首先对表单数据进行校验,然后发送数据到后端

    onSubmit () {
      this.$refs.form.validate((valid, params) => {  //数据校验
        if (valid) {
          this.loading = true
          if (!this.showOther) {
            this.form.networkParameter = ''
          }
          //发送数据
          System.saveHostInfo({ ...this.form, ...params, userId: this.userName }).then(res => {
            if (res.data) {
              this.$eg_messagebox((this.form.id ? this.$t('api.modify') : this.$t('system.addHost')) + this.$t('system.success'), 'success')
              this.onClose()
            } else {
              throw new Error()
            }
          }).catch(error => {
            if (error.response.data.message === 'mecHost already exists!') {
              this.$eg_messagebox(this.$t('system.imageMgmt.tip.mecHostExist'), 'error')
            }
            let defaultMsg = this.$t('system.addHostFail')
            commonUtil.showTipMsg(this.language, error, defaultMsg)
          }).finally(() => {
            this.loading = false
            this.getListData()
          })
        }
      })
    },

请求接口

  saveHostInfo: function (params) {
    const func = params.id ? Put : Post
    const path = params.id ? `mec/developer/v2/mephosts/${params.id}` : 'mec/developer/v2/mephosts'
    const data = { ...params }
    return func(path, data)
  },

4.2 能力中心管理

代码路径  developer\developer-fe\src\pages\system\MepList.vue

(1)table表格

<el-table
    v-loading="loading"
    row-key="id"
    :data="allListData"  //数据来源
    class="tableStyle"
  >
    <el-table-column
      prop="name"
      :label="$t('system.serviceName')"
      min-width="14%"
    >

页面加载会调用getListData 函数,请求接口数据

getListData () {
  this.loading = true
  const qs = { offset: this.offsetPage, limit: this.limitSize }
  if (this.language === 'cn') {
    qs.name = this.enterQuery
    Capability.getCapabilityByNameWithFuzzy(qs).then(result => {
      this.allListData = result.data.results || []
      this.listTotal = result.data.total
    }).finally(() => {
      this.loading = false
    })
  } else {
    qs.nameEn = this.enterQuery
    Capability.getCapabilityByNameWithFuzzy(qs).then(result => {
      this.allListData = result.data.results || []
      this.listTotal = result.data.total
    }).finally(() => {
      this.loading = false
    })
  }
},

请求接口

  getCapabilityByNameWithFuzzy: function (params) {
    return Get('mec/developer/v2/query/capabilities/name', params)
  },

(2)新增服务

点击新增服务,会出现弹窗

<el-dialog
  :close-on-click-modal="false"
  :visible.sync="visible"
  class="dialog_service default_dialog"
  :class="{'dialog_service_en':language==='en'}"
>
  <el-form
    :model="form"
    ref="form"
    :rules="rules"
    :label-width="language==='cn'?formLabelWidth:formLabelWidthEn"
    label-position="right"
    class="clear"
    size="small"
  >

编辑完表单,点击确认后,调用onSubmit函数,将数据发送给后端服务

onSubmit () {
  if (!this.isAddService && this.logoFileList.length > 0) {
    this.form.appIcon = this.logoFileList
  }
  this.$refs['form'].validate((valid, params) => {
    if (valid) {
      this.loading = true
      let data = { ...this.form, ...params }
      data.group.type = 'OPENMEP'
      if (this.isAddService) {
        this.createCapabilityFun(data)   //创建
      } else {
        this.editCapabilityFun(data)  //编辑
      }
      this.loading = false
      sessionStorage.setItem('currentPage', 1)
    }
  })
},
createCapabilityFun (data) {  //创建
  Capability.createCapability(data).then(res => {
    if (res && res.data && res.data.id) {
      this.$eg_messagebox(this.$t('system.addMep') + this.$t('system.success'), 'success')
      this.onClose()
      this.$refs['form'].resetFields()
    } else {
      throw new Error()
    }
    this.getListData()
  }).catch(err => {
    if (err.response.data.message === 'The capability is exist') {
      this.$eg_messagebox(this.$t('system.isExistCapability'), 'error')
    } else {
      this.$eg_messagebox(this.$t('system.addMep') + this.$t('system.error'), 'error')
    }
  })
},
editCapabilityFun (data) {  //编辑
  Capability.editCapability(this.form.id, data).then(() => {
    this.$eg_messagebox(this.$t('api.modify') + this.$t('system.success'), 'success')
    this.onClose()
    this.$refs['form'].resetFields()
    this.getListData()
  }).catch(() => {
    this.$eg_messagebox(this.$t('api.modify') + this.$t('system.error'), 'error')
  })
},

调用接口

createCapability: function (capability) {  //创建
return Post('mec/developer/v2/capabilities', capability)
},
editCapability: function (capabilityId, capability) {   //编辑
return Put('mec/developer/v2/capabilities/' + capabilityId, capability)
},

4.3 系统镜像管理

代码路径 developer\developer-fe\src\pages\system\imagemgmt\Index.vue

(1)容器

代码路径 developer\developer-fe\src\pages\system\imagemgmt\ContainerImage.vue
<el-table
    :data="imageListData" //数据来源
    @sort-change="doSort"
    :default-sort="{prop: 'uploadTime', order: 'descending'}"
    v-loading="dataLoading"
    style="width: 100%"
    class="tableStyle default_dropdown"
  >
    <el-table-column
      prop="imageName"
      :label="$t('system.imageMgmt.imgName')"
      min-width="14%"
    >

页面挂载调用getImageDataList 函数,该函数请求后端接口数据

getImageDataList () {
  this.dataLoading = true
  imageMgmtService.getContainerImageDataList(this.buildQueryReq()).then(response => {
    this.imageListData = response.data.results
    this.listTotal = response.data.total
    this.dataLoading = false
  }).catch(() => {
    this.dataLoading = false
    this.$eg_messagebox(this.$t('system.imageMgmt.tip.queryImgFailed'), 'error')
  })
},

接口

  getContainerImageDataList: function (queryData) {
    return Post('mec/developer/v2/containerimages/action/get-all-images', queryData)
  },

(2)虚拟机和容器页面一样,请求的数据接口不同

代码路径  developer\developer-fe\src\pages\system\imagemgmt\VMImage.vue

请求接口

  getImageDataList: function (queryData) {
    return Post('mec/developer/v2/vmimages/action/get-list', queryData)
  },

(3)新建系统镜像

1)容器

代码路径 developer\developer-fe\src\pages\system\imagemgmt\UploadContainerImage.vue
onFileComplete () {
  this.isUploading = true
  this.isMerging = true
  const file = arguments[0].file
  //调用接口
  imageMgmtService.mergeContainerImage(this.imageId, file.name, arguments[0].uniqueIdentifier).then(response => {
    this.$message.success(this.$t('system.imageMgmt.tip.uploadImgSucceed'))
    let _timer = setTimeout(() => {
      clearTimeout(_timer)
      this.doClose()
    }, 1000)
    this.isUploading = false
  }).catch((error) => {
    let defaultMsg = this.$t('promptMessage.uploadFailure')
    commonUtil.showTipMsg(this.language, error, defaultMsg)
    this.doClose()
    this.isUploading = false
  })
},
  mergeContainerImage: function (imageId, fileName, identifier) {
    return Get('mec/developer/v2/containerimages/' + imageId + '/action/merge?fileName=' + fileName + '&guid=' + identifier)
  },

2)虚拟机

代码路径 developer\developer-fe\src\pages\system\imagemgmt\EditImage.vue

点击确认后,调用confirm函数

confirm () {
  this.$refs['imageDataForm'].validate((valid) => {
    if (!valid) {
      return
    }

    if (!this.isModify) {
      imageMgmtService.newImage(this.imageDataForm).then(() => {
        this.$message.success(this.$t('system.imageMgmt.tip.newImg') + this.$t('system.success'))
        this.$emit('processEditImageSuccess', 'vm')
      }).catch((error) => {
        this.processEditError(error)
      })
    } else {
      imageMgmtService.modifyImage(this.imageDataForm, this.systemIdToModi).then(() => {
        this.$message.success(this.$t('promptMessage.editSuccess'))
        this.$emit('processEditImageSuccess', 'vm')
      }).catch((error) => {
        this.processEditError(error)
      })
    }
  })
},

后端接口

  newImage: function (imgData) {
    return Post('mec/developer/v2/vmimages', imgData)
  },

4.4 场景管理

代码路径 developer\developer-fe\src\pages\system\profileMgmt\profileList.vue

该页面为table表格构成

<el-table
    v-loading="loading"
    row-key="hostId"
    :data="allListData"  //数据来源
    class="tableStyle"
  >
    <el-table-column
      prop="name"
      :label="$t('system.name')"
      min-width="10%"
    />

页面挂载调用getListData函数,发送请求

getListData () {
  profileMgmtApi.getProfileDataList({ name: this.enterQuery, limit: this.limitSize, offset: this.offsetPage }).then(res => {
    this.allListData = res.data.results || []
    this.listTotal = res.data.total
    if (this.allListData.length > 0) {
      this.allListData.forEach(item => {
        item.appList = item.appList.toString()
        this.changeIndustry(item)
        this.changeType(item)
      })
    }
  }).catch(() => {
    this.loading = false
  })
},

请求接口

  getProfileDataList: function (params) {
    return Get('mec/developer/v2/profiles', params)
  },


http://www.niftyadmin.cn/n/5420028.html

相关文章

【FreeRTOS任务调度机制学习】

FreeRTOS任务调度机制 1、通过就绪态&#xff08;ready&#xff09;、阻塞态链表&#xff08;delay&#xff09;、挂起态链表&#xff08;suspend&#xff09;进行任务调度。链表定义 2、TCB控制块结构体描述3、向就绪态任务链表增加任务就绪态链表结构体 4、向阻塞态任务链表增…

jar运行报错Unable to read meta-data for class

目录 一、场景描述 二、解决办法 1&#xff09;情况一 2&#xff09;情况二 贴一下部署报错堆栈信息&#xff1a; java.lang.IllegalStateException: Unable to read meta-data for class com.zhh.zhhd.biz.config.Test1Configat org.springframework.boot.autoconfigure.…

DHCP中继实验(思科)

华为设备参考&#xff1a;DHCP中继实验&#xff08;华为&#xff09; 一&#xff0c;技术简介 DHCP中继&#xff0c;可以实现在不同子网和物理网段之间处理和转发DHCP信息的功能。如果DHCP客户机与DHCP服务器在同一个物理网段&#xff0c;则客户机可以正确地获得动态分配的IP…

【数据可视化】动手用matplotlib绘制关联规则网络图

下载文中数据、代码、绘图结果 文章目录 关于数据绘图函数完整可运行的代码运行结果 关于数据 如果想知道本文的关联规则数据是怎么来的&#xff0c;请阅读这篇文章 绘图函数 Python中似乎没有很方便的绘制网络图的函数。 下面是本人自行实现的绘图函数&#xff0c;如果想…

打卡--MySQL8.0 一(单机部署)

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; MySQL 8.0 简介 MySQL 8.0与5.7的区别主要体现在&#xff1a;1、性能提升&#xff1b;2、新的默认…

谷歌浏览器批量下载单词限制为10

批量下载时&#xff0c;如果文件超过10个&#xff0c;谷歌浏览器只会下载前10个。【谷歌浏览器的一种压力保护吧】 可以使用以下方式解决这个问题。 fileList:[];//要下载的文件 downFile(url){let a document.createElement(a)console.log(this.downUrlurl)a.setAttrib…

c++之迭代器与反向迭代器

&#xff09; 正向迭代器迭代器的变量与typedef与模版operator()operator--()operator*()operator->() 反向迭代器模版与typedef与变量operator()operator--()operator*()operator->() 正向迭代器 以链表的迭代器为例 具体的代码以及可以看上一篇链表的文章:链表 迭代器的…

数字化转型导师坚鹏:科技金融政策、案例及营销创新

科技金融政策、案例及营销创新 课程背景&#xff1a; 很多银行存在以下问题&#xff1a; 不清楚科技金融有哪些利好的政策&#xff1f; 不知道科技金融有哪些成功的案例&#xff1f; 不知道科技金融如何进行营销创新&#xff1f; 课程特色&#xff1a; 以案例的方式解…