(el-Transfer)操作(不使用 ts):Element-plus 中 Transfer 穿梭框右侧数据不展示的问题

Ⅰ、Element-plus 提供的Transfer树形控件组件与想要目标情况的对比:

1、Element-plus 提供Transfer组件情况:

其一、Element-ui 自提供的Transfer代码情况为(示例的代码):

在这里插入图片描述


<template>
  <p style="text-align: center; margin: 0 0 20px">
    Customize data items using render-content
  </p>
  <div style="text-align: center">
    <el-transfer
      v-model="leftValue"
      style="text-align: left; display: inline-block"
      filterable
      :left-default-checked="[2, 3]"
      :right-default-checked="[1]"
      :titles="['Source', 'Target']"
      :button-texts="['To left', 'To right']"
      :format="{
        noChecked: '${total}',
        hasChecked: '${checked}/${total}',
      }"
      :data="data"
      @change="handleChange"
    >
      <template #left-footer>
        <el-button class="transfer-footer" size="small">Operation</el-button>
      </template>
      <template #right-footer>
        <el-button class="transfer-footer" size="small">Operation</el-button>
      </template>
    </el-transfer>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'

const generateData = () => {
  const data = []
  for (let i = 1; i <= 15; i++) {
    data.push({
      key: i,
      label: `Option ${i}`,
      disabled: i % 4 === 0,
    })
  }
  return data
}

const data = ref(generateData())
const leftValue = ref([1])
</script>

<style>
.transfer-footer {
  margin-left: 15px;
  padding: 6px 5px;
}
</style>

代码地址:https://element-plus.gitee.io/zh-CN/component/transfer.html

其二、页面的显示情况为:
在这里插入图片描述

Ⅱ、在项目中使用 Transfer 组件遇到的问题:

1、在 table 表格中选中值后,并调用 transfer 后右侧的已选端口值不展示:

其一、代码:

// 此下的有些代码是默认不展示的:
<script setup>
import axios from 'axios';
const rootapi = inject("rootapi");
import { ref,inject,onMounted,reactive } from 'vue'
import { ElMessage } from 'element-plus'

const addFormRef = ref(null)
const aggrEditFormRef = ref(null)
const aggrEditDialogVisible = ref(false)
const aggrLabelWidth = '100px'
const edit_table_data = ref([])
const aggrEditForm = ref({})
const multipleTable = ref('')

const value = ref([])
const checkedArray = ref([])

const rightPorts = ref([])

// const configurationForm = ref({
//   lag_mode: "hash_mac"
// })

const addForm = ref({
  lag_id: ''
})

const tableData = ref([])

// 生成有效端口值;
const generateData = () => {
  const data = []
  for (let i = 1; i <= 28; i++) {
    data.push({
      key: i,
      // key: `${i}`,
      label: `GigabitEthernet0/${i}`
    })
  }
  return data
}

// 注意:此时 generateData() 函数一定要在定义 data 数据前,才不会报错; 
const data = ref(generateData())

const tableRowClassName = (val) => {
  if(val.rowIndex %2 === 0) {
    return 'success-row'
  } else {
    return 'warning-row'
  }
}


// 添加 LAG 的校验;
const checkAggrLag = (rule, value, callback) => {
  if (!value) {
    return callback(new Error('此处不能为空'))
  }
  setTimeout(() => {
    if(/^([1-9]|(1[0-6]))$/.test(value)) {
      callback()
    } else {
      callback(new Error('请填写 1~16 的值'))
    }
  }, 10)
}

// 添加 LAG 聚合表组的校验;
const addRules = ref({
  lag_id: [
    {required: true, validator: checkAggrLag, trigger: 'blur' }
  ]
})


// 聚合组表的单选操作(之前仅存在第一次进入右侧没数据的代码);
const changeSelect = (val) => {
  // edit_table_data.value = val
  // console.log(edit_table_data.value,111111);
  let res = val.map((item) => {
      let obj = {
        lag_id: item.lag_id,
        member_ports: item.member_ports.map(item => {
          return item.split('/')[1]
        })
      }
      return obj     
  })
  // rightPorts.value=res
  edit_table_data.value = res
  handleRightChange()
  console.log(edit_table_data.value,1111111);
  // select_table_data.value = res
}


// 聚合组表的多选操作;
const changeAllSelect = (val) => {
  // edit_table_data.value = val
  // console.log(edit_table_data.value,111111);
  let res = val.map((item) => {
      let obj = {
        lag_id: item.lag_id,
        member_ports: item.member_ports.map(item => {
          return item.split('/')[1]
        })
      }
      return obj     
  })
  edit_table_data.value = res
  console.log(edit_table_data.value,1111111);
  // select_table_data.value = res
}


// 聚合组表的修改操作(之前仅存在第一次进入右侧没数据的代码);
const handleAggrEdit = () => {
  if(edit_table_data.value.length === 1) {
    aggrEditDialogVisible.value = true

    aggrEditForm.value = edit_table_data.value[0]
    // aggrEditForm.value = edit_table_data.value[0]

    // aggrEditForm.value.lag_id = edit_table_data.value[0].lag_id
    // aggrEditForm.value.member_ports = edit_table_data.value[0].member_ports.map(item => 'GigabitEthernet0/'+item)
    // rightPorts.value = edit_table_data.value[0].member_ports

    // aggrEditForm.value.member_ports = edit_table_data.value[0].member_ports

    console.log(edit_table_data.value,666666666);
    console.log(edit_table_data.value[0],7777777777);
    console.log(aggrEditForm.value,8888888888888);
    console.log(aggrEditForm.value.member_ports,89898989898);
    // console.log(tableData.value,123);

    // 重新调用生成端口的函数,防止某些值被清理;
    generateData()

    // 选中所有表中所有的 member 值(此时才没有问题);
    let seletedArray1 = []
    tableData.value.forEach(item => item.member_ports.forEach(it => seletedArray1.push(it.split('/')[1])))
    checkedArray.value = seletedArray1
    seletedArray1 = []

    // let disableArray = edit_table_data.value[0].member_ports.map(item => 'GigabitEthernet0/'+item)

    // console.log(disableArray,1111111111111111);
    console.log(edit_table_data.value[0].member_ports,1111111111111111);
    console.log(checkedArray.value,222222222222);

    // 去除待选择的 member 值(即:从一个数组中去除另一个数组中存在数据的操作);
    checkedArray.value = checkedArray.value.filter(item => !edit_table_data.value[0].member_ports.includes(item));

    data.value = data.value.filter(item => item.label =  item.label.split('/')[1])

    console.log(checkedArray.value,123);
    console.log(data.value,456);
    
    // 有效端口的禁选操作;
    let res = data.value.map(item => {
      // 此时返回值 flag 是数值,而不是布尔值;
      let flag = checkedArray.value.find(it => it === item.label)
      let obj
      if(flag) {
        obj = {
          key: flag,
          label: `GigabitEthernet0/${flag}`,
          disabled: true
        }
      } else {
        obj = {
          key: item.key,
          // key: `${item.key}`,
          label: `GigabitEthernet0/${item.key}`,
        }
      }
      return obj
    })


    // 另一种解决方案:
    // let res = data.value.filter(item => {
    //   let flag = checkedArray.value.find(it => it === item.key)
    //   return item.key !== flag
    // })
    
    // console.log(res,123456);

    data.value = res
    console.log(data.value,789);
  } else if(edit_table_data.value.length === 0 ) { 
    ElMessage({ message: '请选择一个来修改!',type: 'warning'})
  } else {
    ElMessage.error('只能选择一个来修改!')
  }
}

const aggrOnCancle = () => {
  toggleSelection()
  // 此时是取消:修改和删除的记忆功能(即:取消后,不能直接点击修改或删除按钮);
  edit_table_data.value = []
  aggrEditDialogVisible.value = false
}

// 清除 Table 清空用户选择的操作;
const toggleSelection = (rows) => {
  if (rows) {
    rows.forEach((row) => {
      multipleTable.value.toggleRowSelection(row, undefined)
    })
  } else {
    multipleTable.value.clearSelection()
  }
}

