ofbiz学习——选择目录

来源:互联网 发布:淘宝中老年装 编辑:程序博客网 时间:2024/06/04 19:49

这篇文章介绍主页中左上角的 选择目录 视图是如何实现的。



在 ofbiz学习——ecommerce项目主页面  文章中介绍了主页的整体视图模板的组成。这章详细介绍界面中选择目录 界面 的实现。

1. 首先打开主页,https://10.100.1.240:8443/ecommerce/control/main  

2.找到 选择目录 界面对应的html源码。我用的是chrome浏览器,直接在选择目录区域右键——》检出,得到下面源码:


3.打开文件${Ofbiz_Home}\specialpurpose\ecommerce\widget\CommonScreens.xml查找<screen name="main-decorator"> 定义。

根据上面的源码分析,div的id由ecom-mainarea -》 div1 -》choosecatalog

所以主页关注main-decorator定义的

<container id="div1" style="left"><include-screen name="${leftbarScreenName}" location="${leftbarScreenLocation}"/></container>

CommonScreens.xml#main中我们能找到${leftbarScreenName}的值为  leftbar

<set field="leftbarScreenName" value="leftbar"/>
所以查看CommonScreens.xml#leftbar

    <screen name="leftbar">        <section>            <widgets>                    <include-screen name="choosecatalog" location="component://ecommerce/widget/CatalogScreens.xml"/>                    <include-screen name="keywordsearchbox" location="component://ecommerce/widget/CatalogScreens.xml"/>                    <!--include-screen name="sidedeepcategory" location="component://ecommerce/widget/CatalogScreens.xml"/-->                    <include-screen name="productCategories" location="component://ecommerce/widget/CatalogScreens.xml"/>                    <include-screen name="LayeredNavBar" location="component://ecommerce/widget/CatalogScreens.xml"/>                    <include-screen name="minireorderprods" location="component://ecommerce/widget/CatalogScreens.xml"/>                    <include-screen name="signupforcontactlist" location="component://ecommerce/widget/EmailContactListScreens.xml"/>                    <include-screen name="minipoll" location="component://ecommerce/widget/ContentScreens.xml"/>                    <include-screen name="forums" location="component://ecommerce/widget/ForumScreens.xml"/>                    <include-screen name="content_categories" location="component://ecommerce/widget/ContentScreens.xml"/>                    <include-screen name="blogs" location="component://ecommerce/widget/blog/BlogScreens.xml"/>            </widgets>        </section>    </screen>


根据上面的配置,找到CatalogScreens.xml#choosecatalog,并打开。

    <screen name="choosecatalog">        <section>            <actions>                <property-map resource="ProductUiLabels" map-name="uiLabelMap" global="true"/>                <property-map resource="CommonUiLabels" map-name="uiLabelMap" global="true"/>            </actions>            <widgets>                <platform-specific><html><html-template location="component://ecommerce/template/catalog/ChooseCatalog.ftl"/></html></platform-specific>            </widgets>        </section>    </screen>


打开ChooseCatalog.ftl:
<#assign catalogCol = Static["org.apache.ofbiz.product.catalog.CatalogWorker"].getCatalogIdsAvailable(request)!><#assign currentCatalogId = Static["org.apache.ofbiz.product.catalog.CatalogWorker"].getCurrentCatalogId(request)!><#assign currentCatalogName =    Static["org.apache.ofbiz.product.catalog.CatalogWorker"].getCatalogName(request, currentCatalogId)!><#-- Only show if there is more than 1 (one) catalog, no sense selecting when there is only one option... --><#if (catalogCol?size > 1)>  <div id="choosecatalog" class="screenlet">    <div class="screenlet-title-bar">      <ul>        <li class="h3">${uiLabelMap.ProductChooseCatalog}</li>      </ul>      <br class="clear"/>    </div>    <div class="screenlet-body">      <form name="choosecatalogform" method="post" action="<@ofbizUrl>main</@ofbizUrl>">        <select name='CURRENT_CATALOG_ID' class='selectBox' onchange="submit()">          <option value='${currentCatalogId}'>${currentCatalogName}</option>          <option value='${currentCatalogId}'></option>          <#list catalogCol as catalogId>            <#assign thisCatalogName =                Static["org.apache.ofbiz.product.catalog.CatalogWorker"].getCatalogName(request, catalogId)>            <option value='${catalogId}'>${thisCatalogName}</option>          </#list>        </select>      </form>    </div>  </div></#if>

