.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. 【Docker】04 部署MySQL

    从官网上拉取最新MySQL镜像: docker pull mysql:latest 创建并运行一个MySQL镜像的容器 docker run -itd --name mysql-test -p 330 ...

  2. 【Layui】16 表单元素 Form

    文档地址: https://www.layui.com/demo/form.html 表单元素: 1.输入框 2.密码框 3.下拉列表 4.单选框 5.复选框 6.文档域 7.富文本 8.开关 单行输 ...

  3. 记一次失败记录: MindSpore1.3.0 GPU 源码安装 —— Ubuntu18.04系统 (最终安装结果为失败)

    官网地址: https://www.mindspore.cn/install 系统:Ubuntu18.04 硬件: i7-9700k CPU 2060super nvidia显卡 由于考虑到minds ...

  4. [USACO22FEB] Paint by Rectangles P 题解

    前言 没用线段树的小常数.小短码. 题目链接:洛谷. 题意简述 给出 \(n\) 个平行于坐标轴的矩形,各边所在直线互不重合,钦定最外面为白色,对这个平面图黑白染色,分别求黑色块数和白色块数. 题目分 ...

  5. 最近公共祖先模板(LCA)

    include <bits/stdc++.h> using namespace std; struct LCA { int n; vector<int> dep; vector ...

  6. sshpass 带密码登陆

    brew install hudochenkov/sshpass/sshpass sshpass -p password ssh -p port user@xxxx.xxxx.xxxx.xxxx

  7. Ubuntu 修改密码

    强制修改密码 可以通过切换到 root 帐户强制修改密码来绕过密码长度限制: sudo su # 切换到 root 帐户 passwd USER # 修改密码 或者: sudo passwd $(wh ...

  8. office系列软件(word、ppt、excel)打不开的解决方案

    前言 ​ 这里我遇到的情况是点击都没反应,而不像很多人那样有报错弹窗,费劲千辛万苦才最终解决,中间一度自暴自弃想着干脆用WPS得了(大可不必),中间我尝试了三种方法,不一定哪种有效,权当分享: 一.使 ...

  9. Go plan9 汇编:说透函数栈

    原创文章,欢迎转载,转载请注明出处,谢谢. 0. 前言 函数是 Go 的一级公民,本文从汇编角度出发看看我们常用的一些函数在干什么. 1. 函数 1.1 main 函数 在 main 函数中计算两数之 ...

  10. 性能、成本与 POSIX 兼容性比较: JuiceFS vs EFS vs FSx for Lustre

    JuiceFS 是一款为云环境设计的分布式高性能文件系统.Amazon EFS 易于使用且可伸缩,适用于多种应用.Amazon FSx for Lustre 则是面向处理快速和大规模数据工作负载的高性 ...