onMounted(() => {
  getAggrGroupTable()
})

// 组合组配置的应用操作;
// const handleAggrApply = async() => {
//   try {

//     // (后面需要放开的二次认证)
//     // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
//     // if (!result) return;

//     let url = "api/lag/config"

//     const respond = await axios.post(url, new URLSearchParams({lag_mode: configurationForm.value.lag_mode}));
//     if(respond.status === 200) {
//       ElMessage({ message: '应用成功!',type: 'success',})
//       getAggrGroupTable()
//     } else if (respond.status === 400) {
//       ElMessage.error('应用失败!'+ respond.message)
//     }
//   } catch(err) {
//     if (err.response) {
//         let resp = err.response;
//         rootapi.show_dialog("unexpected error for POST api/lag/config:", resp.data, true);
//     }
//     else {
//         rootapi.show_dialog("unexpected frontend error:", err.message, true);
//     }
//   }
// }

// 添加 LAG 得操作;
const handleAddAggr = async() => {
  if(!addFormRef.value) return
  addFormRef.value.validate(async (valid) => {
    if(valid) {
      try {
        let url = "api/lag/add"
        const res = await axios.post(url, new URLSearchParams({lag_id: addForm.value.lag_id}))
        if(res.status === 200) {
          ElMessage({ message: '添加成功!',type: 'success',})
          getAggrGroupTable()
          addForm.value.lag_id = ''
        } else if (res.status === 400) {
          ElMessage.error('添加失败!'+ res.message)
        }
      } catch(err) {
        if (err.response) {
            let resp = err.response;
            rootapi.show_dialog("unexpected error for POST /api/lag/add:", resp.data, true);
        }
        else {
            rootapi.show_dialog("unexpected frontend error:", err.message, true);
        }
      }
    }
  })    
}

// 获取聚合组表的数据的操作;
const getAggrGroupTable = async() => {
  // const resp = await axios.get("/api/lag/config");
  const resp = { 
    "data": [ 
      {
        "lag_id": 9,
        "member_ports": [1,2,3,4,5,7,8,11],
        "efficient_members": []}
        ,
        {
        "lag_id": 10,
        "member_ports": [6],
        "efficient_members": []
      }
    ]
    ,
    "lag_mode": "src-dst-mac"
    ,
    "totol": 2
  }

  // if(resp?.status === 200 && resp?.data?.lag_mode && resp?.data?.data) {
  if( resp?.lag_mode && resp?.data) {
    // configurationForm.value.lag_mode = resp.lag_mode
    tableData.value = resp.data
    let intermediateArray = []
    resp.data.forEach(item => {
      let lag_id = item.lag_id
      let efficient_members = item.efficient_members
      let member_ports = item.member_ports.map(item => 'GigabitEthernet0/' + item)
      let res = {}
      res.lag_id = lag_id
      res.efficient_members = efficient_members
      res.member_ports = member_ports
      intermediateArray.push(res)
    })
    tableData.value = intermediateArray
    intermediateArray = []
  }
}

// 删除数据的操作:
const handleAggrDelete = async() => {
  try {

  // (后面需要放开的二次认证)
  // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
  // if (!result) return;
    if(edit_table_data.value.length) {
      let url = "api/lag/del"
      let count = edit_table_data.value.length;

      for (let i = 0; i < count; i++) {
        let param = {...edit_table_data.value[i]};
        const res = await axios.post(url, new URLSearchParams(param));
        if(res.status === 200 && i === count-1) {
          ElMessage({ message: '删除成功!',type: 'success',})
          getAggrGroupTable()
        } else if (res.status === 400) {
          ElMessage.error('删除失败!'+ res.message)
        }
      }
    } else {
      ElMessage({ message: '请至少选择一个来删除!',type: 'warning'})
    }
  } catch(err) {
    if (err.response) {
        let resp = err.response;
        rootapi.show_dialog("unexpected error for POST api/lag/del:", resp.data, true);
    }
    else {
        rootapi.show_dialog("unexpected frontend error:", err.message, true);
    }
  }
}


// 修改链路聚合组的应用操作;
const aggrOnSubmit = async() => {
  try {

    // (后面需要放开的二次认证)
    // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
    // if (!result) return;

    let url = "/api/lag/bind"
    let outparam
    if (aggrEditForm.value.member_ports.length) {
      outparam = {
        lag_id : aggrEditForm.value.lag_id,
        member_ports: [...aggrEditForm.value.member_ports]
      }
    } else {
      outparam = {
        lag_id : aggrEditForm.value.lag_id,
        member_ports: 0
      }
    }
    
    console.log(aggrEditForm.value.member_ports,111111);
    console.log(outparam,222222222);

    // const respond = await axios.post(url, outparam);
    const respond = await axios.post(url, new URLSearchParams(outparam));
    if(respond.status === 200) {
      ElMessage({ message: '应用成功!',type: 'success',})
      getAggrGroupTable()
      aggrEditDialogVisible.value = false
    } else if (respond.status === 400) {
      ElMessage.error('应用失败!'+ respond.message)
    }

  } catch(err) {
    aggrEditDialogVisible.value = false
    if (err.response) {
        let resp = err.response;
        rootapi.show_dialog("unexpected error for POST /api/lag/bind:", resp.data, true);
    }
    else {
        rootapi.show_dialog("unexpected frontend error:", err.message, true);
    }
  }
}

// 右边穿梭框变化触发的函数;
const handleRightChange = (val) => {
  if(val.length > 8) {
    ElMessage({ message: '注意:最多 8 个成员!',type: 'warning',})
  }
}


</script>

<template>
  <div class="aggr_group_layout">
    <div class="my_project">
      <!-- <div class="add_configuration">
        <div class="configuration_title"> 聚合组配置 </div>
        <el-form>
          <el-form-item label="负载分担策略:">
            <el-radio-group class='radioDiv' v-model="configurationForm.lag_mode">
              <div><el-radio label="src-dst-ip">源和目的IP地址</el-radio></div>
              <div><el-radio label="src-dst-mac">源和目的MAC地址</el-radio></div>
              <div><el-radio label="dst-ip">目的IP地址</el-radio></div>
              <div><el-radio label="dst-mac">目的MAC地址</el-radio></div>
              <div><el-radio label="src-ip">IP地址</el-radio></div>
              <div><el-radio label="src-mac">MAC地址</el-radio></div>
            </el-radio-group>
          </el-form-item>
        </el-form>
        <div class="configuration_footer" style="margin-top: 20px">
          <el-button type="primary" @click="handleAggrApply">提交</el-button>
        </div>
      </div> -->
      <div class="aggr_group_display">
        <!-- <div class="display_title"> 聚合组表 </div> -->
        <div class="display_title"> 11223344 </div>
        <div class="display_add">
          <el-form :model="addForm" label-width="52px" ref="addFormRef" :rules="addRules" class="demo-ruleForm" status-icon>
            <el-form-item label="LAG:" prop="lag_id">
              <div><el-input v-model="addForm.lag_id" /></div>
            </el-form-item>
          </el-form>
          <div class="add_footer" style="margin-top: 20px">
            <el-button type="primary" @click="handleAddAggr">添加</el-button>
          </div>
        </div>
        <el-table :data="tableData" style="width: 100%" ref="multipleTable" :row-class-name="tableRowClassName" @select="changeSelect" @select-all="changeAllSelect" max-height="342px">
          <el-table-column type="selection" width="80" align="center"/>
          <el-table-column prop="lag_id" label="LAG" max-width="50" align="center"/>
          <el-table-column prop="efficient_members" label="生效端口" min-width="100" align="center"/>
          <el-table-column prop="member_ports" label="成员" min-width="295" align="center"/>
        </el-table>
        <div class="display_footer" style="margin-top: 20px">
          <el-button type="primary" @click="handleAggrEdit">修改</el-button>
          <el-button type="primary" @click="handleAggrDelete">删除</el-button>
          <el-button type="primary" @click="getAggrGroupTable"><el-icon :size="20" style="margin-right: 5px;"><Refresh /></el-icon></el-button>
        </div>
      </div>
    </div>
    <el-dialog v-model="aggrEditDialogVisible" title="修改链路聚合组" width="712" center :close-on-click-modal="false">
      <el-form :model="aggrEditForm" ref="aggrEditFormRef">
        <el-form-item label="LAG:" :label-width="aggrLabelWidth">
          {{ aggrEditForm.lag_id }}
        </el-form-item>
        <el-form-item label-width="56px">
          <el-transfer v-model="aggrEditForm.member_ports" :data="data" :titles="['有效端口','已选端口']" @change="handleRightChange" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="aggrOnSubmit">提交</el-button>
          <el-button @click="aggrOnCancle(aggrEditFormRef)">取消</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.aggr_group_layout {
  margin: 30px auto;
  background-color: #e6f1f9;
  box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 40px 0px;
  .my_project {
    min-width: 500px;
    padding: 30px 30px 10px;
    .add_configuration {
      .configuration_title {
        text-align: center;
        font-weight: 700;
        margin-bottom: 20px;
      }
      .configuration_footer {
        margin: -5px 0 20px !important;
        text-align: left;
      }
      .radioDiv {
        display: table;
        div {
          margin-bottom: -17px;
        }
      }
      .el-form-item {
        // 此时是修改 el-form-item 上下的距离,因此并不起作用;
        // margin-bottom: 1px !important;
        ::v-deep(.el-form-item__label){
          // margin-top: 22px !important;
          font-weight: 500;
        }
      }
    }
    .aggr_group_display {
      .display_title {
        text-align: center;
        font-weight: 700;
        margin-bottom: 20px;
      }
      // 表格表头的背景色;
      ::v-deep(.el-table th) {
        background-color: #e6f1f9;
      }
      // 表格表头的下边框;
      ::v-deep(.el-table th.is-leaf) {
        border-bottom: 1px solid #557A95;
        font-weight: 700;
        font-size: 16px;
        color: black;
      }
      // 表格(除表头)的背景色;
      ::v-deep(.el-table tr) {
        font-weight: 500;
      }
      ::v-deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
        background-color: #afc4d3;
      }
      ::v-deep(.el-table .warning-row) {
        background-color: #d6e6f5;
      }
      ::v-deep(.el-table .success-row) {
        background-color: #e6f1f9;
      }
      .display_add {
        .add_footer {
          margin: -5px 0 20px !important;
          text-align: left;
        }
      }
      .display_footer {
        margin: 20px 0 10px;
        text-align: center;
      }
    }
  }
}
// 修改多选框的样式(即:修改多选框的大小);
// .el-table { 
//   ::v-deep(.el-checkbox__inner){
//     --el-checkbox-input-height: 21px !important;
//     --el-checkbox-input-width: 20px !important;
//     &:after {
//       top: 5px;
//       left: 7px;
//     }
//   }
// }
//去掉 dialog 右侧的 X 标记;
::v-deep(.el-dialog) {
  .el-dialog__header {
    .el-dialog__headerbtn {
      font-size: 30px;
      .el-dialog__close {
        color: red;
        display: none;  
      }
    }        
  }
}
.el-transfer {
  // 去掉穿梭框标题全选框;
  ::v-deep(.el-transfer-panel__header) {
    .el-checkbox {
      .el-checkbox__input {
        display: none;
      }
    }
  }
  // 设置穿梭框左右两边的宽度值(注意:一定不能去掉 !important 否则会出问题)
  --el-transfer-panel-width: 222px !important
}
</style>
其二、页面展示:

// 整体功能模块的展示情况:
在这里插入图片描述

// 选中 table 表格中第一个数据后,右侧的已选端口,应该展示成员值:

在这里插入图片描述

// 即:上述的已选端口要和 table 中第一个成员的值,一一对应;

在这里插入图片描述

2、问题分析:

其一、经操作后发现:

发现 transfer有效端口的值是按照要求的数组(即:按道理说应该展示没问题),且右侧已选端口的值也是按照要求的数组值(即:按道理说应该展示没问题),但是右边的已选端口的值就是展示不出来;

其二、但是切换后,右侧的已选端口的值能成功展示:

// 此时 transfer 组件就又能展示已选端口的值,且此时右侧展示的值就是项目想要的结果,但是第一次进来后页面并没有展示;

// 第一次进入,在 transfer 组件中的已选端口并没有数据,但是这种展示是不正常的,因为在 table 中已经选择了第一行的数据,且数据中的成员是有值的;

在这里插入图片描述

// 此时在切换 table 的第二行后,再切换回来,在 transfer 组件中的已选端口中就有了数据;
// 这样展示没有问题,就是想要的结果,但是第一次进入右侧的已选端口没有数据是不正常的;

在这里插入图片描述

其三、猜测原因:

// 应该是数据在哪里出了问题;

Ⅲ、解决在项目中使用 Transfer 组件遇到的问题:

1、问题原因:

其一、后台返回的数据情况为:

// 虽然此时的展示 "member_ports": [1,2,3,4,5,7,8,11] 是数组类型,但是在使用 transfer 的时候,右侧已选端口绑定的值是字符串类型的,如"member_ports": ['1','2','3','4','5','7','8','11'] ,因此出现了右侧已选端口在第一次加载时页面不显示的情况;

在这里插入图片描述

其二、解决方案为:

// 只需要将左侧最后生成 data 值里的 key 值换成字符串的 key 即可;
// 因为从设置的数据可知,第一次拿到的返回值是字符串类型,而有效端口的值也是字符串类型,这样已选端口的值才能显示出来;

在这里插入图片描述

2、没有问题的代码:


// 即:第一次进入 transfer 组件,右侧的已选端口就成功展示了想要展示的值;
<script setup>
import axios from 'axios';
const rootapi = inject("rootapi");
import { ref,inject,onMounted,reactive } from 'vue'
import { ElMessage } from 'element-plus'

const addFormRef = ref(null)
const aggrEditFormRef = ref(null)
const aggrEditDialogVisible = ref(false)
const aggrLabelWidth = '100px'
const edit_table_data = ref([])
const aggrEditForm = ref({})
const multipleTable = ref('')

const value = ref([])
const checkedArray = ref([])

const rightPorts = ref([])

// const configurationForm = ref({
//   lag_mode: "hash_mac"
// })

const addForm = ref({
  lag_id: ''
})

const tableData = ref([])

// 生成有效端口值;
const generateData = () => {
  const data = []
  for (let i = 1; i <= 28; i++) {
    data.push({
      key: `${i}`,
      label: `GigabitEthernet0/${i}`
    })
  }
  return data
}

// 注意:此时 generateData() 函数一定要在定义 data 数据前,才不会报错; 
const data = ref(generateData())

const tableRowClassName = (val) => {
  if(val.rowIndex %2 === 0) {
    return 'success-row'
  } else {
    return 'warning-row'
  }
}


// 添加 LAG 的校验;
const checkAggrLag = (rule, value, callback) => {
  if (!value) {
    return callback(new Error('此处不能为空'))
  }
  setTimeout(() => {
    if(/^([1-9]|(1[0-6]))$/.test(value)) {
      callback()
    } else {
      callback(new Error('请填写 1~16 的值'))
    }
  }, 10)
}

// 添加 LAG 聚合表组的校验;
const addRules = ref({
  lag_id: [
    {required: true, validator: checkAggrLag, trigger: 'blur' }
  ]
})


// 聚合组表的单选操作(之前仅存在第一次进入右侧没数据的代码);
const changeSelect = (val) => {
  // edit_table_data.value = val
  // console.log(edit_table_data.value,111111);
  let res = val.map((item) => {
      let obj = {
        lag_id: item.lag_id,
        member_ports: item.member_ports.map(item => {
          return item.split('/')[1]
        })
      }
      return obj     
  })
  // rightPorts.value=res
  edit_table_data.value = res
  handleRightChange()
  console.log(edit_table_data.value,1111111);
  // select_table_data.value = res
}


// 聚合组表的多选操作;
const changeAllSelect = (val) => {
  // edit_table_data.value = val
  // console.log(edit_table_data.value,111111);
  let res = val.map((item) => {
      let obj = {
        lag_id: item.lag_id,
        member_ports: item.member_ports.map(item => {
          return item.split('/')[1]
        })
      }
      return obj     
  })
  edit_table_data.value = res
  console.log(edit_table_data.value,1111111);
  // select_table_data.value = res
}


// 聚合组表的修改操作(之前仅存在第一次进入右侧没数据的代码);
const handleAggrEdit = () => {
  if(edit_table_data.value.length === 1) {
    aggrEditDialogVisible.value = true

    aggrEditForm.value = edit_table_data.value[0]
    // aggrEditForm.value = edit_table_data.value[0]

    // aggrEditForm.value.lag_id = edit_table_data.value[0].lag_id
    // aggrEditForm.value.member_ports = edit_table_data.value[0].member_ports.map(item => 'GigabitEthernet0/'+item)
    // rightPorts.value = edit_table_data.value[0].member_ports

    // aggrEditForm.value.member_ports = edit_table_data.value[0].member_ports

    console.log(edit_table_data.value,666666666);
    console.log(edit_table_data.value[0],7777777777);
    console.log(aggrEditForm.value,8888888888888);
    console.log(aggrEditForm.value.member_ports,89898989898);
    // console.log(tableData.value,123);

    // 重新调用生成端口的函数,防止某些值被清理;
    generateData()

    // 选中所有表中所有的 member 值(此时才没有问题);
    let seletedArray1 = []
    tableData.value.forEach(item => item.member_ports.forEach(it => seletedArray1.push(it.split('/')[1])))
    checkedArray.value = seletedArray1
    seletedArray1 = []

    // let disableArray = edit_table_data.value[0].member_ports.map(item => 'GigabitEthernet0/'+item)

    // console.log(disableArray,1111111111111111);
    console.log(edit_table_data.value[0].member_ports,1111111111111111);
    console.log(checkedArray.value,222222222222);

    // 去除待选择的 member 值(即:从一个数组中去除另一个数组中存在数据的操作);
    checkedArray.value = checkedArray.value.filter(item => !edit_table_data.value[0].member_ports.includes(item));

    data.value = data.value.filter(item => item.label =  item.label.split('/')[1])

    console.log(checkedArray.value,123);
    console.log(data.value,456);
    
    // 有效端口的禁选操作;
    let res = data.value.map(item => {
      // 此时返回值 flag 是数值,而不是布尔值;
      let flag = checkedArray.value.find(it => it === item.label)
      let obj
      if(flag) {
        obj = {
          key: flag,
          label: `GigabitEthernet0/${flag}`,
          disabled: true
        }
      } else {
        obj = {
          key: `${item.key}`,
          label: `GigabitEthernet0/${item.key}`,
        }
      }
      return obj
    })


    // 另一种解决方案:
    // let res = data.value.filter(item => {
    //   let flag = checkedArray.value.find(it => it === item.key)
    //   return item.key !== flag
    // })
    
    // console.log(res,123456);

    data.value = res
    console.log(data.value,789);
  } else if(edit_table_data.value.length === 0 ) { 
    ElMessage({ message: '请选择一个来修改!',type: 'warning'})
  } else {
    ElMessage.error('只能选择一个来修改!')
  }
}

const aggrOnCancle = () => {
  toggleSelection()
  // 此时是取消:修改和删除的记忆功能(即:取消后,不能直接点击修改或删除按钮);
  edit_table_data.value = []
  aggrEditDialogVisible.value = false
}

// 清除 Table 清空用户选择的操作;
const toggleSelection = (rows) => {
  if (rows) {
    rows.forEach((row) => {
      multipleTable.value.toggleRowSelection(row, undefined)
    })
  } else {
    multipleTable.value.clearSelection()
  }
}

onMounted(() => {
  getAggrGroupTable()
})

// 组合组配置的应用操作;
// const handleAggrApply = async() => {
//   try {

//     // (后面需要放开的二次认证)
//     // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
//     // if (!result) return;

//     let url = "api/lag/config"

//     const respond = await axios.post(url, new URLSearchParams({lag_mode: configurationForm.value.lag_mode}));
//     if(respond.status === 200) {
//       ElMessage({ message: '应用成功!',type: 'success',})
//       getAggrGroupTable()
//     } else if (respond.status === 400) {
//       ElMessage.error('应用失败!'+ respond.message)
//     }
//   } catch(err) {
//     if (err.response) {
//         let resp = err.response;
//         rootapi.show_dialog("unexpected error for POST api/lag/config:", resp.data, true);
//     }
//     else {
//         rootapi.show_dialog("unexpected frontend error:", err.message, true);
//     }
//   }
// }

// 添加 LAG 得操作;
const handleAddAggr = async() => {
  if(!addFormRef.value) return
  addFormRef.value.validate(async (valid) => {
    if(valid) {
      try {
        let url = "api/lag/add"
        const res = await axios.post(url, new URLSearchParams({lag_id: addForm.value.lag_id}))
        if(res.status === 200) {
          ElMessage({ message: '添加成功!',type: 'success',})
          getAggrGroupTable()
          addForm.value.lag_id = ''
        } else if (res.status === 400) {
          ElMessage.error('添加失败!'+ res.message)
        }
      } catch(err) {
        if (err.response) {
            let resp = err.response;
            rootapi.show_dialog("unexpected error for POST /api/lag/add:", resp.data, true);
        }
        else {
            rootapi.show_dialog("unexpected frontend error:", err.message, true);
        }
      }
    }
  })    
}

// 获取聚合组表的数据的操作;
const getAggrGroupTable = async() => {
  // const resp = await axios.get("/api/lag/config");
  const resp = { 
    "data": [ 
      {
        "lag_id": 9,
        "member_ports": [1,2,3,4,5,7,8,11],
        "efficient_members": []}
        ,
        {
        "lag_id": 10,
        "member_ports": [6],
        "efficient_members": []
      }
    ]
    ,
    "lag_mode": "src-dst-mac"
    ,
    "totol": 2
  }

  // if(resp?.status === 200 && resp?.data?.lag_mode && resp?.data?.data) {
  if( resp?.lag_mode && resp?.data) {
    // configurationForm.value.lag_mode = resp.lag_mode
    tableData.value = resp.data
    let intermediateArray = []
    resp.data.forEach(item => {
      let lag_id = item.lag_id
      let efficient_members = item.efficient_members
      let member_ports = item.member_ports.map(item => 'GigabitEthernet0/' + item)
      let res = {}
      res.lag_id = lag_id
      res.efficient_members = efficient_members
      res.member_ports = member_ports
      intermediateArray.push(res)
    })
    tableData.value = intermediateArray
    intermediateArray = []
  }
}

// 删除数据的操作:
const handleAggrDelete = async() => {
  try {

  // (后面需要放开的二次认证)
  // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
  // if (!result) return;
    if(edit_table_data.value.length) {
      let url = "api/lag/del"
      let count = edit_table_data.value.length;

      for (let i = 0; i < count; i++) {
        let param = {...edit_table_data.value[i]};
        const res = await axios.post(url, new URLSearchParams(param));
        if(res.status === 200 && i === count-1) {
          ElMessage({ message: '删除成功!',type: 'success',})
          getAggrGroupTable()
        } else if (res.status === 400) {
          ElMessage.error('删除失败!'+ res.message)
        }
      }
    } else {
      ElMessage({ message: '请至少选择一个来删除!',type: 'warning'})
    }
  } catch(err) {
    if (err.response) {
        let resp = err.response;
        rootapi.show_dialog("unexpected error for POST api/lag/del:", resp.data, true);
    }
    else {
        rootapi.show_dialog("unexpected frontend error:", err.message, true);
    }
  }
}