所以我们找到选择目录的下拉框数据填充逻辑。  前面2个选择时写死的,就是当前选择目录。

填充数据主要是catalogCol对象的获取。

<#assign catalogCol = Static["org.apache.ofbiz.product.catalog.CatalogWorker"].getCatalogIdsAvailable(request)!>
根据这条语句找到对应的java代码。(查找方法:包名中第四层级是product表示源码在product项目中。)

打开文件${Ofbiz_Home}\applications\product\src\main\java\org\apache\ofbiz\product\catalog\CatalogWorker.java

    public static List<String> getCatalogIdsAvailable(ServletRequest request) {        List<GenericValue> partyCatalogs = getPartyCatalogs(request);        List<GenericValue> storeCatalogs = getStoreCatalogs(request);        return getCatalogIdsAvailable(partyCatalogs, storeCatalogs);    }    public static List<String> getCatalogIdsAvailable(Delegator delegator, String productStoreId, String partyId) {        List<GenericValue> storeCatalogs = getStoreCatalogs(delegator, productStoreId);        List<GenericValue> partyCatalogs = getPartyCatalogs(delegator, partyId);        return getCatalogIdsAvailable(partyCatalogs, storeCatalogs);    }    public static List<String> getCatalogIdsAvailable(List<GenericValue> partyCatalogs, List<GenericValue> storeCatalogs) {        List<String> categoryIds = new LinkedList<String>();        List<GenericValue> allCatalogLinks = new LinkedList<GenericValue>();        if (partyCatalogs != null) allCatalogLinks.addAll(partyCatalogs);        if (storeCatalogs != null) allCatalogLinks.addAll(storeCatalogs);        if (allCatalogLinks.size() > 0) {            for (GenericValue catalogLink: allCatalogLinks) {                categoryIds.add(catalogLink.getString("prodCatalogId"));            }        }        return categoryIds;    }

    public static List<GenericValue> getPartyCatalogs(ServletRequest request) {        HttpSession session = ((HttpServletRequest) request).getSession();        GenericValue userLogin = (GenericValue) session.getAttribute("userLogin");        if (userLogin == null) userLogin = (GenericValue) session.getAttribute("autoUserLogin");        if (userLogin == null) return null;        String partyId = userLogin.getString("partyId");        if (partyId == null) return null;        Delegator delegator = (Delegator) request.getAttribute("delegator");        return getPartyCatalogs(delegator, partyId);    }    public static List<GenericValue> getPartyCatalogs(Delegator delegator, String partyId) {        if (delegator == null || partyId == null) {            return null;        }        try {            return EntityQuery.use(delegator).from("ProdCatalogRole").where("partyId", partyId, "roleTypeId", "CUSTOMER").orderBy("sequenceNum", "prodCatalogId").cache(true).filterByDate().queryList();        } catch (GenericEntityException e) {            Debug.logError(e, "Error looking up ProdCatalog Roles for party with id " + partyId, module);        }        return null;    }

    public static List<GenericValue> getStoreCatalogs(ServletRequest request) {        String productStoreId = ProductStoreWorker.getProductStoreId(request);        Delegator delegator = (Delegator) request.getAttribute("delegator");        return getStoreCatalogs(delegator, productStoreId);    }    public static List<GenericValue> getStoreCatalogs(Delegator delegator, String productStoreId) {        try {            return EntityQuery.use(delegator).from("ProductStoreCatalog").where("productStoreId", productStoreId).orderBy("sequenceNum", "prodCatalogId").cache(true).filterByDate().queryList();        } catch (GenericEntityException e) {            Debug.logError(e, "Error looking up store catalogs for store with id " + productStoreId, module);        }        return null;    }

