<template>
|
<div class="sample">
|
<div class="main-content"
|
v-if="!isDetail">
|
<div class="search">
|
<div class="search_thing">
|
<div class="search_label">仓库名称:</div>
|
<div class="search_input">
|
<el-select v-model="entity.warehouseId"
|
placeholder="选择仓库"
|
size="small"
|
@change="warehouseChange">
|
<el-option v-for="item in warehouse"
|
:key="item.id"
|
:label="item.label"
|
:value="item.id">
|
</el-option>
|
</el-select>
|
</div>
|
</div>
|
<div class="search_thing">
|
<div class="search_label">货架:</div>
|
<div class="search_input">
|
<el-select v-model="entity.shelfId"
|
placeholder="选择货架"
|
size="small"
|
@change="handleShelf">
|
<el-option v-for="item in shelf"
|
:key="item.id"
|
:label="item.label"
|
:value="item.id">
|
</el-option>
|
</el-select>
|
</div>
|
</div>
|
<!-- <div class="search_thing">
|
<el-button size="small" @click="handleShelf(entity.shelfId,'')">重置</el-button>
|
<el-button size="small" type="primary" @click="handleShelf(entity.shelfId)">查询</el-button>
|
</div> -->
|
<div class="btns">
|
<el-button size="small"
|
style="color:#3A7BFA"
|
@click="keepVisible=true">维护</el-button>
|
<el-button size="small"
|
style="color:#3A7BFA"
|
@click="warehouseVisible=true,isEdit=false">添加仓库</el-button>
|
<el-button size="small"
|
style="color:#3A7BFA"
|
@click="shelvesVisible=true,isEdit=false"
|
:disabled="entity.warehouseId==null">添加货架</el-button>
|
</div>
|
</div>
|
<div class="table"
|
v-loading="tableLoading">
|
<table class="tables"
|
style="table-layout:fixed;"
|
v-if="tableList.length>0">
|
<tbody>
|
<tr v-for="(item,index) in tableList"
|
:key="index">
|
<td v-for="(m,i) in item"
|
:key="i"
|
class="content">
|
<h4 v-if="m.row!=undefined">{{ m.row }} - {{ m.col }}</h4>
|
<ul>
|
<el-tooltip effect="dark"
|
placement="top"
|
v-for="(n,j) in m.documentationDtoList"
|
:key="j">
|
<template #content><span>{{ n.docName }}</span>
|
<span> [{{ n.docNumber }}]</span></template>
|
<li class="green"
|
@click="handelDetail(n)">
|
<i></i>
|
<span>{{ n.docName }}</span>
|
<span> [{{ n.docNumber }}] <span :style="{ color: getStatusColor(n.docStatus) }">({{ n.docStatus }})</span></span>
|
</li>
|
</el-tooltip>
|
</ul>
|
</td>
|
</tr>
|
<tr>
|
<td v-for="(item,index) in rowList"
|
:key="index"
|
style="background: ghostwhite;height: 20px;">{{ item }}
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
<span v-else
|
style="color: rgb(144, 147, 153);display: inline-block;position: absolute;top: 60%;left: 50%;transform: translate(-50%,-50%);">暂无数据</span>
|
</div>
|
</div>
|
<Detail v-else
|
@hanldeBack="isDetail=false"
|
:current="current" />
|
<!-- 库位维护对话框 -->
|
<el-dialog v-model="keepVisible"
|
title="库位维护"
|
width="350px"
|
:append-to-body="true">
|
<el-tree :data="warehouse"
|
ref="tree"
|
node-key="id"
|
highlight-current
|
v-if="keepVisible"
|
empty-text="暂无数据">
|
<template #default="{ node, data }">
|
<div class="custom-tree-node"
|
style="width: 100%;">
|
<el-row style="width: 100%;display: flex;align-items: center;">
|
<el-col :span="14">
|
<span>
|
<el-icon v-if="node.level < 2"
|
class="folder-icon">
|
<FolderOpened />
|
</el-icon>
|
<el-icon v-else
|
class="file-icon">
|
<Document />
|
</el-icon>
|
{{ data.label }}
|
</span>
|
</el-col>
|
<el-col :span="10"
|
v-if="node.level<3">
|
<el-button type="link"
|
size="small"
|
:icon="Edit"
|
@click.stop="handleEdit(data,node.level)">
|
</el-button>
|
<el-button type="danger"
|
size="small"
|
:icon="Delete"
|
@click.stop="handleDelete(data,node.level)">
|
</el-button>
|
</el-col>
|
</el-row>
|
</div>
|
</template>
|
</el-tree>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary"
|
@click="keepVisible = false">确 定</el-button>
|
<el-button @click="keepVisible = false">取 消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
<!-- 仓库新增/修改对话框 -->
|
<el-dialog v-model="warehouseVisible"
|
:title="isEdit?'仓库修改':'仓库新增'"
|
width="350px">
|
<el-row>
|
<el-col class="search_thing"
|
:span="24">
|
<div class="search_label"><span class="required-span">* </span>仓库名称:</div>
|
<div class="search_input">
|
<el-input v-model="name"
|
size="small"
|
@keyup.enter="confirmWarehouse"></el-input>
|
</div>
|
</el-col>
|
</el-row>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary"
|
@click="confirmWarehouse"
|
:loading="upLoadWarehouse">确 定</el-button>
|
<el-button @click="warehouseVisible = false">取 消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
<!-- 货架新增/修改对话框 -->
|
<el-dialog v-model="shelvesVisible"
|
:title="isEdit?'货架修改':'货架新增'"
|
width="350px">
|
<el-row>
|
<el-col class="search_thing"
|
:span="24">
|
<div class="search_label"><span class="required-span">* </span>货架名称:</div>
|
<div class="search_input">
|
<el-input v-model="shelves.name"
|
size="small"></el-input>
|
</div>
|
</el-col>
|
</el-row>
|
<el-row>
|
<el-col class="search_thing"
|
:span="24">
|
<div class="search_label"><span class="required-span">* </span>货架层数:</div>
|
<div class="search_input">
|
<el-input v-model="shelves.row"
|
size="small"></el-input>
|
</div>
|
</el-col>
|
</el-row>
|
<el-row>
|
<el-col class="search_thing"
|
:span="24">
|
<div class="search_label"><span class="required-span">* </span>货架列数:</div>
|
<div class="search_input">
|
<el-input v-model="shelves.col"
|
size="small"></el-input>
|
</div>
|
</el-col>
|
</el-row>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary"
|
@click="confirmShelves"
|
:loading="upLoadShelves">确 定</el-button>
|
<el-button @click="shelvesVisible = false">取 消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted, watch } from "vue";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
import { Edit, Delete, FolderOpened, Document } from "@element-plus/icons-vue";
|
import {
|
getWarehouseList,
|
addWarehouse,
|
updateWarehouse,
|
deleteWarehouse,
|
getWarehouseStructure,
|
addShelf,
|
updateShelf,
|
deleteShelf,
|
} from "@/api/fileManagement/bookshelf";
|
import Detail from "./detail.vue";
|
|
// 响应式数据
|
const entity = reactive({
|
warehouseId: null,
|
shelfId: null,
|
});
|
|
const warehouse = ref([]);
|
const shelf = ref([]);
|
const keepVisible = ref(false);
|
const warehouseVisible = ref(false);
|
const shelvesVisible = ref(false);
|
const upLoadWarehouse = ref(false);
|
const upLoadShelves = ref(false);
|
const tableList = ref([]);
|
const rowList = ref([]);
|
const value = ref("");
|
const name = ref("");
|
const shelves = reactive({});
|
const isEdit = ref(false);
|
const isDetail = ref(false);
|
const currentEdit = ref(null);
|
const tableLoading = ref(false);
|
const current = ref({});
|
|
// 模板引用
|
const organization = ref(null);
|
|
// 监听器
|
watch(isEdit, newVal => {
|
if (!newVal) {
|
Object.keys(shelves).forEach(key => delete shelves[key]);
|
}
|
});
|
|
// 方法
|
|
const selectList = async () => {
|
// 这里需要替换为实际的API调用
|
const res = await getWarehouseList();
|
warehouse.value = res.data;
|
|
if (warehouse.value.length == 0) {
|
entity.warehouseId = "";
|
entity.shelfId = "";
|
tableList.value = [];
|
}
|
|
if (!entity.warehouseId && warehouse.value.length > 0) {
|
entity.warehouseId = warehouse.value[0].id;
|
warehouseChange(entity.warehouseId);
|
if (shelf.value.length > 0) {
|
entity.shelfId = shelf.value[0].id;
|
handleShelf(entity.shelfId);
|
} else {
|
tableList.value = [];
|
}
|
} else if (warehouse.value.length > 0) {
|
warehouseChange(entity.warehouseId);
|
if (shelf.value.length > 0) {
|
entity.shelfId = shelf.value[0].id;
|
handleShelf(entity.shelfId);
|
} else {
|
tableList.value = [];
|
}
|
}
|
};
|
|
const confirmWarehouse = () => {
|
if (!name.value) {
|
ElMessage.error("请填写仓库名称");
|
return;
|
}
|
upLoadWarehouse.value = true;
|
|
if (currentEdit.value && currentEdit.value.id) {
|
// 修改仓库
|
// 这里需要替换为实际的API调用
|
updateWarehouse({
|
id: currentEdit.value.id,
|
warehouseName: name.value,
|
}).then(res => {
|
upLoadWarehouse.value = false;
|
warehouseVisible.value = false;
|
currentEdit.value = null;
|
ElMessage.success("修改成功");
|
selectList();
|
name.value = "";
|
warehouseChange(entity.warehouseId);
|
});
|
} else {
|
// 新增仓库
|
// 这里需要替换为实际的API调用
|
addWarehouse({
|
warehouseName: name.value,
|
}).then(res => {
|
upLoadWarehouse.value = false;
|
warehouseVisible.value = false;
|
ElMessage.success("添加成功");
|
selectList();
|
name.value = "";
|
warehouseChange(entity.warehouseId);
|
});
|
}
|
};
|
|
const confirmShelves = () => {
|
if (!shelves.name) {
|
ElMessage.error("请填写货架名称");
|
return;
|
}
|
if (!shelves.row) {
|
ElMessage.error("请填写货架层数");
|
return;
|
}
|
if (!shelves.col) {
|
ElMessage.error("请填写货架列数");
|
return;
|
}
|
upLoadShelves.value = true;
|
|
if (currentEdit.value && currentEdit.value.id) {
|
// 修改
|
updateShelf({
|
id: currentEdit.value.id,
|
name: shelves.name,
|
row: Number(shelves.row),
|
col: Number(shelves.col),
|
warehouseId: entity.warehouseId,
|
})
|
.then(res => {
|
upLoadShelves.value = false;
|
shelvesVisible.value = false;
|
ElMessage.success("修改成功");
|
selectList();
|
currentEdit.value = {};
|
})
|
.catch(err => {
|
upLoadShelves.value = false;
|
shelvesVisible.value = false;
|
ElMessage.error("修改失败");
|
});
|
} else {
|
// 新增
|
// 这里需要替换为实际的API调用
|
addShelf({
|
name: shelves.name,
|
row: Number(shelves.row),
|
col: Number(shelves.col),
|
warehouseId: entity.warehouseId,
|
})
|
.then(res => {
|
upLoadShelves.value = false;
|
shelvesVisible.value = false;
|
ElMessage.success("添加成功");
|
selectList();
|
Object.keys(shelves).forEach(key => delete shelves[key]);
|
})
|
.catch(err => {
|
upLoadShelves.value = false;
|
shelvesVisible.value = false;
|
ElMessage.error("添加失败");
|
});
|
}
|
warehouseChange(entity.warehouseId);
|
};
|
|
const handleDelete = (row, level) => {
|
ElMessageBox.confirm("是否删除当前数据?", "警告", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
if (level == 1) {
|
// 删除仓库
|
deleteWarehouse([row.id]).then(res => {
|
ElMessage.success("删除成功");
|
selectList();
|
});
|
} else {
|
// 删除货架
|
deleteShelf({
|
id: row.id,
|
}).then(res => {
|
ElMessage.success("删除成功");
|
selectList();
|
});
|
}
|
warehouseChange(entity.warehouseId);
|
})
|
.catch(() => {});
|
};
|
|
const handleEdit = (data, level) => {
|
isEdit.value = true;
|
if (level == 1) {
|
warehouseVisible.value = true;
|
currentEdit.value = data;
|
name.value = data.label;
|
} else {
|
shelvesVisible.value = true;
|
currentEdit.value = data;
|
Object.assign(shelves, {
|
name: data.label,
|
row: data.row,
|
col: data.col,
|
warehouseId: data.warehouseId,
|
});
|
}
|
};
|
|
const handelDetail = row => {
|
current.value = row;
|
isDetail.value = true;
|
};
|
|
// 根据文档状态返回对应的颜色
|
const getStatusColor = status => {
|
if (status === "正常") {
|
return "#34BD66"; // 绿色
|
} else if (status === "借出") {
|
return "#F56C6C"; // 红色
|
}
|
return "#606266"; // 默认颜色
|
};
|
|
const warehouseChange = val => {
|
tableList.value = [];
|
let map = warehouse.value.find(a => {
|
return a && a.id === val ? a : null;
|
});
|
if (map && map.children) {
|
shelf.value = map.children;
|
entity.shelfId = "";
|
} else {
|
shelf.value = [];
|
}
|
currentEdit.value = null;
|
};
|
|
const handleShelf = async e => {
|
if (e) {
|
tableLoading.value = true;
|
let data = [];
|
const res = await getWarehouseStructure({ warehouseGoodsShelvesId: e });
|
if (res.code == 200) {
|
data = res.data.map(m => {
|
m.books = m.documentationDtoList | [];
|
return m;
|
});
|
} else {
|
ElMessage.error(res.message);
|
}
|
setTimeout(() => {
|
tableLoading.value = false;
|
let set = new Set();
|
tableList.value = [];
|
let arr = [];
|
|
if (data && data.length > 0) {
|
data.forEach(m => {
|
if (m && m.row && m.col) {
|
set.add(m.col);
|
if (arr.length > 0) {
|
if (arr.find(n => n.row == m.row)) {
|
arr.push(m);
|
} else {
|
tableList.value.push(arr);
|
arr = [];
|
arr.push(m);
|
}
|
} else {
|
arr.push(m);
|
}
|
}
|
});
|
|
if (arr.length > 0) {
|
tableList.value.push(arr);
|
}
|
}
|
|
rowList.value = [];
|
for (let i = 0; i < set.size; i++) {
|
rowList.value.push(`${i + 1} 列`);
|
}
|
console.log(6666, tableList.value, rowList.value, data);
|
}, 1000);
|
}
|
};
|
|
// 生命周期
|
onMounted(() => {
|
selectList();
|
});
|
</script>
|
|
<style scoped>
|
.main-content {
|
width: 100%;
|
height: 100%;
|
padding: 20px;
|
box-sizing: border-box;
|
}
|
|
.title {
|
height: 20px;
|
line-height: 20px;
|
margin-bottom: 20px;
|
}
|
|
.search {
|
background-color: #fff;
|
height: 80px;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 0 20px;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
margin-bottom: 20px;
|
}
|
|
.search_thing {
|
display: flex;
|
align-items: center;
|
height: 50px;
|
margin-right: 20px;
|
}
|
|
.search_label {
|
width: 90px;
|
font-size: 14px;
|
text-align: right;
|
color: #606266;
|
font-weight: 500;
|
margin-right: 10px;
|
}
|
|
.search_input {
|
width: 200px;
|
}
|
|
.table {
|
background-color: #fff;
|
width: 100%;
|
height: calc(100% - 100px);
|
padding: 20px;
|
overflow-y: auto;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.el-form-item {
|
margin-bottom: 16px;
|
}
|
|
.btns {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
}
|
|
.tables {
|
width: 100%;
|
height: 100%;
|
border-collapse: collapse;
|
border: 1px solid #e4e7ed;
|
}
|
|
.tables th {
|
font-size: 14px;
|
border: 1px solid #e4e7ed;
|
background-color: #fafafa;
|
padding: 8px;
|
font-weight: 500;
|
}
|
|
.tables td {
|
font-size: 12px;
|
text-align: center;
|
vertical-align: top;
|
border: 1px solid #e4e7ed;
|
padding: 8px;
|
box-sizing: border-box;
|
height: 120px;
|
background-color: #fff;
|
}
|
|
.tables ul {
|
list-style-type: none;
|
}
|
|
.tables ul li {
|
border-radius: 3px;
|
padding: 4px 10px;
|
box-sizing: border-box;
|
margin-bottom: 5px;
|
font-size: 12px;
|
display: flex;
|
align-items: center;
|
justify-content: start;
|
color: #333333;
|
cursor: pointer;
|
overflow: hidden;
|
white-space: nowrap;
|
text-overflow: ellipsis;
|
}
|
|
.tables h4 {
|
color: #999999;
|
font-size: 14px;
|
font-weight: 400;
|
padding: 6px 0;
|
}
|
|
.tables i {
|
display: inline-block;
|
width: 6px;
|
height: 6px;
|
border-radius: 50%;
|
margin-right: 6px;
|
}
|
|
li:hover {
|
background: rgba(58, 123, 250, 0.18);
|
}
|
|
li:hover i {
|
background: #3a7bfa;
|
}
|
|
li:hover .num {
|
color: #3a7bfa;
|
}
|
|
.green {
|
background: #e0f6ea;
|
}
|
|
.green i {
|
background: #34bd66;
|
}
|
|
.green .num {
|
color: #34bd66;
|
}
|
|
.el-dialog {
|
position: relative;
|
}
|
|
.shaoma {
|
display: flex;
|
align-items: center;
|
font-size: 14px;
|
color: #3a7bfa;
|
position: absolute;
|
top: 23px;
|
right: 54px;
|
cursor: pointer;
|
}
|
|
.folder-icon {
|
color: #409eff;
|
font-size: 16px;
|
margin-right: 6px;
|
}
|
|
.file-icon {
|
color: #67c23a;
|
font-size: 16px;
|
margin-right: 6px;
|
}
|
|
.node_i {
|
color: orange;
|
font-size: 18px;
|
}
|
|
.custom-tree-node .el-button {
|
opacity: 0;
|
}
|
|
.custom-tree-node:hover .el-button {
|
opacity: 1;
|
}
|
|
:deep(.el-loading-mask) {
|
z-index: 10;
|
}
|
|
.required-span {
|
color: #f56c6c;
|
}
|
|
.table-row {
|
border-bottom: 1px solid #e4e7ed;
|
}
|
|
.table-row:last-child {
|
border-bottom: none;
|
}
|
|
.column-header {
|
background-color: #fafafa !important;
|
font-weight: 500;
|
color: #606266;
|
}
|
|
.content {
|
transition: background-color 0.2s ease;
|
}
|
|
.content:hover {
|
background-color: #f5f7fa;
|
}
|
</style>
|