// 修改链路聚合组的应用操作;
const aggrOnSubmit = async() => {
  try {

    // (后面需要放开的二次认证)
    // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
    // if (!result) return;

    let url = "/api/lag/bind"
    let outparam
    if (aggrEditForm.value.member_ports.length) {
      outparam = {
        lag_id : aggrEditForm.value.lag_id,
        member_ports: [...aggrEditForm.value.member_ports]
      }
    } else {
      outparam = {
        lag_id : aggrEditForm.value.lag_id,
        member_ports: 0
      }
    }
    
    console.log(aggrEditForm.value.member_ports,111111);
    console.log(outparam,222222222);

    // const respond = await axios.post(url, outparam);
    const respond = await axios.post(url, new URLSearchParams(outparam));
    if(respond.status === 200) {
      ElMessage({ message: '应用成功!',type: 'success',})
      getAggrGroupTable()
      aggrEditDialogVisible.value = false
    } else if (respond.status === 400) {
      ElMessage.error('应用失败!'+ respond.message)
    }

  } catch(err) {
    aggrEditDialogVisible.value = false
    if (err.response) {
        let resp = err.response;
        rootapi.show_dialog("unexpected error for POST /api/lag/bind:", resp.data, true);
    }
    else {
        rootapi.show_dialog("unexpected frontend error:", err.message, true);
    }
  }
}

// 右边穿梭框变化触发的函数;
const handleRightChange = (val) => {
  if(val.length > 8) {
    ElMessage({ message: '注意:最多 8 个成员!',type: 'warning',})
  }
}


</script>

<template>
  <div class="aggr_group_layout">
    <div class="my_project">
      <!-- <div class="add_configuration">
        <div class="configuration_title"> 聚合组配置 </div>
        <el-form>
          <el-form-item label="负载分担策略:">
            <el-radio-group class='radioDiv' v-model="configurationForm.lag_mode">
              <div><el-radio label="src-dst-ip">源和目的IP地址</el-radio></div>
              <div><el-radio label="src-dst-mac">源和目的MAC地址</el-radio></div>
              <div><el-radio label="dst-ip">目的IP地址</el-radio></div>
              <div><el-radio label="dst-mac">目的MAC地址</el-radio></div>
              <div><el-radio label="src-ip">IP地址</el-radio></div>
              <div><el-radio label="src-mac">MAC地址</el-radio></div>
            </el-radio-group>
          </el-form-item>
        </el-form>
        <div class="configuration_footer" style="margin-top: 20px">
          <el-button type="primary" @click="handleAggrApply">提交</el-button>
        </div>
      </div> -->
      <div class="aggr_group_display">
        <!-- <div class="display_title"> 聚合组表 </div> -->
        <div class="display_title"> 11223344 </div>
        <div class="display_add">
          <el-form :model="addForm" label-width="52px" ref="addFormRef" :rules="addRules" class="demo-ruleForm" status-icon>
            <el-form-item label="LAG:" prop="lag_id">
              <div><el-input v-model="addForm.lag_id" /></div>
            </el-form-item>
          </el-form>
          <div class="add_footer" style="margin-top: 20px">
            <el-button type="primary" @click="handleAddAggr">添加</el-button>
          </div>
        </div>
        <el-table :data="tableData" style="width: 100%" ref="multipleTable" :row-class-name="tableRowClassName" @select="changeSelect" @select-all="changeAllSelect" max-height="342px">
          <el-table-column type="selection" width="80" align="center"/>
          <el-table-column prop="lag_id" label="LAG" max-width="50" align="center"/>
          <el-table-column prop="efficient_members" label="生效端口" min-width="100" align="center"/>
          <el-table-column prop="member_ports" label="成员" min-width="295" align="center"/>
        </el-table>
        <div class="display_footer" style="margin-top: 20px">
          <el-button type="primary" @click="handleAggrEdit">修改</el-button>
          <el-button type="primary" @click="handleAggrDelete">删除</el-button>
          <el-button type="primary" @click="getAggrGroupTable"><el-icon :size="20" style="margin-right: 5px;"><Refresh /></el-icon></el-button>
        </div>
      </div>
    </div>
    <el-dialog v-model="aggrEditDialogVisible" title="修改链路聚合组" width="712" center :close-on-click-modal="false">
      <el-form :model="aggrEditForm" ref="aggrEditFormRef">
        <el-form-item label="LAG:" :label-width="aggrLabelWidth">
          {{ aggrEditForm.lag_id }}
        </el-form-item>
        <el-form-item label-width="56px">
          <el-transfer v-model="aggrEditForm.member_ports" :data="data" :titles="['有效端口','已选端口']" @change="handleRightChange" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="aggrOnSubmit">提交</el-button>
          <el-button @click="aggrOnCancle(aggrEditFormRef)">取消</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.aggr_group_layout {
  margin: 30px auto;
  background-color: #e6f1f9;
  box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 40px 0px;
  .my_project {
    min-width: 500px;
    padding: 30px 30px 10px;
    .add_configuration {
      .configuration_title {
        text-align: center;
        font-weight: 700;
        margin-bottom: 20px;
      }
      .configuration_footer {
        margin: -5px 0 20px !important;
        text-align: left;
      }
      .radioDiv {
        display: table;
        div {
          margin-bottom: -17px;
        }
      }
      .el-form-item {
        // 此时是修改 el-form-item 上下的距离,因此并不起作用;
        // margin-bottom: 1px !important;
        ::v-deep(.el-form-item__label){
          // margin-top: 22px !important;
          font-weight: 500;
        }
      }
    }
    .aggr_group_display {
      .display_title {
        text-align: center;
        font-weight: 700;
        margin-bottom: 20px;
      }
      // 表格表头的背景色;
      ::v-deep(.el-table th) {
        background-color: #e6f1f9;
      }
      // 表格表头的下边框;
      ::v-deep(.el-table th.is-leaf) {
        border-bottom: 1px solid #557A95;
        font-weight: 700;
        font-size: 16px;
        color: black;
      }
      // 表格(除表头)的背景色;
      ::v-deep(.el-table tr) {
        font-weight: 500;
      }
      ::v-deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
        background-color: #afc4d3;
      }
      ::v-deep(.el-table .warning-row) {
        background-color: #d6e6f5;
      }
      ::v-deep(.el-table .success-row) {
        background-color: #e6f1f9;
      }
      .display_add {
        .add_footer {
          margin: -5px 0 20px !important;
          text-align: left;
        }
      }
      .display_footer {
        margin: 20px 0 10px;
        text-align: center;
      }
    }
  }
}
// 修改多选框的样式(即:修改多选框的大小);
// .el-table { 
//   ::v-deep(.el-checkbox__inner){
//     --el-checkbox-input-height: 21px !important;
//     --el-checkbox-input-width: 20px !important;
//     &:after {
//       top: 5px;
//       left: 7px;
//     }
//   }
// }
//去掉 dialog 右侧的 X 标记;
::v-deep(.el-dialog) {
  .el-dialog__header {
    .el-dialog__headerbtn {
      font-size: 30px;
      .el-dialog__close {
        color: red;
        display: none;  
      }
    }        
  }
}
.el-transfer {
  // 去掉穿梭框标题全选框;
  ::v-deep(.el-transfer-panel__header) {
    .el-checkbox {
      .el-checkbox__input {
        display: none;
      }
    }
  }
  // 设置穿梭框左右两边的宽度值(注意:一定不能去掉 !important 否则会出问题)
  --el-transfer-panel-width: 222px !important
}
</style>

3、没有问题的页面展示:

在这里插入图片描述

在这里插入图片描述

Ⅳ、整体代码的面貌:

其一、整体代码为:


<script setup>
import axios from 'axios';
const rootapi = inject("rootapi");
import { ref,inject,onMounted,reactive } from 'vue'
import { ElMessage } from 'element-plus'

const addFormRef = ref(null)
const aggrEditFormRef = ref(null)
const aggrEditDialogVisible = ref(false)
const aggrLabelWidth = '100px'
const edit_table_data = ref([])
const aggrEditForm = ref({})
const multipleTable = ref('')

const value = ref([])
const checkedArray = ref([])

const rightPorts = ref([])

const configurationForm = ref({
  lag_mode: "hash_mac"
})

const addForm = ref({
  lag_id: ''
})

const tableData = ref([])

// 生成有效端口值;
const generateData = () => {
  const data = []
  for (let i = 1; i <= 28; i++) {
    data.push({
      key: `${i}`,
      label: `GigabitEthernet0/${i}`
    })
  }
  return data
}

