Browse Source

部门功能修改

dev-V1.0.1
庄锐波 4 months ago
parent
commit
d70babfebb
  1. 21
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java
  2. 83
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/vo/SysDeptMinVo.java
  3. 12
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/ISysDeptService.java
  4. 50
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java
  5. 9
      zdxt-web-client/zdxt-admin-plus-ui/src/api/system/dept/index.ts
  6. 1
      zdxt-web-client/zdxt-admin-plus-ui/src/api/system/dept/types.ts
  7. 52
      zdxt-web-client/zdxt-admin-plus-ui/src/views/system/dept/index-fold.vue

21
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java

@ -11,6 +11,7 @@ import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.SysDeptBo;
import org.dromara.system.domain.vo.SysDeptMinVo;
import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.service.ISysDeptService;
import org.dromara.system.service.ISysPostService;
@ -34,13 +35,13 @@ public class SysDeptController extends BaseController {
private final ISysPostService postService;
/**
* 获取部门列表
* 获取部门列表精简字段减少传输量
*/
@SaCheckPermission("system:dept:list")
@GetMapping("/list")
public R<List<SysDeptVo>> list(SysDeptBo dept) {
public R<List<SysDeptMinVo>> list(SysDeptBo dept) {
List<SysDeptVo> depts = deptService.selectDeptList(dept);
return R.ok(depts);
return R.ok(depts.stream().map(SysDeptMinVo::from).toList());
}
/**
@ -143,4 +144,18 @@ public class SysDeptController extends BaseController {
return R.ok(deptService.selectDeptByIds(deptIds == null ? null : List.of(deptIds)));
}
/**
* 搜索部门列表含祖级节点补全
* <p>
* 用于前端搜索场景搜索匹配的部门并自动补全其所有祖级节点
* 保证前端能构建从根节点到匹配节点的完整树路径
* </p>
*/
@SaCheckPermission("system:dept:list")
@GetMapping("/list/search")
public R<List<SysDeptMinVo>> searchList(SysDeptBo dept) {
List<SysDeptVo> depts = deptService.selectDeptListWithAncestors(dept);
return R.ok(depts.stream().map(SysDeptMinVo::from).toList());
}
}

83
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/domain/vo/SysDeptMinVo.java

@ -0,0 +1,83 @@
package org.dromara.system.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 部门精简视图对象用于列表接口减少传输数据量
* <p>
* 相比 SysDeptVo 去掉了: creditcode, deptCategory, leader, phone, email, createTime, zzDisplayPath
* </p>
*
* @author system
*/
@Data
public class SysDeptMinVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 部门id
*/
private String deptId;
/**
* 父部门id
*/
private String parentId;
/**
* 父部门名称
*/
private String parentName;
/**
* 祖级列表
*/
private String ancestors;
/**
* 部门名称
*/
private String deptName;
/**
* 显示顺序
*/
private Integer orderNum;
/**
* 负责人
*/
private String leaderName;
/**
* 部门状态0正常 1停用
*/
private String status;
/**
* 区域标识
*/
private Integer zone;
/**
* SysDeptVo 转换
*/
public static SysDeptMinVo from(SysDeptVo vo) {
SysDeptMinVo min = new SysDeptMinVo();
min.setDeptId(vo.getDeptId());
min.setParentId(vo.getParentId());
min.setParentName(vo.getParentName());
min.setAncestors(vo.getAncestors());
min.setDeptName(vo.getDeptName());
min.setOrderNum(vo.getOrderNum());
min.setLeaderName(vo.getLeaderName());
min.setStatus(vo.getStatus());
min.setZone(vo.getZone());
return min;
}
}

12
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/ISysDeptService.java

@ -176,4 +176,16 @@ public interface ISysDeptService {
SysDeptVo iterationDeptParentToBureau(String deptId);
List<SysDeptVo> selectDeptByZone(SysDeptBo dept1);
/**
* 搜索部门并补全祖级节点
* <p>
* 根据条件搜索匹配的部门同时通过 ancestors 字段回溯补全所有祖级节点
* 确保前端能构建完整的树路径
* </p>
*
* @param dept 部门查询条件
* @return 匹配部门 + 祖级部门的合并列表
*/
List<SysDeptVo> selectDeptListWithAncestors(SysDeptBo dept);
}

50
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java

