ofbiz学习——选择目录
这篇文章介绍主页中左上角的 选择目录 视图是如何实现的。
在 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>
<#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)是多对一的关系。即一个网站对应一个店铺,一个店铺可以对应多个网站。
上一篇: 在win10的vs2019上安装并编译libevent库
下一篇: 织梦仿产品展示页产品图集调用方法