boom-light-ui/src/views/bst/location/components/LocationTree.vue
2025-06-07 18:02:41 +08:00

246 lines
6.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div v-loading="loading">
<!-- 搜索框 -->
<div style="margin-bottom: 10px;">
<el-input v-model="searchValue" placeholder="请输入位置名称" @input="handleSearch" size="small"/>
</div>
<!-- 树形结构 -->
<el-tree
:data="treeData"
:props="defaultProps"
node-key="id"
default-expand-all
:filter-node-method="filterNode"
ref="tree"
@node-click="handleNodeClick"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<!-- 店铺节点:显示新增按钮 -->
<span class="operation-group" v-if="data.type === 'store'">
<el-button type="text" size="mini" icon="el-icon-plus" @click.stop="handleAdd(data)"></el-button>
</span>
<!-- 位置节点:显示修改和删除按钮 -->
<span class="operation-group" v-if="data.type === 'location'">
<el-button type="text" size="mini" icon="el-icon-edit" @click.stop="handleEdit(data)"></el-button>
<el-button type="text" size="mini" icon="el-icon-delete" @click.stop="handleDelete(data)"></el-button>
</span>
</span>
</el-tree>
<!-- 新增/编辑对话框 -->
<el-dialog :title="form.id ? '编辑位置' : '新增位置'" :visible.sync="dialogVisible" width="400px">
<el-form :model="form" label-width="80px" ref="formRef">
<el-form-item label="所属店铺" prop="storeId">
<div class="category-wrapper">
<el-select
v-model="form.storeId"
placeholder="请选择店铺"
clearable
>
<el-option
v-for="item in stores"
:key="item.storeId"
:label="item.storeName"
:value="item.storeId"
/>
</el-select>
</div>
</el-form-item>
<el-form-item label="位置名称" prop="name">
<el-input v-model="form.name" placeholder="请输入位置名称"/>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {listStore} from "@/api/bst/store";
import {listLocation, addLocation, updateLocation, delLocation} from "@/api/bst/location";
export default {
name: "LocationTree",
props: {
storeId: {
type: [String, Number],
default: null
}
},
data() {
return {
stores :[], // 店铺选项
loading: false,
searchValue: "",
treeData: [],
defaultProps: {
children: "children",
label: "name"
},
dialogVisible: false,
form: {
id: null,
storeId: null,
storeName: "",
name: ""
}
};
},
mounted() {
this.getList();
},
methods: {
handleSearch() {
this.$refs.tree.filter(this.searchValue);
},
filterNode(value, data) {
if (!value) return true;
if (data.type === "location" && data.originalName) {
return data.originalName.includes(value);
}
return data.name.includes(value);
},
async getList() {
this.loading = true;
try {
// 获取店铺列表
const storeRes = await listStore();
this.stores = storeRes.rows;
// 获取位置列表如果传递了storeId则根据storeId查询否则查询所有
const params = { storeId: this.storeId };
const locationRes = await listLocation(params);
const locations = locationRes.rows;
// 构建树结构:店铺 -> 位置
this.treeData = this.stores.map(store => ({
id: store.storeId,
name: store.storeName,
storeId: store.storeId,
type: "store",
children: locations
.filter(location => location.storeId === store.storeId)
.map(location => ({
id: location.id,
name: `${location.name}(${location.currentNum || 0})`,
originalName: location.name,
storeId: location.storeId,
storeName: store.storeName,
locationId: location.id,
type: "location",
currentNum: location.currentNum
}))
}));
console.log("this.treeData:", this.treeData);
} catch (error) {
console.error("获取数据失败:", error);
} finally {
this.loading = false;
}
},
handleNodeClick(data) {
this.$emit('node-click', data);
},
// 新增按钮点击
handleAdd(data) {
this.form = {
storeId: data.storeId,
name: ""
};
this.dialogVisible = true;
},
// 编辑按钮点击
handleEdit(data) {
console.log("data:", data);
this.form = {
id: data.locationId || data.id,
storeId: data.storeId,
name: data.originalName
};
this.dialogVisible = true;
},
// 删除按钮点击
handleDelete(data) {
this.$confirm(`是否确认删除【${data.originalName}】?`, "提示", {
type: "warning"
}).then(async () => {
await delLocation(data.locationId);
this.$message.success("删除成功");
this.getList(); // 刷新列表
}).catch(() => {
});
},
// 提交表单
submitForm() {
if (!this.form.name.trim()) {
this.$message.warning("请输入位置名称");
return;
}
const api = this.form.id ? updateLocation : addLocation;
const params = {
id: this.form.id || undefined,
storeId: this.form.storeId,
name: this.form.name
};
api(params)
.then(() => {
this.$message.success(this.form.id ? "更新成功" : "新增成功");
this.dialogVisible = false;
this.getList(); // 刷新列表
})
.catch(err => {
this.$message.error("操作失败:" + err.message);
});
}
},
watch: {
storeId: {
handler() {
this.getList();
}
}
}
};
</script>
<style lang="scss" scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.operation-group {
.el-button {
margin-left: 8px;
&:first-child {
margin-left: 0;
}
&[class*="el-icon-delete"] {
color: #f56c6c;
}
}
}
</style>