产品编码关联相关订单的校验
业务场景
产品编码下拉是多选,选择产品编码关联出对应的订单号,赋值到订单编号的输入框中。
因为产品编码是多选,要求多个产品编码对应的订单号应该一致
注意点
- 产品编码点击选择后,该条产品编码会放到绑定的数组中,这里绑定change事件,因为每次选择产品编码都会触发change事件,所以每次都只需要判断最后一个产品编码
- 要分为订单编号已存在和不存在两种情况判断
业务实现
// 根据产品编码关联订单
relationOrderByProduct(e) {
// 获取长度,清空时会变成空数组
let l = e.length - 1;
// 获取产品编码对应的数据
// 选中一个,触发一次,因此每次只需要判断最后一个即可
let item = this.productionList.find(code => code.productCode == e[l]);
if(!this.form.orderNos) {
// 相关订单没值时直接赋值
this.form.orderNos = item.orderNos;
}else{
// 相关订单存在,判断产品编码关联的订单与之前的订单是否一致
// 订单一致,不处理产品编码,订单不一致,提示,并移出这个产品编码
if(this.form.orderNos != item.orderNos) {
let arr = this.form.productionSn.filter(code => code != e[l]);
this.$message(`产品编码${item.productCode}关联的订单不一致!`);
this.form.productionSn = arr;
}
}
console.log('值:',e);
console.log('编码:',this.form.productionSn);
},
表格里有输入框造成页面加载缓慢甚至浏览器崩溃
业务场景
1、点击转入单据选择一些数据带到表格里,某些数值可以进行修改
2、表格下面对几个数量进行合计,数据新增、编辑、删除重新计算值
问题是这样的,正常情况是没问题的,但用户的操作时一次选几十条,甚至上百,因此就造成加载缓慢甚至浏览器崩溃(用户电脑还是单核的)
问题点1: 加载渲染输入框和普通div标签用的时间完全不同,输入框之类的比较费时间。
- 解决:初始时全都渲染成span标签,当点击第一行时(以两行数据为例),第一行显示输入框,点击第二行时,第一行变回span,第二行显示输入框;如果失去焦点时也变回span
- 注意点: 使用v-if不用v-show;
文档里提供了单选和点击行的事件,这里用点击行事件,单选事件第二次点时不会触发
//表格所用属性和事件
highlight-current-row @row-click="handleCurrentChange"
:row-class-name="setCurrentRowIndex"
// data属性
currentRowIndex: -1 // 记录当前点击行的下标
//插槽格式
<template v-slot="scope">
<span v-if="scope.$index!=currentRowIndex">{{ scope.row.invoiceQty }}</span>
<el-input-number v-else controls-position="right" :min="0" :precision="4" :max="scope.row.remainQty" :disabled="orderLook" v-model="scope.row.invoiceQty" placeholder="" @change="changePriceRow(scope.$index,scope.row, 0)"></el-input-number>
</template>
//方法
// 单选事件
handleCurrentChange(currentRow) {
// debugger;
this.currentRowIndex = currentRow.index;
},
// 设置当前行下标
setCurrentRowIndex({row,rowIndex}) {
row.index = rowIndex;
},
稍微还有点bug,最后点击的哪一个无法变成span标签。目前的解决方案是在table外的其他标签上添加一个点击事件
<div @click="currentRowIndex=-1">
效果
写个demo吧,后期遇到可以直接拿来使用
问题点2:
每次改变都计算没错,有问题的计算的方式。拿200条数据为例,200次 sum+=5*10
和 200次 sum+=50
一定是后面的更节省性能
商品弹窗:goods.vue
<template>
<div>
<el-dialog v-model="visible" title="商品列表" width="40%" @close="closeDialog">
<el-table ref="multipleTable" :data="tableData" style="width: 100%" border
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column type="index" label="序号" width="55" />
<el-table-column property="name" label="商品名称" min-width="120" />
<el-table-column property="color" label="颜色" min-width="120" />
<el-table-column property="price" label="价格" min-width="120" />
</el-table>
<template #footer>
<div>
<el-button type="primary" @click="saveData">转入</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script>
import {ref} from "vue"
export default {
props: {
visible: {
type: Boolean,
default: false,
},
},
setup(props,context) {
//表格数据
let tableData=ref([
{ name:'手机', color:'黑色', price:5600},
{ name:'笔记本', color:'银白', price:6500},
{ name:'电动车', color:'黑白', price:2600},
{ name:'洗衣机', color:'白色', price:4600},
{ name:'冰箱', color:'银色', price:4800}
])
//勾选的数据
let multipleSelection=ref([])
//处理勾选
let handleSelectionChange=(val)=> {
multipleSelection.value = val
}
//将数据返回给父组件
let saveData=()=>{
context.emit('getGoods',multipleSelection.value)
closeDialog()
}
//关闭弹窗
let closeDialog = () => {
context.emit("update:visible", false);
};
return {
tableData,
handleSelectionChange,
saveData,
closeDialog,
};
},
};
</script>
主页面
<template>
<div>
<div style="margin: 16px 32px">
<el-button type="primary" @click="openDialog">转入商品</el-button>
</div>
<el-table ref="multipleTable" :data="tableData" style="width: 100%" border
:row-class-name="setRowIndex" highlight-current-row @current-change="handleCurrentChange">
<el-table-column type="index" label="序号" width="55" />
<el-table-column property="name" label="商品名称" min-width="120" />
<el-table-column property="color" label="颜色" min-width="120" />
<el-table-column property="price" label="价格" min-width="120">
<template v-slot:default="scope">
<div>
<span v-if="currentRowIndex!=scope.$index">{{scope.row.price}}</span>
<el-input-number v-else v-model="scope.row.price" :min="0" @change="handleChange(scope.row)" />
</div>
</template>
</el-table-column>
<el-table-column property="number" label="数量" min-width="120">
<template v-slot:default="scope">
<div>
<span v-if="currentRowIndex!=scope.$index">{{scope.row.number}}</span>
<el-input-number v-else v-model="scope.row.number" :min="0" @change="handleChange(scope.row)" />
</div>
</template>
</el-table-column>
</el-table>
<div style="margin:20px 50px;">
<span>总数量:{{totalNumber}}</span>
<span>总价格:{{totalPrice}}</span>
</div>
<!-- 商品弹窗 -->
<goods v-model:visible="opneGoods" @getGoods="getGoods"></goods>
</div>
</template>
<script>
//商品弹窗
import goods from "./goods.vue";
import { ref } from "vue";
//处理商品
let handleGood=()=>{
//商品弹窗
let opneGoods = ref(false);
//打开弹窗
let openDialog = () => {
opneGoods.value = true;
};
return {
opneGoods,
openDialog,
}
}
//处理表格
let handleTable=()=>{
//表格
let tableData=ref([])
//记录点击的行下标
let currentRowIndex=ref(-1)
//总数量、总价格
let totalNumber=ref(0)
let totalPrice=ref(0)
//获取商品信息
let getGoods=(data)=>{
data.forEach(item=>{
tableData.value.push(
{
...item,
//表格里没有,特地加上便于后续使用
totalRowSum:0
}
)
})
}
//给每一行添加一个行下标
let setRowIndex=({row,rowIndex})=>{
row.index=rowIndex
}
//处理当前选中的行
let handleCurrentChange=(currentRow,oldCurrentRow)=>{
currentRowIndex.value=currentRow.index
}
//处理数值改变
let handleChange=(row)=>{
row.totalRowSum=row.number*row.price
calculateTotal()
}
//计算总数量、总价格
let calculateTotal=()=>{
totalPrice.value=0
totalNumber.value=0
tableData.value.forEach(e=>{
totalNumber.value+=e.number
totalPrice.value+=e.totalRowSum
})
}
return {
tableData,
currentRowIndex,
totalNumber,
totalPrice,
getGoods,
setRowIndex,
handleCurrentChange,
handleChange
}
}
export default {
components: { goods },
setup() {
return {
...handleGood(),
...handleTable()
};
},
};
</script>
工序保证唯一
需求: 工艺参数单位保证唯一,例如功率已经被选择了,那么其他行就不能再选择功率。一开始自己理解错了,逻辑写的多,并且有bug,后来同事一说,就被点醒了。
解决思路:
每一行的select
选择器都是独立的,选择器内的选项是否禁用,只需要循环一下存放表格的这个数组,判断已经有没有这个值就好。
代码:
<el-table :data="DtoList.paramDtoList" border>
<el-table-column prop="paramName" label="工艺参数(单位)" width="200px" align="left">
<template #header>
<span>
<span style="color:red;">*</span><span>工艺参数(单位)</span>
</span>
</template>
<template v-slot="scope">
<el-select v-model="scope.row.paramName" placeholder="请选择" clearable>
<el-option v-for="item in paramNameList" :key="item.id"
:label="item.codeName" :value="item.codeName" :disabled="getParamDiasbled(item.codeName)"></el-option>
</el-select>
</template>
</el-table-column>
</el-table>
getParamDiasbled(value) {
// 保证工序唯一
let index = this.DtoList.paramDtoList.findIndex(e => e.paramName == value);
return index != -1;
},