出現的問題
1.el-input輸入不上,el-select選擇不了
2.使用強制重新整理後,能選擇,但是表單驗證失效
3.最終解決方案(代碼裡有注釋)
重要部分(思路)
<el-form :model="registerForm" ref="ruleFormProp" :rules="rules">
<div v-for="(item,index) in registerForm.processData" :key="index">
<el-form-item :prop="'processData.'+index+'.assetsName'" :rules="rules.assetsName">
<el-input placeholder="請輸入" class="addinput" v-model="item.assetsName">
</el-input>
</el-form-item>
</div>
</el-form>
3-1. 後端擷取的數組用registerForm對象包裹,processData為後端數組
3-2. :prop="'processData.'+index+'.assetsName'" 綁定動态屬性,也可使用模闆拼接
:prop="`processData.${index}.assetsName`"
3-3. :rules="rules.assetsName" 進行表單驗證
data() {
var checkassetsName = (rule, value, callback) => {
if (!value) {
return callback(new Error('請輸入資産名稱'));
} else {
callback();
}
};
return {
assetsName: [{ validator: checkassetsName, trigger: 'blur' }],
}
}
3-4. 最後确定時觸發rlues驗證
onSubmit() {
this.$refs.ruleFormProp.validate((valid)=>{
if(valid){ }
}
}
4. 完整代碼
index.vue頁面
<template>
<div>
<div style="margin-top: 125px">
<div class="el-dialog-register-top">資産登記</div>
<div style="padding: 10px" class="row-col-columns">
<div class="row-col-columns-1">序号</div>
<div class="row-col-columns-2">主機序列号</div>
<div class="row-col-columns-3"><span class="register-star">*</span>轄區</div>
<div class="row-col-columns-2"><span class="register-star">*</span>型号</div>
<div class="row-col-columns-2"><span class="register-star">*</span>資産名稱</div>
<div class="row-col-columns-3"><span class="register-star">*</span>所屬廠家/品牌</div>
<div class="row-col-columns-2"><span class="register-star">*</span>使用機關</div>
</div>
<el-form style="width: 100%;" size="medium" :model="registerForm" ref="ruleFormProp" :rules="rules">
<div v-for="(item,index) in registerForm.processData" :key="index" class="row-col-columns">
<div class="row-col-columns-1 number">{{ index+1 }}</div>
<div class="row-col-columns-2">
<el-input v-model="item.serialNumber" disabled></el-input>
</div>
<div class="row-col-columns-3">
<!-- 轄區 -->
<el-form-item :prop="`processData.${index}.jurisdictionName`" :rules="rules.jurisdictionName">
<el-input v-model="item.jurisdictionName" disabled></el-input>
</el-form-item>
</div>
<div class="row-col-columns-2">
<!-- 型号 -->
<el-form-item :prop="`processData.${index}.model`" :rules="rules.model">
<el-input v-model="item.model" disabled></el-input>
</el-form-item>
</div>
<div class="row-col-columns-2">
<el-form-item :prop="'processData.'+index+'.assetsName'" :rules="rules.assetsName">
<el-input placeholder="請輸入" class="addinput" v-model="item.assetsName">
</el-input>
</el-form-item>
</div>
<div class="row-col-columns-3"> // 所屬廠家/品牌
<el-form-item :prop="`processData.${index}.belongBrandId`" :rules="rules.belongBrandId">
<el-cascader
v-model.trim="item.belongBrandId"
ref="cascaderList"
@change="handleChange($event, index)"
:props="{
lazy: true,
lazyLoad: lazyLoadAdd,
}">
</el-cascader>
</el-form-item>
</div>
<div class="row-col-columns-2">
<!-- 使用機關 -->
<el-form-item :prop="`processData.${index}.useId`" :rules="rules.useId">
<el-select v-model="item.useId" clearable placeholder="使用機關" class="inputSelect">
<el-option v-for="item2 in item.useOptions" :key="item2.value" :label="item2.label" :value="item2.value"></el-option>
</el-select>
</el-form-item>
</div>
<div class="row-col-columns-1 number" @click="clearItem(item)" >
<svg class="iconfont" aria-hidden="true" style="width: 18px; height: 18px">
<use xlink:href="#el-icon-myshanchu" target="_blank" rel="external nofollow" />
</svg>
</div>
</div>
</el-form>
<div class="footer-btn">
<el-button @click="onCancel" class="btnSizeStyle">取 消</el-button>
<el-button type="primary" @click="onSubmit" class="btnSizeStyle">确 定</el-button>
</div>
</div>
</div>
</template>
<script>
import { recordFindHost, batchAssetsRegister } from '@/api/property/networkAccess' // 接口
import { organizationApiManagement } from '@/api/property/pointInterface' // 接口
import { belongBrand } from '@/utils/manufacturerBrand' // 廠家及品牌聯級選擇
export default {
data() {
var checkassetsName = (rule, value, callback) => {
console.log(value)
if (!value) {
return callback(new Error('請輸入資産名稱'));
} else {
callback();
}
};
var checkbelongBrandId = (rule, value, callback) => {
console.log(value)
if (value.length === 0) {
return callback(new Error('請選擇所屬廠家'));
} else if (value.length === 1) {
return callback(new Error('請選擇品牌'));
} else if (value[2] === 0 && value[1] === 'ditto') {
// value第三個值代表循環資料的下标,下标為0時不能選擇同上
return callback(new Error('第一條資料不能選為同上'));
}
else {
callback();
}
};
var checkuseId = (rule, value, callback) => {
if (!value) {
return callback(new Error('請選擇使用機關'));
} else {
callback();
}
};
return {
registerForm: { // 表單包含數組
processData: []
},
rules: {
assetsName: [{ validator: checkassetsName, trigger: 'blur' }],
belongBrandId: [{ validator: checkbelongBrandId, trigger: 'change' }],
useId: [{ validator: checkuseId, trigger: 'change'}],
},
}
},
created() {
this.assetsRegister()
},
methods: {
async assetsRegister() {
const useOptions = await this.getUse() // 擷取使用機關清單
const params = { hostSerialNumber: this.$route.query.host }
recordFindHost(params).then(res => {
res.data.forEach((item, index) => {
item.assetsName = '' // 資産名稱
item.jurisdictionCode = item.streetCode // 後端接收的轄區字段
item.jurisdictionName = item.provinceName + item.cityName + item.areaName + item.streetName // 前端顯示省市區街道
item.belongBrandId = [] // 用于儲存所屬廠家及品牌的id
item.useId = '' // 使用機關
item.useOptions = useOptions // 使用機關
item.assetsTypeThree = 53 // 添加資料時傳給背景預設的值
const dittoVal = [{value: "ditto" , label: '同上'}]
if (index !== 0) { // 不是第一條,都同上
item.useId = 'ditto'
// 不用push是因為會改變原數組,導緻第一條使用機關清單也包括同上選項
item.useOptions = item.useOptions.concat(dittoVal)
}
})
this.registerForm.processData = res.data // 組成自己想要的資料結構
})
},
// 擷取廠家及品牌
async lazyLoadAdd(node, resolve) {
if (node.level === 0) {
return resolve(await belongBrand(node.level+1))
} else if (node.level === 1) {
return resolve(await belongBrand(node.level+1, node.value ))
}
},
// 即選擇廠家也選擇品牌,才能給數組push下标,進行rules驗證
handleChange(e,index) {
if (e.length !== 1) {
e.push(index)
}
},
// 取消
onCancel() {
this.registerForm.processData = []
},
// 清除, 隻有資産名稱,所屬廠家/品牌, 使用機關需要清除
clearItem(item) {
item.assetsName = ''
item.belongBrandId = []
item.useId = ''
},
// 确定,這個可以不做參考,隻是生成後端想要的值
onSubmit() {
this.$refs.ruleFormProp.validate((valid)=>{
if(valid){
var serialNumberArr = [], assetsNameArr =[], belongingIdArr = [], modelArr = [],
brandIdArr = [], jurisdictionCodeArr = [], useIdArr = [], assetsTypeThreeArr = []
this.registerForm.processData.forEach(item => {
serialNumberArr.push(item.serialNumber)
assetsNameArr.push(item.assetsName)
belongingIdArr.push(item.belongBrandId[0]) // 關聯下拉選擇,廠家為數組第一個
brandIdArr.push(item.belongBrandId[1]) // 關聯下拉選擇,品牌為數組第二個
modelArr.push(item.model)
jurisdictionCodeArr.push(item.jurisdictionCode)
useIdArr.push(item.useId)
assetsTypeThreeArr.push(item.assetsTypeThree)
})
const params = new URLSearchParams()
params.append('serialNumber', serialNumberArr)
params.append('assetsName', assetsNameArr)
params.append('belongingId', belongingIdArr)
params.append('brandId', brandIdArr)
params.append('model', modelArr)
params.append('jurisdictionCode', jurisdictionCodeArr)
params.append('useId', useIdArr)
params.append('assetsTypeThree', assetsTypeThreeArr)
batchAssetsRegister(params).then(res => {
if (res.code !== '0000') {
this.$message.error(res.message)
return
}
this.$router.push({ path:'/networkAccessList' }) // 傳回
})
}
})
},
// 使用機關
getUse() {
return new Promise((resolve) => {
organizationApiManagement('GET', '', 'find').then(res => {
const arr = [] // 全部
if (res.code !== '0000') {
resolve(arr)
} else {
res.data.list.forEach(item => {
const k = {
serialNo: item.serialNo,
value: item.id,
label: item.organizationName
}
arr.push(k)
resolve(arr)
})
}
})
})
},
}
}
</script>
<style scoped>
.el-dialog-register-top {
margin-top: -30px;
padding: 10px;
border-bottom: 1px solid #E4E7ED;
}
.row-col-columns {
display: flex;
margin-left: 8px;
div{
padding-right: 5px;
}
::v-deep .el-input.is-disabled .el-input__inner{
color: #333;
}
.number{
padding: 10px 0 0 15px;
}
.row-col-columns-1 {
width: 40px;
}
.row-col-columns-2 {
width: 142px;
// width: 125px;
}
.row-col-columns-3 {
width: 200px;
// width: 175px;
}
.register-star {
color: #F56C6C;
}
}
.footer-btn {
display: flex;
justify-content: center;
}
</style>
2.廠家,品牌聯級選擇 manufacturerBrand.js頁面,使用Promise将值傳回給index.vue頁面
import { organizationApiManagement } from '@/api/property/pointInterface'
import { getBrandApi } from '@/api/property/assets'
const belongBrand = async (level, id) => {
return new Promise((resolve) => {
console.log(level)
if (level === 1) {
const organizationArr = []
// 擷取所屬廠家
organizationApiManagement('GET', '', 'findList').then(res => {
if (res.code === '0000') {
res.data.forEach((item) => {
const k = {
value: item.id,
label: item.organizationName,
children: []
}
organizationArr.push(k)
})
const ditto = {value: "ditto" , label: '同上'}
organizationArr.push(ditto)
resolve(organizationArr)
} else {
resolve(organizationArr)
}
})
} else if (level === 2) {
if (id === 'ditto') { // 如果廠家選中為同上,廠家資料隻有同上
const val = [{ value: 'ditto', label: '同上', children: [], leaf: true }]
resolve(val)
} else {
const arr = []
const params = {
factoryId: id
}
// 擷取品牌
getBrandApi(params).then(res => {
if (res.code === '0000') {
res.data.forEach(item => {
const k = {
value: item.id,
label: item.typeName,
children: [],
leaf: true
}
arr.push(k)
})
resolve(arr)
} else {
resolve(arr)
}
})
}
}
})
}
export { belongBrand }
4. 完成頁面

如有不懂可以詢問,我看到的話必回