// 注意:此时 generateData() 函数一定要在定义 data 数据前,才不会报错; 
const data = ref(generateData())

const tableRowClassName = (val) => {
  if(val.rowIndex %2 === 0) {
    return 'success-row'
  } else {
    return 'warning-row'
  }
}


// 添加 LAG 的校验;
const checkAggrLag = (rule, value, callback) => {
  if (!value) {
    return callback(new Error('此处不能为空'))
  }
  setTimeout(() => {
    if(/^([1-9]|(1[0-6]))$/.test(value)) {
      callback()
    } else {
      callback(new Error('请填写 1~16 的值'))
    }
  }, 10)
}

// 添加 LAG 聚合表组的校验;
const addRules = ref({
  lag_id: [
    {required: true, validator: checkAggrLag, trigger: 'blur' }
  ]
})


// 聚合组表的单选操作(之前仅存在第一次进入右侧没数据的代码);
const changeSelect = (val) => {
  // edit_table_data.value = val
  // console.log(edit_table_data.value,111111);
  let res = val.map((item) => {
      let obj = {
        lag_id: item.lag_id,
        member_ports: item.member_ports.map(item => {
          return item.split('/')[1]
        })
      }
      return obj     
  })
  // rightPorts.value=res
  edit_table_data.value = res
  handleRightChange()
  console.log(edit_table_data.value,1111111);
  // select_table_data.value = res
}


// 聚合组表的多选操作;
const changeAllSelect = (val) => {
  // edit_table_data.value = val
  // console.log(edit_table_data.value,111111);
  let res = val.map((item) => {
      let obj = {
        lag_id: item.lag_id,
        member_ports: item.member_ports.map(item => {
          return item.split('/')[1]
        })
      }
      return obj     
  })
  edit_table_data.value = res
  console.log(edit_table_data.value,1111111);
  // select_table_data.value = res
}


// 聚合组表的修改操作(之前仅存在第一次进入右侧没数据的代码);
const handleAggrEdit = () => {
  if(edit_table_data.value.length === 1) {
    aggrEditDialogVisible.value = true

    aggrEditForm.value = edit_table_data.value[0]
    // aggrEditForm.value = edit_table_data.value[0]

    // aggrEditForm.value.lag_id = edit_table_data.value[0].lag_id
    // aggrEditForm.value.member_ports = edit_table_data.value[0].member_ports.map(item => 'GigabitEthernet0/'+item)
    // rightPorts.value = edit_table_data.value[0].member_ports

    // aggrEditForm.value.member_ports = edit_table_data.value[0].member_ports

    console.log(edit_table_data.value,666666666);
    console.log(edit_table_data.value[0],7777777777);
    console.log(aggrEditForm.value,8888888888888);
    console.log(aggrEditForm.value.member_ports,89898989898);
    // console.log(tableData.value,123);

    // 重新调用生成端口的函数,防止某些值被清理;
    generateData()

    // 选中所有表中所有的 member 值(此时才没有问题);
    let seletedArray1 = []
    tableData.value.forEach(item => item.member_ports.forEach(it => seletedArray1.push(it.split('/')[1])))
    checkedArray.value = seletedArray1
    seletedArray1 = []

    // let disableArray = edit_table_data.value[0].member_ports.map(item => 'GigabitEthernet0/'+item)

    // console.log(disableArray,1111111111111111);
    console.log(edit_table_data.value[0].member_ports,1111111111111111);
    console.log(checkedArray.value,222222222222);

    // 去除待选择的 member 值(即:从一个数组中去除另一个数组中存在数据的操作);
    checkedArray.value = checkedArray.value.filter(item => !edit_table_data.value[0].member_ports.includes(item));

    data.value = data.value.filter(item => item.label =  item.label.split('/')[1])

    console.log(checkedArray.value,123);
    console.log(data.value,456);
    
    // 有效端口的禁选操作;
    let res = data.value.map(item => {
      // 此时返回值 flag 是数值,而不是布尔值;
      let flag = checkedArray.value.find(it => it === item.label)
      let obj
      if(flag) {
        obj = {
          key: flag,
          label: `GigabitEthernet0/${flag}`,
          disabled: true
        }
      } else {
        obj = {
          key: `${item.key}`,
          label: `GigabitEthernet0/${item.key}`,
        }
      }
      return obj
    })


    // 另一种解决方案:
    // let res = data.value.filter(item => {
    //   let flag = checkedArray.value.find(it => it === item.key)
    //   return item.key !== flag
    // })
    
    // console.log(res,123456);

    data.value = res
    console.log(data.value,789);
  } else if(edit_table_data.value.length === 0 ) { 
    ElMessage({ message: '请选择一个来修改!',type: 'warning'})
  } else {
    ElMessage.error('只能选择一个来修改!')
  }
}

const aggrOnCancle = () => {
  toggleSelection()
  // 此时是取消:修改和删除的记忆功能(即:取消后,不能直接点击修改或删除按钮);
  edit_table_data.value = []
  aggrEditDialogVisible.value = false
}

// 清除 Table 清空用户选择的操作;
const toggleSelection = (rows) => {
  if (rows) {
    rows.forEach((row) => {
      multipleTable.value.toggleRowSelection(row, undefined)
    })
  } else {
    multipleTable.value.clearSelection()
  }
}

onMounted(() => {
  getAggrGroupTable()
})

// 组合组配置的应用操作;
const handleAggrApply = async() => {
  try {

    // (后面需要放开的二次认证)
    // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
    // if (!result) return;

    let url = "api/lag/config"

    const respond = await axios.post(url, new URLSearchParams({lag_mode: configurationForm.value.lag_mode}));
    if(respond.status === 200) {
      ElMessage({ message: '应用成功!',type: 'success',})
      getAggrGroupTable()
    } else if (respond.status === 400) {
      ElMessage.error('应用失败!'+ respond.message)
    }
  } catch(err) {
    if (err.response) {
        let resp = err.response;
        rootapi.show_dialog("unexpected error for POST api/lag/config:", resp.data, true);
    }
    else {
        rootapi.show_dialog("unexpected frontend error:", err.message, true);
    }
  }
}

// 添加 LAG 得操作;
const handleAddAggr = async() => {
  if(!addFormRef.value) return
  addFormRef.value.validate(async (valid) => {
    if(valid) {
      try {
        let url = "api/lag/add"
        const res = await axios.post(url, new URLSearchParams({lag_id: addForm.value.lag_id}))
        if(res.status === 200) {
          ElMessage({ message: '添加成功!',type: 'success',})
          getAggrGroupTable()
          addForm.value.lag_id = ''
        } else if (res.status === 400) {
          ElMessage.error('添加失败!'+ res.message)
        }
      } catch(err) {
        if (err.response) {
            let resp = err.response;
            rootapi.show_dialog("unexpected error for POST /api/lag/add:", resp.data, true);
        }
        else {
            rootapi.show_dialog("unexpected frontend error:", err.message, true);
        }
      }
    }
  })    
}

// 获取聚合组表的数据的操作;
const getAggrGroupTable = async() => {
  // const resp = await axios.get("/api/lag/config");
  const resp = { 
    "data": [ 
      {
        "lag_id": 9,
        "member_ports": [1,2,3,4,5,7,8,11],
        "efficient_members": []}
        ,
        {
        "lag_id": 10,
        "member_ports": [6],
        "efficient_members": []
      }
    ]
    ,
    "lag_mode": "src-dst-mac"
    ,
    "totol": 2
  }

  // if(resp?.status === 200 && resp?.data?.lag_mode && resp?.data?.data) {
  if( resp?.lag_mode && resp?.data) {
    configurationForm.value.lag_mode = resp.lag_mode
    tableData.value = resp.data
    let intermediateArray = []
    resp.data.forEach(item => {
      let lag_id = item.lag_id
      let efficient_members = item.efficient_members
      let member_ports = item.member_ports.map(item => 'GigabitEthernet0/' + item)
      let res = {}
      res.lag_id = lag_id
      res.efficient_members = efficient_members
      res.member_ports = member_ports
      intermediateArray.push(res)
    })
    tableData.value = intermediateArray
    intermediateArray = []
  }
}

