web端-新增风采墙模块(工会信息传播与文化展示): 修复栏目管理下级栏目无法打开等问题;

This commit is contained in:
2026-07-30 16:59:50 +08:00
parent 5043cee747
commit b3406f8b00
3 changed files with 43 additions and 22 deletions
@@ -36,7 +36,9 @@ public class SpreadCategoryServiceImpl extends BaseServiceImpl<SpreadCategory> i
public List<NutMap> categoryTree(boolean visibleOnly) {
List<SpreadCategory> categories = listCategories(visibleOnly);
Map<String, NutMap> nodeMap = new LinkedHashMap<>();
Map<String, List<NutMap>> childrenMap = new LinkedHashMap<>();
for (SpreadCategory category : categories) {
List<NutMap> children = new ArrayList<>();
nodeMap.put(category.getId(), NutMap.NEW()
.addv("id", category.getId())
.addv("parentId", category.getParentId())
@@ -45,7 +47,8 @@ public class SpreadCategoryServiceImpl extends BaseServiceImpl<SpreadCategory> i
.addv("sortOrder", category.getSortOrder())
.addv("visible", category.getVisible())
.addv("slider", category.getSlider())
.addv("children", new ArrayList<>()));
.addv("children", children));
childrenMap.put(category.getId(), children);
}
List<NutMap> roots = new ArrayList<>();
for (NutMap node : nodeMap.values()) {
@@ -53,9 +56,16 @@ public class SpreadCategoryServiceImpl extends BaseServiceImpl<SpreadCategory> i
if ("0".equals(parentId) || !nodeMap.containsKey(parentId)) {
roots.add(node);
} else {
nodeMap.get(parentId).getList("children", NutMap.class).add(node);
// 直接向节点持有的原始集合追加,避免 NutMap 类型转换后子节点没有写回。
childrenMap.get(parentId).add(node);
}
}
// 叶子栏目不返回空 children,避免级联选择器误判为仍有下一级。
nodeMap.forEach((id, node) -> {
if (childrenMap.get(id).isEmpty()) {
node.remove("children");
}
});
return roots;
}
@@ -125,11 +135,9 @@ public class SpreadCategoryServiceImpl extends BaseServiceImpl<SpreadCategory> i
if (category == null || StrUtil.isBlank(category.getName())) {
throw new RuntimeException("栏目名称不能为空");
}
if (StrUtil.isBlank(category.getCode())) {
throw new RuntimeException("栏目编码不能为空");
}
category.setName(category.getName().trim());
category.setCode(category.getCode().trim());
// 参考模块不要求用户维护栏目编码,空值统一保存为 NULL。
category.setCode(StrUtil.isBlank(category.getCode()) ? null : category.getCode().trim());
category.setParentId(StrUtil.blankToDefault(category.getParentId(), "0"));
if (category.getId() != null && category.getId().equals(category.getParentId())) {
throw new RuntimeException("上级栏目不能选择自身");
@@ -146,17 +154,12 @@ public class SpreadCategoryServiceImpl extends BaseServiceImpl<SpreadCategory> i
Cnd nameCnd = Cnd.where("name", "=", category.getName())
.and("parentId", "=", category.getParentId())
.and("delFlag", "=", false);
Cnd codeCnd = Cnd.where("code", "=", category.getCode()).and("delFlag", "=", false);
if (StrUtil.isNotBlank(excludeId)) {
nameCnd.and("id", "!=", excludeId);
codeCnd.and("id", "!=", excludeId);
}
if (count(nameCnd) > 0) {
throw new RuntimeException("同级栏目名称已存在");
}
if (count(codeCnd) > 0) {
throw new RuntimeException("栏目编码已存在");
}
}
private void applyDefaults(SpreadCategory category) {
+1 -1
View File
@@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS `spread_category` (
`id` varchar(32) NOT NULL COMMENT 'ID',
`parentId` varchar(32) NOT NULL DEFAULT '0' COMMENT '父栏目ID0表示顶级栏目',
`name` varchar(100) NOT NULL COMMENT '栏目名称',
`code` varchar(50) NOT NULL COMMENT '栏目编码',
`code` varchar(50) DEFAULT NULL COMMENT '栏目编码(兼容预置数据,页面无需维护)',
`sortOrder` int NOT NULL DEFAULT 255 COMMENT '排序,数值越小越靠前',
`visible` tinyint NOT NULL DEFAULT 1 COMMENT '是否可见:0否,1是',
`slider` tinyint NOT NULL DEFAULT 0 COMMENT '是否参与轮播:0否,1是',
@@ -6,11 +6,12 @@ layout("/layouts/platform.html"){
<el-card shadow="never">
<table-tool :app="this" label="风采墙栏目">
<el-button size="medium" type="primary" icon="el-icon-plus" @click="openAdd">新增栏目</el-button>
<el-button size="medium" icon="el-icon-s-unfold" @click="expandAll">展开全部</el-button>
<el-button size="medium" icon="el-icon-s-fold" @click="collapseAll">折叠全部</el-button>
</table-tool>
<el-table v-loading="loading" :data="tableData" border row-key="id"
<el-table ref="categoryTable" v-loading="loading" :data="tableData" border row-key="id"
:tree-props="{children: 'children'}" default-expand-all>
<el-table-column prop="name" label="栏目名称" min-width="220"></el-table-column>
<el-table-column prop="code" label="栏目编码" min-width="180"></el-table-column>
<el-table-column prop="sortOrder" label="排序" width="90" align="center"></el-table-column>
<el-table-column label="显示" width="100" align="center">
<template slot-scope="{row}">
@@ -46,9 +47,6 @@ layout("/layouts/platform.html"){
<el-form-item label="栏目名称" prop="name">
<el-input v-model.trim="formData.name" maxlength="100" show-word-limit></el-input>
</el-form-item>
<el-form-item label="栏目编码" prop="code">
<el-input v-model.trim="formData.code" maxlength="50" placeholder="例如:teacher_style"></el-input>
</el-form-item>
<el-form-item label="排序" prop="sortOrder">
<el-input-number v-model="formData.sortOrder" :min="0" :max="9999" style="width: 100%"></el-input-number>
</el-form-item>
@@ -88,10 +86,6 @@ layout("/layouts/platform.html"){
rules: {
parentId: [{required: true, message: "请选择上级栏目", trigger: "change"}],
name: [{required: true, message: "请输入栏目名称", trigger: "blur"}],
code: [
{required: true, message: "请输入栏目编码", trigger: "blur"},
{pattern: /^[A-Za-z][A-Za-z0-9_-]*$/, message: "编码须以字母开头,仅支持字母、数字、下划线和短横线", trigger: "blur"}
],
sortOrder: [{required: true, message: "请输入排序", trigger: "change"}]
}
}
@@ -104,6 +98,8 @@ layout("/layouts/platform.html"){
if (resp.code === 0) {
this.tableData = resp.data || []
this.rootOptions = (resp.data || []).slice()
// 栏目数据为异步加载,赋值后显式展开,避免组件只展示顶级栏目。
this.$nextTick(this.expandAll)
} else {
this.$message.warning(resp.msg)
}
@@ -112,7 +108,7 @@ layout("/layouts/platform.html"){
// 构造新增栏目默认值。
openAdd() {
this.dialogTitle = "新增栏目"
this.formData = {parentId: "0", name: "", code: "", sortOrder: 255, visible: 1, slider: 0}
this.formData = {parentId: "0", name: "", sortOrder: 255, visible: 1, slider: 0}
this.dialogVisible = true
this.$nextTick(() => this.$refs.categoryForm && this.$refs.categoryForm.clearValidate())
},
@@ -124,6 +120,28 @@ layout("/layouts/platform.html"){
this.dialogVisible = true
this.$nextTick(() => this.$refs.categoryForm && this.$refs.categoryForm.clearValidate())
},
// 展开当前栏目树中的全部父级栏目。
expandAll() {
this.setAllExpanded(true)
},
// 折叠当前栏目树中的全部父级栏目。
collapseAll() {
this.setAllExpanded(false)
},
// Element UI 异步树表格需要逐行设置展开状态。
setAllExpanded(expanded) {
const table = this.$refs.categoryTable
if (!table) return
const walk = rows => {
(rows || []).forEach(row => {
if (row.children && row.children.length) {
table.toggleRowExpansion(row, expanded)
walk(row.children)
}
})
}
walk(this.tableData)
},
// 校验后调用新增或编辑接口。
submit() {
this.$refs.categoryForm.validate(valid => {