getStoreCatalogs方法:

select * from ProductStoreCatalog where productStoreId = ? order by sequenceNum,prodCatalogId

getPartyCatalogs方法:

select * from ProdCatalogRole where partyId=?and roleTypeId='CUSTOMER' order by  sequenceNum,prodCatalogId


getCatalogIdsAvailable方法最终方法的结果是上面结果prodcatalogid字段的union,即

select  prodCatalogId  from ProductStoreCatalog where productStoreId = ? order by sequenceNum,prodCatalogId

union

selectprodCatalogId  from ProdCatalogRole where partyId=?and roleTypeId='CUSTOMER' order by  sequenceNum,prodCatalogId


如果要改填充数据,则需要修改getCatalogIdsAvailable方法就好了。

如果要改界面,则修改ChooseCatalog.ftl文件。


在数据库测试了下,发现ProductStoreCatalog和ProdCatalogRole不存在,既不是表也不是视图。

查找实体模型的定义文件。实体模型定义文件现在不在下面的entitydef文件夹下了,都统一放入了下面路径:

${Ofbiz_Home}\applications\datamodel\entitydef

打开product-entitymodel.xml文件找到

ProductStoreCatalog的定义:

 <entity entity-name="ProductStoreCatalog"            package-name="org.apache.ofbiz.product.store"            title="Product Store Catalog Association Entity">      <field name="productStoreId" type="id-ne"></field>      <field name="prodCatalogId" type="id-ne"></field>      <field name="fromDate" type="date-time"></field>      <field name="thruDate" type="date-time"></field>      <field name="sequenceNum" type="numeric"></field>      <prim-key field="productStoreId"/>      <prim-key field="prodCatalogId"/>      <prim-key field="fromDate"/>      <relation type="one" fk-name="PS_CAT_PRDSTR" rel-entity-name="ProductStore">        <key-map field-name="productStoreId"/>      </relation>      <relation type="one" fk-name="PS_CAT_CATALOG" rel-entity-name="ProdCatalog">        <key-map field-name="prodCatalogId"/>      </relation>    </entity>

ProdCatalogRole的定义:

<entity entity-name="ProdCatalogRole"            package-name="org.apache.ofbiz.product.catalog"            title="ProdCatalog Role Association Entity">      <field name="partyId" type="id-ne"></field>      <field name="roleTypeId" type="id-ne"></field>      <field name="prodCatalogId" type="id-ne"></field>      <field name="fromDate" type="date-time"></field>      <field name="thruDate" type="date-time"></field>      <field name="sequenceNum" type="numeric"></field>      <prim-key field="partyId"/>      <prim-key field="roleTypeId"/>      <prim-key field="prodCatalogId"/>      <prim-key field="fromDate"/>      <relation type="one-nofk" rel-entity-name="Party">        <key-map field-name="partyId"/>      </relation>      <relation type="one-nofk" rel-entity-name="RoleType">        <key-map field-name="roleTypeId"/>      </relation>      <relation type="one-nofk" rel-entity-name="Person">        <key-map field-name="partyId"/>      </relation>      <relation type="one-nofk" rel-entity-name="PartyGroup">        <key-map field-name="partyId"/>      </relation>      <relation type="one" fk-name="PCATRLE_PTYRLE" rel-entity-name="PartyRole">        <key-map field-name="partyId"/>        <key-map field-name="roleTypeId"/>      </relation>      <relation type="one" fk-name="PCATRLE_CATALOG" rel-entity-name="ProdCatalog">        <key-map field-name="prodCatalogId"/>      </relation>    </entity>

