.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rgba(37, 41, 51, 1) }
.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { line-height: 1.5; margin-top: 35px; margin-bottom: 10px; padding-bottom: 5px }
.markdown-body h1 { font-size: 24px; line-height: 38px; margin-bottom: 5px }
.markdown-body h2 { font-size: 22px; line-height: 34px; padding-bottom: 12px; border-bottom: 1px solid rgba(236, 236, 236, 1) }
.markdown-body h3 { font-size: 20px; line-height: 28px }
.markdown-body h4 { font-size: 18px; line-height: 26px }
.markdown-body h5 { font-size: 17px; line-height: 24px }
.markdown-body h6 { font-size: 16px; line-height: 24px }
.markdown-body p { line-height: inherit; margin-top: 22px; margin-bottom: 22px }
.markdown-body img { max-width: 100% }
.markdown-body hr { border-top: 1px solid rgba(221, 221, 221, 1); border-right: none; border-bottom: none; border-left: none; margin-top: 32px; margin-bottom: 32px }
.markdown-body code { border-radius: 2px; overflow-x: auto; background-color: rgba(255, 245, 245, 1); color: rgba(255, 80, 44, 1); font-size: 0.87em; padding: 0.065em 0.4em }
.markdown-body code, .markdown-body pre { font-family: Menlo, Monaco, Consolas, Courier New, monospace }
.markdown-body pre { overflow: auto; position: relative; line-height: 1.75 }
.markdown-body pre>code { font-size: 12px; padding: 15px 12px; margin: 0; word-break: normal; display: block; overflow-x: auto; color: rgba(51, 51, 51, 1); background: rgba(248, 248, 248, 1) }
.markdown-body a { text-decoration: none; color: rgba(2, 105, 200, 1); border-bottom: 1px solid rgba(209, 233, 255, 1) }
.markdown-body a:active, .markdown-body a:hover { color: rgba(39, 91, 140, 1) }
.markdown-body table { display: inline-block !important; font-size: 12px; width: auto; max-width: 100%; overflow: auto; border: 1px solid rgba(246, 246, 246, 1) }
.markdown-body thead { background: rgba(246, 246, 246, 1); color: rgba(0, 0, 0, 1); text-align: left }
.markdown-body tr:nth-child(2n) { background-color: rgba(252, 252, 252, 1) }
.markdown-body td, .markdown-body th { padding: 12px 7px; line-height: 24px }
.markdown-body td { min-width: 120px }
.markdown-body blockquote { color: rgba(102, 102, 102, 1); padding: 1px 23px; margin: 22px 0; border-left: 4px solid rgba(203, 203, 203, 1); background-color: rgba(248, 248, 248, 1) }
.markdown-body blockquote:after { display: block; content: "" }
.markdown-body blockquote>p { margin: 10px 0 }
.markdown-body ol, .markdown-body ul { padding-left: 28px }
.markdown-body ol li, .markdown-body ul li { margin-bottom: 0; list-style: inherit }
.markdown-body ol li .task-list-item, .markdown-body ul li .task-list-item { list-style: none }
.markdown-body ol li .task-list-item ol, .markdown-body ol li .task-list-item ul, .markdown-body ul li .task-list-item ol, .markdown-body ul li .task-list-item ul { margin-top: 0 }
.markdown-body ol ol, .markdown-body ol ul, .markdown-body ul ol, .markdown-body ul ul { margin-top: 3px }
.markdown-body ol li { padding-left: 6px }
.markdown-body .contains-task-list { padding-left: 0 }
.markdown-body .task-list-item { list-style: none }
@media (max-width: 720px) { .markdown-body h1 { font-size: 24px } .markdown-body h2 { font-size: 20px } .markdown-body h3 { font-size: 18px } }.markdown-body pre, .markdown-body pre>code.hljs { color: rgba(51, 51, 51, 1); background: rgba(248, 248, 248, 1) }
.hljs-comment, .hljs-quote { color: rgba(153, 153, 136, 1); font-style: italic }
.hljs-keyword, .hljs-selector-tag, .hljs-subst { color: rgba(51, 51, 51, 1); font-weight: 700 }
.hljs-literal, .hljs-number, .hljs-tag .hljs-attr, .hljs-template-variable, .hljs-variable { color: rgba(0, 128, 128, 1) }
.hljs-doctag, .hljs-string { color: rgba(221, 17, 68, 1) }
.hljs-section, .hljs-selector-id, .hljs-title { color: rgba(153, 0, 0, 1); font-weight: 700 }
.hljs-subst { font-weight: 400 }
.hljs-class .hljs-title, .hljs-type { color: rgba(68, 85, 136, 1); font-weight: 700 }
.hljs-attribute, .hljs-name, .hljs-tag { color: rgba(0, 0, 128, 1); font-weight: 400 }
.hljs-link, .hljs-regexp { color: rgba(0, 153, 38, 1) }
.hljs-bullet, .hljs-symbol { color: rgba(153, 0, 115, 1) }
.hljs-built_in, .hljs-builtin-name { color: rgba(0, 134, 179, 1) }
.hljs-meta { color: rgba(153, 153, 153, 1); font-weight: 700 }
.hljs-deletion { background: rgba(255, 221, 221, 1) }
.hljs-addition { background: rgba(221, 255, 221, 1) }
.hljs-emphasis { font-style: italic }
.hljs-strong { font-weight: 700 }