// 删除数据的操作:
const handleAggrDelete = async() => {
  try {

  // (后面需要放开的二次认证)
  // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
  // if (!result) return;
    if(edit_table_data.value.length) {
      let url = "api/lag/del"
      let count = edit_table_data.value.length;

      for (let i = 0; i < count; i++) {
        let param = {...edit_table_data.value[i]};
        const res = await axios.post(url, new URLSearchParams(param));
        if(res.status === 200 && i === count-1) {
          ElMessage({ message: '删除成功!',type: 'success',})
          getAggrGroupTable()
        } else if (res.status === 400) {
          ElMessage.error('删除失败!'+ res.message)
        }
      }
    } else {
      ElMessage({ message: '请至少选择一个来删除!',type: 'warning'})
    }
  } catch(err) {
    if (err.response) {
        let resp = err.response;
        rootapi.show_dialog("unexpected error for POST api/lag/del:", resp.data, true);
    }
    else {
        rootapi.show_dialog("unexpected frontend error:", err.message, true);
    }
  }
}


// 修改链路聚合组的应用操作;
const aggrOnSubmit = async() => {
  try {

    // (后面需要放开的二次认证)
    // let result = await rootapi.post_crit_auth(url, {dummy: "dummy"}, count);
    // if (!result) return;

    let url = "/api/lag/bind"
    let outparam
    if (aggrEditForm.value.member_ports.length) {
      outparam = {
        lag_id : aggrEditForm.value.lag_id,
        member_ports: [...aggrEditForm.value.member_ports]
      }
    } else {
      outparam = {
        lag_id : aggrEditForm.value.lag_id,
        member_ports: 0
      }
    }
    
    console.log(aggrEditForm.value.member_ports,111111);
    console.log(outparam,222222222);

    // const respond = await axios.post(url, outparam);
    const respond = await axios.post(url, new URLSearchParams(outparam));
    if(respond.status === 200) {
      ElMessage({ message: '应用成功!',type: 'success',})
      getAggrGroupTable()
      aggrEditDialogVisible.value = false
    } else if (respond.status === 400) {
      ElMessage.error('应用失败!'+ respond.message)
    }

  } catch(err) {
    aggrEditDialogVisible.value = false
    if (err.response) {
        let resp = err.response;
        rootapi.show_dialog("unexpected error for POST /api/lag/bind:", resp.data, true);
    }
    else {
        rootapi.show_dialog("unexpected frontend error:", err.message, true);
    }
  }
}

// 右边穿梭框变化触发的函数;
const handleRightChange = (val) => {
  if(val.length > 8) {
    ElMessage({ message: '注意:最多 8 个成员!',type: 'warning',})
  }
}


</script>

<template>
  <div class="aggr_group_layout">
    <div class="my_project">
      <div class="add_configuration">
        <div class="configuration_title"> 聚合组配置 </div>
        <el-form>
          <el-form-item label="负载分担策略:">
            <el-radio-group class='radioDiv' v-model="configurationForm.lag_mode">
              <div><el-radio label="src-dst-ip">源和目的IP地址</el-radio></div>
              <div><el-radio label="src-dst-mac">源和目的MAC地址</el-radio></div>
              <div><el-radio label="dst-ip">目的IP地址</el-radio></div>
              <div><el-radio label="dst-mac">目的MAC地址</el-radio></div>
              <div><el-radio label="src-ip">IP地址</el-radio></div>
              <div><el-radio label="src-mac">MAC地址</el-radio></div>
            </el-radio-group>
          </el-form-item>
        </el-form>
        <div class="configuration_footer" style="margin-top: 20px">
          <el-button type="primary" @click="handleAggrApply">提交</el-button>
        </div>
      </div>
      <div class="aggr_group_display">
        <!-- <div class="display_title"> 聚合组表 </div> -->
        <div class="display_title"> 11223344 </div>
        <div class="display_add">
          <el-form :model="addForm" label-width="52px" ref="addFormRef" :rules="addRules" class="demo-ruleForm" status-icon>
            <el-form-item label="LAG:" prop="lag_id">
              <div><el-input v-model="addForm.lag_id" /></div>
            </el-form-item>
          </el-form>
          <div class="add_footer" style="margin-top: 20px">
            <el-button type="primary" @click="handleAddAggr">添加</el-button>
          </div>
        </div>
        <el-table :data="tableData" style="width: 100%" ref="multipleTable" :row-class-name="tableRowClassName" @select="changeSelect" @select-all="changeAllSelect" max-height="342px">
          <el-table-column type="selection" width="80" align="center"/>
          <el-table-column prop="lag_id" label="LAG" max-width="50" align="center"/>
          <el-table-column prop="efficient_members" label="生效端口" min-width="100" align="center"/>
          <el-table-column prop="member_ports" label="成员" min-width="295" align="center"/>
        </el-table>
        <div class="display_footer" style="margin-top: 20px">
          <el-button type="primary" @click="handleAggrEdit">修改</el-button>
          <el-button type="primary" @click="handleAggrDelete">删除</el-button>
          <el-button type="primary" @click="getAggrGroupTable"><el-icon :size="20" style="margin-right: 5px;"><Refresh /></el-icon></el-button>
        </div>
      </div>
    </div>
    <el-dialog v-model="aggrEditDialogVisible" title="修改链路聚合组" width="712" center :close-on-click-modal="false">
      <el-form :model="aggrEditForm" ref="aggrEditFormRef">
        <el-form-item label="LAG:" :label-width="aggrLabelWidth">
          {{ aggrEditForm.lag_id }}
        </el-form-item>
        <el-form-item label-width="56px">
          <el-transfer v-model="aggrEditForm.member_ports" :data="data" :titles="['有效端口','已选端口']" @change="handleRightChange" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="aggrOnSubmit">提交</el-button>
          <el-button @click="aggrOnCancle(aggrEditFormRef)">取消</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.aggr_group_layout {
  margin: 30px auto;
  background-color: #e6f1f9;
  box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 40px 0px;
  .my_project {
    min-width: 500px;
    padding: 30px 30px 10px;
    .add_configuration {
      .configuration_title {
        text-align: center;
        font-weight: 700;
        margin-bottom: 20px;
      }
      .configuration_footer {
        margin: -5px 0 20px !important;
        text-align: left;
      }
      .radioDiv {
        display: table;
        div {
          margin-bottom: -17px;
        }
      }
      .el-form-item {
        // 此时是修改 el-form-item 上下的距离,因此并不起作用;
        // margin-bottom: 1px !important;
        ::v-deep(.el-form-item__label){
          // margin-top: 22px !important;
          font-weight: 500;
        }
      }
    }
    .aggr_group_display {
      .display_title {
        text-align: center;
        font-weight: 700;
        margin-bottom: 20px;
      }
      // 表格表头的背景色;
      ::v-deep(.el-table th) {
        background-color: #e6f1f9;
      }
      // 表格表头的下边框;
      ::v-deep(.el-table th.is-leaf) {
        border-bottom: 1px solid #557A95;
        font-weight: 700;
        font-size: 16px;
        color: black;
      }
      // 表格(除表头)的背景色;
      ::v-deep(.el-table tr) {
        font-weight: 500;
      }
      ::v-deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
        background-color: #afc4d3;
      }
      ::v-deep(.el-table .warning-row) {
        background-color: #d6e6f5;
      }
      ::v-deep(.el-table .success-row) {
        background-color: #e6f1f9;
      }
      .display_add {
        .add_footer {
          margin: -5px 0 20px !important;
          text-align: left;
        }
      }
      .display_footer {
        margin: 20px 0 10px;
        text-align: center;
      }
    }
  }
}
// 修改多选框的样式(即:修改多选框的大小);
// .el-table { 
//   ::v-deep(.el-checkbox__inner){
//     --el-checkbox-input-height: 21px !important;
//     --el-checkbox-input-width: 20px !important;
//     &:after {
//       top: 5px;
//       left: 7px;
//     }
//   }
// }
//去掉 dialog 右侧的 X 标记;
::v-deep(.el-dialog) {
  .el-dialog__header {
    .el-dialog__headerbtn {
      font-size: 30px;
      .el-dialog__close {
        color: red;
        display: none;  
      }
    }        
  }
}
.el-transfer {
  // 去掉穿梭框标题全选框;
  ::v-deep(.el-transfer-panel__header) {
    .el-checkbox {
      .el-checkbox__input {
        display: none;
      }
    }
  }
  // 设置穿梭框左右两边的宽度值(注意:一定不能去掉 !important 否则会出问题)
  --el-transfer-panel-width: 222px !important
}
</style>

其二、整体页面为:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Ⅴ、小结:

其一、哪里有不对或不合适的地方,还请大佬们多多指点和交流!
其二、有兴趣的话,可以多多关注这个专栏(Vue(Vue2+Vue3)面试必备专栏):https://blog.csdn.net/weixin_43405300/category_11525646.html?spm=1001.2014.3001.5482

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/585091.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nacos原理-2024

文章目录 1. 什么是Nacos2. 注册中心原理3. 配置中心原理 1. 什么是Nacos Nacos注册中心分为server与client&#xff0c;server采用Java编写&#xff0c;为client提供注册发现服务与配置服务。而client可以用多语言实现&#xff0c;client与微服务嵌套在一起&#xff0c;nacos…

让大模型prompt生成Mermaid流程图

生成内容、总结文章让大模型Mermaid流程图展示&#xff1a; mermaid 美人鱼, 是一个类似 markdown&#xff0c;用文本语法来描述文档图形(流程图、 时序图、甘特图)的工具&#xff0c;您可以在文档中嵌入一段 mermaid 文本来生成 SVG 形式的图形 kimi效果示例&#xff1a; 使用…

【算法一则】【动态规划】求二维数组可组成的最大正方形

题目 在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内&#xff0c;找到只包含 ‘1’ 的最大正方形&#xff0c;并返回其面积。 示例 1&#xff1a; 输入&#xff1a;matrix [["1","0","1","0","0"],["1","0&…

大模型应用开发极简入门

简单的归纳一下书的前序部分 目录 LLM&#xff08;Large Language Model&#xff09;的应用技术栈通常包括以下几个方面&#xff1a; 深度学习框架&#xff1a; 数据预处理工具&#xff1a; 训练资源&#xff1a; 模型优化和调参工具&#xff1a; 部署和应用集成&#xf…

最新AI实景无人自动直播软件:一部手机就可以实现无人直播;商业拓客带货的必备利器

智享实景无人直播系统在商业拓展中的作用不可忽视。本文将探讨该系统的特点和优势&#xff0c;展示其省时省力的优势以及在商家拓客和源头公司项目招商中的关键作用。 随着人工智能技术的飞速发展&#xff0c;智能化解决方案正逐渐渗透到各行业&#xff0c;在商业拓展领域取得了…

刷题训练之位运算

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握位运算算法。 > 毒鸡汤&#xff1a;学习&#xff0c;学习&#xff0c;再学习 ! 学&#xff0c;然后知不足。 > 专栏选自&#xff1a;刷题…

数据库分库分表

数据库分库分表 分库分表到底是什么 分库分表其实是分库,分表,分库分表的总称 分库 将数据按照一定规则存储到不同的数据库中,每个数据库存储一部分数据 分库主要解决的是并发量过大的问题&#xff0c;并发量一旦上升&#xff0c;那么数据库就可能成为系统的瓶颈&#xff…

综合性练习(后端代码练习2)——用户登录

目录 一、准备工作 二、约定前后端交互接口 1、需求分析 2、接口定义 1、输入账户密码界面 2、当前登录的用户界面 三、实现服务端代码 四、调整前端页面代码 1、login.html代码&#xff1a; 页面跳转的三种方式&#xff1a; 2、index.html代码&#xff1a; 五、运…

[华为OD] C卷 服务器cpu交换 现有两组服务器QA和B,每组有多个算力不同的CPU 100

题目&#xff1a; 现有两组服务器QA和B,每组有多个算力不同的CPU,其中A[i]是A组第i个CPU的运算能 力&#xff0c;B[i]是B组第i个CPU的运算能力。一组服务器的总算力是各CPU的算力之和。 为了让两组服务器的算力相等&#xff0c;允许从每组各选出一个CPU进行一次交换。 求两…

计算机网络----第十三天

DNS协议和文件传输协议 DNS&#xff1a; 含义&#xff1a;用于域名和IP地址的互相解析 DNS域名&#xff1a; 背景&#xff1a;通过IP地址访问目标主机&#xff0c;不便于记忆 域名的树形层次化结构&#xff1a; ①根域 ②顶级域&#xff1a;主机所处的国家/区域&#xf…

个人学习资源整理

文章目录 视频相关stl源码讲解相关 网站相关CPP网站 视频相关 stl源码讲解相关 跳转 网站相关 CPP网站 https://cplusplus.com/ https://gcc.gnu.org/

PostgreSQL的扩展(extensions)-常用的扩展之pg_repack

PostgreSQL的扩展&#xff08;extensions&#xff09;-常用的扩展之pg_repack pg_repack 是一款非常有用的 PostgreSQL 扩展工具&#xff0c;它能够重新打包&#xff08;repack&#xff09;表和索引以回收空间并减少碎片&#xff0c;而且在这个过程中不会锁定表&#xff0c;允…

软件测试常问的超高频面试题目,2022最强版,附答案

1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自己&…

基于Vue3的Axios异步请求

基于Vue3的Axios异步请求 1. Axios安装与应用2. Axios网络请求封装3. axios网络请求跨域前端解决方案server.proxy 1. Axios安装与应用 Axios是一个基于promise的网络请求库&#xff0c;Axios.js.中文文档&#xff1a;https://axios.js.cn/ 安装&#xff1a;npm install --sa…

Apollo Dreamview+之Studio插件安装

步骤一&#xff1a;登录 Apollo Studio 工作台 登录 Apollo Studio 工作台。 步骤二&#xff1a;获取插件安装链接 在账户信息中&#xff0c;单击 我的服务 。 2. 选择 仿真 页签。 3. 在 插件安装 中单击 生成 &#xff0c;选择 Apollo 最新版本&#xff0c;并单击 确定 。…

计算机视觉大项目(1)-水果分级系统

项目来源&#xff1a;河北大学计算机视觉课程-杨老师. 一共有四个标题&#xff0c;本篇博客只完成前两问。 目录 实验目的: 实验内容&#xff1a; 实验步骤&#xff1a; 1.水果图像的分割 >掩膜图像Mask 是什么&#xff1f; >改进:去除反光部分的影响 2&#xf…

ES6之rest参数、扩展运算符

文章目录 前言一、rest参数二、扩展运算符 1.将数组转化为逗号分隔的参数序列2.应用总结 前言 rest参数与arguments变量相似。ES6引入rest参数代替arguments&#xff0c;获取函数实参。扩展运算符能将数组转化为参数序列。 一、rest参数 function namelist1() {console.log(ar…

【无标题】场外个股期权多少钱才能做?个人能做吗?

场外个股期权的交易门槛相对较高&#xff0c;主要面向符合特定条件的机构投资者。一般来说&#xff0c;法人或合伙企业等组织参与的&#xff0c;需要满足最近1年末净资产不低于5000万元人民币、金融资产不低于2000万元人民币的条件&#xff0c;并具备3年以上证券、基金、期货、…

【postgresql】实时查询表字段相关数据

需求&#xff1a;数据库设计时候时不时变动&#xff0c;想根据实际编号进行查询表字段相关信息 库表 脚本 原始 优化后 查询 文档

[C++][算法基础]最大不相交区间数量(贪心 + 区间问题2)

给定 &#x1d441; 个闭区间 [&#x1d44e;&#x1d456;,&#x1d44f;&#x1d456;]&#xff0c;请你在数轴上选择若干区间&#xff0c;使得选中的区间之间互不相交&#xff08;包括端点&#xff09;。 输出可选取区间的最大数量。 输入格式 第一行包含整数 &#x1d4…