网站运营需要多少钱,制作小程序难吗,海外seo网站推广,WordPress提高打开速度最近的新项目有个需求需要合并单元列表。ElementPlus 的 Table 提供了合并行或列的方法#xff0c;可以参考一下https://element-plus.org/zh-CN/component/table.html 但项目中#xff0c;后台数据返回格式和指定合并是动态且没有规律的#xff0c;Element 的示例过于简单可以参考一下https://element-plus.org/zh-CN/component/table.html 但项目中后台数据返回格式和指定合并是动态且没有规律的Element 的示例过于简单因此记录下来大家可以参考一下 效果图 后台返回的数据结构 代码详解
实操中需要合并的代码通常就是 list_cnt 数据需要进行合并因为后台返回的格式都是Data 数据中包裹着 list_cnt 数据这种格式看起来也是比较清晰。由 Element 文档可知el-table 组件主要靠 :span-method 方法实现合并。 完整代码
templatediv classapp-containerdiv classsearch-barel-form :inlinetrue :modelformData classcommon-form-inlineel-form-item label名称搜索el-input v-modelformData.name clearable clearqueryAndroidList(true) placeholder请输入 //el-form-itemel-form-itemel-button typeprimary clickqueryAndroidList(true)搜索/el-button/el-form-item/el-form/divel-table :datalist :stripetrue fit highlight-current-row :show-overflow-tooltiptruestylewidth: 100%; margin-top: 20px v-loadingloading selection-changehandleSelectionChange:span-methodobjectSpanMethod borderel-table-column typeselection aligncenter width55 /el-table-column aligncenter label实例 propidx width220pxtemplate #defaultscopeel-button sizesmall round实例: {{ scope.row.idx }}/el-buttonel-button typeprimary sizesmall clickhandleEdit(scope.row)编辑/el-buttonel-button typeprimary sizesmall clickhandleCreate(scope.row)创建/el-buttondiv classtime-linespan到期时间: {{ scope.row.update_time || 未授权 }}/span/div/template/el-table-columnel-table-column aligncenter labelip propip width180px/el-table-columnel-table-column aligncenter labelADB/API端口 proplevelName width180pxtemplate #defaultscopespan v-ifscope.row.adb_port || scope.row.sdk_port{{ scope.row.adb_port || - }} - {{ scope.row.sdk_port|| - }}/spanspan v-else - /span/template/el-table-columnel-table-column aligncenter label名称 propname width120pxtemplate #defaultscopespan v-ifscope.row.name{{ scope.row.name }}/spanspan v-else-/span/template/el-table-columnel-table-column aligncenter label状态 propstatus width150pxtemplate #defaultscopeel-button plain :style{backgroundColor: scope.row.status 20 ? #fef0f0 : scope.row.status 10 ? #f0f9eb : ,borderColor: scope.row.status 20 ? #fde2e2 : scope.row.status 10 ? #e1f3d8 : ,color: scope.row.status 20 ? #f56c6c : scope.row.status 10 ? #67c23a : } v-ifscope.row.status{{ scope.row.status 10 ? 运行中 : scope.row.status 20 ? 关机 : 空闲 }}/el-button/template/el-table-columnel-table-column aligncenter label系统版本 propserial_no width150pxtemplate #defaultscopespan版本1.0/span/template/el-table-columnel-table-column :show-overflow-tooltipfalse aligncenter label操作template #defaultscopediv classcellel-button :typescope.row.status 20 ? success : danger sizesmallclickhandlePowerAction(scope.row){{ scope.row.status 20 ? 开机 : 关机 }}/el-buttondiv classel-dropdown flex flex-wrap items-centerel-dropdownel-button typeinfo更多操作el-icon classel-icon--rightarrow-down //el-icon/el-buttontemplate #dropdownel-dropdown-menuel-dropdown-item clickhandleoperate(restart, scope.row)重启云机/el-dropdown-itemel-dropdown-item clickhandleoperate(edit, scope.row)修改名称/el-dropdown-itemel-dropdown-item clickhandleoperate(remark, scope.row)设置备注/el-dropdown-itemel-dropdown-item clickhandleoperate(random, scope.row)随机设备信息/el-dropdown-itemel-dropdown-item clickhandleoperate(mirror, scope.row)切换镜像/el-dropdown-itemel-dropdown-item clickhandleoperate(reset, scope.row)重置云机/el-dropdown-itemel-dropdown-item clickhandleoperate(copy, scope.row)复制云机/el-dropdown-itemel-dropdown-item clickhandleoperate(delete, scope.row)删除云机/el-dropdown-itemel-dropdown-item clickhandleoperate(terminal, scope.row)终端窗口/el-dropdown-item/el-dropdown-menu/template/el-dropdown/divdiv classflex flex-wrap items-centerel-dropdownel-button typeprimary选择网络el-icon classel-icon--rightarrow-down //el-icon/el-buttontemplate #dropdownel-dropdown-menuel-dropdown-item clickhandleSelectVPC旧选择VPC网络/el-dropdown-itemel-dropdown-item新选择VPC网络/el-dropdown-item/el-dropdown-menu/template/el-dropdown/div/div/template/el-table-column/el-table!-- 创建 --el-dialog v-modelcreatedVisible title创建安卓 width500el-form :modelformCreateel-form-item label云机数量 :label-widthformLabelWidthel-input-number v-modelformCreate.num autocompleteoff :min1 :max12 //el-form-itemel-form-item label镜像类型 :label-widthformLabelWidthel-radio-group v-modelformCreate.img_typeel-radio label10基础镜像/el-radioel-radio label20GMS镜像/el-radio/el-radio-groupel-button typeprimary sizesmall stylemargin-left: 10px clickhandleSwitchImageel-iconRefresh //el-iconnbsp; 切换/el-button/el-form-itemel-form-item labelDNS设置 :label-widthformLabelWidthel-select v-modelformCreate.dns changeselectDns placeholder请选择DNS classw130 filterableel-option v-foritem in setDns :keyitem.id :labelitem.name :valueitem.id //el-select/el-form-itemel-form-item label屏幕刷新率 :label-widthformLabelWidthel-select v-modelformCreate.fps placeholder请选择刷新率el-option label60 FPS value60 /el-option label90 FPS value90 /el-option label120 FPS value120 //el-select/el-form-item!-- el-form-item labelVPC网络 :label-widthformLabelWidthel-select v-modelformCreate.vpc placeholder请选择VPCel-option labelVPC网络 1 valuevpc1 /el-option labelVPC网络 2 valuevpc2 /el-option labelVPC网络 3 valuevpc3 //el-select/el-form-item --/el-formtemplate #footerdiv classdialog-footerel-button clickcreatedVisible false取消/el-buttonel-button typeprimary clickcreatedDialog(row)确定/el-button/div/template/el-dialog!-- 修改 --el-dialog v-modeldialogFormVisible title修改云机名称 width500el-form :modelformEditel-form-item label名称 :label-widthformLabelWidthel-input v-modelformEdit.new_name autocompleteoff //el-form-item/el-formtemplate #footerdiv classdialog-footerel-button clickdialogFormVisible false取消/el-buttonel-button typeprimary clickeditDialog(row)确定/el-button/div/template/el-dialog!-- 设置备注 --el-dialog v-modelremarkVisible title设置云机备注 width500el-form :modelformRemarkel-form-item label云机备注 :label-widthformLabelWidthel-input v-modelformRemark.name autocompleteoff //el-form-item/el-formtemplate #footerdiv classdialog-footerel-button clickremarkVisible false取消/el-buttonel-button typeprimary clickremarkVisible false确定/el-button/div/template/el-dialog!-- 切换云机镜像 --el-dialog v-modelmirrorVisible title切换云机镜像 width500el-form :modelformMirrorel-form-item label云机镜像 :label-widthformLabelWidthel-select v-modelformMirror.mirror multiple placeholder请选择 stylewidth: 240pxel-option v-foritem in mirrorList :keyitem.value :labelitem.label :valueitem.value //el-select/el-form-itemp说明如何切换的镜像不存在系统会先拉取镜像这个过程比较耗时请耐心等待。/p/el-formtemplate #footerdiv classdialog-footerel-button clickmirrorVisible false取消/el-buttonel-button typeprimary clickmirrorVisible false确定/el-button/div/template/el-dialog!-- 随机设备信息 --el-dialog v-modelrandomVisible title随机设备信息 width500 /el-dialog!-- 复制云机 --el-dialog v-modelcopyVisible title复制云机 width500el-form :modelformCopyspan云机复制数量/spanel-input-number v-modelformCopy.num :min1 :max10 //el-formspan说明复制请先关闭云机。相同实例号的云机同时只能有一台为开机状态。复制云机比较耗时请耐心等待/spantemplate #footerdiv classdialog-footerel-button clickcopyVisible false取消/el-buttonel-button typeprimary clickhandleCopy(row)确定/el-button/div/template/el-dialog!-- 重置云机 --el-dialog v-modelresetVisible title提示 width500el-iconWarningFilled //el-icon span确定要重置此云机?/spantemplate #footerdiv classdialog-footerel-button clickresetVisible false取消/el-buttonel-button typeprimary clickhandleReset(row)确定/el-button/div/template/el-dialog!-- 删除云机 --el-dialog v-modeldeleteVisible title提示 width500el-iconWarningFilled //el-icon span确定要删除此云机?/spantemplate #footerdiv classdialog-footerel-button clickdeleteVisible false取消/el-buttonel-button typeprimary clickhandleDele(row)确定/el-button/div/template/el-dialog!-- 终端窗口 --el-dialog v-modelterminalVisible title终端窗口 width500iframe srchttp://192.168.1.100:8080 frameborder0 width100% height500px/iframetemplate #footer /template/el-dialog!-- 选择网络 --el-dialog v-modelnetworkVisible title选择网络 width500el-form :modelformNetworkel-form-item labelVPC网络 :label-widthformLabelWidthel-select v-modelformNetwork.network placeholder请选择el-option labelVPC网络1 value1 /el-option labelVPC网络2 value2 /el-option labelVPC网络3 value3 //el-select/el-form-item/el-form/el-dialog/div
/template
script setup
import { ref, reactive, nextTick } from vue
import andriodList from /network/andriodList
import { ElMessage } from element-plus// 搜索条件
const formData reactive({name: ,
})
const loading ref(false); // 列表的加载中
const list ref([{}]) // 列表的数据const queryAndroidList async (flag) {// 根据搜索条件设置查询参数if (flag) {formData.name formData.name.trim()}loading.value truetry {const res await andriodList.getAllAndroidList({name: formData.name})if (res.code 200) {let allDataList [];res.data res.data.length 0 res.data.forEach((item, index) {item.list_cnt item.list_cnt.length 0 item.list_cnt.forEach((item2, index2) {allDataList.push({...item,// ...item2, 看具体需求 处理列表所需字段, 将list_cnt里的数据平铺开idx: item2.idx,name: item2.name,status: item2.status,data_dir: item2.data_dir,update_time: item2.update_time,sdk_port1: item2.sdk_port,adb_port1: item2.adb_port,cnt_id1: item2.cnt_id,})})})list.value allDataList;} else {list.value []}} catch (error) {list.value []} finally {loading.value false}
}
// 初始化获取列表
queryAndroidList()const selectIds ref([]);
// 行复选框选中项变化
function handleSelectVPC(selection) {selectIds.value selection.map(item item.id);
}function handleQuery() {loading.value true;
}
// 多选框选中数据
function handleSelectionChange(selection) {selectIds.value selection.map(item item.id);
}/*** 合并行或列* param row 行号* param col 列号* param rowspan 行合并数* param colspan 列合并数* param rowIndex 当前行号* param columnIndex 当前列号* */
const objectSpanMethod ({row,column,rowIndex,columnIndex,
}) {if (column.property idx) {if (rowIndex 0 list.value[rowIndex].idx list.value[rowIndex - 1].idx) {return {rowspan: 0,colspan: 0,}}return {rowspan: getRowspan(idx, rowIndex),colspan: 1,}}
}// 获取行合并数
const getRowspan (key, rowIndex) {let rowspan 1; //默认合并1行let curVal list.value[rowIndex][key]; //存储了当前值for (let i rowIndex 1; i list.value.length; i) {if (list.value[i][key] curVal) {rowspan;} else {break;}}return rowspan;
}// 选择DNS
const setDns ref([{id: 1,name: DNS1
},
{id: 2,name: DNS2}])
const selectDns async () { }//创建弹窗
const formCreate reactive({idx: ,num: 1,img_type: 10,dns: ,fps: ,
})const createdVisible ref(false)
// 创建实例
function handleCreate(row) {createdVisible.value true;formCreate.idx row.idx; // 保存idx到formCreate中
}const handleCreateAndroid async () {try {const res await andriodList.createAPI({idx: formCreate.idx, // 使用保存的idxnum: formCreate.num,img_type: formCreate.img_type,dns: formCreate.dns,fps: formCreate.fps,})if (res.code 200) {ElMessage.success(res.msg)createdVisible.value false// 刷新列表queryAndroidList()} else {ElMessage.error(res.msg)}} catch (error) {ElMessage.error(res.msg)}
}//确定创建弹窗
function createdDialog() {handleCreateAndroid()
}// 编辑实例
function handleEdit(row) {console.log(编辑实例:, row);
}//切换镜像
const handleSwitchImage () {console.log(切换镜像);
}//开机--关机 --status 容器状态 10 运行中 20 关机
let runId null
async function handlePowerAction(row) {runId row.cnt_id1const status row.statustry {let resif (status 10) {res await andriodList.stopAPI({cnt_id: runId})} else {res await andriodList.runAPI({cnt_id: runId})}if (res.code 200) {ElMessage.success(res.msg)queryAndroidList()} else {ElMessage.error(res.msg)}} catch (error) {ElMessage.error(res.msg)}
}//重启云机
const restarCnt async () {try {const res await andriodList.restart({cnt_id: publicId})if (res.code 200) {ElMessage.success(res.msg)// 重启成功后重新获取列表queryAndroidList()} else {ElMessage.error(res.msg)}} catch (error) {ElMessage.error(res.msg)}
}const formEdit reactive({cnt_id: ,new_name: ,
})
const dialogFormVisible ref(false)
const formLabelWidth 140pxconst handleEditName async () {try {const res await andriodList.renameAPI({cnt_id: formEdit.cnt_id,new_name: formEdit.new_name})if (res.code 200) {ElMessage.success(res.msg)dialogFormVisible.value falsequeryAndroidList()} else {ElMessage.error(res.msg)}} catch (error) {ElMessage.error(res.msg)}
}
//修改弹窗
function editDialog() {handleEditName()
}//设置备注
const formRemark reactive({name: ,
})
const remarkVisible ref(false)//切换
const formMirror reactive({mirror: ,
})
const mirrorList [{value: 1,label: 镜像1
}]
const mirrorVisible ref(false)//随机
const randomVisible ref(false)//复制
const formCopy reactive({num: 1,src_cnt_id: ,target_cnt_idx: ,target_cnt_name: ,
})
const copyVisible ref(false)
//复制弹窗
function handleCopy() {handleCopyAPI()
}const handleCopyAPI async () {try {const res await andriodList.copyAPI({num: formCopy.num,src_cnt_id: formCopy.src_cnt_id,target_cnt_idx: formCopy.target_cnt_idx,target_cnt_name: formCopy.target_cnt_name,})if (res.code 200) {ElMessage.success(res.msg)copyVisible.value falsequeryAndroidList()} else {ElMessage.error(res.msg)}} catch (error) {ElMessage.error(res.msg)}
}//重置
const resetVisible ref(false)
const handleResetId async () {try {const res await andriodList.resetAPI({cnt_id: publicId})if (res.code 200) {ElMessage.success(res.msg)deleteVisible.value falsequeryAndroidList()} else {ElMessage.error(res.msg)}} catch (error) {ElMessage.error(res.msg)}
}//重置弹窗
function handleReset() {handleResetId()
}//删除
const deleteVisible ref(false)
const handleDeleId async () {try {const res await andriodList.deleteCntAPI({cnt_id: publicId})if (res.code 200) {ElMessage.success(res.msg)deleteVisible.value falsequeryAndroidList()} else {ElMessage.error(res.msg)}} catch (error) {ElMessage.error(res.msg)}
}//删除
function handleDele() {handleDeleId()
}//终端
const terminalVisible ref(false)//选择网络
const formNetwork reactive({network: ,
})
const networkVisible ref(false) //选择网络弹窗 //操作
let publicId null // 公共id
function handleoperate(type, row) {publicId row.cnt_id1 // 获取第一个云机的cnt_idswitch (type) {case restart:restarCnt(row)break;case edit:dialogFormVisible.value true;formEdit.cnt_id publicId;formEdit.new_name row.name;break;case remark:remarkVisible.value true;break;case random:randomVisible.value true;break;case mirror:mirrorVisible.value true;break;case copy:copyVisible.value true;formCopy.src_cnt_id publicId;formCopy.target_cnt_name row.name;formCopy.target_cnt_idx row.idx;break;case terminal:terminalVisible.value true;break;case reset:// 处理重置操作resetVisible.value true;break;case delete:// 处理删除操作deleteVisible.value true;break;default:break;}
}/scriptstyle langscss scoped
.app-container {.search-bar {.el-icon {color: #fff;}}.cell {display: flex;justify-content: center;align-items: center;}.el-dropdown {margin-left: 10px;}.examples {display: flex;justify-content: center;}.time-line {margin-top: 10px;color: rgb(235, 0, 0);font-size: 14px;}
}
/style 代码中会有一些注释根据个人需求可以进行参考此需求也涉及到按钮操作的如果没有次需求可以忽略不看。 以上就是列表的合并单元格如果对你有帮助麻烦点个赞呗~