说点废话,最近在做一个重构的项目。我感觉学不到东西,业务也就那样。这个简单的我感觉要是之前的我。我就很快做出来了,这次我做了相对久了。很难受。吐槽一下吧,这个项目代码经过很多人说是屎山也不为过。但是搭建确实做的很好,应该仔细研究学习一下。

上成品

数据格式

这次做的久很大一部分原因是我直接就做了,并没有考虑数据,在做着做着就会出现很问题。开发很重要一点先定义数据,再根据数据生成相应的页面。

错误的原因是一开始取巧了打算利用subOrdershoppingList 里面有的数据作为shoppingShow 展示的数据在这里所以在显示开发的时候总有些问题。没有设计数据格式,打算利用subOrdershoppingLis反而浪费了很多时间。


[
{
"interfaceSubOrderId": "1",
"subOrderName": "子订单1",
"subOrdershoppingList": [],
"interfaceOrderId": "1",
"parentOrderName": "父订单1",
"packageList": [
{
"expressName": "",
"expressNo": "",
"expressCode": "",
"shoppingShow": [],
"packageChildren": [
{
"expressName": "",
"expressNo": "",
"expressCode": "",
"shoppingShowChildren": []
},
{
"expressName": "",
"expressNo": "",
"expressCode": "",
"shoppingShowChildren": []
},
{
"expressName": "",
"expressNo": "",
"expressCode": "",
"shoppingShowChildren": []
}
]
},
{
"expressName": "",
"expressNo": "",
"expressCode": "",
"shoppingShow": [],
"packageChildren": [
{
"expressName": "",
"expressNo": "",
"expressCode": "",
"shoppingShowChildren": []
}
]
}, ]
}
]

页面展示

<el-dilog :title="title" v-model="modelValue" @close="closeGroup">
<div
class="select-table-main"
v-for="v in deliverGoodsData.newGoodList"
:key="v.interfaceSubOrderId"
>
<div class="select-table-title">
<h3>子订单号:{{ v.interfaceSubOrderId }}</h3>
<el-button type="text" @click="addGroup(v.interfaceSubOrderId)"
>添加包裹</el-button
>
</div>
<el-form label-width="80px" class="form-detail">
<el-form-item
:label="'包裹' + (index + 1) + ':'"
v-for="(item, index) in v.packageList"
:key="index"
>
<el-select
style="display: inline-block; width: 150px; margin-left: 10px"
v-model="item.expressName"
placeholder="请选择物流"
filterable
>
<el-option
v-for="it in deliverGoodsData.expressCompanyList"
:label="it.dictValue"
:value="it.dictValue"
:key="it.dictValue"
></el-option>
</el-select>
<el-input
style="display: inline-block; width: 260px"
v-model="item.expressNo"
placeholder="请输入快递单号"
></el-input>
<el-button v-if="index != 0" type="text" @click="ycFun(index)"
>移除</el-button
>
<el-button
type="text"
@click="
handleSelectGood({
pitchShopIndex: index,
type: null,
data: v.subOrdershoppingList,
})
"
>选择商品</el-button
>
<el-button
type="text"
@click="addDeliver(index, v.interfaceSubOrderId)"
>添加子包裹</el-button
>
<div>
<div
v-for="sle in item.shoppingShow"
:key="sle.id"
style="margin-left: 10px; font-size: 12px; color: gray"
>
<div v-if="sle.number">
{{ sle.showTitle }}&nbsp;&nbsp; {{ sle.specsName }}*{{
sle.number
}}
</div>
</div>
</div> <el-form-item
:label="'子包裹' + (subindex + 1) + ':'"
v-for="(pac, subindex) in item.packageChildren"
:key="subindex"
>
<el-select
style="display: inline-block; width: 150px; margin-left: 10px"
v-model="pac.expressName"
placeholder="请选择物流"
filterable
>
<el-option
v-for="exp in deliverGoodsData.expressCompanyList"
:label="exp.dictValue"
:value="exp.dictValue"
:key="exp.dictValue"
></el-option>
</el-select>
<el-input
style="display: inline-block; width: 180px"
v-model="pac.expressNo"
placeholder="请输入快递单号"
></el-input>
<el-button
v-if="subindex != 0"
type="text"
@click="subYcFun(index, subindex)"
>移除</el-button
>
<el-button
type="text"
@click="
handleSelectGood({
pitchShopIndex: index,
subPitchShopIndex: subindex,
type: 'sub',
data: v.subOrdershoppingList,
})
"
>选择子商品</el-button
>
<div
v-for="subSle in pac.shoppingShowChildren"
:key="subSle.id"
style="margin-left: 10px; font-size: 12px; color: gray"
>
<div v-if="subSle.number">
{{ subSle.showTitle }}&nbsp;&nbsp; {{ subSle.specsName }}*{{
subSle.number
}}
</div>
</div>
</el-form-item>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="default" @click="closeGroup">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</div>
</template>
</el-dilog>

其实这个现在想想很简单只要维护packageList就可以了。期间遇到一个问题在改变数据的时候不回显,这个项目用的是vue3 确是vue2和vue3混合写很恶心。我又全删了重新写的vue3.
在vue2 使用$set 解决 在vue3直接使用 reactive就可以了 computed 并不会随着数组更新而影响视图变化


