一、a-table合并单元格
1、根据mainTaskId
合并,定义一个方法来记录每个 mainTaskId
的出现次数和它在表格中首次出现的位置
setupSpanMap(data) { // data是组件的数据源 dataSource
const spanMap = {};
let lastTaskId = null;
let lastIndex = 0;
data.forEach((row, index) => {
if (row.mainTaskId !== lastTaskId) {
if (lastTaskId !== null) {
spanMap[lastIndex] = index - lastIndex; // 设置之前mainTaskId的span
}
lastIndex = index;
lastTaskId = row.mainTaskId;
}
// 根据批次合并检查项目
// 开始合并的下标
let start = 0
// 合并的行数
let count = 1
// 上一行的检测项
let perItem = null
// 上一行的批次
let perBath = null
// 根据批次合并检查项目
if (index == 0) {
perItem = row.inspectionItem
perBath = row.sampleBatch
} else if (row.inspectionItem == perItem && row.sampleBatch == perBath) {
count++
} else {
this.inspectionItemMap[start] = count
// 重置从下一个不一样的检测项的下标
start = start + count
// 重置合并的行数
count = 1
}
// 当长度是最后一个的时候push一次
if (index == data.length - 1) {
this.inspectionItemMap[start] = count
}
perBath = row.sampleBatch
perItem = row.inspectionItem
});
if (lastTaskId !== null) {
spanMap[lastIndex] = data.length - lastIndex; // 最后一组mainTaskId
}
this.spanMap = spanMap;
this.dataSource = data // 处理完上序操作再给dataSource赋值
},
2、需要修改组件绑定列(column)的 customRender
方法来动态计算 rowSpan
。包括:
在首次遇到新的
mainTaskId
时设置rowSpan
。对后续相同的
mainTaskId
设置rowSpan
为 0。
{
title: '样品单号',
align: 'center',
dataIndex: 'mainTaskId',
customRender: (value, row, index) => {
const span = this.spanMap[index] || 0 // 获取当前索引的rowSpan
const obj = {
children: value,
attrs: {},
}
if (span > 0) {
obj.attrs.rowSpan = span
} else {
obj.attrs.rowSpan = 0 // 相同mainTaskId的其他行
}
return obj
},
},
二、 在jEditTable里面的插槽<a-select>组件的options下拉框选了值但是在选择框内没有值
没有正确使用setValue方法赋值
区分下拉框的text和label
三、格式化北京时间
// 格式化时间
formatDateTime(date) {
// 获取本地时区偏移量
const offset = date.getTimezoneOffset() * 60000 // 转换为毫秒
// 创建一个新的日期对象,已根据时区偏移调整
const localDate = new Date(date.getTime() - offset)
// 将调整后的日期转换为 ISO 格式的字符串,并进行格式化
return localDate.toISOString().replace('T', ' ').substring(0, 19)
},
// 调用
const now = new Date()
let time = this.formatDateTime(now)
四、set去重
let inspectionMethod = 'apple,apple,orange,banana,apple,banana'
let inspectionMethods = [...new Set(inspectionMethod.split(','))] // ['apple','orange','banana']
五、同一页面多模版打印标签点击第一个后面的标签显示空白bug
在preview.vue文件中,不同的标签应该给不同的id类名
<div id="preview_content_qy"></div> <!-- 第一个模版标签容器 -->
<div id="preview_content"></div> <!-- 第二个模版标签容器 -->
// 获取容器填充内容
$('#preview_content_qy').html(hiprintTemplate.getHtml(printData))
$('#preview_content').html(hiprintTemplate.getHtml(printData))
六、jEditable组件结合switch开关 插槽
<j-editable-table :ref="refKeys[0]" :loading="matBomDtTable.loading" :columns="matBomDtTable.columns" :dataSource="matBomDtTable.dataSource" :maxHeight="300" :disabled="formDisabled" :rowNumber="true" :rowSelection="true" :actionButton="true">
<template v-slot:isRequired="props">
<!-- 使用:checked绑定开关 -->
<!-- 一般其他插槽使用 :value="props.text"绑定值 -->
<a-switch :checked="props.text == 1" :disabled="formDisabled" @change="(value) => handleRequired(value, props)" />
</template>
</j-editable-table>
handleRequired(value, row) {
// 根据开关得值给组件字段赋值
this.$refs.matBomDt.setValues([{ rowKey: row.rowId, values: { isRequired: value ? 1 : 0} }])
},
七、删除对象中的字段
delete this.model.testItems // delete obj.属性名
八、当页面有多个滚动条时,a-select组件的下拉框停留在页面,没有跟随组件位置变化
通过 getPopupContainer
属性可以指定渲染下拉选项的父容器。将其设置为渲染在组件的父级元素中
<a-select
v-model="value"
show-search
:options="valueOption"
:filter-option="filterOption"
:getPopupContainer="triggerNode => triggerNode.parentNode" />
// filterOption根据下拉框的text进行搜索筛选,在methods中定义
filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
九、根据value属性对数组对象去重
const array = [
{ text: 1, value: 1 },
{ text: 1, value: 1 },
{ text: 2, value: 2 },
{ text: 3, value: 1 }
];
// 使用Map来进行去重
const uniqueArray = Array.from(new Map(array.map(item => [item.value, item])).values());
十、从数组对象 B
中获取 A
数组中ID对应的对象
const A = [1, 2, 3]; // A是部分id的数组
const B = [
{ id: 1, name: 'Object 1' },
{ id: 2, name: 'Object 2' },
{ id: 3, name: 'Object 3' },
{ id: 4, name: 'Object 4' }
]; // B是包含对象的数组
const result = B.filter(obj => A.includes(obj.id));十一
十一、递归找父label
// 将option的label转换成父子text
transformParentOption(array) {
// 构建一个映射,方便通过value查找节点
const sonMap = {};
array.forEach(item => {
sonMap[item.value] = item;
});
// 转换数据
const transformedData = array.map(item => {
return {
value: item.value,
label: this.buildLabel(item, sonMap), // 构建完整的label
warehouseType: item.warehouseType,
pid: item.pid
}
})
this.parentArrOption = transformedData
},
// 递归函数
buildLabel(node, sonMap) {
if (!node.pid || !sonMap[node.pid]) {
return node.label // 如果没有父节点,直接返回当前label
}
const parent = sonMap[node.pid]
return this.buildLabel(parent, sonMap) + '/' + node.label // 递归获取父节点的label
},