如何开发自定义的左树右表F7列表选择界面原创
金蝶云社区-丨Nick丨
丨Nick丨
11人赞赏了该文章 3336次浏览 未经作者许可,禁止转载编辑于2022年04月16日 09:46:27

关键词:F7已选字段

一、需求

众所周知苍穹的f7是基础资料字段独有的一种展示形式,用于选择数据

但是有的时候我们不止想要选择基础资料,也想选择单据数据

或者有些数据不是结构化的需要拆分构建不好展示

甚至,有些数据根本不是存在数据表中的是凭空出现或者计算出来的

这时候我们还想弹出f7并且让用户选择,返回一些数据,那么我们就可以利用苍穹自己实现这个功能

二、思路与方案

首先我们可以看下页面如何设计

参考标准f7即可

image.png

三、实现过程

页面:标识:kdec_testf7andentry

数据因为存在不确定性,这里面我们可以用单据体承载数据,将锁定并且将选择模式改为列表,添加一些必要的控件

image.png

将页面设计一下既可开始实现逻辑,插件代码实现

插件:

先构建树 可以参考https://club.kdcloud.com/article/246958760772928000

1、通过数据源构建左树

        @Override
	public void afterCreateNewData(EventObject e) {
		super.afterCreateNewData(e);
		TreeView tv1 = this.getView().getControl("kdec_treeview");
		this.constructorData(tv1);
		this.loadEntryData(new QFilter("1", "=", "1"));
	}

	/**
	 * 构造数据
	 */
	private void constructorData(TreeView tv1) {
		final String rootId = "0"; // 根节点id
		TreeNode rootNode = new TreeNode(null, rootId, "根节点", true);
		rootNode.setIsOpened(true); // 设置默认展开
		// 查出分组数据
		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);
	}

2、构建单据体数据,我这里呢用的是单据的数据构建的,大家可以自己搞各类数据源渲染到字段上就行,这里可扩展性很广,可以加很多字段,只要能对应渲染好即可

        /**
	 * 加载单据体数据
	 */
	private void loadEntryData(QFilter qFilter) {
		DynamicObjectCollection entrys = this.getModel().getEntryEntity("kdec_entryentity");
		entrys.clear();
		DynamicObject[] datas = BusinessDataServiceHelper.load("kdec_demo1111tree", "Id,billno,kdec_channel.name",
				qFilter.toArray());
		for (DynamicObject data : datas) {
			DynamicObject entry = new DynamicObject(entrys.getDynamicObjectType());
			entry.set("kdec_zj", data.getPkValue());
			entry.set("kdec_number", data.getString("billno"));
			entry.set("kdec_name", data.getString("kdec_channel.name"));
			entrys.add(entry);
		}
		this.getModel().updateCache();
		this.getModel().updateEntryCache(entrys);
		this.getView().updateView("kdec_entryentity");
	}

3、监听f7控件的事件为了联动勾选功能,并且监听单据体行点击,定义一个全局集合为的是记录f7数据,这里我只是找了简单方式实现,推荐大家使用页面缓存,或者redis记录集合,亦或者在页面加个隐藏的单据体记录,这样就不用考虑清理机制,还有就是数据隔离的问题

public class EntryTreeF7CusPlugin extends AbstractFormPlugin implements TreeNodeClickListener,
		F7SelectedListRemoveListener, F7SelectedListSortListener, RowClickEventListener {

	private static List<ValueTextItem> valueTextItems = new ArrayList<>();

	@Override
	public void registerListener(EventObject e) {
		super.registerListener(e);
		TreeView tv1 = this.getView().getControl("kdec_treeview");
		tv1.addTreeNodeClickListener(this);
		F7SelectedList f7SelectedList = this.getControl("kdec_f7selectedlistap");
		f7SelectedList.addF7SelectedListRemoveListener(this);
		f7SelectedList.addF7SelectedListRemoveAllListener(this);
		f7SelectedList.addF7SelectedListSortListener(this);
		EntryGrid entryGrid = this.getControl("kdec_entryentity");
		entryGrid.addRowClickListener(this);
	}

	@Override
	public void afterCreateNewData(EventObject e) {
		super.afterCreateNewData(e);
		TreeView tv1 = this.getView().getControl("kdec_treeview");
		this.constructorData(tv1);
		this.loadEntryData(new QFilter("1", "=", "1"));
	}

4、treeNodeClick 树点击实现数据的重新加载,还有一些默认勾选的数据,由f7控件带过来

@Override
	public void treeNodeClick(TreeNodeEvent e) {
		if (e.getNodeId().equals("0")) {
			this.loadEntryData(new QFilter("1", "=", "1"));
		} else {
			this.loadEntryData(new QFilter("kdec_channel.id", QCP.equals, e.getNodeId())
					.or(new QFilter("kdec_channel.group.id", QCP.equals, e.getNodeId())));
		}
		if (valueTextItems.size()>0) {
			selectDefaultRows();
		}
	}
private void selectDefaultRows() {
		EntryGrid entryGrid = this.getControl("kdec_entryentity");
		List<String> pks = (valueTextItems.stream().map(ValueTextItem::getValue)).collect(Collectors.toList());
		DynamicObjectCollection entrys = this.getModel().getEntryEntity("kdec_entryentity");
		List<Integer>selectRows = new ArrayList<>();
		for (DynamicObject entry : entrys) {
			if (pks.contains(entry.getString("kdec_zj"))) {
				selectRows.add(entry.getInt("seq")-1);
			}
		}
		entryGrid.selectRows(selectRows.stream().mapToInt(Integer::valueOf).toArray(), 0);
	}

5、行点击里面实现赋值f7的功能

	@Override
	public void entryRowClick(RowClickEvent evt) {
		RowClickEventListener.super.entryRowClick(evt);
		DynamicObjectCollection entrys = this.getModel().getEntryEntity("kdec_entryentity");
		EntryGrid entryGrid = this.getControl("kdec_entryentity");
		F7SelectedList f7SelectedList = this.getControl("kdec_f7selectedlistap");
		int[] rows = entryGrid.getSelectRows();
		valueTextItems.clear();
		for (int i : rows) {
			ValueTextItem item = new ValueTextItem(entrys.get(i).getString("kdec_zj"),
					entrys.get(i).getString("kdec_number"));
			valueTextItems.add(item);
		}
		f7SelectedList.addItems(valueTextItems);
	}

6、移除f7数据实现单据体联动

@Override
	public void RemoveClick(F7SelectedListRemoveEvent arg0) {
		EntryGrid entryGrid = this.getControl("kdec_entryentity");
		if (arg0.getParam() == null) {// 清空
			entryGrid.clearEntryState();
		} else {
			String pk = (String) arg0.getParam();
			DynamicObjectCollection entrys = this.getModel().getEntryEntity("kdec_entryentity");
			for (DynamicObject entry : entrys) {
				if (entry.getString("kdec_zj").equals(pk)) {
					List<Integer> rows = Arrays.stream(entryGrid.getSelectRows()).boxed().collect(Collectors.toList());
					rows = rows.stream().filter(e -> (entry.getInt("seq") - 1) != e).collect(Collectors.toList());
					entryGrid.selectRows(rows.stream().mapToInt(Integer::valueOf).toArray(), 0);
					break;
				}
			}
		}
	}

7、清除变量集合

@Override
	public void beforeClosed(BeforeClosedEvent e) {
		super.beforeClosed(e);
		valueTextItems.clear();
	}

四、效果图

image.png

五、开发环境版本

4.0及以上

六、注意事项

主要是数据联动的功能,因为f7不具备get数据集的功能,所以要自己记录

通过主键等字段确定唯一性


七、参考资料

开发平台

学习成长中心

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



赞 11