791 lines
26 KiB
Vue
791 lines
26 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<el-row :gutter="20">
|
||
<!-- 左侧树形结构 -->
|
||
<el-col :span="6">
|
||
<div class="tree-container">
|
||
<div class="tree-header">
|
||
<span class="tree-title">资产位置</span>
|
||
|
||
</div>
|
||
<el-divider class="tree-divider"></el-divider>
|
||
<el-tree
|
||
ref="locationTree"
|
||
:data="locationTree"
|
||
:props="defaultProps"
|
||
node-key="id"
|
||
:expand-on-click-node="false"
|
||
highlight-current
|
||
@node-click="handleNodeClick"
|
||
:default-expanded-keys="defaultExpandedKeys">
|
||
<span class="custom-tree-node" slot-scope="{ node, data }">
|
||
<span>{{ node.label }}</span>
|
||
<span v-if="data.children && data.children.length > 0" class="node-count">
|
||
({{ data.children.length }})
|
||
</span>
|
||
</span>
|
||
</el-tree>
|
||
</div>
|
||
</el-col>
|
||
|
||
<!-- 右侧列表 -->
|
||
<el-col :span="18">
|
||
<el-card class="box-card">
|
||
<div slot="header" class="clearfix">
|
||
<span>位置列表</span>
|
||
<el-button
|
||
style="float: right; margin-left: 10px;"
|
||
type="primary"
|
||
icon="el-icon-plus"
|
||
size="mini"
|
||
@click="handleAdd">新增位置</el-button>
|
||
<el-button
|
||
style="float: right;"
|
||
type="danger"
|
||
icon="el-icon-delete"
|
||
size="mini"
|
||
:disabled="multipleSelection.length === 0"
|
||
@click="handleBatchDelete">批量删除</el-button>
|
||
</div>
|
||
|
||
<!-- 搜索表单 -->
|
||
<el-form :inline="true" :model="queryParams" class="demo-form-inline">
|
||
<el-form-item label="位置编码">
|
||
<el-input v-model="queryParams.locationCode" placeholder="请输入位置编码" clearable size="small" />
|
||
</el-form-item>
|
||
<el-form-item label="位置名称">
|
||
<el-input v-model="queryParams.locationName" placeholder="请输入位置名称" clearable size="small" />
|
||
</el-form-item>
|
||
<el-form-item label="状态">
|
||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
|
||
<el-option label="启用" value="1" />
|
||
<el-option label="禁用" value="0" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<el-table
|
||
v-loading="loading"
|
||
:data="locationList"
|
||
border
|
||
stripe
|
||
style="width: 100%"
|
||
@selection-change="handleSelectionChange">
|
||
<el-table-column type="selection" width="55" />
|
||
<el-table-column prop="locationCode" label="位置编码" width="150" />
|
||
<el-table-column prop="locationName" label="位置名称" width="200" />
|
||
<el-table-column label="上级位置" width="200">
|
||
<template slot-scope="scope">
|
||
<span>{{ getParentName(scope.row.parentId) }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- <el-table-column prop="levelCode" label="层级编码" width="120" /> -->
|
||
<el-table-column prop="status" label="状态" width="100">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.status === '1' ? 'success' : 'info'">
|
||
{{ scope.row.status === '1' ? '启用' : '禁用' }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="remark" label="备注" />
|
||
<el-table-column label="操作" width="180" fixed="right">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" type="text" @click="handleEdit(scope.row)">修改</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="text"
|
||
@click="handleStatusChange(scope.row)">
|
||
{{ scope.row.status === '1' ? '禁用' : '启用' }}
|
||
</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="text"
|
||
style="color: #F56C6C"
|
||
@click="handleDelete(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<!-- 分页 -->
|
||
<el-pagination
|
||
@size-change="handleSizeChange"
|
||
@current-change="handleCurrentChange"
|
||
:current-page="queryParams.pageNum"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
:page-size="queryParams.pageSize"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
:total="total"
|
||
class="pagination">
|
||
</el-pagination>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 新增/编辑对话框 -->
|
||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px" append-to-body>
|
||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||
<el-form-item label="位置编码" prop="locationCode">
|
||
<el-input v-model="form.locationCode" placeholder="请输入位置编码" />
|
||
</el-form-item>
|
||
<el-form-item label="位置名称" prop="locationName">
|
||
<el-input v-model="form.locationName" placeholder="请输入位置名称" />
|
||
</el-form-item>
|
||
<el-form-item label="上级位置" prop="parentId">
|
||
<el-cascader
|
||
v-model="form.parentId"
|
||
:options="locationTreeOptions"
|
||
:props="{
|
||
checkStrictly: true,
|
||
emitPath: false,
|
||
expandTrigger: 'hover',
|
||
value: 'id',
|
||
label: 'label'
|
||
}"
|
||
clearable
|
||
filterable
|
||
placeholder="请选择上级位置"
|
||
style="width: 100%">
|
||
</el-cascader>
|
||
</el-form-item>
|
||
<!-- <el-form-item label="层级编码" prop="levelCode">
|
||
<el-input v-model="form.levelCode" placeholder="请输入层级编码" />
|
||
</el-form-item> -->
|
||
<el-form-item label="状态" prop="status">
|
||
<el-radio-group v-model="form.status">
|
||
<el-radio label="1">启用</el-radio>
|
||
<el-radio label="0">禁用</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { listLocation, getLocation, addLocation, updateLocation, delLocation, enableLocation, disableLocation, getLocationTree, checkLocationInUse, getChildLocations, delLocationBatch, checkLocationCode } from '@/api/asset/location'
|
||
|
||
export default {
|
||
name: 'AssetLocation',
|
||
data() {
|
||
return {
|
||
// 遮罩层
|
||
loading: false,
|
||
// 总条数
|
||
total: 0,
|
||
// 位置列表
|
||
locationList: [],
|
||
// 位置树形数据
|
||
locationTree: [],
|
||
// 处理后的树形选项数据(用于级联选择器)
|
||
locationTreeOptions: [],
|
||
// 默认展开的节点
|
||
defaultExpandedKeys: [],
|
||
// 树形配置
|
||
defaultProps: {
|
||
children: 'children',
|
||
label: 'label'
|
||
},
|
||
// 弹出层标题
|
||
dialogTitle: '',
|
||
// 是否显示弹出层
|
||
dialogVisible: false,
|
||
// 查询参数
|
||
queryParams: {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
locationCode: undefined,
|
||
locationName: undefined,
|
||
status: undefined,
|
||
parentId: undefined
|
||
},
|
||
// 表单参数
|
||
form: {},
|
||
// 表单校验
|
||
rules: {
|
||
locationCode: [
|
||
{ required: true, message: '请输入位置编码', trigger: 'blur' },
|
||
{ min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
|
||
{ validator: this.validateLocationCode, trigger: 'blur' }
|
||
],
|
||
locationName: [
|
||
{ required: true, message: '请输入位置名称', trigger: 'blur' },
|
||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||
],
|
||
parentId: [
|
||
{ required: false, message: '请选择上级位置', trigger: 'change' }
|
||
],
|
||
remark: [
|
||
{ max: 200, message: '长度不能超过200个字符', trigger: 'blur' }
|
||
]
|
||
},
|
||
// 多选选中项
|
||
multipleSelection: []
|
||
}
|
||
},
|
||
created() {
|
||
this.getTree()
|
||
this.getList()
|
||
},
|
||
methods: {
|
||
/** 检验位置编码唯一性 */
|
||
validateLocationCode(rule, value, callback) {
|
||
if (value === '') {
|
||
callback()
|
||
return
|
||
}
|
||
checkLocationCode(this.form.id, value).then(res => {
|
||
if (res.code === '000000') {
|
||
if (res.data) {
|
||
callback()
|
||
} else {
|
||
callback(new Error('该位置编码已存在'))
|
||
}
|
||
} else {
|
||
callback()
|
||
}
|
||
}).catch(() => {
|
||
callback()
|
||
})
|
||
},
|
||
/** 获取位置树形结构 */
|
||
getTree() {
|
||
this.loading = true
|
||
const params = {
|
||
status: undefined // 获取所有状态的位置
|
||
}
|
||
getLocationTree(params).then(res => {
|
||
if (res.code === '000000') {
|
||
// 处理返回的树形数据,确保字段名称正确
|
||
this.locationTree = this.processTreeData(res.data)
|
||
|
||
// 准备级联选择器的数据源
|
||
this.locationTreeOptions = this.prepareTreeSelectOptions(this.locationTree)
|
||
|
||
// 如果之前已经有展开的节点,保持这些节点展开
|
||
// 否则只展开第一级有子节点的节点
|
||
if (!this.defaultExpandedKeys || this.defaultExpandedKeys.length === 0) {
|
||
this.defaultExpandedKeys = this.getFirstLevelKeys(this.locationTree)
|
||
}
|
||
|
||
// 强制刷新树组件
|
||
this.$nextTick(() => {
|
||
if (this.$refs.locationTree) {
|
||
this.$refs.locationTree.$forceUpdate()
|
||
}
|
||
})
|
||
} else {
|
||
this.$message.error(res.msg || '获取位置树失败')
|
||
}
|
||
this.loading = false
|
||
}).catch(error => {
|
||
console.error('获取位置树失败', error)
|
||
this.$message.error('系统错误,获取位置树失败')
|
||
this.loading = false
|
||
})
|
||
},
|
||
|
||
/** 获取第一级节点的key,仅展开有子节点的 */
|
||
getFirstLevelKeys(tree) {
|
||
if (!tree || !Array.isArray(tree)) return []
|
||
|
||
return tree
|
||
.filter(node => node.children && node.children.length > 0)
|
||
.map(node => node.id)
|
||
},
|
||
|
||
/** 获取所有节点key,用于全部展开 */
|
||
getExpandedKeys(tree, keys = []) {
|
||
for (const node of tree) {
|
||
if (node.children && node.children.length > 0) {
|
||
keys.push(node.id)
|
||
this.getExpandedKeys(node.children, keys)
|
||
}
|
||
}
|
||
return keys
|
||
},
|
||
|
||
/** 处理树形数据,确保字段名称正确 */
|
||
processTreeData(data) {
|
||
if (!data || !Array.isArray(data)) return []
|
||
|
||
const processNode = (node) => {
|
||
// 创建一个新对象,使用驼峰命名
|
||
const processedNode = {
|
||
id: node.id,
|
||
// 转换label,格式为"编码-名称"
|
||
label: `${node.code || ''}-${node.locationName || node.label || ''}`,
|
||
// 驼峰命名
|
||
locationName: node.locationName || node.label || '',
|
||
locationCode: node.code || '',
|
||
status: node.status || '1',
|
||
parentId: node.parentId || null,
|
||
levelCode: node.levelCode || '',
|
||
children: []
|
||
}
|
||
|
||
// 递归处理子节点
|
||
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
||
processedNode.children = node.children.map(child => processNode(child))
|
||
}
|
||
|
||
return processedNode
|
||
}
|
||
|
||
return data.map(item => processNode(item))
|
||
},
|
||
|
||
/** 准备级联选择器的数据源 */
|
||
prepareTreeSelectOptions(data) {
|
||
if (!data || !Array.isArray(data)) return []
|
||
|
||
// 创建一个无上级选项
|
||
const options = [{
|
||
id: '',
|
||
label: '无上级位置',
|
||
children: []
|
||
}]
|
||
|
||
// 添加所有位置节点
|
||
const cloneData = JSON.parse(JSON.stringify(data))
|
||
options.push(...cloneData)
|
||
|
||
return options
|
||
},
|
||
|
||
/** 转换下划线命名为驼峰命名 */
|
||
convertSnakeToCamel(list) {
|
||
if (!list || !Array.isArray(list)) return []
|
||
|
||
return list.map(item => {
|
||
return {
|
||
id: item.id,
|
||
locationCode: item.locationCode || '',
|
||
locationName: item.locationName || '',
|
||
parentId: item.parentId || null,
|
||
levelCode: item.levelCode || '',
|
||
status: item.status || '1',
|
||
remark: item.remark || '',
|
||
createTime: item.createTime || '',
|
||
createUserId: item.createUserId || '',
|
||
lastModUserId: item.lastModUserId || '',
|
||
lastModTime: item.lastModTime || ''
|
||
}
|
||
})
|
||
},
|
||
/** 查询位置列表 */
|
||
getList() {
|
||
this.loading = true
|
||
listLocation(this.queryParams).then(res => {
|
||
if (res.code === '000000') {
|
||
// 转换API返回数据结构为驼峰命名
|
||
this.locationList = this.convertSnakeToCamel(res.data.list)
|
||
this.total = res.data.total
|
||
} else {
|
||
this.$message.error(res.msg || '获取位置列表失败')
|
||
}
|
||
this.loading = false
|
||
}).catch(error => {
|
||
console.error('获取位置列表失败', error)
|
||
this.$message.error('系统错误,获取位置列表失败')
|
||
this.loading = false
|
||
})
|
||
},
|
||
/** 节点单击事件 */
|
||
handleNodeClick(data) {
|
||
this.queryParams.parentId = data.id
|
||
// 使用新的获取子位置API
|
||
this.loading = true
|
||
getChildLocations(data.id, {
|
||
pageNum: this.queryParams.pageNum,
|
||
pageSize: this.queryParams.pageSize
|
||
}).then(res => {
|
||
if (res.code === '000000') {
|
||
this.locationList = this.convertSnakeToCamel(res.data.list)
|
||
this.total = res.data.total
|
||
} else {
|
||
this.$message.error(res.msg || '获取子位置列表失败')
|
||
}
|
||
this.loading = false
|
||
}).catch(error => {
|
||
console.error('获取子位置列表失败', error)
|
||
this.$message.error('系统错误,获取子位置列表失败')
|
||
this.loading = false
|
||
})
|
||
},
|
||
/** 搜索按钮操作 */
|
||
handleQuery() {
|
||
this.queryParams.pageNum = 1
|
||
this.queryParams.parentId = undefined
|
||
this.getList()
|
||
},
|
||
/** 重置按钮操作 */
|
||
resetQuery() {
|
||
this.queryParams = {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
locationCode: undefined,
|
||
locationName: undefined,
|
||
status: undefined,
|
||
parentId: undefined
|
||
}
|
||
this.getList()
|
||
},
|
||
/** 新增按钮操作 */
|
||
handleAdd() {
|
||
this.dialogTitle = '新增位置'
|
||
this.form = {
|
||
locationCode: '',
|
||
locationName: '',
|
||
parentId: this.queryParams.parentId || '', // 如果当前有选中节点,则默认为父节点
|
||
levelCode: '',
|
||
status: '1',
|
||
remark: '',
|
||
createUserId: this.$store.getters.userId || ''
|
||
}
|
||
this.dialogVisible = true
|
||
this.$nextTick(() => {
|
||
if (this.$refs.form) {
|
||
this.$refs.form.clearValidate()
|
||
}
|
||
})
|
||
},
|
||
/** 修改按钮操作 */
|
||
handleEdit(row) {
|
||
const id = row.id
|
||
getLocation(id).then(res => {
|
||
if (res.code === '000000') {
|
||
// 将API响应数据映射到表单字段,使用驼峰命名
|
||
this.form = {
|
||
id: res.data.id,
|
||
locationCode: res.data.locationCode,
|
||
locationName: res.data.locationCode,
|
||
parentId: res.data.parentId || '',
|
||
levelCode: res.data.levelCode || '',
|
||
status: res.data.status,
|
||
remark: res.data.remark,
|
||
// 添加最后修改人
|
||
lastModUserId: this.$store.getters.userId || ''
|
||
}
|
||
|
||
this.dialogTitle = '编辑位置'
|
||
this.dialogVisible = true
|
||
// 重置表单验证
|
||
this.$nextTick(() => {
|
||
if (this.$refs.form) {
|
||
this.$refs.form.clearValidate()
|
||
}
|
||
})
|
||
} else {
|
||
this.$message.error(res.msg || '获取位置详情失败')
|
||
}
|
||
}).catch(error => {
|
||
console.error('获取位置详情失败', error)
|
||
this.$message.error('系统错误,获取位置详情失败')
|
||
})
|
||
},
|
||
/** 提交按钮 */
|
||
submitForm() {
|
||
this.$refs['form'].validate(valid => {
|
||
if (valid) {
|
||
// A. 构建提交数据,映射表单字段到API字段
|
||
const submitData = {
|
||
id: this.form.id,
|
||
locationCode: this.form.locationCode,
|
||
locationName: this.form.locationName,
|
||
parentId: this.form.parentId,
|
||
levelCode: this.form.levelCode,
|
||
status: this.form.status,
|
||
remark: this.form.remark
|
||
}
|
||
|
||
// B. 添加创建/修改用户信息
|
||
if (this.form.id) {
|
||
submitData.lastModUserId = this.form.lastModUserId || this.$store.getters.userId || ''
|
||
} else {
|
||
submitData.createUserId = this.form.createUserId || this.$store.getters.userId || ''
|
||
}
|
||
|
||
const method = this.form.id ? updateLocation : addLocation
|
||
method(submitData).then(res => {
|
||
if (res.code === '000000') {
|
||
this.$message.success('操作成功')
|
||
this.dialogVisible = false
|
||
|
||
// 重新获取树形结构,确保更新多级结构
|
||
this.getTree()
|
||
|
||
// 如果是新增子位置,更新当前列表
|
||
if (this.queryParams.parentId && !this.form.id) {
|
||
this.handleNodeClick({ id: this.queryParams.parentId })
|
||
} else {
|
||
this.getList()
|
||
}
|
||
} else {
|
||
this.$message.error(res.msg || '操作失败')
|
||
}
|
||
}).catch(error => {
|
||
console.error('提交表单失败', error)
|
||
this.$message.error('系统错误,提交失败')
|
||
})
|
||
}
|
||
})
|
||
},
|
||
/** 删除按钮操作 */
|
||
handleDelete(row) {
|
||
this.$confirm('是否确认删除该位置?', '警告', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
// 先检查位置是否被使用
|
||
checkLocationInUse(row.id).then(res => {
|
||
if (res.code === '000000' && res.data) {
|
||
this.$message.error('该位置已被使用,无法删除')
|
||
return
|
||
}
|
||
// 未被使用,执行删除操作
|
||
const lastModUserId = this.$store.getters.userId || ''
|
||
delLocation(row.id, lastModUserId).then(res => {
|
||
if (res.code === '000000') {
|
||
this.$message.success('删除成功')
|
||
// 重新获取树形结构,确保更新多级结构
|
||
this.getTree()
|
||
this.getList()
|
||
} else {
|
||
this.$message.error(res.msg || '删除失败')
|
||
}
|
||
}).catch(error => {
|
||
console.error('删除操作失败', error)
|
||
this.$message.error('系统错误,删除失败')
|
||
})
|
||
})
|
||
}).catch(() => {})
|
||
},
|
||
/** 状态修改按钮操作 */
|
||
handleStatusChange(row) {
|
||
const action = row.status === '1' ? '禁用' : '启用'
|
||
this.$confirm(`是否确认${action}该位置?`, '警告', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
// 获取当前用户ID
|
||
const lastModUserId = this.$store.getters.userId || ''
|
||
const method = row.status === '1' ? disableLocation : enableLocation
|
||
method(row.id, lastModUserId).then(res => {
|
||
if (res.code === '000000') {
|
||
this.$message.success(`${action}成功`)
|
||
// 状态变更后,可能会影响树的显示,所以也需要刷新树
|
||
this.getTree()
|
||
this.getList()
|
||
} else {
|
||
this.$message.error(res.msg || `${action}失败`)
|
||
}
|
||
}).catch(error => {
|
||
console.error(`${action}操作失败`, error)
|
||
this.$message.error(`系统错误,${action}失败`)
|
||
})
|
||
}).catch(() => {})
|
||
},
|
||
/** 分页大小改变 */
|
||
handleSizeChange(val) {
|
||
this.queryParams.pageSize = val
|
||
this.getList()
|
||
},
|
||
/** 分页页码改变 */
|
||
handleCurrentChange(val) {
|
||
this.queryParams.pageNum = val
|
||
this.getList()
|
||
},
|
||
/** 获取上级位置名称 */
|
||
getParentName(parentId) {
|
||
if (!parentId) return '无';
|
||
|
||
// 先在树形数据中查找
|
||
const findParentInTree = (tree, id) => {
|
||
for (const node of tree) {
|
||
if (node.id === id) {
|
||
return node.locationCode + '-' + node.locationName;
|
||
}
|
||
if (node.children && node.children.length > 0) {
|
||
const found = findParentInTree(node.children, id);
|
||
if (found) return found;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
|
||
const parentName = findParentInTree(this.locationTree, parentId);
|
||
if (parentName) return parentName;
|
||
|
||
// 如果在树中没找到,可能在列表数据中
|
||
const parent = this.locationList.find(item => item.id === parentId);
|
||
return parent ? (parent.locationCode + '-' + parent.locationName) : '未知';
|
||
},
|
||
/** 多选选中项改变 */
|
||
handleSelectionChange(val) {
|
||
this.multipleSelection = val;
|
||
},
|
||
/** 批量删除按钮操作 */
|
||
handleBatchDelete() {
|
||
if (this.multipleSelection.length === 0) {
|
||
this.$message.warning('请至少选择一个位置')
|
||
return
|
||
}
|
||
|
||
this.$confirm('是否确认删除选中的位置?', '警告', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
// 获取选中的位置ID列表
|
||
const selectedIds = this.multipleSelection.map(item => item.id)
|
||
// 获取当前用户ID
|
||
const lastModUserId = this.$store.getters.userId || ''
|
||
|
||
// 执行批量删除操作
|
||
this.loading = true
|
||
delLocationBatch(selectedIds, lastModUserId).then(res => {
|
||
if (res.code === '000000') {
|
||
this.$message.success('批量删除成功')
|
||
// 重新获取树形结构,确保更新多级结构
|
||
this.getTree()
|
||
this.getList()
|
||
} else {
|
||
this.$message.error(res.msg || '批量删除失败')
|
||
}
|
||
this.loading = false
|
||
}).catch(error => {
|
||
console.error('批量删除操作失败', error)
|
||
this.$message.error('系统错误,批量删除失败')
|
||
this.loading = false
|
||
})
|
||
}).catch(() => {})
|
||
},
|
||
/** 展开所有节点 */
|
||
expandAll() {
|
||
const allKeys = this.getExpandedKeys(this.locationTree)
|
||
this.defaultExpandedKeys = allKeys
|
||
this.$nextTick(() => {
|
||
if (this.$refs.locationTree) {
|
||
this.$refs.locationTree.$forceUpdate()
|
||
}
|
||
})
|
||
},
|
||
/** 收起所有节点 */
|
||
collapseAll() {
|
||
this.defaultExpandedKeys = []
|
||
this.$nextTick(() => {
|
||
if (this.$refs.locationTree) {
|
||
this.$refs.locationTree.$forceUpdate()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.app-container {
|
||
.tree-container {
|
||
background-color: #fff;
|
||
padding: 15px;
|
||
margin-bottom: 20px;
|
||
border-radius: 4px;
|
||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||
height: calc(100vh - 140px);
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.tree-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.tree-title {
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
color: #303133;
|
||
}
|
||
|
||
.tree-actions {
|
||
display: flex;
|
||
gap: 8px;
|
||
}
|
||
|
||
.tree-divider {
|
||
margin: 5px 0 15px;
|
||
}
|
||
|
||
.box-card {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.custom-tree-node {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
font-size: 14px;
|
||
padding-right: 8px;
|
||
}
|
||
|
||
.node-count {
|
||
font-size: 12px;
|
||
color: #909399;
|
||
margin-left: 5px;
|
||
}
|
||
|
||
.pagination {
|
||
margin-top: 15px;
|
||
text-align: right;
|
||
}
|
||
|
||
/* 让所有输入框和下拉框保持一致宽度 */
|
||
.el-input, .el-select, .el-textarea {
|
||
width: 100%;
|
||
}
|
||
|
||
/* 确保所有表单元素的高度和边距一致 */
|
||
::v-deep .el-form-item {
|
||
margin-bottom: 18px;
|
||
|
||
.el-form-item__content {
|
||
line-height: 36px;
|
||
}
|
||
}
|
||
|
||
/* 确保el-select和普通输入框宽度一致 */
|
||
::v-deep .el-select, ::v-deep .el-tree-select {
|
||
width: 100%;
|
||
}
|
||
|
||
/* 树形选择器样式优化 */
|
||
::v-deep .el-tree-select .el-select-dropdown__item {
|
||
height: auto;
|
||
padding: 0;
|
||
}
|
||
|
||
/* 树节点样式优化 */
|
||
::v-deep .el-tree-node__content {
|
||
height: 32px;
|
||
}
|
||
|
||
::v-deep .el-tree-node__expand-icon {
|
||
padding: 6px;
|
||
}
|
||
}
|
||
</style> |