ofbiz学习——创建一个查询页面
来源:互联网 发布:淘宝店铺分类导航 编辑:程序博客网 时间:2024/06/06 04:46
创建一个查询页面,比如下面这个demo。
1. 分析界面的html源码。
右击查询按钮 ——》检查 弹出开发工具窗口,查看对应的html。
从上面的源码可以知道,该查找界面是通过component://common/widget/CommonScreens.xml#FindScreenDecorator这个装饰器界面实现的。
打开component://common/widget/CommonScreens.xml#FindScreenDecorator
<screen name="FindScreenDecorator"> <section> <widgets> <section> <condition> <if-empty field="titleProperty"/> </condition> <widgets> <container style="page-title"><label text="${title}"></label></container> </widgets> <fail-widgets> <container style="page-title"><label text="${uiLabelMap[titleProperty]}"></label></container> </fail-widgets> </section> <decorator-section-include name="menu-bar"/> <container style="clear"/> <screenlet id="searchOptions" name="findScreenlet" collapsible="true" title="${uiLabelMap.CommonSearchOptions}"> <container id="search-options"> <decorator-section-include name="search-options" /> </container> </screenlet> <screenlet padded="false"> <label style="h3" text="${uiLabelMap.CommonSearchResults}"/> <container id="search-results"> <decorator-section-include name="search-results"/> </container> </screenlet> </widgets> </section> </screen>
从该装饰器可以看到还需要实现的3个widgets:menu-bar,search-options,search-results。
2. 如何调用装饰器FindScreenDecorator的呢?
打开component://manufacturing/webapp/manufacturing/WEB-INF/controller.xml找到对uri请求/main的处理配置:
<request-map uri="main"> <security https="true" auth="true"/> <response name="success" type="view" value="main"/> </request-map> <view-map name="main" page="component://manufacturing/widget/manufacturing/JobshopScreens.xml#FindProductionRun" type="screen"/>打开component://manufacturing/widget/manufacturing/JobshopScreens.xml#FindProductionRun
<screen name="FindProductionRun"> <section> <actions> <set field="titleProperty" value="ManufacturingFindProductionRun"/> <set field="headerItem" value="jobshop"/> <set field="viewIndex" from-field="parameters.VIEW_INDEX" type="Integer"/> <property-to-field resource="widget" property="widget.form.defaultViewSize" field="viewSizeDefaultValue"/> <set field="viewSize" from-field="parameters.VIEW_SIZE" type="Integer" default-value="${viewSizeDefaultValue}"/> </actions> <widgets> <decorator-screen name="CommonManufacturingDecorator" location="${parameters.commonManufacturingDecoratorLocation}"> <decorator-section name="body"> <section> <widgets> <decorator-screen name="FindScreenDecorator" location="component://common/widget/CommonScreens.xml"> <decorator-section name="menu-bar"> <container style="button-bar"> <link target="CreateProductionRun" text="${uiLabelMap.ManufacturingCreateProductionRun}" style="buttontext create"/> </container> </decorator-section> <decorator-section name="search-options"> <include-form name="FindProductionRun" location="component://manufacturing/widget/manufacturing/ProductionRunForms.xml"/> </decorator-section> <decorator-section name="search-results"> <include-form name="ListFindProductionRun" location="component://manufacturing/widget/manufacturing/ProductionRunForms.xml"/> </decorator-section> </decorator-screen> </widgets> </section> </decorator-section> </decorator-screen> </widgets> </section> </screen>
上面可以看到对装饰器FindScreenDecorator的初始化。
3. 进一步分析装饰器FindScreenDecorator的3个具体实现。
3.1 分析menu-bar
<decorator-section name="menu-bar"><container style="button-bar"><link target="CreateProductionRun" text="${uiLabelMap.ManufacturingCreateProductionRun}" style="buttontext create"/></container></decorator-section>
菜单栏只包含一个按钮栏button-bar,而按钮栏包含一个链接(样式是按钮)link标签。点击后访问CreateProductionRun,按钮显示的文本查找ManufacturingUiLabels.xml的ManufacturingCreateProductionRun定义,如果语言选择中国,应该是 “新建一个生产运行”。
<property key="ManufacturingCreateProductionRun"> <value xml:lang="de">Produktionsauftrag erstellen</value> <value xml:lang="en">Create a Production Run</value> <value xml:lang="es">Crear orden de producción</value> <value xml:lang="fr">Création O.F.</value> <value xml:lang="it">Nuovo ordine di produzione</value> <value xml:lang="ja">生産実行を作成</value> <value xml:lang="pt-BR">Criar execução de produção</value> <value xml:lang="ro">Creare Comanda de Productie</value> <value xml:lang="th">สร้างการผลิตสินค้า</value> <value xml:lang="vi">Bắt đầu Chế tác lô hàng mới</value> <value xml:lang="zh">新建一个生产运行</value> <value xml:lang="zh-TW">新建一個生產運行</value> </property>
3.2 分析search-options
该场景主要是包括一个表单。表单的定义见component://manufacturing/widget/manufacturing/ProductionRunForms.xml<form name="FindProductionRun" target="FindProductionRun" title="" type="single" header-row-style="header-row" default-table-style="basic-table"> <field name="workEffortTypeId"><hidden value="PROD_ORDER_HEADER"/></field> <field name="workEffortId" title="${uiLabelMap.ManufacturingProductionRunId}"><text-find/></field> <field name="currentStatusId" title="${uiLabelMap.CommonStatus}"> <check all-checked="false"> <entity-options entity-name="StatusItem" key-field-name="statusId"> <entity-constraint name="statusTypeId" value="PRODUCTION_RUN"/> </entity-options> </check> </field> <field name="productId" title="${uiLabelMap.ProductProductId}"><lookup target-form-name="LookupProduct"/></field> <field name="workEffortName" title="${uiLabelMap.ManufacturingProductionRunName}"><text-find/></field> <field name="estimatedStartDate" title="${uiLabelMap.ManufacturingStartDate}"><date-find default-value="${nowTimestamp}"/></field> <field name="facilityId" title="${uiLabelMap.ProductFacilityId}"> <drop-down allow-empty="true"> <entity-options entity-name="Facility" key-field-name="facilityId" description="${facilityName} [${facilityId}]"> <!--<entity-constraint name="facilityTypeId" value="WAREHOUSE"/>--> </entity-options> </drop-down> </field> <field name="submitButton" title="${uiLabelMap.CommonFind}"><submit/></field> </form>
<field name="workEffortTypeId"><hidden value="PROD_ORDER_HEADER"/></field>该行代码表示解析一个隐藏字段,如:
<input type="hidden" name="workEffortTypeId" value="PROD_ORDER_HEADER" id="FindProductionRun_workEffortTypeId">
<field name="workEffortId" title="${uiLabelMap.ManufacturingProductionRunId}"><text-find/></field>该行代码就是实现如下效果:
其中<text-find/>标签应该是对应上图中那个下拉框选择,表示该文本是 包含,等于,为空,忽略大小写 等查找方式。
<field name="currentStatusId" title="${uiLabelMap.CommonStatus}"> <check all-checked="false"> <entity-options entity-name="StatusItem" key-field-name="statusId"> <entity-constraint name="statusTypeId" value="PRODUCTION_RUN"/> </entity-options> </check> </field>
这个demo界面的状态复选框选项。对check和entity-option标签不是很了解。所以猜测一下:
${uiLabelMap.CommonStatus}表示形式表单的左边的文本。
SELECT * FROM Status_Item WHERE status_type_id='PRODUCTION_RUN'实际上Status_Item表有个排序字段sequence_id,但根据demo显示结果来看似乎并没有使用。下面是查询结果:
下面这个控件是就牛了,实现了2个功能,一个是输入关键字后会自动提示下拉选项,另一个是可以点击右边的图标,在弹出窗口中选择选项。
<field name="productId" title="${uiLabelMap.ProductProductId}"><lookup target-form-name="LookupProduct"/></field>具体重点应该是lookup标签的配置。访问controller.xml文件,找到LookupProduct的配置:
<screen name="LookupProduct"> <section> <condition> <if-service-permission service-name="catalogPermissionCheck" main-action="VIEW"/> </condition> <actions> <property-map resource="ProductUiLabels" map-name="uiLabelMap" global="true"/> <set field="title" value="${uiLabelMap.PageTitleLookupProduct}"/> <set field="queryString" from-field="result.queryString"/> <set field="entityName" value="Product"/> <set field="searchFields" value="[productId, internalName, brandName]"/> </actions> <widgets> <decorator-screen name="LookupDecorator" location="component://common/widget/CommonScreens.xml"> <decorator-section name="search-options"> <include-form name="LookupProduct" location="component://product/widget/catalog/FieldLookupForms.xml"/> </decorator-section> <decorator-section name="search-results"> <include-form name="ListLookupProduct" location="component://product/widget/catalog/FieldLookupForms.xml"/> </decorator-section> </decorator-screen> </widgets> </section> </screen>
具体实现好像蛮复杂的,暂时不深入研究了,以后再专门研究lookup标签。
好像有点看不懂,这个日期到底是怎么判断的。
<field name="facilityId" title="${uiLabelMap.ProductFacilityId}"> <drop-down allow-empty="true"> <entity-options entity-name="Facility" key-field-name="facilityId" description="${facilityName} [${facilityId}]"> <!--<entity-constraint name="facilityTypeId" value="WAREHOUSE"/>--> </entity-options> </drop-down> </field>
这个是下拉框控件。类似复选框控件,其对应的sql查询是:
/* where facility_Type_Id ='WAREHOUSe' */
<field name="submitButton" title="${uiLabelMap.CommonFind}"><submit/></field>
这个是提交按钮。
3.3 分析search-results
<form name="ListFindProductionRun" list-name="listIt" title="" type="list" paginate-target="FindProductionRun" odd-row-style="alternate-row" default-table-style="basic-table hover-bar"> <actions> <service service-name="performFind" result-map="result" result-map-list="listIt"> <field-map field-name="inputFields" from-field="requestParameters"/> <field-map field-name="entityName" value="WorkEffortAndGoods"/> <field-map field-name="viewIndex" from-field="viewIndex"/> <field-map field-name="viewSize" from-field="viewSize"/> <field-map field-name="orderBy" value="estimatedStartDate"/> </service> </actions> <row-actions> <entity-one entity-name="Product" value-field="product"/> <entity-one entity-name="Uom" value-field="uom"> <field-map field-name="uomId" from-field="product.quantityUomId"/> </entity-one> </row-actions> <field name="workEffortId" title=" " widget-style="buttontext"> <hyperlink description="${workEffortId}" target="ShowProductionRun" also-hidden="false"> <parameter param-name="productionRunId" from-field="workEffortId"/> </hyperlink> </field> <field name="workEffortName" title="${uiLabelMap.ManufacturingProductionRunName}"><display/></field> <field name="productId" title="${uiLabelMap.ProductProductId}"><display/></field> <field name="estimatedQuantity" title="${uiLabelMap.ManufacturingQuantity}"><display/></field> <field name="QuantityUom" title="${uiLabelMap.ProductQuantityUom}"><display description="${uom.abbreviation}"></display></field> <field name="currentStatusId" title="${uiLabelMap.CommonStatus}"> <display-entity entity-name="StatusItem" key-field-name="statusId"/> </field> <field name="estimatedStartDate" title="${uiLabelMap.ManufacturingStartDate}"><display/></field> <field name="description" title="${uiLabelMap.CommonDescription}"><display/></field> <field name="facilityId" title="${uiLabelMap.ProductFacilityId}"><display/></field> </form>
该查询的业务逻辑查看service的配置。service-name="performFind" 。找到performFind服务的定义。通过服务引擎工具查找如下信息:
打开文件org.apache.ofbiz.common.FindServices,路径:framework/common/servicedef/services.xml
<service name="performFind" auth="false" engine="java" invoke="performFind" location="org.apache.ofbiz.common.FindServices"> <description>Generic service to return an entity iterator. set filterByDate to Y to exclude expired records. set noConditionFind to Y to find without conditions. </description> <attribute name="entityName" type="String" mode="IN" optional="false"/> <attribute name="inputFields" type="java.util.Map" mode="IN" optional="false"/> <attribute name="fieldList" type="java.util.List" mode="IN" optional="true"/> <attribute name="orderBy" type="String" mode="IN" optional="true"/> <attribute name="noConditionFind" type="String" mode="IN" optional="true"><!-- find with no condition (empty entityConditionList) only done when this is Y --></attribute> <attribute name="distinct" type="String" mode="IN" optional="true"><!-- distinct find only done when this is Y --></attribute> <attribute name="filterByDate" type="String" mode="IN" optional="true"/> <attribute name="filterByDateValue" type="Timestamp" mode="IN" optional="true"/> <attribute name="fromDateName" type="String" mode="IN" optional="true"/> <attribute name="thruDateName" type="String" mode="IN" optional="true"/> <attribute name="viewIndex" type="Integer" mode="IN" optional="true"/> <attribute name="viewSize" type="Integer" mode="IN" optional="true"/> <attribute name="listIt" type="org.apache.ofbiz.entity.util.EntityListIterator" mode="OUT" optional="true"/> <attribute name="listSize" type="Integer" mode="OUT" optional="true"/> <attribute name="queryString" type="String" mode="OUT" optional="true"/> <attribute name="queryStringMap" type="java.util.Map" mode="OUT" optional="true"/> </service>
打开org.apache.ofbiz.common.FindServices,查看performFind方法:
/** * performFind * * This is a generic method that expects entity data affixed with special suffixes * to indicate their purpose in formulating an SQL query statement. */ public static Map<String, Object> performFind(DispatchContext dctx, Map<String, ?> context) { String entityName = (String) context.get("entityName"); String orderBy = (String) context.get("orderBy"); Map<String, ?> inputFields = checkMap(context.get("inputFields"), String.class, Object.class); // Input String noConditionFind = (String) context.get("noConditionFind"); String distinct = (String) context.get("distinct"); List<String> fieldList = UtilGenerics.<String>checkList(context.get("fieldList")); GenericValue userLogin = (GenericValue) context.get("userLogin"); Locale locale = (Locale) context.get("locale"); Delegator delegator = dctx.getDelegator(); if (UtilValidate.isEmpty(noConditionFind)) { // try finding in inputFields Map noConditionFind = (String) inputFields.get("noConditionFind"); } if (UtilValidate.isEmpty(noConditionFind)) { // Use configured default noConditionFind = EntityUtilProperties.getPropertyValue("widget", "widget.defaultNoConditionFind", delegator); } String filterByDate = (String) context.get("filterByDate"); if (UtilValidate.isEmpty(filterByDate)) { // try finding in inputFields Map filterByDate = (String) inputFields.get("filterByDate"); } Timestamp filterByDateValue = (Timestamp) context.get("filterByDateValue"); String fromDateName = (String) context.get("fromDateName"); if (UtilValidate.isEmpty(fromDateName)) { // try finding in inputFields Map fromDateName = (String) inputFields.get("fromDateName"); } String thruDateName = (String) context.get("thruDateName"); if (UtilValidate.isEmpty(thruDateName)) { // try finding in inputFields Map thruDateName = (String) inputFields.get("thruDateName"); } Integer viewSize = (Integer) context.get("viewSize"); Integer viewIndex = (Integer) context.get("viewIndex"); Integer maxRows = null; if (viewSize != null && viewIndex != null) { maxRows = viewSize * (viewIndex + 1); } LocalDispatcher dispatcher = dctx.getDispatcher(); Map<String, Object> prepareResult = null; try { prepareResult = dispatcher.runSync("prepareFind", UtilMisc.toMap("entityName", entityName, "orderBy", orderBy, "inputFields", inputFields, "filterByDate", filterByDate, "noConditionFind", noConditionFind, "filterByDateValue", filterByDateValue, "userLogin", userLogin, "fromDateName", fromDateName, "thruDateName", thruDateName, "locale", context.get("locale"), "timeZone", context.get("timeZone"))); } catch (GenericServiceException gse) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "CommonFindErrorPreparingConditions", UtilMisc.toMap("errorString", gse.getMessage()), locale)); } EntityConditionList<EntityCondition> exprList = UtilGenerics.cast(prepareResult.get("entityConditionList")); List<String> orderByList = checkList(prepareResult.get("orderByList"), String.class); Map<String, Object> executeResult = null; try { executeResult = dispatcher.runSync("executeFind", UtilMisc.toMap("entityName", entityName, "orderByList", orderByList, "fieldList", fieldList, "entityConditionList", exprList, "noConditionFind", noConditionFind, "distinct", distinct, "locale", context.get("locale"), "timeZone", context.get("timeZone"), "maxRows", maxRows)); } catch (GenericServiceException gse) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "CommonFindErrorRetrieveIterator", UtilMisc.toMap("errorString", gse.getMessage()), locale)); } if (executeResult.get("listIt") == null) { if (Debug.verboseOn()) Debug.logVerbose("No list iterator found for query string + [" + prepareResult.get("queryString") + "]", module); } Map<String, Object> results = ServiceUtil.returnSuccess(); results.put("listIt", executeResult.get("listIt")); results.put("listSize", executeResult.get("listSize")); results.put("queryString", prepareResult.get("queryString")); results.put("queryStringMap", prepareResult.get("queryStringMap")); return results; }
这里涉及到了服务的定义与实现,不是本章关注的重点。本章主要关注的重点是
<form name="ListFindProductionRun" list-name="listIt" title="" type="list" paginate-target="FindProductionRun"
odd-row-style="alternate-row" default-table-style="basic-table hover-bar">
和
<form name="FindProductionRun" target="FindProductionRun" title="" type="single"
header-row-style="header-row" default-table-style="basic-table">
2个表单通过paginate-target属性关联起来。
总结:
查询页面的大体框架布局有了初步了解。介绍了常用的表单控件的使用。
还有待深入研究的lookup控件和date-find控件。以及check控件的国际化是在哪里配置的。
- ofbiz学习——创建一个查询页面
- ofbiz实战4——创建学期管理查询界面
- ofbiz实战5——创建学期管理新建和编辑页面
- ofbiz学习——分类
- 创建OFBiz的jQuery Mobile入门页面
- ofbiz学习——选择目录
- ofbiz学习——畅销产品展示
- ofbiz实战3——创建booking项目首页
- ofbiz——如何使用set标签定义一个数组
- ofbiz——工作流学习笔记一(xpdl)
- 【电子商务平台】Ofbiz研究学习详细记录——概况
- 【电子商务平台】Ofbiz研究学习详细记录——部署
- ofbiz学习——ecommerce项目主页面
- ofbiz学习——推广/宣传产品展示
- ofbiz学习——深入分析lookup标签实现原理
- ofbiz总结——学习widget-form.xsd文档
- Ofbiz学习
- OFBiz学习
- C语言实验——打印图形
- hadoop环境的配置
- JavaScript链式调用
- 使用VS2010开发Qt程序的一点经验
- 欢迎使用CSDN-markdown编辑器
- ofbiz学习——创建一个查询页面
- Apache的HttpClient创建CloseableHttpClient的例子
- oracle rman 备份归档日志常用脚本
- lib库实现UI定制化
- 网络学英语
- Faster RCNN改进思路
- jfinal-web
- idea的properties文件高亮显示
- 【51NOD 1440】迈克打电话