const deliverGoodsData = reactive({
expressCompanyList: [], // 快递公司列表
subDeliver: false,
tableGoods: [],
newGoodList: [],
pitchShopIndex: null,
subPitchShopIndex: null,
}) const selectGoodsRef = ref() const props = defineProps({
modelValue: Boolean,
rowData: {
type: Object,
default: function () {
return {}
},
},
title: {
type: String,
default: function () {
return '订单发货'
},
},
opeType: {
//操作类型 delivery发货,changeEms变更物流
type: String,
default: function () {
return 'delivery'
},
},
sendType: {
//发货 send 与 变更发货状态 change(无移除,无添加包裹)
type: String,
default: function () {
return 'send'
},
},
}) const emit = defineEmits(['updateTable', 'modelValue']) watch(
() => props.rowData,
(newData, oldData) => {
if (newData) {
let newSubOrderList = newData.map((v) => v.interfaceSubOrderId)
let arr = []
newSubOrderList.map((v) => {
newTableData.forEach((i) => {
i.subOrderList.filter((sub, index) => {
sub.packageList = [
{
expressName: '', //快递名称
expressNo: '', //快递单号
expressCode: '',
shoppingShow: [],
packageChildren: [
{
expressName: '', //快递名称
expressNo: '', //快递单号
expressCode: '',
shoppingShowChildren: [],
},
],
},
]
if (sub.interfaceSubOrderId === v) {
arr.push(sub)
}
})
})
}) console.log('arr: ', arr)
deliverGoodsData.newGoodList = arr
}
},
{ deep: true, immediate: true },
) onMounted(() => {
globalApi.queryDictsByAlias('ExpressCompany').then((res) => {
deliverGoodsData.expressCompanyList = res.data
})
}) const subPitchData = (data) => {
deliverGoodsData.newGoodList = deliverGoodsData.newGoodList.map((item) => {
item.packageList[deliverGoodsData.pitchShopIndex].packageChildren[
deliverGoodsData.subPitchShopIndex
].shoppingShowChildren = item.subOrdershoppingList.filter((v) => {
if (data.includes(v.id)) {
// v.subShowGoods = true
return v
}
})
return item
})
} const pitchData = (data) => {
deliverGoodsData.newGoodList = deliverGoodsData.newGoodList.map((item) => {
item.packageList[deliverGoodsData.pitchShopIndex].shoppingShow =
item.subOrdershoppingList.filter((v) => {
if (data.includes(v.id)) {
// v.showGoods = true
return v
}
})
return item
})
} const closeGroup = () => {
emit('update:modelValue', false)
} const addGroup = (id) => {
deliverGoodsData.newGoodList.forEach((item) => {
if (item.interfaceSubOrderId === id) {
item.packageList.push({
expressName: '', //快递名称
expressNo: '', //快递单号
expressCode: '',
shoppingShow: [],
packageChildren: [
{
expressName: '', //快递名称
expressNo: '', //快递单号
expressCode: '',
shoppingShowChildren: [],
},
],
})
}
})
} const addDeliver = (index, id) => {
deliverGoodsData.newGoodList.forEach((item) => {
if (item.interfaceSubOrderId === id) {
item.packageList[index].packageChildren.push({
expressName: '', //快递名称
expressNo: '', //快递单号
expressCode: '',
shoppingShowChildren: [],
})
}
})
} const subYcFun = (index, subIndex) => {
deliverGoodsData.newGoodList.forEach((item) => {
item.packageList[index].packageChildren.splice(subIndex, 1)
})
} const ycFun = (index) => {
deliverGoodsData.newGoodList.forEach((item) => {
item.packageList.splice(index, 1)
})
} const handleSelectGood = (selData) => {
let { pitchShopIndex, subPitchShopIndex, type, data } = selData
deliverGoodsData.tableGoods = data
deliverGoodsData.subPitchShopIndex = subPitchShopIndex
deliverGoodsData.pitchShopIndex = pitchShopIndex
if (type === 'sub') {
deliverGoodsData.subDeliver = true
} else {
deliverGoodsData.subDeliver = false
}
selectGoodsRef.value.goodsModel = true
} const submit = () => {}
const getQueryOrderPackageList = () => {}
</script> <style scoped lang="stylus">
.icon-style {
font-size: 20px;
color: #ff9900;
position: reactive;
top: 3px;
margin-right: 5px;
}
.select-table-main{
background-color rgba(242, 242, 242, 1)
padding 10px
}
.select-table-title{
display: flex;
justify-content: space-between; }
</style>

vue3实现多层级的动态表单增减的更多相关文章

  1. antd+vue3实现动态表单的自动校验

    由于vue3用的人还不多,所以有些问题博主踩了坑只能自己爬出来了,特此做个记录.如有错误,请大家指正. 回归正题,我所做的业务是,动态添加表单项,对每一项单独做校验,效果如下: 主要代码如下: 1 & ...

  2. K3CLOUD开发-动态表单树形单据体实现银行交易对账

    背景:系统手机开单生成销售单据,通过银行pos机收款,系统收款流水与银行流水可能存在差异,所以通过获取银行接口,获取消费信息自动插入到生产系统数据库,开发对账报表,实现差异汇总! 展示效果如下: 开发 ...

  3. [K/3Cloud] 如何从被调用的动态表单界面返回数据

    在需要返回数据的地方调用表单返回方法完成数据返回 this.View.ReturnToParentWindow(retData); 在调用界面的回调函数中取出返回结果的ReturnData即可使用. ...

  4. Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)

    Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...

  5. 简易OA漫谈之工作流设计(六,快捷表单和动态表单)

    如果没有表单设计功能,我们一般建物理表,再把表单挂接到流程, 我们可以把外接表单的地址填到表单地址中,地址中会传递一个id. 如果使用外接表单,在审批的时候可能会“不太友好”,因为在审批单上看不到任何 ...

  6. angularjs 动态表单, 原生事件中调用angular方法

    1. 原生事件中调用angular方法, 比如 input的onChange事件想调用angular里面定义的方法 - onChange="angular.element(this).sco ...

  7. vue 开发系列(八) 动态表单开发

    概要 动态表单指的是我们的表单不是通过vue 组件一个个编写的,我们的表单是根据后端生成的vue模板,在前端通过vue构建出来的.主要的思路是,在后端生成vue的模板,前端通过ajax的方式加载后端的 ...

  8. Struts动态表单(DynamicForm)

    动态表单的含义是不要手动定义,直接在配置文件中进行定义. 1.手动进行定义 <form-beans > <form-bean name="userForm" ty ...

  9. 如何在.Net Core MVC中为动态表单开启客户端验证

    非Core中的请参照: MVC的验证 jquery.validate.unobtrusive mvc验证jquery.unobtrusive-ajax 参照向动态表单增加验证 页面引入相关JS: &l ...

  10. Angular动态表单生成(八)

    动态表单生成之拖拽生成表单(下) 我们的动态表单,最终要实现的效果与Form.io的在线生成表单的效果类似,可以参考它的demo地址:https://codepen.io/travist/full/x ...

随机推荐

  1. 【Windows】使用Dism++打包系统

    目的: 封装自己装好的操作系统,以便后续系统重装提高效率 纯净原生系统需要自己搭建开发环境,许多系统库也没有添加,费劲 网络下的整合包总是参杂些垃圾广告,不如自己封装一个 思路: 利用VMware虚拟 ...

  2. 实用英语:英文中经常出现“ i.e.、e.g.、etc."缩写究竟啥意思?

    地址: https://mp.weixin.qq.com/s?__biz=MzIyMzU5NDE1Mw==&mid=2247487840&idx=1&sn=013992683c ...

  3. lanczos算法——求解线性方程组时的辅助算法

    lanczos算法 Lanczos算法是一种将对称矩阵通过正交相似变换变成对称三对角矩阵的算法,以20世纪匈牙利数学家Cornelius Lanczos命名. 注意:Lanczos算法只能对" ...

  4. mindspore.ops.Pow()等算子不能处理float64类型的数据

    原文地址: https://gitee.com/mindspore/mindspore/issues/I3ZG99 Software Environment: -- MindSpore r1.2 GP ...

  5. 经典视频分享:Machine Learning: A New ICE (Identification, Control, Estimation) Age ? —— 自动控制和人工智能的结合前景

    机器学习作为近几年兴起的学科,虽然他诞生的时间已经而久远了,但是真正走进人们视野也就是这几年的事情. 机器学习领域本身只有强化学习这个分支和控制类是天然关联的,因此近几年国内的知名高校的强化学习研究者 ...

  6. 后端开发学习敏捷需求-->专题的目标与价值成效

    专题的目标与价值成效 什么是专题 公司或企业为了抓住业务机会或者解决痛点问题,而采取的具体的行动和举措 专题的目标分析 1.业务调研了解目标的预期 利用5W2H来进行专题分析 what--是什么?目的 ...

  7. Docker 之 RabbitMQ安装教程 基于腾讯云

    由于需要学习RabbitMQ(主要是项目启动了mq本地却没有服务控制台老是在连mq,致使我热部署都不知道到底成功没),所以才有了这个教程,下面介绍RabbitMQ准备工作 下载所需环境 yum -y ...

  8. AtCoder Beginner Contest 310

    freee Programming Contest 2023(AtCoder Beginner Contest 310) - AtCoder A - Order Something Else (atc ...

  9. 如何让你的C语言程序打印的log多一点色彩?(超级实用)

    接着上一篇文章<由字节对齐引发的一场"血案" > 在平常的调试中,printf字体格式与颜色都是默认一致的. 如果可以根据log信息的重要程度,配以不同的颜色与格式,可 ...

  10. CANopen学习笔记(三)NMT

    NMT NMT主要用来管理和控制各个节点的状态,具体协议可以分为以下四类: NMT protocol Node guard protocol Heartbeat protocol Bootup pro ...