装备台账

This commit is contained in:
itcast 2025-10-29 18:40:16 +08:00
parent 5d9703e026
commit e7f903991f
1 changed files with 418 additions and 145 deletions

View File

@ -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>