JeecgBoot高级查询中部门组件的配置与使用技巧
还在为复杂的组织架构查询而烦恼?面对多层级部门树形结构,如何在高级查询中精准筛选数据?JeecgBoot的部门选择组件(JSelectDept)提供了完美的解决方案!本文将深入解析部门组件在高级查询中的应用技巧,助你轻松驾驭企业级数据筛选。
📋 读完本文你将掌握
- JSelectDept组件核心配置参数详解
- 高级查询中部门筛选的多种实现方式
- 部门树形数据的异步加载与性能优化
- 多选模式下的数据处理技巧
- 实际业务场景中的最佳实践案例
🔧 JSelectDept组件核心配置
基础属性配置
<template>
<j-select-dept
v-model:value="formData.department"
:multiple="true"
placeholder="请选择部门"
:disabled="isDisabled"
@change="handleDepartmentChange"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const formData = ref({
department: [] // 支持字符串或数组格式
});
const handleDepartmentChange = (value) => {
console.log('选中的部门:', value);
};
</script>
关键配置参数说明
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | String/Array | - | 绑定值,支持逗号分隔字符串或数组 |
multiple | Boolean | true | 是否允许多选 |
disabled | Boolean | false | 是否禁用组件 |
placeholder | String | '请选择' | 占位提示文本 |
🎯 高级查询中的部门筛选实现
方案一:基础表单集成
<template>
<a-form :model="queryForm" layout="inline">
<a-form-item label="部门筛选">
<j-select-dept
v-model:value="queryForm.departIds"
:multiple="true"
placeholder="选择查询部门"
/>
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSearch">查询</a-button>
</a-form-item>
</a-form>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const queryForm = ref({
departIds: [] // 部门ID数组
});
const handleSearch = () => {
// 构建查询参数
const params = {
...queryForm.value,
// 其他查询条件
};
// 执行查询操作
fetchData(params);
};
</script>
方案二:动态条件构建
<template>
<advanced-query
:conditions="queryConditions"
@change="handleConditionChange"
>
<template #department>
<j-select-dept
v-model:value="departmentValue"
@change="updateDepartmentCondition"
/>
</template>
</advanced-query>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const departmentValue = ref([]);
const queryConditions = ref([]);
const updateDepartmentCondition = (value) => {
// 更新查询条件
const condition = {
field: 'department_id',
operator: 'in',
value: value.join(',')
};
// 替换或添加部门条件
const index = queryConditions.value.findIndex(c => c.field === 'department_id');
if (index > -1) {
queryConditions.value[index] = condition;
} else {
queryConditions.value.push(condition);
}
};
</script>
🌳 部门树形数据处理
异步加载优化
数据格式转换
// 部门数据转换工具函数
const transformDepartmentData = (rawData: any[]) => {
return rawData.map(dept => ({
key: dept.id,
title: dept.departName,
value: dept.id,
isLeaf: !dept.hasChildren,
children: dept.children ? transformDepartmentData(dept.children) : []
}));
};
// 使用示例
const loadDepartmentTree = async () => {
try {
const response = await api.getDepartmentTree();
const treeData = transformDepartmentData(response.data);
return treeData;
} catch (error) {
console.error('加载部门树失败:', error);
return [];
}
};
⚡ 性能优化技巧
懒加载策略
<template>
<j-select-dept
v-model:value="selectedDepartments"
:load-data="loadDepartmentChildren"
:tree-data="departmentTree"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const selectedDepartments = ref([]);
const departmentTree = ref([]);
const loadDepartmentChildren = async (treeNode) => {
const { dataRef } = treeNode;
if (dataRef.children && dataRef.children.length > 0) {
return;
}
try {
const children = await api.getDepartmentChildren(dataRef.key);
dataRef.children = children.map(child => ({
key: child.id,
title: child.name,
isLeaf: !child.hasChildren
}));
departmentTree.value = [...departmentTree.value];
} catch (error) {
console.error('加载子部门失败:', error);
}
};
</script>
数据缓存机制
// 部门数据缓存管理
class DepartmentCache {
private cache = new Map<string, any>();
private static instance: DepartmentCache;
static getInstance() {
if (!DepartmentCache.instance) {
DepartmentCache.instance = new DepartmentCache();
}
return DepartmentCache.instance;
}
// 获取部门数据
async getDepartmentTree(forceRefresh = false) {
const cacheKey = 'department_tree';
if (!forceRefresh && this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const data = await api.getDepartmentTree();
this.cache.set(cacheKey, data);
return data;
}
// 清空缓存
clearCache() {
this.cache.clear();
}
}
// 使用缓存
const departmentCache = DepartmentCache.getInstance();
const treeData = await departmentCache.getDepartmentTree();
🎨 多选模式高级应用
选择结果处理
<template>
<div>
<j-select-dept
v-model:value="selectedIds"
:multiple="true"
@select="handleSelect"
@deselect="handleDeselect"
/>
<div v-if="selectedDepartments.length > 0">
<h4>已选部门:</h4>
<a-tag
v-for="dept in selectedDepartments"
:key="dept.id"
closable
@close="removeDepartment(dept.id)"
>
{{ dept.name }}
</a-tag>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
const selectedIds = ref([]);
const selectedDepartments = ref([]);
// 监听选择变化
watch(selectedIds, async (newIds) => {
if (newIds.length === 0) {
selectedDepartments.value = [];
return;
}
// 获取部门详情
const details = await api.getDepartmentsByIds(newIds);
selectedDepartments.value = details;
});
const handleSelect = (selectedKeys, { selected, selectedNodes }) => {
console.log('选中部门:', selectedNodes);
};
const handleDeselect = (selectedKeys, { selected, selectedNodes }) => {
console.log('取消选中部门:', selectedNodes);
};
const removeDepartment = (id) => {
selectedIds.value = selectedIds.value.filter(item => item !== id);
};
</script>
选择限制策略
// 部门选择验证器
const validateDepartmentSelection = (selectedIds: string[], maxSelect: number = 5) => {
if (selectedIds.length > maxSelect) {
return {
valid: false,
message: `最多只能选择 ${maxSelect} 个部门`
};
}
// 检查是否包含禁用部门
const disabledDepartments = ['disabled_dept_1', 'disabled_dept_2'];
const hasDisabled = selectedIds.some(id => disabledDepartments.includes(id));
if (hasDisabled) {
return {
valid: false,
message: '不能选择禁用的部门'
};
}
return { valid: true };
};
// 在组件中使用
const handleSelectionChange = (value) => {
const validation = validateDepartmentSelection(value);
if (!validation.valid) {
message.error(validation.message);
// 回滚选择
return;
}
selectedIds.value = value;
};
🔍 实际业务场景应用
场景一:用户权限过滤
<template>
<div class="permission-filter">
<h3>按部门筛选用户权限</h3>
<j-select-dept
v-model:value="filterDepartments"
:multiple="true"
placeholder="选择要过滤的部门"
/>
<a-button
type="primary"
:disabled="!filterDepartments.length"
@click="applyFilter"
>
应用筛选
</a-button>
<a-table
:data-source="filteredUsers"
:loading="loading"
:pagination="pagination"
>
<a-table-column title="用户名" data-index="username" />
<a-table-column title="所属部门" data-index="departmentName" />
<a-table-column title="角色" data-index="roleName" />
</a-table>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
const filterDepartments = ref([]);
const allUsers = ref([]);
const loading = ref(false);
// 计算属性过滤用户
const filteredUsers = computed(() => {
if (filterDepartments.value.length === 0) {
return allUsers.value;
}
return allUsers.value.filter(user =>
filterDepartments.value.includes(user.departmentId)
);
});
const applyFilter = async () => {
loading.value = true;
try {
const response = await api.getUsersByDepartments(filterDepartments.value);
allUsers.value = response.data;
} catch (error) {
console.error('获取用户数据失败:', error);
} finally {
loading.value = false;
}
};
</script>
场景二:跨部门数据统计
<template>
<div class="cross-department-stats">
<div class="filter-section">
<j-select-dept
v-model:value="selectedDepartmentGroups"
:multiple="true"
placeholder="选择统计部门组"
/>
<a-range-picker v-model:value="dateRange" />
<a-button type="primary" @click="loadStatistics">生成报表</a-button>
</div>
<div class="stats-results">
<a-tabs v-model:activeKey="activeTab">
<a-tab-pane key="summary" tab="汇总统计">
<summary-chart :data="summaryData" />
</a-tab-pane>
<a-tab-pane key="detail" tab="明细数据">
<detail-table :data="detailData" />
</a-tab-pane>
</a-tabs>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const selectedDepartmentGroups = ref([]);
const dateRange = ref([]);
const summaryData = ref({});
const detailData = ref([]);
const activeTab = ref('summary');
const loadStatistics = async () => {
if (selectedDepartmentGroups.value.length === 0) {
message.warning('请至少选择一个部门');
return;
}
const params = {
departmentIds: selectedDepartmentGroups.value,
startDate: dateRange.value[0]?.format('YYYY-MM-DD'),
endDate: dateRange.value[1]?.format('YYYY-MM-DD')
};
try {
const [summaryRes, detailRes] = await Promise.all([
api.getDepartmentSummary(params),
api.getDepartmentDetail(params)
]);
summaryData.value = summaryRes.data;
detailData.value = detailRes.data;
} catch (error) {
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