所以上面的sql语句要执行成功,必须修改表名,大写字母前面必须加上下划线。正确的查询sql

select  prod_Catalog_Id  from Product_Store_Catalog where product_Store_Id = ? order by sequence_Num,prod_Catalog_Id

union

select  prod_Catalog_Id  from Prod_Catalog_Role where party_Id=?and role_Type_Id='CUSTOMER' order by  sequence_Num,prod_Catalog_Id


查询结果发现Prod_Catalog_Role 表中没数据。Product_Store_Catalog 表数据如下:


产品店铺id为10000的是我后来添加的。框架默认查询的product_Store_Id 是9000的记录。所以我们看到选择目录后面有4条待选记录。

productStoreId 取值是根据    ${Ofbiz_Home}\specialpurpose\ecommerce\webapp\ecommerce\WEB-INF\web.xml

文件中配置的webSiteId参数。从Web_Site表获取对应记录的product_Store_Id 字段值

<context-param>        <description>A unique ID used to look up the WebSite entity</description>        <param-name>webSiteId</param-name>        <param-value>WebStore</param-value>    </context-param>

${Ofbiz_Home}\framework\webapp\src\main\java\org\apache\ofbiz\webapp\website\WebSiteWorker.java

package org.apache.ofbiz.webapp.website;import javax.servlet.ServletContext;import javax.servlet.ServletRequest;import org.apache.ofbiz.base.util.Debug;import org.apache.ofbiz.entity.Delegator;import org.apache.ofbiz.entity.GenericEntityException;import org.apache.ofbiz.entity.GenericValue;import org.apache.ofbiz.entity.util.EntityQuery;/** * WebSiteWorker - Worker class for web site related functionality */public final class WebSiteWorker {    public static final String module = WebSiteWorker.class.getName();    private WebSiteWorker() {}    public static String getWebSiteId(ServletRequest request) {        ServletContext application = ((ServletContext) request.getAttribute("servletContext"));        if (application == null) return null;        return application.getInitParameter("webSiteId");    }    public static GenericValue getWebSite(ServletRequest request) {        String webSiteId = getWebSiteId(request);        if (webSiteId == null) {            return null;        }        return findWebSite((Delegator) request.getAttribute("delegator"), webSiteId, true);    }    /**     * returns a WebSite-GenericValue     *     * @param delegator     * @param webSiteId     * @param useCache     * @return     */    private static GenericValue findWebSite(Delegator delegator, String webSiteId, boolean useCache) {        GenericValue result = null;        try {            result = EntityQuery.use(delegator).from("WebSite").where("webSiteId", webSiteId).cache(useCache).queryOne();        }        catch (GenericEntityException e) {            Debug.logError("Error looking up website with id " + webSiteId, module);        }        return result;    }}

所以最终要显示  选择目录 下拉框的数据  流程。

1. 首先必须有个定义一个网站。即Web_Site表中添加一条记录。可以通过进入 内容模块——》创建网站 完成这一步骤。


2. 创建完成后配置${Ofbiz_Home}\specialpurpose\ecommerce\webapp\ecommerce\WEB-INF\web.xml

将webSiteId参数的值设置为新创建的网站id。

3.新增目录。进入 目录模块 ——》新增目录


4.创建店铺。


5.关联店铺与产品目录。点击菜单   目录 ——》店铺 ——》店铺id ——》目录    对指定目录添加新的产品目录。



6.最后由于店铺是后来创建的,所以需要修改网站的产品店铺标识。


这样重新启动系统后,主页显示的网站就是新定义的网站内容了。选择目录就是产品店铺关联的产品目录了。

通过分析之前的ofbiz系统的源码。总结一下一些主要表之间的关系。

1. 目录(Prod_Catalog)和店铺(Product_Store)是多对多的关系。 关系表(Product_Store_Catalog)

2. 网站(Web_Site)和店铺(Product_Store)是多对一的关系。即一个网站对应一个店铺,一个店铺可以对应多个网站。