如何开发自定义列表界面-使用bos_treelist构造左树右表列表界面原创
金蝶云社区-丨Nick丨
丨Nick丨
14人赞赏了该文章 4142次浏览 未经作者许可,禁止转载编辑于2022年08月05日 15:51:45
封面

关键词:单据列表、树形控件

一、需求

物品代购单

二、思路与方案

代购单中含有一个渠道分类,类似京东(电商)、沃尔玛(线下)、米国代购(跨境)等渠道

左树用于记录层分类,右侧展示单据列表,并且可以按照左树点击过滤单据数据

三、实现过程

  1. 新建分组基础资料(kdec_channel) - 采购渠道 :用于维护代购的渠道

  2. 新建基础资料(:kdec_channel_type) - 采购渠道分类 :用于维护采购渠道的分组,使其具有层级关系

  3. 新建单据 (kdec_demo1111tree)- 代购单 :记录代购数据

  4. 维护渠道以及渠道分类

    image.pngimage.png

  5. 在代购单中添加基础资料,绑定渠道,用于记录分组

    image.png

  6. 因为我们要展示树形列表,所以我们要将模板改为bos_treelist,但是注意我们不能直接预览,因为这是单据列表并未实现树形结构,顾我们要在插件中手动构建左树

    image.png

  7. 插件要继承StandardTreeListPlugin 否则无法使用树形列表模板 (extends StandardTreeListPlugin)

  8. 在afterCreateNewData事件中构造数据


  9. /**
    	 * 构造数据
    	 */
    	private void constructorData(TreeView tv1) {
    		// final String rootId = "0"; // 根节点id
    		// TreeNode rootNode = new TreeNode(null, rootId, "根节点", true);
    		// rootNode.setIsOpened(true); // 设置默认展开
    		TreeNode rootNode = this.getTreeModel().getRoot();
    		String rootId = rootNode.getId();
    		// 查出分组数据
    		DynamicObjectCollection types = QueryServiceHelper.query("kdec_channel_type", "Id,name", null);
    		// 查出渠道数据
    		DynamicObjectCollection channels = QueryServiceHelper.query("kdec_channel", "Id,name,group.Id", null);
    		//按照分类分组
    		Map<String, List<DynamicObject>> datatypeMap = channels.stream()
    				.collect(Collectors.groupingBy(it -> it.getString("group.Id")));
    		for (DynamicObject type : types) {//构建树节点
    			// 构造一级子节点
    			String typeId = type.getString("Id");
    			TreeNode tn1 = new TreeNode(rootId, typeId, type.getString("name"), true);
    			tn1.setIsOpened(true);
    			tn1.setColor("red"); // 设置节点文字颜色
    			List<DynamicObject> channelsByType = datatypeMap.get(type.getString("Id"));
    			for (DynamicObject channel : channelsByType) {
    				// 构造二级子节点
    				String channelId = channel.getString("Id");
    				TreeNode tn2 = new TreeNode(typeId, channelId, channel.getString("name"), false);
    				tn1.addChild(tn2);
    			}
    			rootNode.addChild(tn1);
    		}
    
    		// tv1.addNode(rootNode);
    		this.getTreeModel().setRoot(rootNode);//将树节点加到树模型
    		// this.getTreeModel().getRoot().addChild(rootNode);
    	}
  10. 这时候预览就可以看到效果了,但是我们还要实现点击树节点对右侧数据过滤刷新

    image.png

  11. 我们要实现TreeNodeClickListener (TreeNodeClickListener)并做监听(固定的树标识为treeview,模板自带)


  12. @Override
    	public void registerListener(EventObject e) {
    		super.registerListener(e);
    		TreeView tv1 = this.getView().getControl("treeview");
    		tv1.addTreeNodeClickListener(this);
    	}
  13. 在点击事件中默认都写对列表的刷新,这里会触发setfilter方法,所有的过滤都在这个方法实现,不要在其他位置添加过滤,统一由刷新去触发过滤设置

  14. 在setfilter中获取聚焦树节点,获取节点nodeId,因为在构建的时候是将主键设置为nodeId的所以直接可以将其添加为过滤,因为节点可能是渠道分类或渠道,所以书写如下


  15. @Override
    	public void treeNodeClick(TreeNodeEvent e) {
    		super.treeNodeClick(e);
    		BillList billList = this.getControl("billlistap");
    		billList.refresh();
    	}
    
    	@Override
    	public void setFilter(SetFilterEvent e) {
    		super.setFilter(e);
    		String nodeId = this.getTreeModel().getCurrentNodeId().toString();
    		if (this.getTreeModel().getRoot().getId().equals(nodeId)) {
    			return;
    		}
    		e.getQFilters().add(new QFilter("kdec_channel.id", QCP.equals, nodeId)
    				.or(new QFilter("kdec_channel.group.id", QCP.equals, nodeId)));
    
    	}
  16. 将插件注册到列表页,保存,

四、效果图

预览即可

image.png

    image.png

五、开发环境版本

4.0及以上

六、注意事项

1.要将模板改为bos_treelist,否者插件也报错,页面也渲染不出来树

2.不要在列表插件的其他方法setQfilter,所有的位置都可以调用refresh,统一在setFilter设置过滤

思考:

如何在新增数据时将左树数据代入到单据中并赋值渠道字段?

如何实现左树的工具栏中新增分类功能?


七、参考资料

开发平台

学习成长中心

插件开发—标准单据列表插件


赞 14