elementUI嵌套动态增删表单升级版
比较昨日,今日新添嵌套
相关代码细节
<el-button type="primary" @click="clickCateSmallItemAdd(subIdx)">添加分类项目</el-button>
<template v-for="(casmaItem, casmaIdx) in form.categoryItem[subIdx].cateSmallItems || []">
<el-row :gutter="24" :key="casmaIdx">
<el-col :md="12" :lg="12" :xl="12">
<el-form-item>
<sp-text v-model="casmaItem.itemName" placeholder="请输入分类项目"
:maxlength="10" :precision="0" :size="formSize"
:readonly="isView" />
</el-form-item>
</el-col>
<el-col :md="9" :lg="9" :xl="9">
<el-form-item>
<sp-text v-model="casmaItem.score" :maxlength="10" style="width: 93%;"
placeholder="请输入分值" :readonly="isView" />
</el-form-item>
</el-col>
<el-col :md="1" :lg="1" :xl="1">
<el-form-item>
</el-form-item>
</el-col>
<el-col :md="2" :lg="2" :xl="2">
<el-form-item>
<el-button v-if="form.categoryItem[subIdx].cateSmallItems.length != 1" circle icon="el-icon-delete-solid" @click="clickCateSmallItemDel(subIdx, subItem, casmaIdx)" style="margin: 0%;"></el-button>
</el-form-item>
</el-col>
</el-row>
<div v-for="(item, i) in form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards || []">
<el-row :gutter="24" :key="i">
<el-col :md="24" :lg="24" :xl="24">
<el-form-item>
<sp-text v-model="item.standard" :data-list="[]" :maxlength="50"
:readonly="isView" style="width:84.5%" placeholder="请输入标准"/>
<el-button v-if="form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards.length != 1" circle icon="el-icon-delete" @click="clickStandardItemDel(subIdx, casmaIdx, subItem, i)" style="margin: 0%;"></el-button>
<el-button circle icon="el-icon-plus" @click="clickStandardItemAdd(subIdx, casmaIdx)" style="margin: 0%;"></el-button>
</el-form-item>
</el-col>
</el-row>
</div>
</template>
//控制标准输入框增删
clickStandardItemAdd(subIdx, casmaIdx) {
this.form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards.unshift({
standard:'',
standardTypeId: '',
standardType: '',
})
},
clickStandardItemDel(subIdx, casmaIdx, row, idx) {
this.form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards.splice(idx, 1)
},
//控制分类项增删
clickCateSmallItemAdd(subIdx) {
this.form.categoryItem[subIdx].cateSmallItems.unshift({
itemName: undefined,
score: undefined,
standards: [
{ standard:undefined,standardTypeId: undefined,standardType: undefined }
],
})
},
clickCateSmallItemDel(subIdx, row, casmaIdx) {
this.form.categoryItem[subIdx].cateSmallItems.splice(casmaIdx, 1)
},
动态显示删除按钮
导师说标准框和分类项目剩一个时都不要显示删除按钮,做个判断就好了,成果如上图
<el-button v-if="form.categoryItem[subIdx].cateSmallItems.length != 1" circle icon="el-icon-delete-solid" @click="clickCateSmallItemDel(subIdx, subItem, casmaIdx)" style="margin: 0%;"></el-button>
<el-button v-if="form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards.length != 1" circle icon="el-icon-delete" @click="clickStandardItemDel(subIdx, casmaIdx, subItem, i)" style="margin: 0%;"></el-button>
源码
<template>
<component :is="componentName" v-if="isDialog ? dialog.visible : true" :visible.sync="dialog.visible"
v-loading="formModel ? false : fullLoading" v-bind="dynamicAttr">
<div class="detailForm" :style="formModel === 'drawer' ? 'padding: 0px 32px 128px;' : ''">
<section>
<header v-if="!isDialog" class="spui-header">
<span class="spui-header-title">{{title}}</span>
<div>
<el-button v-if="isEdit" type="primary" size="small" :loading="btnLoading" @click="onSubmit()">
完成</el-button>
<el-button size="small" :loading="btnLoading" @click="back()">返回</el-button>
</div>
</header>
<main class="e-main">
<el-form ref="ruleForm" class="spui-form" :class="isView ? 'spui-form-view' : ''" :model="form"
:rules="isEdit ? ruleForm : null" label-width="130px" :size="formSize" label-position="top"
@submit.native.prevent v-loading="fullLoading">
<sp-form-group v-model="isCollapse['base']" name="基本信息" :border="true">
<el-row :gutter="24">
<el-col :md="12" :lg="12" :xl="12">
<el-form-item label="模板名称1" prop="templateName">
<sp-text v-model="form.templateName" :maxlength="255" placeholder="请输入模板名称"
:readonly="isView" />
</el-form-item>
</el-col>
<el-col :md="12" :lg="12" :xl="12">
<el-form-item label="模板属性" prop="attribute">
<sp-numeric v-model="form.attribute" placeholder="请输入模板属性(0:总部1:大区)"
:maxlength="11" :precision="0" :size="formSize" :readonly="isView" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :md="12" :lg="12" :xl="12">
<el-form-item label="模板类型" prop="type">
<sp-select v-model="form.type" :data-list="[]" :readonly="isView"
placeholder="请选择类型" style="width:100%" />
</el-form-item>
</el-col>
<el-col :md="12" :lg="12" :xl="12">
<el-form-item label="权重占比" prop="proportionOfWeight">
<sp-numeric v-model="form.proportionOfWeight" placeholder="请输入权重占比"
:maxlength="11" :precision="0" :size="formSize" :readonly="isView" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="备注" prop="">
<el-input type="textarea" :autosize="{ minRows: 4 }" size="small"
placeholder="请输入备注" maxlength="256" show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
</sp-form-group>
<sp-form-group v-model="isCollapse['categoryItem']" name="分类标准" :add="isEdit"
:clear="form.categoryItem && form.categoryItem.length > 1 && form.categoryItem.filter(row => row.isDeleted !== 1).length > 1 && isEdit"
@add="clickCategoryItemAdd()" @clear="clearSub(form.categoryItem, '分类标准')">
<ul class="form-group-list">
<template v-for="(subItem, subIdx) in form.categoryItem || []">
<li v-if="subItem.isDeleted != 1" :key="subIdx" class="form-group-list-item"
style="background: #f2f3f5">
<div style="flex: 1;">
<el-row :gutter="24">
<el-col :md="16" :lg="16" :xl="16">
<el-form-item label="标准分类" :required="true"
:prop="'categoryItem.' + subIdx + '.categoryName'"
:rules="ruleForm.categoryItem.categoryName">
<sp-select v-model="subItem.categoryName" :maxlength="255"
placeholder="请选择分类" :readonly="isView" />
<el-button icon="el-icon-plus" @click="clickCategoryItemAdd()">
</el-button>
<el-button type="primary"
@click="clickCateSmallItemAdd(subIdx)">添加分类项目</el-button>
</el-form-item>
</el-col>
</el-row>
<template
v-for="(casmaItem, casmaIdx) in form.categoryItem[subIdx].cateSmallItems || []">
<el-row :gutter="24" :key="casmaIdx">
<el-col :md="12" :lg="12" :xl="12">
<el-form-item>
<sp-text v-model="casmaItem.itemName" placeholder="请输入分类项目"
:maxlength="10" :precision="0" :size="formSize"
:readonly="isView" />
</el-form-item>
</el-col>
<el-col :md="9" :lg="9" :xl="9">
<el-form-item>
<sp-text v-model="casmaItem.score" :maxlength="10"
style="width: 93%;" placeholder="请输入分值"
:readonly="isView" />
</el-form-item>
</el-col>
<el-col :md="1" :lg="1" :xl="1">
<el-form-item>
</el-form-item>
</el-col>
<el-col :md="2" :lg="2" :xl="2">
<el-form-item>
<el-button
v-if="form.categoryItem[subIdx].cateSmallItems.length != 1"
circle icon="el-icon-delete-solid"
@click="clickCateSmallItemDel(subIdx, subItem, casmaIdx)"
style="margin: 0%;"></el-button>
</el-form-item>
</el-col>
</el-row>
<div
v-for="(item, i) in form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards || []">
<el-row :gutter="24" :key="i">
<el-col :md="24" :lg="24" :xl="24">
<el-form-item>
<sp-text v-model="item.standard" :data-list="[]"
:maxlength="50" :readonly="isView"
style="width:84.5%" placeholder="请输入标准" />
<el-button
v-if="form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards.length != 1"
circle icon="el-icon-delete"
@click="clickStandardItemDel(subIdx, casmaIdx, subItem, i)"
style="margin: 0%;"></el-button>
<el-button circle icon="el-icon-plus"
@click="clickStandardItemAdd(subIdx, casmaIdx)"
style="margin: 0%;"></el-button>
</el-form-item>
</el-col>
</el-row>
</div>
</template>
</div>
<el-popconfirm placement="top-end" title="确定删除该条子表信息?"
@confirm="clickCategoryItemDel(subItem, subIdx)">
<el-link slot="reference" type="danger" style="margin-left: 30px;">删除
</el-link>
</el-popconfirm>
</li>
</template>
</ul>
</sp-form-group>
</el-form>
</main>
</section>
</div>
<div v-if="isDialog"
v-bind="formModel == 'dialog' ? { slot: 'footer' } : { slot: 'title', style: 'display: flex; justify-content: space-between; align-items: center;' }">
<span v-if="formModel == 'drawer'" style="font-size: 20px; color: #1d2129;">{{ title }}</span>
<span>
<el-button size="small" @click="back">取 消</el-button>
<el-button v-if="params.state !== 'view'" size="small" type="primary" @click="onSubmit"
:loading="btnLoading">确 定</el-button>
</span>
</div>
</component>
</template>
<script>
import {
AppraisalTemplateApi
} from '@/api/module/appraisalTemplate/appraisal.template.js'
export default {
props: {
dialog: {
type: Object,
default: () => {
return {}
},
},
formModel: {
type: String,
},
},
components: {},
data() {
let isDialog = (this.dialog.visible != undefined && this.formModel) || false
return {
// 判断是否为弹窗
isDialog: isDialog,
params: isDialog ? this.dialog : this.$route.query,
isFormChange: false,
fullLoading: false,
btnLoading: false,
formSize: 'small',
ruleForm: {
categoryItem: {},
},
form: {
templateName: undefined,
type: undefined,
attribute: undefined,
proportionOfWeight: undefined,
parkId: undefined,
status: undefined,
categoryItem: [],
},
// 折叠
isCollapse: {
base: true,
categoryItem: false,
},
}
},
computed: {
componentName() {
const n = {
default: 'sp-container',
dialog: 'p-dialog',
drawer: 'el-drawer',
}
return n[this.formModel || 'default']
},
// 动态属性
dynamicAttr() {
const attrData = {
default: {
background: '#f2f3f5',
block: true,
style: 'min-height: 100vh',
},
dialog: {
title: this.title,
width: '80vw',
'max-width': '860px',
'before-close': this.back,
'append-to-body': true,
},
drawer: {
title: this.title,
size: '60vw',
'before-close': this.back,
'append-to-body': true,
'show-close': false,
wrapperClosable: false,
},
}
return attrData[this.formModel || 'default']
},
// 判断是否为新增
isAdd() {
return this.params.state === 'add' || !this.params.state
},
// 判断是否为新增或修改
isEdit() {
return this.params.state !== 'view'
},
// 判断是否为新增或修改
isView() {
return this.params.state === 'view'
},
title() {
return '考核模板' + (this.isAdd ? '新增' : this.isEdit ? '修改' : '查看')
}
},
created() {},
mounted() {
if (this.isAdd && this.params.parkId) {
this.form.parkId = this.params.parkId
}
this.loadData()
},
methods: {
loadData() {
if (!this.isAdd) {
this.fullLoading = true
this.btnLoading = true
AppraisalTemplateApi.get(this.params.id).then((res) => {
const data = res.data
data.categoryItem = data.categoryItem || []
this.form = data
}).finally(() => {
this.fullLoading = false
this.btnLoading = false
})
}
},
onSubmit() {
this.$refs.ruleForm.validate(valid => {
if (valid) {
this.fullLoading = true
this.btnLoading = true
let apiMethod = this.isAdd ? AppraisalTemplateApi.add : AppraisalTemplateApi.update
apiMethod(this.form).then((res) => {
if (res.success) {
this.$notify({
type: 'success',
message: '保存成功',
title: '提示',
})
this.isFormChange = true
this.back()
}
}).finally(() => {
this.fullLoading = false
this.btnLoading = false
})
} else {
// TODO 表单验证未通过处理
}
})
},
clearSub(sub, title) {
this.$confirm('确定清空' + title + '吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
for (let i = 0, len = sub.length; i < len; i++) {
if (sub[i].id) {
sub[i].isDeleted = 1
} else {
sub.splice(i, 1)
i--
len--
}
}
})
},
//控制标准输入框增删
clickStandardItemAdd(subIdx, casmaIdx) {
this.form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards.unshift({
standard: '',
standardTypeId: '',
standardType: '',
})
},
clickStandardItemDel(subIdx, casmaIdx, row, idx) {
this.form.categoryItem[subIdx].cateSmallItems[casmaIdx].standards.splice(idx, 1)
},
//控制分类项增删
clickCateSmallItemAdd(subIdx) {
this.form.categoryItem[subIdx].cateSmallItems.unshift({
itemName: undefined,
score: undefined,
standards: [{
standard: undefined,
standardTypeId: undefined,
standardType: undefined
}],
})
},
clickCateSmallItemDel(subIdx, row, casmaIdx) {
this.form.categoryItem[subIdx].cateSmallItems.splice(casmaIdx, 1)
},
//控制标准分类增删
clickCategoryItemAdd() {
this.form.categoryItem.unshift({
categoryName: undefined,
cateSmallItems: [{
itemName: undefined,
score: undefined,
standards: [{
standard: undefined,
standardTypeId: undefined,
standardType: undefined
}, ],
}, ],
templateId: undefined,
parkId: undefined,
})
},
clickCategoryItemDel(row, idx) {
if (row.id) {
row.isDeleted = 1
} else {
this.form.categoryItem.splice(idx, 1)
}
},
// 子表操作 end
back() {
if (this.isDialog) {
if (this.isFormChange) {
this.$emit('updateList')
}
this.$emit('update:dialog', {
...this.dialog,
visible: false
})
} else {
let router = {
path: '/appraisal-template',
}
this.$router.push(router)
}
},
}
}
</script>
<style lang="less" scoped>
</style>