编辑事件响应机制

NC65中提供了关于编辑事件的多个抽象类,按表单结构和编辑前后划分为4类,外加新增和组织变更事件,一共是6种响应事件,分别为:

  • 表头表尾编辑前事件 CardHeadTailBeforeEditEvent
  • 表头表尾编辑后事件 CardHeadTailAfterEditEvent
  • 表体编辑前事件 CardBodyBeforeEditEvent
  • 表体编辑后事件 CardBodyAfterEditEvent
  • 新增事件 AddEvent
  • 组织变更事件 OrgChangedEvent

理解这样的事件划分还要理解表头表尾和表体的划分机制。在NC系统中,我们打开“模板设置-集团”,随意打开一个单据模板就可以发现模板被分为三个部分:表头、表体和表尾。其中,表头和表尾的许多事件是被视为一个项目解决的,表体则是作为一个单独的项目进行处理。

编写相应事件均需编写事件类并注册相应的事件XML。

编辑事件开发实践

0. 需求分析

在参照开发的文章中,我提到了编辑事件相应的需求,这个需求是这样的:在NC单据的表头中存在一个仓库字段,我们需要使用该字段过滤表体参照当中的数据。即当表头选取为“A仓库”时,参照中仅包含A仓库的物料。

实现这个需求我们可以考虑两种方式:

  1. 表头仓库字段编辑后更新参照中的物料;
  2. 点击表体参照编辑前获取仓库字段中的值;

两种方式都可以,但很显然,在点击参照前去获取值是更容易的操作,也更符合我们“找仓库 -> 找物料”的线性逻辑。所以我们选择开发一个表体编辑前事件来实现这个需求。

完成需求分析后,应当定位到需求功能所在的模块和包,在指定包下创建编辑事件代码。若原来的模块下没有包括编辑事件handler的包,则需自行创建。

1. 事件代码开发

编写编辑事件均需实现IAppEventHandler接口,该接口定义了处理特定事件的方法,然后须要重写handleAppEvent方法,在这里编写具体的业务逻辑。

package nc.ui.ic.m4k.ace.handler;

import nc.ui.pub.beans.UIRefPane;
import nc.ui.pub.bill.BillCardPanel;
import nc.ui.pubapp.uif2app.event.IAppEventHandler; 
import nc.ui.pubapp.uif2app.event.card.CardBodyBeforeEditEvent;
import nc.ui.pubapp.uif2app.view.ShowUpableBillForm;

// 单据表体字段编辑前事件处理类
public class AceBodyBeforeEditHandler implements IAppEventHandler<CardBodyBeforeEditEvent> {

    private ShowUpableBillForm billForm;

    public void setBillForm(ShowUpableBillForm billForm) {
        this.billForm = billForm;
    }

    // 实现IAppEventHandler接口中的handleAppEvent方法,用于处理表体编辑前的事件
    @Override
    public void handleAppEvent(CardBodyBeforeEditEvent event) {
        // 获取当前编辑的BillCardPanel
        BillCardPanel currentPanel = event.getBillCardPanel();
        // 获取当前编辑的字段名
        String key = event.getKey();
        
        // 判断是否是我们要处理的字段(jc_view_allstore)
        if (key.equals("jc_view_allstore")) {
            // 获取表头中的仓库字段值
            String wareHouse = event.getBillCardPanel().getHeadItem("cwarehouseid").getValue();
            // 获取当前编辑字段的UIRefPane组件
            UIRefPane refPanel = (UIRefPane)currentPanel.getBodyItem("jc_view_allstore").getComponent();
            // 在参照模型的过滤条件中添加仓库过滤,仅显示当前表头选择的仓库
            refPanel.getRefModel().addWherePart("and pk_warehouse = '" + wareHouse + "'");
        }
        
        // 设置事件处理结果为true,表示允许编辑操作继续进行
        event.setReturnValue(true);
    }
}

2. 注册事件代码

完成代码编写后,我们需要找到对应模块下的XML配置文件,一般在对应功能模块的一级包下,命名为xxx_config.xml。打开该文件后我们需要检索事件监听相关的部分关键词,若不存在相关代码则需要手动注册事件监听:

	<!-- 事件监听newadd -->
	<bean id="bmModelEventMediator" class="nc.ui.pubapp.uif2app.model.AppEventHandlerMediator">

加入一个编辑事件至少需要事件监听相关模块和自己编写的编辑事件,本例提供参考如下:

	<!-- 事件监听newadd -->
    <bean id="bmModelEventMediator" class="nc.ui.pubapp.uif2app.model.AppEventHandlerMediator">
        <property name="model" ref="icBizModel" />
        <property name="handlerGroup">
            <list>
                <!-- 表体字段编辑前事件 -->
                <bean class="nc.ui.pubapp.uif2app.event.EventHandlerGroup">
                    <property name="event" value="nc.ui.pubapp.uif2app.event.card.CardBodyBeforeEditEvent" />
                    <property name="handler">
                        <bean class="nc.ui.ic.m4k.ace.handler.AceBodyBeforeEditHandler" />
                    </property>
                </bean>
            </list>
        </property>
    </bean>

在完成XML注册后,记得在包资源管理器中右键该XML配置文件,选择“SpringXML to Java”将其转换为配置类,这是UAP开发提供的转换功能。

附:响应事件XML参考

注意:在向一个XML中注册新的事件监听类时,应当注意修改其中的<property name="model" ref="bmModel" />相关字段,参考其它部分解决的问题,与上下文保持一致,以避免类缺失或引用错误的问题。

	<!-- 事件监听newadd -->
	<bean id="bmModelEventMediator" class="nc.ui.pubapp.uif2app.model.AppEventHandlerMediator">
		<property name="model" ref="bmModel" />
		<property name="handlerGroup">
			<list>
				<!-- nc.ui.pubapp.uif2app.event.OrgChangedEvent -->
				<bean class="nc.ui.pubapp.uif2app.event.EventHandlerGroup">
					<property name="event"
						value="nc.ui.pubapp.uif2app.event.OrgChangedEvent" />
					<property name="handler">
						<bean class="nc.ui.hrwa.insurancedata.ace.handler.AceOrgChangeHandler">
							<property name="billForm" ref="billForm" />
						</bean>
					</property>
				</bean>
				<!-- nc.ui.pubapp.uif2app.event.billform.AddEvent -->
				<bean class="nc.ui.pubapp.uif2app.event.EventHandlerGroup">
					<property name="event"
						value="nc.ui.pubapp.uif2app.event.billform.AddEvent" />
					<property name="handler">
						<bean class="nc.ui.hrwa.insurancedata.ace.handler.AceAddHandler" />
					</property>
				</bean>

				<!-- 表头表尾字段编辑前事件 -->
				<bean class="nc.ui.pubapp.uif2app.event.EventHandlerGroup">
					<property name="event"
						value="nc.ui.pubapp.uif2app.event.card.CardHeadTailBeforeEditEvent" />
					<property name="handler">
						<bean
							class="nc.ui.hrwa.insurancedata.ace.handler.AceHeadTailBeforeEditHandler" />
					</property>
				</bean>

				<!-- 表头表尾字段编辑后事件 -->
				<bean class="nc.ui.pubapp.uif2app.event.EventHandlerGroup">
					<property name="event"
						value="nc.ui.pubapp.uif2app.event.card.CardHeadTailAfterEditEvent" />
					<property name="handler">
						<bean
							class="nc.ui.hrwa.insurancedata.ace.handler.AceHeadTailAfterEditHandler">
						</bean>
					</property>
				</bean>

				<!-- 表体编辑后事件 -->
				<bean class="nc.ui.pubapp.uif2app.event.EventHandlerGroup">
					<property name="event"
						value="nc.ui.pubapp.uif2app.event.card.CardBodyAfterEditEvent" />
					<property name="handler">
						<bean
							class="nc.ui.hrwa.insurancedata.ace.handler.AceCardBodyAfterEditHandler">
							<property name="billForm" ref="billForm" />
						</bean>
					</property>
				</bean>
				<!-- 表体编辑前事件 -->
				<bean class="nc.ui.pubapp.uif2app.event.EventHandlerGroup">
					<property name="event"
						value="nc.ui.pubapp.uif2app.event.card.CardBodyBeforeEditEvent" />
					<property name="handler">
						<bean
							class="nc.ui.hrwa.insurancedata.ace.handler.AceCardBodyBeforeEditHandler">
							<property name="billForm" ref="billForm" />
						</bean>
					</property>
				</bean>
			</list>
		</property>
	</bean>

参考阅读: