项目为vue3+elementPlus开发的项目
业务要求:table表格展示数据,其中有一行是ip地址可展示可修改,此处要求增加自定义校验规则
先看一下效果:
此处先描述一下,问题出在了哪里,我将el-table的data,使用一个ref数组存储,表格校验使用了一个对象存储,导致,校验的时候拿不到数据,代码如下
<template>
<el-form ref="ruleFormRef" :model="form" :rules="probeIpFormRules">
<el-table
:data="tableData"
empty-text="暂无数据"
height="calc(100% - 40px)"
:border="true"
style="width: 100%"
v-loading="loading"
element-loading-background="rgba(255, 255, 255, 0.5)"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="portName" min-width="190" label="端口号" />
<el-table-column prop="probeIp" min-width="160" label="探针IP">
<template #default="{ row, $index }">
<el-form-item :prop="`tableData[${$index}].probeIp`" :rules="probeIpFormRules.probeIp">
<el-input class="probeIp-style" v-model.trim="row.probeIp" autocomplete="off" clearable />
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
</template>
<script setup lang="ts">
const probeIpFormRules= {
probeIp: [{ required: false, message: '请输入ip地址', trigger: 'change' }, { validator: checkIp }],
}
const tableData=ref([])
</script>
以下是正确代码,就是将tableData和probeIpFormRules放到同一个对象里
<template>
<el-dialog
title="设置交换机端口"
v-model="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
draggable
width="90%"
@closed="handleClose"
>
<el-form ref="ruleFormRef" :model="form" :rules="form.probeIpFormRules">
<div class="box-warp">
<div class="hd-header">
<span>交换机ip: {{ switchIp }}</span>
<div class="hd-btn">
<el-button type="primary" @click="handleSave(ruleFormRef)" :loading="btnLoading">保存</el-button>
<el-button @click="handleClose">关闭</el-button>
</div>
</div>
<el-table
:data="form.tableData"
empty-text="暂无数据"
height="calc(100% - 40px)"
:border="true"
style="width: 100%"
v-loading="loading"
element-loading-background="rgba(255, 255, 255, 0.5)"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="portName" min-width="190" label="端口号" />
<el-table-column prop="portDes" min-width="200" label="端口描述" />
<el-table-column prop="portRunningStatus" min-width="90">
<template #header>
<el-tooltip :visible="tooltipVisible" placement="top">
<template #content>
<span>端口状态改变后请等待1分钟刷新查看</span>
</template>
<div class="status-style" @mouseenter="tooltipVisible = true" @mouseleave="tooltipVisible = false">
<span>当前端口状态</span>
<el-icon><QuestionFilled /></el-icon>
</div>
</el-tooltip>
</template>
<template #default="{ row }">
<el-tag :type="showStatus(row.portRunningStatus)">
{{ filterStatus(row.portRunningStatus) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="nominalBandwidth" min-width="100" label="额定带宽(Mb)">
<template #default="{ row }">
<el-input-number
v-model="row.nominalBandwidth"
:controls="false"
:step="1"
:min="0"
:max="9999"
:precision="0"
style="width: 100%"
/>
</template>
</el-table-column>
<el-table-column prop="probeName" min-width="190" label="探针名称">
<template #default="{ row }">
<el-input v-model.trim="row.probeName" maxlength="30" autocomplete="off" />
</template>
</el-table-column>
<el-table-column prop="probeIp" min-width="160" label="探针IP">
<template #default="{ row, $index }">
<el-form-item :prop="`tableData[${$index}].probeIp`" :rules="form.probeIpFormRules.probeIp">
<el-input class="probeIp-style" v-model.trim="row.probeIp" autocomplete="off" clearable />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="端口操作" fixed="right" width="140">
<template #default="{ row }">
<el-switch
v-model="row.portChangeStatus"
:active-value="1"
:inactive-value="2"
active-text="ON"
inactive-text="OFF"
inline-prompt
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #f56c6c"
@change="changevisible"
/>
</template>
</el-table-column>
</el-table>
</div>
</el-form>
</el-dialog>
</template>
<script setup lang="ts">
import { getPortByIp, savePort } from '@/api/switchModule'
import { validIpC } from '@/utils/validate.js'
const tooltipVisible = ref(false)
const ruleFormRef = ref()
/**
* 状态显示
*/
const changevisible = () => {
tooltipVisible.value = true
const timer = setTimeout(() => {
tooltipVisible.value = false
clearTimeout(timer)
}, 1000)
}
//校验子网地址格式
const checkIp = (rule: any, value: any, callback: any) => {
if (value?.trim().length === 0) {
callback(new Error('请输入ip地址'))
} else if (value && !validIpC(value?.trim())) {
callback(new Error('请输入正确格式的ip地址'))
} else {
callback()
}
}
const dialogVisible = ref(false)
/**
* 关闭弹窗
*/
const handleClose = () => {
dialogVisible.value = false
}
const portStatus: Record<string, { label: string; color: 'success' | 'danger' }> = {
'1': {
label: '开启',
color: 'success',
},
'2': {
label: '关闭',
color: 'danger',
},
}
const filterStatus = (status: number) => {
return portStatus[String(status)].label
}
const showStatus = (status: number) => {
return portStatus[String(status)].color
}
const switchIp = ref('')
const btnLoading = ref(false)
const form = ref({
tableData: [],
probeIpFormRules: {
probeIp: [{ required: false, message: '请输入ip地址', trigger: 'change' }, { validator: checkIp }],
},
})
const handleSave = async (formEl: any) => {
if (!formEl) return
formEl.validate(async (valid: any) => {
if (!valid) return
ElMessageBox.confirm('确定提交端口信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
btnLoading.value = true
try {
const params = {
switchIp: switchIp.value,
resSwitchPortEntities: form.value.tableData,
}
console.log('请求保存的参数是==》', params)
const { code, data } = await savePort(params)
console.log('保存的数值为=》', code, data)
dialogVisible.value = false
} catch (error) {
console.log('保存失败==》', error)
} finally {
btnLoading.value = false
}
})
})
}
/**
* 查询数据
* @param switchIp
*/
const queryList = async (switchIp: string) => {
loading.value = true
try {
const { code, data } = await getPortByIp({ switchIp })
if (code !== 200 || data.resSwitchPortEntities.length === 0) return
form.value.tableData = data.resSwitchPortEntities
} catch (error) {
console.log('错误==》', error)
} finally {
loading.value = false
}
}
const openDialog = (ip: string) => {
switchIp.value = ip
//通过ip请求数据
queryList(ip)
dialogVisible.value = true
}
defineExpose({
openDialog,
})
// 搜索对象
const searchForm = reactive({
pageNum: 1,
pageSize: 100,
total: 0,
})
// 表格数据
const loading: Ref<boolean> = ref(false)
</script>
<style lang="scss" scoped>
.box-warp {
height: 70vh;
:deep(.el-input__wrapper) {
box-shadow: 0 0 0 0px;
}
.hd-header {
display: flex;
justify-content: space-between;
// margin-top: -20px;
margin-bottom: 20px;
}
.probeIp-style{
margin-top: 18px ;
}
.status-style {
display: flex;
align-items: center;
justify-content: center;
}
}
</style>
最终样式如下
Ï