装备台账
This commit is contained in:
parent
5d9703e026
commit
e7f903991f
|
|
@ -7,18 +7,66 @@
|
|||
<!-- 只有在未折叠状态显示标题 -->
|
||||
<span class="card-title">装备分类</span>
|
||||
</div>
|
||||
|
||||
|
||||
<el-form
|
||||
ref="queryFormLeft"
|
||||
v-show="showSearch"
|
||||
:model="queryParams"
|
||||
:rules="queryRules"
|
||||
style="margin-top: 20px; padding: 0 15px;"
|
||||
>
|
||||
<el-form-item prop="name" style="margin-bottom: 0;">
|
||||
<el-input
|
||||
v-model="treeSearchKey"
|
||||
placeholder="搜索"
|
||||
@keyup.enter.native="getDeviceListByTreeSearch"
|
||||
class="tree-search-input"
|
||||
|
||||
|
||||
>
|
||||
<template #suffix>
|
||||
<div class="tree-search-buttons">
|
||||
<el-button
|
||||
icon="el-icon-search"
|
||||
size="mini"
|
||||
@click="getDeviceListByTreeSearch"
|
||||
title="查询"
|
||||
class="search-btn-embedded"
|
||||
/>
|
||||
<el-button
|
||||
icon="el-icon-refresh"
|
||||
size="mini"
|
||||
@click="resetTreeSearch"
|
||||
title="重置"
|
||||
class="search-btn-embedded"
|
||||
style="margin-left: 0;"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 树组件,折叠时隐藏 -->
|
||||
<el-tree
|
||||
v-if="!collapsed"
|
||||
v-show="!collapsed"
|
||||
:data="treeData"
|
||||
:props="defaultProps"
|
||||
:indent="6"
|
||||
@node-click="handleNodeClick"
|
||||
default-expand-all
|
||||
:default-expanded-keys="defaultExpandedKeys"
|
||||
class="tree-container"
|
||||
:loading="treeLoading"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="position: relative; width: 20px; height: calc(100vh - 130px); margin-left: 5px">
|
||||
<!-- 右侧折叠/展开按钮 -->
|
||||
<el-button
|
||||
|
|
@ -254,6 +302,7 @@
|
|||
<el-button
|
||||
icon="el-icon-refresh"
|
||||
style="float: right; margin-left: 20px"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="resetQuery"
|
||||
>
|
||||
|
|
@ -306,15 +355,6 @@
|
|||
>
|
||||
装备退役
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
icon="el-icon-document-checked"
|
||||
@click="onHandleReturn"
|
||||
class="operation-btn"
|
||||
>
|
||||
装备退库
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
|
@ -354,7 +394,6 @@
|
|||
:key="Date.now()"
|
||||
@selection-change="handleSelectionChange"
|
||||
v-loading="tableLoading"
|
||||
border stripe
|
||||
>
|
||||
<el-table-column align="center" show-overflow-tooltip type="selection" width="50"/>
|
||||
<el-table-column align="center" show-overflow-tooltip type="index" label="序号" width="50"/>
|
||||
|
|
@ -772,6 +811,10 @@ export default {
|
|||
name: 'EquipmentLedger',
|
||||
data() {
|
||||
return {
|
||||
treeSearchKey: '', //用于存储左侧树搜索框内容
|
||||
|
||||
defaultExpandedKeys: [], //用于存储需要默认展开的节点id
|
||||
|
||||
showSearch: true,
|
||||
total: 0,
|
||||
tableHeight: 510,
|
||||
|
|
@ -1062,9 +1105,6 @@ export default {
|
|||
onHandleRetire() {
|
||||
this.$router.push('/equipment/equ-retire')
|
||||
},
|
||||
onHandleReturn() {
|
||||
this.$router.push('/equipment/equStore')
|
||||
},
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
|
|
@ -1083,22 +1123,227 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 获取左侧树形结构数据
|
||||
*/
|
||||
async getDeviceTree() {
|
||||
try {
|
||||
this.treeLoading = true
|
||||
const res = await getDeviceTreeAPI()
|
||||
this.treeData = res.data ? [res.data] : []
|
||||
this.treeLoading = true;
|
||||
const res = await getDeviceTreeAPI();
|
||||
this.treeData = res.data ? [res.data] : [];
|
||||
|
||||
// 👇 加这一行
|
||||
console.log('treeData', JSON.stringify(this.treeData, null, 2));
|
||||
|
||||
// 重置默认展开的节点ID数组
|
||||
this.defaultExpandedKeys = [];
|
||||
|
||||
// 只收集第一级和第二级节点的ID,第三级默认不展开
|
||||
this.collectFirstAndSecondLevelKeys(this.treeData);
|
||||
console.log('✅ defaultExpandedKeys:', this.defaultExpandedKeys);
|
||||
|
||||
// 3. 关键:等 DOM 渲染完再赋值
|
||||
this.$nextTick(() => {
|
||||
this.defaultExpandedKeys = [...this.defaultExpandedKeys];
|
||||
});
|
||||
|
||||
console.log('默认展开的第一级和第二级节点ID:', this.defaultExpandedKeys);
|
||||
} catch (error) {
|
||||
this.$message.error('获取树形结构失败:' + (error.message || '未知错误'))
|
||||
console.error(error)
|
||||
this.$message.error('获取树形结构失败:' + (error.message || '未知错误'));
|
||||
console.error(error);
|
||||
} finally {
|
||||
this.treeLoading = false
|
||||
this.treeLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 收集第一级和第二级节点的ID,第三级默认不展开
|
||||
*/
|
||||
collectFirstAndSecondLevelKeys(nodes) {
|
||||
if (!nodes || !nodes.length) return;
|
||||
|
||||
nodes.forEach(firstLevelNode => {
|
||||
// 展开第一级节点
|
||||
if (firstLevelNode.id) {
|
||||
this.defaultExpandedKeys.push(firstLevelNode.id);
|
||||
console.log(`展开第一级节点: ${firstLevelNode.name}, ID: ${firstLevelNode.id}`);
|
||||
}
|
||||
|
||||
// 检查是否有子节点(第二级节点)
|
||||
if (firstLevelNode.children && firstLevelNode.children.length) {
|
||||
// 遍历所有第二级节点
|
||||
firstLevelNode.children.forEach(secondLevelNode => {
|
||||
if (secondLevelNode.id) {
|
||||
this.defaultExpandedKeys.push(secondLevelNode.id);
|
||||
console.log(`展开第二级节点: ${secondLevelNode.name}, ID: ${secondLevelNode.id}`);
|
||||
// 第三级及更深层级默认不展开(保持折叠状态)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 左侧树查询:匹配节点显示自身及下一级,但默认只显示到第二级
|
||||
*/
|
||||
async getDeviceListByTreeSearch() {
|
||||
try {
|
||||
// 1. 获取输入的查询关键词(去空格)
|
||||
const searchKey = this.treeSearchKey ? this.treeSearchKey.trim() : '';
|
||||
|
||||
// 如果没有搜索关键词,则重置为原始树(显示到第二级)
|
||||
if (!searchKey) {
|
||||
await this.resetTreeSearch();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 重新获取原始树形数据
|
||||
this.treeLoading = true;
|
||||
const res = await getDeviceTreeAPI();
|
||||
const originalTreeData = res.data ? [res.data] : [];
|
||||
|
||||
// 3. 筛选逻辑:匹配节点显示自身及下一级
|
||||
const filteredTreeData = this.filterTreeWithNextLevel(originalTreeData, searchKey);
|
||||
|
||||
// 4. 收集所有匹配节点的ID,用于默认展开
|
||||
const expandedIds = [];
|
||||
this.collectMatchedNodeIds(filteredTreeData, searchKey, expandedIds);
|
||||
|
||||
// 5. 更新树形数据和默认展开节点
|
||||
this.treeData = filteredTreeData;
|
||||
this.defaultExpandedKeys = expandedIds;
|
||||
|
||||
// 6. 无匹配结果时提示
|
||||
if (filteredTreeData.length === 0 || this.isTreeEmpty(filteredTreeData)) {
|
||||
this.$message.info('未找到匹配的类型分支');
|
||||
} else {
|
||||
this.$message.success(`找到 ${expandedIds.length} 个匹配项`);
|
||||
}
|
||||
} catch (error) {
|
||||
this.$message.error('树形查询失败:' + (error.message || '未知错误'));
|
||||
console.error(error);
|
||||
} finally {
|
||||
this.treeLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 辅助方法:筛选节点并包含下一级
|
||||
*/
|
||||
filterTreeWithNextLevel(treeData, key) {
|
||||
if (!treeData || !treeData.length) return [];
|
||||
|
||||
return treeData
|
||||
.map(node => {
|
||||
// 深拷贝节点
|
||||
const newNode = {...node};
|
||||
|
||||
const isNodeMatch = key ? node.name.includes(key) : true;
|
||||
|
||||
if (isNodeMatch) {
|
||||
// 匹配节点:保留所有直接子节点
|
||||
if (newNode.children && newNode.children.length) {
|
||||
// 保留第二级,但第三级及更深层级保持原样(默认不展开)
|
||||
newNode.children = [...newNode.children];
|
||||
}
|
||||
return newNode;
|
||||
} else {
|
||||
// 不匹配节点:检查子节点是否有匹配的
|
||||
if (newNode.children && newNode.children.length) {
|
||||
const filteredChildren = this.filterTreeWithNextLevel(newNode.children, key);
|
||||
|
||||
if (filteredChildren.length > 0) {
|
||||
newNode.children = filteredChildren;
|
||||
return newNode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(node => node !== null);
|
||||
},
|
||||
|
||||
/**
|
||||
* 辅助方法:收集所有匹配关键词的节点ID(用于默认展开)
|
||||
* @param {Array} treeData - 筛选后的树形数据
|
||||
* @param {String} key - 查询关键词
|
||||
* @param {Array} expandedIds - 存储展开节点ID的数组
|
||||
*/
|
||||
collectMatchedNodeIds(treeData, key, expandedIds) {
|
||||
if (!treeData || !treeData.length) return;
|
||||
|
||||
treeData.forEach(node => {
|
||||
// 若当前节点匹配关键词,记录其ID(用于展开)
|
||||
if (key ? node.name.includes(key) : true) {
|
||||
if (node.id) expandedIds.push(node.id);
|
||||
}
|
||||
|
||||
// 递归处理子级,确保深层子级的匹配节点也被收集
|
||||
if (node.children && node.children.length) {
|
||||
this.collectMatchedNodeIds(node.children, key, expandedIds);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 辅助方法:检查树是否为空(没有任何有效节点)
|
||||
*/
|
||||
isTreeEmpty(treeData) {
|
||||
if (!treeData || !treeData.length) return true;
|
||||
|
||||
// 递归检查所有节点
|
||||
for (const node of treeData) {
|
||||
if (node && node.id) {
|
||||
return false; // 发现有效节点
|
||||
}
|
||||
if (node.children && node.children.length) {
|
||||
if (!this.isTreeEmpty(node.children)) {
|
||||
return false; // 子节点中有有效节点
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 左侧树重置:仅恢复树形原始状态(不联动右侧列表)
|
||||
*/
|
||||
/**
|
||||
* 左侧树重置:恢复树形原始状态,默认显示到第二级
|
||||
*/
|
||||
async resetTreeSearch() {
|
||||
try {
|
||||
// 1. 清空左侧表单输入和查询参数
|
||||
if (this.$refs.queryFormLeft) {
|
||||
this.$refs.queryFormLeft.resetFields();
|
||||
}
|
||||
this.treeSearchKey = ''; // 手动清空类型分支查询值
|
||||
this.queryParams.typeId = undefined; // 清空可能存在的节点ID缓存
|
||||
|
||||
// 2. 恢复原始树形数据,默认显示到第二级
|
||||
this.treeLoading = true;
|
||||
const res = await getDeviceTreeAPI();
|
||||
this.treeData = res.data ? [res.data] : [];
|
||||
|
||||
// 重置默认展开的节点ID数组
|
||||
this.defaultExpandedKeys = [];
|
||||
|
||||
// 只展开第一级和第二级节点
|
||||
this.collectFirstAndSecondLevelKeys(this.treeData);
|
||||
|
||||
this.$message.success('树形查询已重置');
|
||||
} catch (error) {
|
||||
this.$message.error('树形重置失败:' + (error.message || '未知错误'));
|
||||
console.error(error);
|
||||
} finally {
|
||||
this.treeLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 获取右侧列表数据
|
||||
*/
|
||||
|
|
@ -1401,10 +1646,16 @@ export default {
|
|||
// 最后加载列表数据
|
||||
await this.getDeviceList()
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
|
|
@ -1693,27 +1944,49 @@ export default {
|
|||
flex-direction: row;
|
||||
}
|
||||
|
||||
::v-deep .el-table {
|
||||
// 启用斑马纹
|
||||
&.el-table--striped .el-table__body {
|
||||
tr.el-table__row--striped td {
|
||||
background-color: #F6FBFA !important; // 浅紫色
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* 简洁紧凑版树搜索输入框样式 */
|
||||
.tree-search-input ::v-deep .el-input__inner {
|
||||
padding-right: 65px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.el-table__header {
|
||||
background: #E9F0EE;
|
||||
|
||||
th {
|
||||
background: #E9F0EE !important;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
height: 50px;
|
||||
}
|
||||
.tree-search-input ::v-deep .el-input__suffix {
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.el-table--striped .el-table__body tr.el-table__row:hover>td.el-table__cell {
|
||||
background-color: #CCF1E9 !important;
|
||||
.tree-search-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
gap: 0; /* 关键:移除按钮间距 */
|
||||
}
|
||||
|
||||
.search-btn-embedded {
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
color: #909399 !important;
|
||||
border-radius: 0 !important;
|
||||
padding: 11px 8px !important; /* 适中的内边距 */
|
||||
height: 100% !important;
|
||||
min-width: 24px !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
.search-btn-embedded:hover {
|
||||
color: #409EFF !important;
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
|
||||
.tree-search-input ::v-deep .el-input__clear {
|
||||
right: 55px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue