效果图
三级嵌套:
四级嵌套:
页面需求是根据工单类型不同 分为三级嵌套和四级嵌套,且点击展开实时发送请求获取数据,最后一级统一为标签页且点击标签页发送请求。
<template>
<div class="JNPF-common-layout">
<div class="JNPF-common-layout-center">
<el-row class="JNPF-common-search-box" :gutter="16">
<el-form @submit.native.prevent>
<el-col :span="6">
<el-form-item label="工单编号">
<el-input v-model="queryObj.mo_code" placeholder="请输入工单编号" clearable
@keyup.enter.native="search()" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="生产任务单编号">
<el-input v-model="queryObj.mo_task_code" placeholder="请输入生产任务单编号" clearable
@keyup.enter.native="search()" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="标签扫码">
<el-input v-model="queryObj.barcode" placeholder="请标签扫码" clearable
@keyup.enter.native="search()" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="search()">
{{ $t('common.search') }}</el-button>
<el-button icon="el-icon-refresh-right" @click="init()">{{ $t('common.reset') }}
</el-button>
</el-form-item>
</el-col>
</el-form>
</el-row>
<!-- 下 -->
<div class="JNPF-common-layout-main JNPF-flex-main">
<!-- 1 -->
<el-table :data="oneList" style="overflow: auto;" v-loading="packTaskLoading" @expand-change="expandChange">
<el-table-column type="expand">
<template slot-scope="props">
<div class="div1">
<!-- 2 -->
<el-table :data="props.row.ruleItemData" style="width: 100%"
@expand-change="expandChangeThree">
<el-table-column type="expand">
<!-- 3 -->
<template slot-scope="props">
<div v-if="props.row.type == 2">
<el-table :data="props.row.ruleItemData" style="width: 100%"
@expand-change="expandChangefour">
<el-table-column type="expand">
<template slot-scope="props">
<el-tabs v-model="props.row.activeName">
<el-tab-pane name="ren">
<div slot="label"
@click="handleClick('ren', props.row)">员工详情
</div>
<el-table :data="props.row.ruleItemData"
style="width: 100%">
<el-table-column type="index" label="序号"
:index="1" />
<el-table-column prop="employee_name"
label="员工名称" />
<el-table-column prop="start_time" label="开始时间" />
</el-table>
</el-tab-pane>
<el-tab-pane name="ji">
<div slot="label" @click="handleClick('ji', props.row)">
设备详情
</div>
<el-table :data="props.row.ruleItemData"
style="width: 100%">
<el-table-column type="index" label="序号"
:index="1" />
<el-table-column prop="equip_code" label="设备编码" />
<el-table-column prop="mold_code" label="模具编码" />
</el-table>
</el-tab-pane>
<el-tab-pane name="liao">
<div slot="label"
@click="handleClick('liao', props.row)">物料详情
</div>
<el-table :data="props.row.ruleItemData"
style="width: 100%">
<el-table-column type="index" label="序号"
:index="1" />
<el-table-column prop="material_code"
label="投入物料编号" />
<el-table-column prop="material_name" label="名称" />
<el-table-column prop="batch" label="批次号" />
<el-table-column prop="supplier_name" label="供应商" />
<el-table-column prop="check_conclusion"
label="检验结论" />
<el-table-column prop="instock_time" label="入库时间" />
<el-table-column prop="feeding_time" label="投料时间" />
</el-table>
</el-tab-pane>
</el-tabs>
</template>
</el-table-column>
<el-table-column label="序号" type="index" />
<el-table-column label="子任务单号" prop="mo_task_code" />
<el-table-column label="工位" prop="station_name" />
<el-table-column label="工序" prop="process_name" />
<el-table-column label="产出物料" prop="material_name" />
<el-table-column label="批次号" prop="batch" />
</el-table>
</div>
<el-tabs v-model="props.row.activeName" v-if="props.row.type == 1">
<el-tab-pane name="ren">
<div slot="label" @click="handleClick('ren', props.row)">员工详情</div>
<el-table :data="props.row.ruleItemData" style="width: 100%">
<el-table-column type="index" label="序号" :index="1" />
<el-table-column prop="employee_name" label="员工名称" />
<el-table-column prop="start_time" label="开始时间" />
</el-table>
</el-tab-pane>
<el-tab-pane name="ji">
<div slot="label" @click="handleClick('ji', props.row)">设备详情</div>
<el-table :data="props.row.ruleItemData" style="width: 100%">
<el-table-column type="index" label="序号" :index="1" />
<el-table-column prop="equip_code" label="设备编码" />
<el-table-column prop="mold_code" label="模具编码" />
</el-table>
</el-tab-pane>
<el-tab-pane name="liao">
<div slot="label" @click="handleClick('liao', props.row)">物料详情</div>
<el-table :data="props.row.ruleItemData" style="width: 100%">
<el-table-column type="index" label="序号" :index="1" />
<el-table-column prop="material_code" label="投入物料编号" />
<el-table-column prop="material_name" label="名称" />
<el-table-column prop="batch" label="批次号" />
<el-table-column prop="supplier_name" label="供应商" />
<el-table-column prop="check_conclusion" label="检验结论" />
<el-table-column prop="instock_time" label="入库时间" />
<el-table-column prop="feeding_time" label="投料时间" />
</el-table>
</el-tab-pane>
</el-tabs>
</template>
<!-- <template slot-scope="props" v-if="props.row.type == 2"> -->
<!-- <div class="div5"> -->
<!-- <el-table :data="props.row.ruleItemData" style="width: 100%">
</el-table> -->
<!-- </div> -->
<!-- </template> -->
</el-table-column>
<el-table-column type="index" label="序号" :index="1" />
<el-table-column label="生产任务单" prop="mo_task_code" />
<el-table-column label="物料编码" prop="material_code" />
<el-table-column label="物料名称" prop="material_name" />
<el-table-column label="规格型号" prop="material_standard" />
<el-table-column label="开始时间" prop="act_start_date" />
<el-table-column label="结束时间" prop="act_end_date" />
<el-table-column label="生产线 或 车间/工位">
<template slot-scope="props">
<div>{{ props.row.type == 1 ? props.row.workshop_name + '/' +
props.row.station_name : props.row.workline_name }}</div>
</template>
</el-table-column>
<el-table-column label="生产BOM版本 或 设备编号">
<template slot-scope="props">
<div>{{ props.row.type == 1 ? props.row.equip_code : props.row.mbom_version }}
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
<el-table-column type="index" label="序号" :index="1" />
<el-table-column label="生产工单" prop="mo_code" />
<el-table-column label="物料编码" prop="material_code" />
<el-table-column label="物料名称" prop="material_name" />
<el-table-column label="规格型号" prop="material_standard" />
<el-table-column label="开始时间" prop="act_start_date" />
<el-table-column label="结束时间" prop="act_end_date" />
</el-table>
<pagination :total="total" :page.sync="queryObj.currentPage" :limit.sync="queryObj.pageSize"
@pagination="search" />
</div>
</div>
</div>
</template>
<script>
import { getOneList, getTwoList, getThreeList, getListByMan, getListByEqu, getListByMat } from "@/api/retrospect/codeRetrospect";
export default {
data() {
return {
oneList: [],
packTaskLoading: false,
total: 0,
queryObj: {
currentPage: 1,
pageSize: 20,
mo_code: "",
mo_task_code: "",
barcode: ""
},
}
},
activated() {
},
watch: {
},
created() {
this.search()
},
mounted() {
},
methods: {
async init() {
this.queryObj = {
currentPage: 1,
pageSize: 20,
mo_code: "",
mo_task_code: "",
barcode: ""
}
this.search()
},
async search() {
this.packTaskLoading = true
const { data } = await getOneList(this.queryObj)
this.total = data.pagination.total
data.list.map(item => {
item.ruleItemData = [];
});
this.oneList = data.list
this.packTaskLoading = false
},
// 第一级点击
async expandChange(row, expandedRows) {
if (expandedRows.length == 0) return
const obj = {
mo_id: row.id,
mo_task_code: this.queryObj.mo_task_code,
barcode: this.queryObj.barcode,
}
const { data } = await getTwoList(obj)
this.oneList.forEach((item, index) => {
// 找到当前点击的行,把动态获取到的数据赋值进去
if (item.id === row.id) {
// this.$nextTick(()=>{
data.forEach((it, index) => {
it.type = row.type
it.parentId = item.id
it.ruleItemData = []
})
this.oneList[index].ruleItemData = data
// this.$set(this.oneList[index], 'ruleItemData', data)
// })
}
});
},
// 第二级点击
async expandChangeThree(row, expandedRows) {
if (expandedRows.length == 0) return
this.oneList.forEach((item, index) => {
if (item.id !== row.parentId) return
this.oneList[index].ruleItemData.forEach((it, ind) => {
// 找到当前点击的行,把动态获取到的数据赋值进去
if (it.id !== row.id) return
if (row.type == 1) {
this.oneList[index].ruleItemData[ind].activeName = 'ren'
const obj = {
mo_task_id: row.id,
barcode: this.queryObj.barcode,
}
getListByMan(obj).then(({ data }) => {
this.oneList[index].ruleItemData[ind].ruleItemData = data
})
return
}
const obj = {
mo_task_id: row.id,
mo_task_code: this.queryObj.mo_task_code,
barcode: this.queryObj.barcode,
}
getThreeList(obj).then(({ data }) => {
data.forEach((elitem, elindex) => {
elitem.type = row.type
elitem.granddadId = it.parentId
elitem.parentId = it.id
elitem.ruleItemData = []
})
this.oneList[index].ruleItemData[ind].ruleItemData = data
})
})
});
},
// 第三级点击
async expandChangefour(row, expandedRows) {
if (expandedRows.length == 0) return
this.oneList.forEach((item, index) => {
if (item.id !== row.granddadId) return
this.oneList[index].ruleItemData.forEach((it, ind) => {
// 找到当前点击的行,把动态获取到的数据赋值进去
if (it.id !== row.parentId) return
this.oneList[index].ruleItemData[ind].ruleItemData.forEach((elitem, indx) => {
if (elitem.id !== row.id) return
const obj = {
mo_task_id: row.id,
barcode: this.queryObj.barcode,
}
this.oneList[index].ruleItemData[ind].ruleItemData[indx].activeName = 'ren'
getListByMan(obj).then(({ data }) => {
this.oneList[index].ruleItemData[ind].ruleItemData[indx].ruleItemData = data
})
})
})
});
},
handleClick(fig, row) {
if (row.type == 1) {
this.oneList.forEach((item, index) => {
if (item.id !== row.parentId) return
this.oneList[index].ruleItemData.forEach((it, ind) => {
// 找到当前点击的行,把动态获取到的数据赋值进去
if (it.id !== row.id) return
const obj = {
mo_task_id: row.id,
barcode: this.queryObj.barcode,
}
// fig == 'ren' ? getListByMan(obj) : fig == 'ji' ? getListByEqu(obj) : getListByMat(obj).then(({ data }) => {
// this.$set(this.oneList[index].ruleItemData[ind], 'ruleItemData', data)
// this.$forceUpdate()
// })
if (fig == 'ren') {
getListByMan(obj).then(({ data }) => {
this.$set(this.oneList[index].ruleItemData[ind], 'ruleItemData', data)
})
}
if (fig == 'ji') {
getListByEqu(obj).then(({ data }) => {
this.$set(this.oneList[index].ruleItemData[ind], 'ruleItemData', data)
})
} else {
getListByMat(obj).then(({ data }) => {
this.$set(this.oneList[index].ruleItemData[ind], 'ruleItemData', data)
})
}
})
});
} else {
this.oneList.forEach((item, index) => {
if (item.id !== row.granddadId) return
this.oneList[index].ruleItemData.forEach((it, ind) => {
if (it.id !== row.parentId) return
this.oneList[index].ruleItemData[ind].ruleItemData.forEach((elitem, indx) => {
// 找到当前点击的行,把动态获取到的数据赋值进去
if (elitem.id !== row.id) return
const obj = {
mo_task_id: row.id,
barcode: this.queryObj.barcode,
}
if (fig == 'ren') {
getListByMan(obj).then(({ data }) => {
this.$set(this.oneList[index].ruleItemData[ind].ruleItemData[indx], 'ruleItemData', data)
})
}
if (fig == 'ji') {
getListByEqu(obj).then(({ data }) => {
this.$set(this.oneList[index].ruleItemData[ind].ruleItemData[indx], 'ruleItemData', data)
})
} else {
getListByMat(obj).then(({ data }) => {
this.$set(this.oneList[index].ruleItemData[ind].ruleItemData[indx], 'ruleItemData', data)
})
}
})
})
});
}
}
}
}
</script>
<style scoped lang="scss">
// .div1 {
// /* width: 300px; */
// /* height: 200px; */
// position: relative;
// color: #fff;
// border: 2px solid rgb(209, 204, 183);
// border-radius: 10px;
// background: #ffd700;
// transition: all .3s;
// }
</style>
思路是第一层el-table为总数据 为oneList,第二层运用el-table-column type="expand" 插入props插槽 通过expand-change(点击展开方法)在此方法里发送请求与后台交互获取第二层数据 通过expand-change方法返回的row(该点击的子项数据)里的id 循环找到oneList对应的子项插进去
这是实现嵌套两层的基本思路 后面的三层 四层都是根据此思路来的
但是有个bug 点击第一次的时候视图不更新 第二次才更新 用了this.$set也没用 所以得在获取oneList的时候就得跟它添加个子项这样bug解除
第三第四的嵌套看代码吧 稍微相比复杂一点 因为到了第三层 没有id来识别此数据是oneList的第一层子级 所以我选择的办法是加了个parentId 识别的时候用了三层循环 第四层也是一样 额外加了granddadId 识别用四层循环。