@ -663,4 +663,54 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
return baseMapper.selectDeptList(lqw);
}
/**
* 搜索部门并补全祖级节点
* <p>
* 先按条件搜索匹配部门再从匹配结果的 ancestors 字段中提取所有祖级 ID
* 一次性补查祖级部门合并后返回完整的树路径数据
* </p>
*/
@Override
public List<SysDeptVo> selectDeptListWithAncestors(SysDeptBo dept) {
LambdaQueryWrapper<SysDept> lqw = buildQueryWrapper(dept);
List<SysDeptVo> matchedDepts = new ArrayList<>(baseMapper.selectDeptList(lqw));
if (CollUtil.isEmpty(matchedDepts)) {
return matchedDepts;
}
// 收集已匹配的部门 ID
Set<String> matchedIds = matchedDepts.stream()
.map(SysDeptVo::getDeptId)
.collect(Collectors.toSet());
// 从 ancestors 字段提取需要补查的祖级 ID
Set<String> ancestorIds = new HashSet<>();
for (SysDeptVo d : matchedDepts) {
if (StringUtils.isNotBlank(d.getAncestors())) {
for (String id : StringUtils.splitList(d.getAncestors())) {
if (!"0".equals(id) && !matchedIds.contains(id)) {
ancestorIds.add(id);
}
}
}
}
// 补查祖级部门(@TableLogic 自动过滤已删除记录)
if (CollUtil.isNotEmpty(ancestorIds)) {
List<SysDeptVo> ancestors = baseMapper.selectVoList(
new LambdaQueryWrapper<SysDept>()
.in(SysDept::getDeptId, ancestorIds)
);
matchedDepts.addAll(ancestors);
}
// 按 parentId → orderNum 排序,便于前端构建树
matchedDepts.sort(Comparator
.comparing(SysDeptVo::getParentId, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(SysDeptVo::getOrderNum, Comparator.nullsLast(Comparator.naturalOrder())));
return matchedDepts;
}
}

9
zdxt-web-client/zdxt-admin-plus-ui/src/api/system/dept/index.ts

@ -11,6 +11,15 @@ export const listDept = (query?: DeptQuery) => {
});
};
// 搜索部门列表(含祖级节点补全)
export const searchDeptList = (query?: DeptQuery) => {
return request({
url: '/system/dept/list/search',
method: 'get',
params: query
});
};
/**
* deptIds查询部门
* @param deptIds

1
zdxt-web-client/zdxt-admin-plus-ui/src/api/system/dept/types.ts

@ -26,6 +26,7 @@ export interface DeptVO extends BaseEntity {
delFlag: string;
ancestors: string;
menuId: string | number;
hasChildren?: boolean;
}
/**

52
zdxt-web-client/zdxt-admin-plus-ui/src/views/system/dept/index-fold.vue

@ -44,24 +44,19 @@
:data="deptList"
row-key="deptId"
border
lazy
:load="loadChildren"
:lazy="!isSearchMode"
:load="isSearchMode ? undefined : loadChildren"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
:default-expand-all="isSearchMode"
>
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
<el-table-column prop="deptName" label="部门名称"></el-table-column>
<el-table-column prop="deptCategory" align="center" label="类别编码" width="200"></el-table-column>
<el-table-column prop="orderNum" align="center" label="排序" width="200"></el-table-column>
<el-table-column prop="status" align="center" label="状态" width="100">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="200">
<template #default="scope">
<span>{{ proxy.parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column fixed="right" align="center" label="操作">
<el-table-column fixed="right" align="center" label="操作" width="260">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button v-hasPermi="['system:dept:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
@ -144,7 +139,7 @@
</template>
<script setup name="Dept" lang="ts">
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from '@/api/system/dept';
import { listDept, searchDeptList, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from '@/api/system/dept';
import { DeptForm, DeptQuery, DeptVO } from '@/api/system/dept/types';
import { UserVO } from '@/api/system/user/types';
import { listUserByDeptId } from '@/api/system/user';
@ -166,6 +161,7 @@ const isExpandAll = ref(false);
const deptUserList = ref<UserVO[]>([]);
const childrenMap = ref<Map<string, DeptVO[]>>(new Map());
const tableKey = ref(0);
const isSearchMode = ref(false);
const dialog = reactive<DialogOption>({
visible: false,
@ -208,13 +204,31 @@ const data = reactive<PageData<DeptForm, DeptQuery>>(initData);
const { queryParams, form, rules } = toRefs<PageData<DeptForm, DeptQuery>>(data);
/** 判断是否有搜索条件 */
const hasSearchParams = () => {
const { deptName, deptCategory, status } = queryParams.value;
return !!(deptName || deptCategory || status);
};
/** 查询部门列表 */
const getList = async () => {
loading.value = true;
const res = await listDept(queryParams.value);
const searchMode = hasSearchParams();
isSearchMode.value = searchMode;
tableKey.value++;
await nextTick();
if (searchMode) {
//
const res = await searchDeptList(queryParams.value);
const tree = proxy?.handleTree<DeptVO>(res.data, 'deptId');
deptList.value = tree || [];
} else {
//
const res = await listDept(queryParams.value);
buildLazyData(res.data);
}
loading.value = false;
};
@ -272,12 +286,24 @@ const resetQuery = () => {
handleQuery();
};
/** 展开/折叠操作(仅切换根节点) */
/** 展开/折叠操作 */
const handleToggleExpandAll = () => {
isExpandAll.value = !isExpandAll.value;
if (isSearchMode.value) {
// /
const toggleAll = (data: DeptVO[], status: boolean) => {
data.forEach((item) => {
deptTableRef.value?.toggleRowExpansion(item, status);
if (item.children && item.children.length > 0) toggleAll(item.children, status);
});
};
toggleAll(deptList.value, isExpandAll.value);
} else {
//
deptList.value.forEach((item) => {
deptTableRef.value?.toggleRowExpansion(item, isExpandAll.value);
});
}
};
/** 新增按钮操作 */

Loading…
Cancel
Save