欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ofbiz学习——选择目录

程序员文章站 2022-07-13 21:50:37
...

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

ofbiz学习——选择目录


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

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

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

ofbiz学习——选择目录

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 表数据如下:

ofbiz学习——选择目录

产品店铺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表中添加一条记录。可以通过进入 内容模块——》创建网站 完成这一步骤。

ofbiz学习——选择目录

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

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

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

ofbiz学习——选择目录

4.创建店铺。

ofbiz学习——选择目录

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

ofbiz学习——选择目录


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

ofbiz学习——选择目录

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

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

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

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