新购到货管理/领料申请-类型规格-优化
This commit is contained in:
parent
a0519e57fa
commit
fa474c8a07
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": false,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"jsxBracketSameLine": true,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"useTabs": false,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSameLine": false,
|
||||||
|
"htmlWhitespaceSensitivity": "ignore",
|
||||||
|
"vueIndentScriptAndStyle": false,
|
||||||
|
"singleAttributePerLine": false,
|
||||||
|
"importStatement": "none"
|
||||||
|
}
|
||||||
|
|
@ -91,20 +91,57 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="类型规格" prop="deviceType">
|
<el-form-item label="类型规格" prop="deviceType">
|
||||||
<el-cascader
|
<el-row :gutter="10">
|
||||||
:key="propsKey"
|
<el-col :span="15">
|
||||||
v-model="deviceType"
|
<el-select
|
||||||
:show-all-levels="false"
|
ref="typeSelect"
|
||||||
:options="equipmentTypeList"
|
v-model="tempDeviceType"
|
||||||
:props="deviceTypeTreeProps"
|
multiple
|
||||||
filterable
|
filterable
|
||||||
|
placeholder="请输入类型规格"
|
||||||
|
style="width: 500px"
|
||||||
|
@change="handleTypeChange"
|
||||||
|
clearable
|
||||||
collapse-tags
|
collapse-tags
|
||||||
style="width: 240px"
|
:filter-method="handleSearchImpl"
|
||||||
placeholder="请选择规格型号"
|
:popper-class="'type-select-dropdown'"
|
||||||
ref="deviceTypeCascader"
|
:popper-append-to-body="false"
|
||||||
popper-class="popper-select"
|
@visible-change="handleVisibleChange"
|
||||||
@change="deviceTypeChange"
|
>
|
||||||
></el-cascader>
|
<el-option
|
||||||
|
v-for="item in filteredOptions"
|
||||||
|
:key="item.typeId"
|
||||||
|
:label="item.fullPath"
|
||||||
|
:value="item.typeId"
|
||||||
|
:data-key="item.typeId"
|
||||||
|
>
|
||||||
|
<span v-html="highlightText(item.fullPath, searchKeyword)"></span>
|
||||||
|
<span style="float: right; color: #8492a6; font-size: 13px">
|
||||||
|
库存:{{ item.storageNum }}
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-input
|
||||||
|
ref="searchInput"
|
||||||
|
v-model="searchKeyword"
|
||||||
|
placeholder="输入类型规格高亮搜索"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
clearable
|
||||||
|
style="width: 300px"
|
||||||
|
@input="handleHighlightSearch"
|
||||||
|
@focus="handleSearchFocus"
|
||||||
|
@click.native="handleSearchClick"
|
||||||
|
>
|
||||||
|
<template slot="append">
|
||||||
|
<span v-if="matchedOptions.length" style="margin: 0 5px">
|
||||||
|
{{ currentMatchIndex + 1 }}/{{ matchedOptions.length }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -340,9 +377,9 @@ export default {
|
||||||
deviceTypeTreeProps: {
|
deviceTypeTreeProps: {
|
||||||
children: "children",
|
children: "children",
|
||||||
label: "typeName",
|
label: "typeName",
|
||||||
// multiple: false,
|
|
||||||
value: "typeId",
|
value: "typeId",
|
||||||
multiple: true,
|
multiple: true,
|
||||||
|
emitPath: true
|
||||||
},
|
},
|
||||||
deviceType: [],
|
deviceType: [],
|
||||||
propsKey: 1000,
|
propsKey: 1000,
|
||||||
|
|
@ -350,6 +387,23 @@ export default {
|
||||||
unitTemp: undefined,
|
unitTemp: undefined,
|
||||||
agreementId: undefined,
|
agreementId: undefined,
|
||||||
// taxRate:0,
|
// taxRate:0,
|
||||||
|
flattenOptions: [], // 扁平化后的选项数据
|
||||||
|
typePopoverVisible: false,
|
||||||
|
typeOptions: [], // 类型选项
|
||||||
|
allTypeList: [], // 所有类型数据
|
||||||
|
flattenTypeOptions: [], // 扁平化后的选项数据(缓存所有选项)
|
||||||
|
typeGroups: [], // 分组后的类型选项
|
||||||
|
typeGroupsBackup: [], // 备份原始分组数据,用于搜索
|
||||||
|
typeMap: new Map(), // 用于快速查找类型数据
|
||||||
|
tempDeviceType: [], // 临时选中值
|
||||||
|
filteredOptions: [], // 过滤后的选项(用于显示)
|
||||||
|
maxShowOptions: 100, // 最大显示选项数
|
||||||
|
searchTimer: null, // 用于自定义防抖
|
||||||
|
searchKeyword: '', // 高亮搜索关键字
|
||||||
|
currentMatchIndex: -1, // 当前匹配项索引
|
||||||
|
matchedOptions: [], // 匹配的选项
|
||||||
|
keepSelectOpen: false, // 控制下拉框是否保持打开
|
||||||
|
isSearching: false, // 添加搜索状态标记
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -363,7 +417,6 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.projectInfoList();//单位工程下拉选
|
this.projectInfoList();//单位工程下拉选
|
||||||
this.equipmentType();//机具类型下拉选
|
this.equipmentType();//机具类型下拉选
|
||||||
|
|
@ -452,84 +505,95 @@ export default {
|
||||||
equipmentType() {
|
equipmentType() {
|
||||||
equipmentTypeTree().then((response) => {
|
equipmentTypeTree().then((response) => {
|
||||||
this.equipmentTypeList = response.data;
|
this.equipmentTypeList = response.data;
|
||||||
this.equipmentTypeList.forEach((item, index) => {
|
// 处理并扁平化所有类型数据
|
||||||
if (item.children && item.children.length > 0) {
|
this.flattenTypeOptions = this.processTypeData(response.data);
|
||||||
item.children.forEach((item2, index2) => {
|
// 初始显示所有选项
|
||||||
if (item2.children && item2.children.length > 0) {
|
this.filteredOptions = [...this.flattenTypeOptions];
|
||||||
item2.children.forEach((item3) => {
|
|
||||||
if (item3.children && item3.children.length > 0) {
|
// 反显选中数据
|
||||||
item3.children.forEach((item4) => {
|
if (this.equipmentList.length > 0) {
|
||||||
item4.maTypeName = item3.typeName;
|
this.deviceType = this.equipmentList.map(item => item.typeId);
|
||||||
item4.specificationType = item4.typeName;
|
|
||||||
// this.$set(item4, "purchaseTaxPrice", 0);
|
|
||||||
// this.$set(item4, "purchasePrice", 0);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//反显
|
|
||||||
let selectList = [];
|
|
||||||
this.equipmentList.forEach((e) => {
|
|
||||||
selectList.push(
|
|
||||||
this.getParentsById(this.equipmentTypeList, e.typeId)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
this.deviceType = selectList;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
//添加机具类型
|
// 处理类型数据
|
||||||
deviceTypeChange(val) {
|
processTypeData(data) {
|
||||||
const deviceTypeList = this.$refs.deviceTypeCascader.getCheckedNodes();
|
const result = [];
|
||||||
let tempList = [];
|
|
||||||
if (val.length > 0) {
|
const traverse = (node, parents = []) => {
|
||||||
const items = val.map((e) => {
|
const path = [...parents, node.typeName];
|
||||||
return e[3];
|
|
||||||
|
if (!node.children || node.children.length === 0) {
|
||||||
|
result.push({
|
||||||
|
typeId: node.typeId,
|
||||||
|
typeName: node.typeName,
|
||||||
|
fullPath: path.join(' / '),
|
||||||
|
searchKey: path.join('').toLowerCase(),
|
||||||
|
storageNum: node.storageNum || 0,
|
||||||
|
maTypeName: parents[parents.length - 1] || '',
|
||||||
|
specificationType: node.typeName,
|
||||||
|
unitName: node.unitName,
|
||||||
|
unitValue: node.unitValue
|
||||||
});
|
});
|
||||||
for (let i of items) {
|
}
|
||||||
for (let z of deviceTypeList) {
|
|
||||||
if (z.data.typeId === i) {
|
if (node.children) {
|
||||||
const obj = JSON.parse(JSON.stringify(z.data));
|
node.children.forEach(child => traverse(child, path));
|
||||||
obj.preNum = 0;
|
}
|
||||||
if(obj.storageNum<=0){
|
};
|
||||||
let index = this.deviceType.length;
|
|
||||||
if(index==1){
|
data.forEach(node => traverse(node));
|
||||||
this.$nextTick(() => {
|
return result;
|
||||||
this.deviceType=[]; // 可选,如果你想要重置选中状态
|
},
|
||||||
|
// 搜索处理函数
|
||||||
|
handleSearchImpl(query) {
|
||||||
|
if (!query) {
|
||||||
|
this.filteredOptions = [...this.flattenTypeOptions];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lowercaseQuery = query.toLowerCase();
|
||||||
|
this.filteredOptions = this.flattenTypeOptions.filter(item =>
|
||||||
|
item.searchKey.includes(lowercaseQuery) ||
|
||||||
|
item.fullPath.toLowerCase().includes(lowercaseQuery)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// 选择变化处理
|
||||||
|
handleTypeChange(val) {
|
||||||
|
if (!val || val.length === 0) return;
|
||||||
|
|
||||||
|
// 获取新选中的项
|
||||||
|
const lastSelected = val[val.length - 1];
|
||||||
|
const typeData = this.flattenTypeOptions.find(item => item.typeId === lastSelected);
|
||||||
|
|
||||||
|
if (typeData) {
|
||||||
|
if (this.equipmentList.some(item => item.typeId === lastSelected)) {
|
||||||
|
this.$message({
|
||||||
|
message: `${typeData.typeName} 已添加到列表中`,
|
||||||
|
type: 'warning'
|
||||||
});
|
});
|
||||||
}else{
|
this.tempDeviceType = this.tempDeviceType.filter(id => id !== lastSelected);
|
||||||
this.deviceType=this.deviceType.splice(0,1)
|
} else if (typeData.storageNum <= 0) {
|
||||||
}
|
this.$message.error("所选物资规格类型暂时无库存,无法申请!");
|
||||||
this.$modal.msgError("所选物资规格类型暂时无库存,无法申请!");
|
this.tempDeviceType = this.tempDeviceType.filter(id => id !== lastSelected);
|
||||||
}else{
|
|
||||||
tempList.push(obj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const newDataListNew = [...this.equipmentList, ...tempList];
|
|
||||||
const map = new Map();
|
|
||||||
for (let item of newDataListNew) {
|
|
||||||
if (!map.has(item.typeId)) {
|
|
||||||
map.set(item.typeId, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const newArray = [...map.values()];
|
|
||||||
let newArray_array = [];
|
|
||||||
items.forEach((e) => {
|
|
||||||
newArray.forEach((j) => {
|
|
||||||
if (e == j.typeId) {
|
|
||||||
newArray_array.push(j);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.equipmentList = newArray_array;
|
|
||||||
} else {
|
} else {
|
||||||
this.equipmentList = [];
|
// 将新项添加到数组开头,实现倒序
|
||||||
|
this.equipmentList.unshift({
|
||||||
|
...typeData,
|
||||||
|
preNum: 0
|
||||||
|
});
|
||||||
|
this.deviceType.push(lastSelected);
|
||||||
|
this.$message({
|
||||||
|
message: `已添加 ${typeData.typeName}`,
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空临时选中值
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.tempDeviceType = [];
|
||||||
|
});
|
||||||
},
|
},
|
||||||
//获取任务详情--- 编辑回显数据
|
//获取任务详情--- 编辑回显数据
|
||||||
async getTaskInfo() {
|
async getTaskInfo() {
|
||||||
|
|
@ -775,42 +839,16 @@ export default {
|
||||||
this.dialogVisible = true;
|
this.dialogVisible = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//树结构数据获取父
|
|
||||||
getParentsById(list, id) {
|
|
||||||
for (let i in list) {
|
|
||||||
if (list[i].typeId == id) {
|
|
||||||
//查询到就返回该数组对象的value
|
|
||||||
return [list[i].typeId];
|
|
||||||
}
|
|
||||||
if (list[i].children) {
|
|
||||||
let node = this.getParentsById(list[i].children, id);
|
|
||||||
if (node !== undefined) {
|
|
||||||
//查询到把父节把父节点加到数组前面
|
|
||||||
node.unshift(list[i].typeId);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
console.log(row)
|
|
||||||
this.$modal
|
this.$modal
|
||||||
.confirm("是否确认删除所选择的数据项?")
|
.confirm("是否确认删除所选择的数据项?")
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.deviceType.forEach((e, index) => {
|
this.equipmentList = this.equipmentList.filter(
|
||||||
console.log("e", e);
|
item => item.typeId !== row.typeId
|
||||||
if (e[3] === row.typeId) {
|
);
|
||||||
this.deviceType.splice(index, 1);
|
// 更新实际存储的选中值
|
||||||
this.propsKey++;
|
this.deviceType = this.equipmentList.map(item => item.typeId);
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log(this.equipmentList)
|
|
||||||
this.equipmentList.forEach((item, index) => {
|
|
||||||
if (item.typeId == row.typeId) {
|
|
||||||
this.equipmentList.splice(index, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
},
|
},
|
||||||
|
|
@ -822,7 +860,88 @@ export default {
|
||||||
`新购到货详情_${new Date().getTime()}.xlsx`
|
`新购到货详情_${new Date().getTime()}.xlsx`
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
// 高亮文本
|
||||||
|
highlightText(text, keyword) {
|
||||||
|
if (!keyword) return text;
|
||||||
|
const reg = new RegExp(keyword, 'gi');
|
||||||
|
return text.replace(reg, match => `<span class="highlight-text">${match}</span>`);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 处理下拉框可见性变化
|
||||||
|
handleVisibleChange(visible) {
|
||||||
|
if (!visible && this.keepSelectOpen && !this.isSearching) {
|
||||||
|
// 只有在非搜索状态下才重新打开下拉框
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.typeSelect.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理搜索框点击
|
||||||
|
handleSearchClick() {
|
||||||
|
this.isSearching = true;
|
||||||
|
this.keepSelectOpen = true;
|
||||||
|
// 确保下拉框打开
|
||||||
|
this.$refs.typeSelect.focus();
|
||||||
|
// 立即将焦点返回给搜索框
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.searchInput.focus();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理搜索框获得焦点
|
||||||
|
handleSearchFocus() {
|
||||||
|
this.isSearching = true;
|
||||||
|
if (!this.$refs.typeSelect.visible) {
|
||||||
|
this.$refs.typeSelect.focus();
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.searchInput.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 高亮搜索处理
|
||||||
|
handleHighlightSearch() {
|
||||||
|
this.isSearching = true;
|
||||||
|
this.keepSelectOpen = true;
|
||||||
|
|
||||||
|
if (!this.searchKeyword) {
|
||||||
|
this.currentMatchIndex = -1;
|
||||||
|
this.matchedOptions = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到所有匹配项
|
||||||
|
this.matchedOptions = this.filteredOptions.filter(item =>
|
||||||
|
item.fullPath.toLowerCase().includes(this.searchKeyword.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.matchedOptions.length > 0) {
|
||||||
|
this.currentMatchIndex = 0;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToMatch();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 滚动到匹配项
|
||||||
|
scrollToMatch() {
|
||||||
|
if (this.currentMatchIndex === -1 || !this.matchedOptions.length) return;
|
||||||
|
|
||||||
|
const option = this.matchedOptions[this.currentMatchIndex];
|
||||||
|
const selectDom = this.$el.querySelector('.el-select-dropdown__wrap');
|
||||||
|
const optionDom = selectDom?.querySelector(`[data-key="${option.typeId}"]`);
|
||||||
|
|
||||||
|
if (optionDom) {
|
||||||
|
optionDom.scrollIntoView({ block: 'center', behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 添加组件销毁时的清理
|
||||||
|
beforeDestroy() {
|
||||||
|
this.keepSelectOpen = false;
|
||||||
|
this.isSearching = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
@ -835,4 +954,75 @@ export default {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-tree-node {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon-arrow-down.is-reverse {
|
||||||
|
transform: rotateZ(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tree {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-text {
|
||||||
|
background-color: #ffd04b;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input-group__append {
|
||||||
|
padding: 0;
|
||||||
|
.el-button {
|
||||||
|
padding: 0 10px;
|
||||||
|
border: none;
|
||||||
|
height: 100%;
|
||||||
|
&:first-child {
|
||||||
|
border-right: 1px solid #dcdfe6;
|
||||||
|
}
|
||||||
|
&[disabled] {
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-select-dropdown {
|
||||||
|
.el-select-dropdown__wrap {
|
||||||
|
max-height: 400px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
height: auto;
|
||||||
|
padding: 8px 20px;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-text {
|
||||||
|
background-color: #ffd04b;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input-group__append {
|
||||||
|
padding: 0;
|
||||||
|
.el-button {
|
||||||
|
padding: 0 10px;
|
||||||
|
border: none;
|
||||||
|
height: 100%;
|
||||||
|
&:first-child {
|
||||||
|
border-right: 1px solid #dcdfe6;
|
||||||
|
}
|
||||||
|
&[disabled] {
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue