ofbiz学习——推广/宣传产品展示
程序员文章站
2022-03-21 23:16:28
...
这篇文章主要分析主页中间的推广/宣传产品展示的相关代码。
1.先把涉及到的源码贴出来
1.1 widget配置文件
打开文件component://ecommerce/widget/CommonScreens.xml#main
<screen name="main">
<section>
<actions>
<set field="leftbarScreenName" value="leftbar"/>
<set field="rightbarScreenName" value="rightbar"/>
<set field="MainColumnStyle" value="center"/>
<set field="titleProperty" value="PageTitleMain"/>
<set field="headerItem" value="main"/>
<set field="randomSurveyGroup" value="testSurveyGroup"/>
<script location="component://ecommerce/groovyScripts/Main.groovy"/>
<script location="component://order/groovyScripts/entry/catalog/Category.groovy"/>
</actions>
<widgets>
<decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
<decorator-section name="body">
<platform-specific>
<html><html-template location="component://ecommerce/template/Main.ftl"/></html>
</platform-specific>
</decorator-section>
</decorator-screen>
</widgets>
</section>
</screen>
<screen name="category-include">
<section>
<widgets>
<section>
<condition>
<not><if-empty field="productCategory"/></not>
</condition>
<widgets>
<include-screen name="${detailScreen}"/>
</widgets>
<fail-widgets>
<label style="head2">${uiLabelMap.ProductCategoryNotFoundForCategoryID} ${productCategoryId}!</label>
</fail-widgets>
</section>
</widgets>
</section>
</screen>
打开文件component://ecommerce/widget/CatalogScreens.xml#categorydetail
<screen name="categorydetail">
<section>
<actions>
<set field="productsummaryScreen" value="component://ecommerce/widget/CatalogScreens.xml#productsummary"/>
<set field="productCategoryLinkScreen" value="component://ecommerce/widget/CatalogScreens.xml#ProductCategoryLink"/>
<script location="component://order/groovyScripts/entry/catalog/CategoryDetail.groovy"/>
<entity-and entity-name="ProductCategoryLink" list="productCategoryLinks" use-cache="true" filter-by-date="true">
<field-map field-name="productCategoryId" from-field="productCategoryId"/>
<order-by field-name="sequenceNum"/>
</entity-and>
<set field="paginateEcommerceStyle" value="Y"/>
</actions>
<widgets>
<platform-specific><html><html-template location="component://order/template/entry/catalog/CategoryDetail.ftl"/></html></platform-specific>
</widgets>
</section>
</screen>
<screen name="productsummary">
<section>
<actions>
<property-map resource="ProductUiLabels" map-name="uiLabelMap" global="true"/>
<property-map resource="CommonUiLabels" map-name="uiLabelMap" global="true"/>
<property-map resource="EcommerceUiLabels" map-name="uiLabelMap" global="true"/>
<script location="component://order/groovyScripts/entry/catalog/ProductSummary.groovy"/>
</actions>
<widgets>
<platform-specific><html><html-template location="component://order/template/entry/catalog/ProductSummary.ftl"/></html></platform-specific>
</widgets>
</section>
</screen>
1.2 相关的groovy脚本
component://order/groovyScripts/entry/catalog/Category.groovy
/*
* This script is also referenced by the ecommerce's screens and
* should not contain order component's specific code.
*/
import org.apache.ofbiz.base.util.*
import org.apache.ofbiz.entity.*
import org.apache.ofbiz.product.catalog.*
import org.apache.ofbiz.product.category.CategoryWorker
import org.apache.ofbiz.product.category.CategoryContentWrapper
import org.apache.ofbiz.product.store.ProductStoreWorker
detailScreen = "categorydetail"
catalogName = CatalogWorker.getCatalogName(request)
productCategoryId = request.getAttribute("productCategoryId") ?: parameters.category_id
context.productCategoryId = productCategoryId
context.productStore = ProductStoreWorker.getProductStore(request)
pageTitle = null
metaDescription = null
metaKeywords = null
category = from("ProductCategory").where("productCategoryId", productCategoryId).cache(true).queryOne()
if (category) {
if (category.detailScreen) {
detailScreen = category.detailScreen
}
categoryPageTitle = from("ProductCategoryContentAndInfo").where("productCategoryId", productCategoryId, "prodCatContentTypeId", "PAGE_TITLE").cache(true).queryList()
if (categoryPageTitle) {
pageTitle = from("ElectronicText").where("dataResourceId", categoryPageTitle.get(0).dataResourceId).cache(true).queryOne()
}
categoryMetaDescription = from("ProductCategoryContentAndInfo").where("productCategoryId", productCategoryId, "prodCatContentTypeId", "META_DESCRIPTION").cache(true).queryList()
if (categoryMetaDescription) {
metaDescription = from("ElectronicText").where("dataResourceId", categoryMetaDescription.get(0).dataResourceId).cache(true).queryOne()
}
categoryMetaKeywords = from("ProductCategoryContentAndInfo").where("productCategoryId", productCategoryId, "prodCatContentTypeId", "META_KEYWORD").cache(true).queryList()
if (categoryMetaKeywords) {
metaKeywords = from("ElectronicText").where("dataResourceId", categoryMetaKeywords.get(0).dataResourceId).cache(true).queryOne()
}
categoryContentWrapper = new CategoryContentWrapper(category, request)
categoryDescription = categoryContentWrapper.get("DESCRIPTION", "html")
if (pageTitle) {
context.title = pageTitle.textData
} else {
context.title = categoryContentWrapper.get("CATEGORY_NAME", "html")
}
if (metaDescription) {
context.metaDescription = metaDescription.textData
} else {
if (categoryDescription) {
context.metaDescription = categoryDescription
}
}
if (metaKeywords) {
context.metaKeywords = metaKeywords.textData
} else {
if (categoryDescription) {
context.metaKeywords = categoryDescription + ", " + catalogName
} else {
context.metaKeywords = catalogName
}
}
context.productCategory = category
}
// check the catalogs template path and update
templatePathPrefix = CatalogWorker.getTemplatePathPrefix(request)
if (templatePathPrefix) {
detailScreen = templatePathPrefix + detailScreen
}
context.detailScreen = detailScreen
request.setAttribute("productCategoryId", productCategoryId)
request.setAttribute("defaultViewSize", 10)
request.setAttribute("limitView", true)
component://order/groovyScripts/entry/catalog/CategoryDetail.groovy
/*
* NOTE: This script is also referenced by the webpos and ecommerce's screens and
* should not contain order component's specific code.
*/
import org.apache.ofbiz.base.util.*
import org.apache.ofbiz.entity.*
import org.apache.ofbiz.entity.condition.*
import org.apache.ofbiz.entity.util.*
import org.apache.ofbiz.service.*
import org.apache.ofbiz.product.catalog.*
import org.apache.ofbiz.product.category.CategoryContentWrapper
import org.apache.ofbiz.product.store.ProductStoreWorker
productCategoryId = request.getAttribute("productCategoryId")
context.productCategoryId = productCategoryId
viewSize = parameters.VIEW_SIZE
viewIndex = parameters.VIEW_INDEX
currentCatalogId = CatalogWorker.getCurrentCatalogId(request)
// set the default view size
defaultViewSize = request.getAttribute("defaultViewSize") ?: EntityUtilProperties.getPropertyValue("widget", "widget.form.defaultViewSize", "20", delegator)
context.defaultViewSize = defaultViewSize
// set the limit view
limitView = request.getAttribute("limitView") ?: true
context.limitView = limitView
// get the product category & members
andMap = [productCategoryId : productCategoryId,
viewIndexString : viewIndex,
viewSizeString : viewSize,
defaultViewSize : defaultViewSize,
limitView : limitView]
andMap.put("prodCatalogId", currentCatalogId)
andMap.put("checkViewAllow", true)
// Prevents out of stock product to be displayed on site
productStore = ProductStoreWorker.getProductStore(request)
if (productStore) {
andMap.put("productStoreId", productStore.productStoreId)
}
if (context.orderByFields) {
andMap.put("orderByFields", context.orderByFields)
} else {
andMap.put("orderByFields", ["sequenceNum", "productId"])
}
catResult = runService('getProductCategoryAndLimitedMembers', andMap)
productCategory = catResult.productCategory
productCategoryMembers = catResult.productCategoryMembers
context.productCategoryMembers = productCategoryMembers
context.productCategory = productCategory
context.viewIndex = catResult.viewIndex
context.viewSize = catResult.viewSize
context.lowIndex = catResult.lowIndex
context.highIndex = catResult.highIndex
context.listSize = catResult.listSize
// set this as a last viewed
// DEJ20070220: WHY is this done this way? why not use the existing CategoryWorker stuff?
LAST_VIEWED_TO_KEEP = 10 // modify this to change the number of last viewed to keep
lastViewedCategories = session.getAttribute("lastViewedCategories")
if (!lastViewedCategories) {
lastViewedCategories = []
session.setAttribute("lastViewedCategories", lastViewedCategories)
}
lastViewedCategories.remove(productCategoryId)
lastViewedCategories.add(0, productCategoryId)
while (lastViewedCategories.size() > LAST_VIEWED_TO_KEEP) {
lastViewedCategories.remove(lastViewedCategories.size() - 1)
}
// set the content path prefix
contentPathPrefix = CatalogWorker.getContentPathPrefix(request)
context.put("contentPathPrefix", contentPathPrefix)
// little routine to see if any members have a quantity > 0 assigned
members = context.get("productCategoryMembers")
if (UtilValidate.isNotEmpty(members)) {
for (i = 0; i < members.size(); i++) {
productCategoryMember = (GenericValue) members.get(i)
if (productCategoryMember.get("quantity") != null && productCategoryMember.getDouble("quantity").doubleValue() > 0.0) {
context.put("hasQuantities", new Boolean(true))
break
}
}
}
CategoryContentWrapper categoryContentWrapper = new CategoryContentWrapper(productCategory, request)
context.put("categoryContentWrapper", categoryContentWrapper)
component://order/groovyScripts/entry/catalog/ProductSummary.groovy
/*
* This script is also referenced by the ecommerce's screens and
* should not contain order component's specific code.
*/
import org.apache.ofbiz.base.util.*
import org.apache.ofbiz.entity.*
import org.apache.ofbiz.entity.util.EntityQuery
import org.apache.ofbiz.service.*
import org.apache.ofbiz.product.product.ProductContentWrapper
import org.apache.ofbiz.product.config.ProductConfigWorker
import org.apache.ofbiz.product.catalog.*
import org.apache.ofbiz.product.store.*
import org.apache.ofbiz.order.shoppingcart.*
import org.apache.ofbiz.product.product.ProductWorker
import org.apache.ofbiz.webapp.website.WebSiteWorker
import java.text.NumberFormat
//either optProduct, optProductId or productId must be specified
product = request.getAttribute("optProduct")
optProductId = request.getAttribute("optProductId")
productId = product?.productId ?: optProductId ?: request.getAttribute("productId")
webSiteId = WebSiteWorker.getWebSiteId(request)
catalogId = CatalogWorker.getCurrentCatalogId(request)
cart = ShoppingCartEvents.getCartObject(request)
productStore = null
productStoreId = null
facilityId = null
if (cart.isSalesOrder()) {
productStore = ProductStoreWorker.getProductStore(request)
productStoreId = productStore.productStoreId
context.productStoreId = productStoreId
facilityId = productStore.inventoryFacilityId
}
if (!facilityId) {
productStoreFacility = EntityQuery.use(delegator).select("facilityId").from("ProductStoreFacility").where("productStoreId", productStoreId).queryFirst()
if (productStoreFacility) {
facilityId = productStoreFacility.facilityId
}
}
autoUserLogin = session.getAttribute("autoUserLogin")
userLogin = session.getAttribute("userLogin")
context.remove("daysToShip")
context.remove("averageRating")
context.remove("numRatings")
context.remove("totalPrice")
// get the product entity
if (!product && productId) {
product = from("Product").where("productId", productId).cache(true).queryOne()
}
if (product) {
//if order is purchase then don't calculate available inventory for product.
if (cart.isSalesOrder()) {
resultOutput = runService('getInventoryAvailableByFacility', [productId : product.productId, facilityId : facilityId, useCache : true])
totalAvailableToPromise = resultOutput.availableToPromiseTotal
if (totalAvailableToPromise && totalAvailableToPromise.doubleValue() > 0) {
productFacility = from("ProductFacility").where("productId", product.productId, "facilityId", facilityId).cache(true).queryOne()
if (productFacility?.daysToShip != null) {
context.daysToShip = productFacility.daysToShip
}
}
} else {
supplierProduct = from("SupplierProduct").where("productId", product.productId).orderBy("-availableFromDate").cache(true).queryFirst()
if (supplierProduct?.standardLeadTimeDays != null) {
standardLeadTimeDays = supplierProduct.standardLeadTimeDays
daysToShip = standardLeadTimeDays + 1
context.daysToShip = daysToShip
}
}
// make the productContentWrapper
productContentWrapper = new ProductContentWrapper(product, request)
context.productContentWrapper = productContentWrapper
}
categoryId = null
reviews = null
if (product) {
categoryId = parameters.category_id ?: request.getAttribute("productCategoryId")
// get the product price
if (cart.isSalesOrder()) {
// sales order: run the "calculateProductPrice" service
priceContext = [product : product, currencyUomId : cart.getCurrency(),
autoUserLogin : autoUserLogin, userLogin : userLogin]
priceContext.webSiteId = webSiteId
priceContext.prodCatalogId = catalogId
priceContext.productStoreId = productStoreId
priceContext.agreementId = cart.getAgreementId()
priceContext.partyId = cart.getPartyId() // IMPORTANT: otherwise it'll be calculating prices using the logged in user which could be a CSR instead of the customer
priceContext.checkIncludeVat = "Y"
priceMap = runService('calculateProductPrice', priceContext)
context.price = priceMap
} else {
// purchase order: run the "calculatePurchasePrice" service
priceContext = [product : product, currencyUomId : cart.getCurrency(),
partyId : cart.getPartyId(), userLogin : userLogin]
priceMap = runService('calculatePurchasePrice', priceContext)
context.price = priceMap
}
// get aggregated product totalPrice
if ("AGGREGATED".equals(product.productTypeId)||"AGGREGATED_SERVICE".equals(product.productTypeId)) {
configWrapper = ProductConfigWorker.getProductConfigWrapper(productId, cart.getCurrency(), request)
if (configWrapper) {
configWrapper.setDefaultConfig()
context.totalPrice = configWrapper.getTotalPrice()
}
}
// get the product review(s)
reviews = product.getRelated("ProductReview", null, ["-postedDateTime"], true)
// get product variant for Box/Case/Each
productVariants = []
boolean isAlternativePacking = ProductWorker.isAlternativePacking(delegator, product.productId, null)
mainProducts = []
if(isAlternativePacking){
productVirtualVariants = from("ProductAssoc").where("productIdTo", product.productId , "productAssocTypeId", "ALTERNATIVE_PACKAGE").cache(true).queryList()
if(productVirtualVariants){
productVirtualVariants.each { virtualVariantKey ->
mainProductMap = [:]
mainProduct = virtualVariantKey.getRelatedOne("MainProduct", true)
quantityUom = mainProduct.getRelatedOne("QuantityUom", true)
mainProductMap.productId = mainProduct.productId
mainProductMap.piecesIncluded = mainProduct.piecesIncluded
mainProductMap.uomDesc = quantityUom.description
mainProducts.add(mainProductMap)
}
}
// get alternative product price when product doesn't have any feature
jsBuf = new StringBuffer()
jsBuf.append("<script language=\"JavaScript\" type=\"text/javascript\">")
// make a list of variant sku with requireAmount
virtualVariantsRes = runService('getAssociatedProducts', [productIdTo : productId, type : "ALTERNATIVE_PACKAGE", checkViewAllow : true, prodCatalogId : categoryId])
virtualVariants = virtualVariantsRes.assocProducts
// Format to apply the currency code to the variant price in the javascript
if (productStore) {
localeString = productStore.defaultLocaleString
if (localeString) {
locale = UtilMisc.parseLocale(localeString)
}
}
variantPriceList = []
numberFormat = NumberFormat.getCurrencyInstance(locale)
if(virtualVariants){
amt = new StringBuffer()
// Create the javascript to return the price for each variant
variantPriceJS = new StringBuffer()
variantPriceJS.append("function getVariantPrice(sku) { ")
virtualVariants.each { virtualAssoc ->
virtual = virtualAssoc.getRelatedOne("MainProduct", false)
// Get price from a virtual product
priceContext.product = virtual
if (cart.isSalesOrder()) {
// sales order: run the "calculateProductPrice" service
virtualPriceMap = runService('calculateProductPrice', priceContext)
BigDecimal calculatedPrice = (BigDecimal)virtualPriceMap.get("price")
// Get the minimum quantity for variants if MINIMUM_ORDER_PRICE is set for variants.
variantPriceList.add(virtualPriceMap)
} else {
virtualPriceMap = runService('calculatePurchasePrice', priceContext)
}
if (virtualPriceMap.basePrice) {
basePrice = numberFormat.format(virtualPriceMap.basePrice)
} else {
basePrice = UtilProperties.getResourceBundleMap("CommonUiLabels", locale).get("CommonNA")
}
variantPriceJS.append(" if (sku == \"" + virtual.productId + "\") return \"" + basePrice + "\"; ")
}
variantPriceJS.append(" } ")
context.variantPriceList = variantPriceList
jsBuf.append(amt.toString())
jsBuf.append(variantPriceJS.toString())
jsBuf.append("</script>")
context.virtualJavaScript = jsBuf
}
}
context.mainProducts = mainProducts
}
// get the average rating
if (reviews) {
totalProductRating = 0
numRatings = 0
reviews.each { productReview ->
productRating = productReview.productRating
if (productRating) {
totalProductRating += productRating
numRatings++
}
}
if (numRatings) {
context.averageRating = totalProductRating/numRatings
context.numRatings = numRatings
}
}
// an example of getting features of a certain type to show
sizeProductFeatureAndAppls = from("ProductFeatureAndAppl").where("productId", productId, "productFeatureTypeId", "SIZE").orderBy("sequenceNum", "defaultSequenceNum").cache(true).queryList()
context.product = product
context.categoryId = categoryId
context.productReviews = reviews
context.sizeProductFeatureAndAppls = sizeProductFeatureAndAppls
1.3 相关的ftl模板
component://ecommerce/template/Main.ftl
<#-- Render the category page -->
<#if requestAttributes.productCategoryId?has_content>
${screens.render("component://ecommerce/widget/CatalogScreens.xml#bestSellingCategory")}
${screens.render("component://ecommerce/widget/CatalogScreens.xml#category-include")}
<#else>
<center><h2>${uiLabelMap.EcommerceNoPROMOTIONCategory}</h2></center>
</#if>
component://order/template/entry/catalog/CategoryDetail.ftl
<script type="text/javascript">
function callDocumentByPaginate(info) {
var str = info.split('~');
var checkUrl = '<@ofbizUrl>categoryAjaxFired</@ofbizUrl>';
if(checkUrl.search("http"))
var ajaxUrl = '<@ofbizUrl>categoryAjaxFired</@ofbizUrl>';
else
var ajaxUrl = '<@ofbizUrl>categoryAjaxFiredSecure</@ofbizUrl>';
//jQuerry Ajax Request
jQuery.ajax({
url: ajaxUrl,
type: 'POST',
data: {"category_id" : str[0], "VIEW_SIZE" : str[1], "VIEW_INDEX" : str[2]},
error: function(msg) {
alert("An error occurred loading content! : " + msg);
},
success: function(msg) {
jQuery('#div3').html(msg);
}
});
}
</script>
<#macro paginationControls>
<#assign viewIndexMax = Static["java.lang.Math"].ceil((listSize)?double / viewSize?double)>
<#if (viewIndexMax?int > 0)>
<div class="product-prevnext">
<select name="pageSelect" onchange="callDocumentByPaginate(this[this.selectedIndex].value);">
<option value="#">${uiLabelMap.CommonPage} ${viewIndex?int + 1} ${uiLabelMap.CommonOf} ${viewIndexMax}</option>
<#if (viewIndex?int > 1)>
<#list 1..viewIndexMax as curViewNum>
<option value="${productCategoryId}~${viewSize}~${curViewNum-1?int}">${uiLabelMap.CommonGotoPage} ${curViewNum}</option>
</#list>
</#if>
</select>
<#-- End Page Select Drop-Down -->
<#if (viewIndex?int > 0)>
<a href="javascript: void(0);" onclick="callDocumentByPaginate('${productCategoryId}~${viewSize}~${viewIndex?int - 1}');" class="buttontext">${uiLabelMap.CommonPrevious}</a> |
</#if>
<#if ((listSize?int - viewSize?int) > 0)>
<span>${lowIndex} - ${highIndex} ${uiLabelMap.CommonOf} ${listSize}</span>
</#if>
<#if highIndex?int < listSize?int>
| <a href="javascript: void(0);" onclick="callDocumentByPaginate('${productCategoryId}~${viewSize}~${viewIndex?int + 1}');" class="buttontext">${uiLabelMap.CommonNext}</a>
</#if>
</div>
</#if>
</#macro>
<#if productCategory??>
<#assign categoryName = categoryContentWrapper.get("CATEGORY_NAME", "html")!/>
<#assign categoryDescription = categoryContentWrapper.get("DESCRIPTION", "html")!/>
<#if categoryName?has_content>
<h1>${categoryName}</h1>
</#if>
<#if categoryDescription?has_content>
<h1>${categoryDescription}</h1>
</#if>
<#if hasQuantities??>
<form method="post" action="<@ofbizUrl>addCategoryDefaults<#if requestAttributes._CURRENT_VIEW_??>/${requestAttributes._CURRENT_VIEW_}</#if></@ofbizUrl>" name="thecategoryform" style='margin: 0;'>
<input type='hidden' name='add_category_id' value='${productCategory.productCategoryId}'/>
<#if requestParameters.product_id??><input type='hidden' name='product_id' value='${requestParameters.product_id}'/></#if>
<#if requestParameters.category_id??><input type='hidden' name='category_id' value='${requestParameters.category_id}'/></#if>
<#if requestParameters.VIEW_INDEX??><input type='hidden' name='VIEW_INDEX' value='${requestParameters.VIEW_INDEX}'/></#if>
<#if requestParameters.SEARCH_STRING??><input type='hidden' name='SEARCH_STRING' value='${requestParameters.SEARCH_STRING}'/></#if>
<#if requestParameters.SEARCH_CATEGORY_ID??><input type='hidden' name='SEARCH_CATEGORY_ID' value='${requestParameters.SEARCH_CATEGORY_ID}'/></#if>
<a href="javascript:document.thecategoryform.submit()" class="buttontext"><span style="white-space: nowrap;">${uiLabelMap.ProductAddProductsUsingDefaultQuantities}</span></a>
</form>
</#if>
<#if searchInCategory?default("Y") == "Y">
<a href="<@ofbizUrl>advancedsearch?SEARCH_CATEGORY_ID=${productCategory.productCategoryId}</@ofbizUrl>" class="buttontext">${uiLabelMap.ProductSearchInCategory}</a>
</#if>
<#assign longDescription = categoryContentWrapper.get("LONG_DESCRIPTION", "html")!/>
<#assign categoryImageUrl = categoryContentWrapper.get("CATEGORY_IMAGE_URL", "url")!/>
<#if categoryImageUrl?string?has_content || longDescription?has_content>
<div>
<#if categoryImageUrl?string?has_content>
<#assign height=100/>
<img src='<@ofbizContentUrl>${categoryImageUrl}</@ofbizContentUrl>' vspace='5' hspace='5' align='left' class='cssImgLarge' />
</#if>
<#if longDescription?has_content>
${longDescription}
</#if>
</div>
</#if>
</#if>
<#if productCategoryLinkScreen?has_content && productCategoryLinks?has_content>
<div class="productcategorylink-container">
<#list productCategoryLinks as productCategoryLink>
${setRequestAttribute("productCategoryLink",productCategoryLink)}
${screens.render(productCategoryLinkScreen)}
</#list>
</div>
</#if>
<#if productCategoryMembers?has_content>
<#-- Pagination -->
<#if paginateEcommerceStyle??>
<@paginationControls/>
<#else>
<#include "component://common/template/includes/HtmlTemplate.ftl"/>
<#assign commonUrl = "category?category_id="+ (parameters.category_id!) + "&"/>
<#--assign viewIndex = viewIndex - 1/-->
<#assign viewIndexFirst = 0/>
<#assign viewIndexPrevious = viewIndex - 1/>
<#assign viewIndexNext = viewIndex + 1/>
<#assign viewIndexLast = Static["org.apache.ofbiz.base.util.UtilMisc"].getViewLastIndex(listSize, viewSize) />
<#assign messageMap = Static["org.apache.ofbiz.base.util.UtilMisc"].toMap("lowCount", lowIndex, "highCount", highIndex, "total", listSize)/>
<#assign commonDisplaying = Static["org.apache.ofbiz.base.util.UtilProperties"].getMessage("CommonUiLabels", "CommonDisplaying", messageMap, locale)/>
<@nextPrev commonUrl=commonUrl ajaxEnabled=false javaScriptEnabled=false paginateStyle="nav-pager" paginateFirstStyle="nav-first" viewIndex=viewIndex highIndex=highIndex listSize=listSize viewSize=viewSize ajaxFirstUrl="" firstUrl="" paginateFirstLabel="" paginatePreviousStyle="nav-previous" ajaxPreviousUrl="" previousUrl="" paginatePreviousLabel="" pageLabel="" ajaxSelectUrl="" selectUrl="" ajaxSelectSizeUrl="" selectSizeUrl="" commonDisplaying=commonDisplaying paginateNextStyle="nav-next" ajaxNextUrl="" nextUrl="" paginateNextLabel="" paginateLastStyle="nav-last" ajaxLastUrl="" lastUrl="" paginateLastLabel="" paginateViewSizeLabel="" />
</#if>
<#assign numCol = numCol?default(1)>
<#assign numCol = numCol?number>
<#assign tabCol = 1>
<div
<#if categoryImageUrl?string?has_content>
style="position: relative; margin-top: ${height}px;"
</#if>
class="productsummary-container<#if (numCol?int > 1)> matrix</#if>">
<#if (numCol?int > 1)>
<table>
</#if>
<#list productCategoryMembers as productCategoryMember>
<#if (numCol?int == 1)>
${setRequestAttribute("optProductId", productCategoryMember.productId)}
${setRequestAttribute("productCategoryMember", productCategoryMember)}
${setRequestAttribute("listIndex", productCategoryMember_index)}
${screens.render(productsummaryScreen)}
<#else>
<#if (tabCol?int = 1)><tr></#if>
<td>
${setRequestAttribute("optProductId", productCategoryMember.productId)}
${setRequestAttribute("productCategoryMember", productCategoryMember)}
${setRequestAttribute("listIndex", productCategoryMember_index)}
${screens.render(productsummaryScreen)}
</td>
<#if (tabCol?int = numCol)></tr></#if>
<#assign tabCol = tabCol+1><#if (tabCol?int > numCol)><#assign tabCol = 1></#if>
</#if>
</#list>
<#if (numCol?int > 1)>
</table>
</#if>
</div>
<#if paginateEcommerceStyle??>
<@paginationControls/>
</#if>
<#else>
<hr />
<div>${uiLabelMap.ProductNoProductsInThisCategory}</div>
</#if>
component://order/template/entry/catalog/ProductSummary.ftl
${virtualJavaScript!}
<script type="text/javascript">
<!--
function displayProductVirtualId(variantId, virtualProductId, pForm) {
if(variantId){
pForm.product_id.value = variantId;
}else{
pForm.product_id.value = '';
variantId = '';
}
var elem = document.getElementById('product_id_display');
var txt = document.createTextNode(variantId);
if(elem.hasChildNodes()) {
elem.replaceChild(txt, elem.firstChild);
} else {
elem.appendChild(txt);
}
var priceElem = document.getElementById('variant_price_display');
var price = getVariantPrice(variantId);
var priceTxt = null;
if(price){
priceTxt = document.createTextNode(price);
}else{
priceTxt = document.createTextNode('');
}
if(priceElem.hasChildNodes()) {
priceElem.replaceChild(priceTxt, priceElem.firstChild);
} else {
priceElem.appendChild(priceTxt);
}
}
//-->
</script>
<#if product??>
<#-- variable setup -->
<#if backendPath?default("N") == "Y">
<#assign productUrl><@ofbizCatalogUrl productId=product.productId productCategoryId=categoryId/></#assign>
<#else>
<#assign productUrl><@ofbizCatalogAltUrl productId=product.productId productCategoryId=categoryId/></#assign>
</#if>
<#if requestAttributes.productCategoryMember??>
<#assign prodCatMem = requestAttributes.productCategoryMember>
</#if>
<#assign smallImageUrl = productContentWrapper.get("SMALL_IMAGE_URL", "url")!>
<#assign largeImageUrl = productContentWrapper.get("LARGE_IMAGE_URL", "url")!>
<#if !smallImageUrl?string?has_content><#assign smallImageUrl = "/images/defaultImage.jpg"></#if>
<#if !largeImageUrl?string?has_content><#assign largeImageUrl = "/images/defaultImage.jpg"></#if>
<#-- end variable setup -->
<#assign productInfoLinkId = "productInfoLink">
<#assign productInfoLinkId = productInfoLinkId + product.productId/>
<#assign productDetailId = "productDetailId"/>
<#assign productDetailId = productDetailId + product.productId/>
<div class="productsummary">
<div class="smallimage">
<a href="${productUrl}">
<span id="${productInfoLinkId}" class="popup_link"><img src="<@ofbizContentUrl>${contentPathPrefix!}${smallImageUrl}</@ofbizContentUrl>" alt="Small Image"/></span>
</a>
</div>
<div id="${productDetailId}" class="popup" style="display:none;">
<table class="ui-widget">
<tr>
<th><img src="<@ofbizContentUrl>${contentPathPrefix!}${largeImageUrl}</@ofbizContentUrl>" alt="Large Image"/></th><td> </td>
</tr>
<tr>
<th>${uiLabelMap.ProductProductId}</th><td>${product.productId!}</td>
</tr>
<tr>
<th>${uiLabelMap.ProductProductName}</th><td>${productContentWrapper.get("PRODUCT_NAME", "html")!}</td>
</tr>
<tr>
<th>${uiLabelMap.CommonDescription}</th><td>${productContentWrapper.get("DESCRIPTION", "html")!}</td>
</tr>
</table>
</div>
<script type="text/javascript">
jQuery("#${productInfoLinkId}").attr('title', jQuery("#${productDetailId}").remove().html());
jQuery("#${productInfoLinkId}").tooltip({
content: function(){
return this.getAttribute("title");
},
tooltipClass: "popup",
track: true
});
</script>
<div class="productbuy">
<#-- check to see if introductionDate hasn't passed yet -->
<#if product.introductionDate?? && nowTimestamp.before(product.introductionDate)>
<div style="color: red;">${uiLabelMap.ProductNotYetAvailable}</div>
<#-- check to see if salesDiscontinuationDate has passed -->
<#elseif product.salesDiscontinuationDate?? && nowTimestamp.after(product.salesDiscontinuationDate)>
<div style="color: red;">${uiLabelMap.ProductNoLongerAvailable}</div>
<#-- check to see if it is a rental item; will enter parameters on the detail screen-->
<#elseif product.productTypeId! == "ASSET_USAGE">
<a href="${productUrl}" class="buttontext">${uiLabelMap.OrderMakeBooking}...</a>
<#-- check to see if it is an aggregated or configurable product; will enter parameters on the detail screen-->
<#elseif product.productTypeId! == "AGGREGATED" || product.productTypeId! == "AGGREGATED_SERVICE">
<a href="${productUrl}" class="buttontext">${uiLabelMap.OrderConfigure}...</a>
<#-- check to see if the product is a virtual product -->
<#elseif product.isVirtual?? && product.isVirtual == "Y">
<a href="${productUrl}" class="buttontext">${uiLabelMap.OrderChooseVariations}...</a>
<#-- check to see if the product requires an amount -->
<#elseif product.requireAmount?? && product.requireAmount == "Y">
<a href="${productUrl}" class="buttontext">${uiLabelMap.OrderChooseAmount}...</a>
<#elseif product.productTypeId! == "ASSET_USAGE_OUT_IN">
<a href="${productUrl}" class="buttontext">${uiLabelMap.OrderRent}...</a>
<#else>
<form method="post" action="<@ofbizUrl>additem</@ofbizUrl>" name="the${requestAttributes.formNamePrefix!}${requestAttributes.listIndex!}form" style="margin: 0;">
<input type="hidden" name="add_product_id" value="${product.productId}"/>
<input type="text" size="5" name="quantity" value="1"/>
<input type="hidden" name="clearSearch" value="N"/>
<input type="hidden" name="mainSubmitted" value="Y"/>
<a href="javascript:document.the${requestAttributes.formNamePrefix!}${requestAttributes.listIndex!}form.submit()" class="buttontext">${uiLabelMap.OrderAddToCart}</a>
<#if mainProducts?has_content>
<input type="hidden" name="product_id" value=""/>
<select name="productVariantId" onchange="javascript:displayProductVirtualId(this.value, '${product.productId}', this.form);">
<option value="">Select Unit Of Measure</option>
<#list mainProducts as mainProduct>
<option value="${mainProduct.productId}">${mainProduct.uomDesc} : ${mainProduct.piecesIncluded}</option>
</#list>
</select>
<div style="display: inline-block;">
<strong><span id="product_id_display"> </span></strong>
<strong><span id="variant_price_display"> </span></strong>
</div>
</#if>
</form>
<#if prodCatMem?? && prodCatMem.quantity?? && 0.00 < prodCatMem.quantity?double>
<form method="post" action="<@ofbizUrl>additem</@ofbizUrl>" name="the${requestAttributes.formNamePrefix!}${requestAttributes.listIndex!}defaultform" style="margin: 0;">
<input type="hidden" name="add_product_id" value="${prodCatMem.productId!}"/>
<input type="hidden" name="quantity" value="${prodCatMem.quantity!}"/>
<input type="hidden" name="clearSearch" value="N"/>
<input type="hidden" name="mainSubmitted" value="Y"/>
<a href="javascript:document.the${requestAttributes.formNamePrefix!}${requestAttributes.listIndex!}defaultform.submit()" class="buttontext">${uiLabelMap.CommonAddDefault}(${prodCatMem.quantity?string.number}) ${uiLabelMap.OrderToCart}</a>
</form>
<#assign productCategory = delegator.findOne("ProductCategory", Static["org.apache.ofbiz.base.util.UtilMisc"].toMap("productCategoryId", prodCatMem.productCategoryId), false)/>
<#if productCategory.productCategoryTypeId != "BEST_SELL_CATEGORY">
<form method="post" action="<@ofbizUrl>additem</@ofbizUrl>" name="the${requestAttributes.formNamePrefix!}${requestAttributes.listIndex!}defaultform" style="margin: 0;">
<input type="hidden" name="add_product_id" value="${prodCatMem.productId!}"/>
<input type="hidden" name="quantity" value="${prodCatMem.quantity!}"/>
<input type="hidden" name="clearSearch" value="N"/>
<input type="hidden" name="mainSubmitted" value="Y"/>
<a href="javascript:document.the${requestAttributes.formNamePrefix!}${requestAttributes.listIndex!}defaultform.submit()" class="buttontext">${uiLabelMap.CommonAddDefault}(${prodCatMem.quantity?string.number}) ${uiLabelMap.OrderToCart}</a>
</form>
</#if>
</#if>
</#if>
</div>
<div class="productinfo">
<div>
<a href="${productUrl}" class="linktext">${productContentWrapper.get("PRODUCT_NAME", "html")!}</a>
</div>
<div>${productContentWrapper.get("DESCRIPTION", "html")!}<#if daysToShip??> - ${uiLabelMap.ProductUsuallyShipsIn} <b>${daysToShip}</b> ${uiLabelMap.CommonDays}!</#if></div>
<#-- Display category-specific product comments -->
<#if prodCatMem?? && prodCatMem.comments?has_content>
<div>${prodCatMem.comments}</div>
</#if>
<#-- example of showing a certain type of feature with the product -->
<#if sizeProductFeatureAndAppls?has_content>
<div>
<#if (sizeProductFeatureAndAppls?size == 1)>
${uiLabelMap.SizeAvailableSingle}:
<#else>
${uiLabelMap.SizeAvailableMultiple}:
</#if>
<#list sizeProductFeatureAndAppls as sizeProductFeatureAndAppl>
${sizeProductFeatureAndAppl.abbrev?default(sizeProductFeatureAndAppl.description?default(sizeProductFeatureAndAppl.productFeatureId))}<#if sizeProductFeatureAndAppl_has_next>,</#if>
</#list>
</div>
</#if>
<div>
<b>${product.productId!}</b>
<#if totalPrice??>
<div>${uiLabelMap.ProductAggregatedPrice}: <span class='basePrice'><@ofbizCurrency amount=totalPrice isoCode=totalPrice.currencyUsed/></span></div>
<#else>
<#if price.competitivePrice?? && price.price?? && price.price?double < price.competitivePrice?double>
${uiLabelMap.ProductCompareAtPrice}: <span class='basePrice'><@ofbizCurrency amount=price.competitivePrice isoCode=price.currencyUsed/></span>
</#if>
<#if price.listPrice?? && price.price?? && price.price?double < price.listPrice?double>
${uiLabelMap.ProductListPrice}: <span class="basePrice"><@ofbizCurrency amount=price.listPrice isoCode=price.currencyUsed/></span>
</#if>
<b>
<#if price.isSale?? && price.isSale>
<span class="salePrice">${uiLabelMap.OrderOnSale}!</span>
<#assign priceStyle = "salePrice">
<#else>
<#assign priceStyle = "regularPrice">
</#if>
<#if (price.price?default(0) > 0 && product.requireAmount?default("N") == "N")>
${uiLabelMap.OrderYourPrice}: <#if "Y" = product.isVirtual!> ${uiLabelMap.CommonFrom} </#if><span class="${priceStyle}"><@ofbizCurrency amount=price.price isoCode=price.currencyUsed/></span>
</#if>
</b>
<#if price.listPrice?? && price.price?? && price.price?double < price.listPrice?double>
<#assign priceSaved = price.listPrice?double - price.price?double>
<#assign percentSaved = (priceSaved?double / price.listPrice?double) * 100>
${uiLabelMap.OrderSave}: <span class="basePrice"><@ofbizCurrency amount=priceSaved isoCode=price.currencyUsed/> (${percentSaved?int}%)</span>
</#if>
</#if>
<#-- show price details ("showPriceDetails" field can be set in the screen definition) -->
<#if (showPriceDetails?? && showPriceDetails?default("N") == "Y")>
<#if price.orderItemPriceInfos??>
<#list price.orderItemPriceInfos as orderItemPriceInfo>
<div>${orderItemPriceInfo.description!}</div>
</#list>
</#if>
</#if>
</div>
<#if averageRating?? && (averageRating?double > 0) && numRatings?? && (numRatings?long > 2)>
<div>${uiLabelMap.OrderAverageRating}: ${averageRating} (${uiLabelMap.CommonFrom} ${numRatings} ${uiLabelMap.OrderRatings})</div>
</#if>
<form method="post" action="<@ofbizUrl secure="${request.isSecure()?string}">addToCompare</@ofbizUrl>" name="addToCompare${requestAttributes.listIndex!}form">
<input type="hidden" name="productId" value="${product.productId}"/>
<input type="hidden" name="mainSubmitted" value="Y"/>
</form>
<a href="javascript:document.addToCompare${requestAttributes.listIndex!}form.submit()" class="buttontext">${uiLabelMap.ProductAddToCompare}</a>
</div>
</div>
<#else>
${uiLabelMap.ProductErrorProductNotFound}.<br />
</#if>
1.4 相关的java文件
org.apache.ofbiz.product.catalog.CatalogWorker
org.apache.ofbiz.product.category.CategoryWorker
服务getProductCategoryAndLimitedMembers具体实现
根据服务引擎工具找到对应getProductCategoryAndLimitedMembers服务的实现源码:
org.apache.ofbiz.product.category.CategoryServices.getProductCategoryAndLimitedMembers
public static Map<String, Object> getProductCategoryAndLimitedMembers(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
LocalDispatcher dispatcher = dctx.getDispatcher();
String productCategoryId = (String) context.get("productCategoryId");
boolean limitView = ((Boolean) context.get("limitView")).booleanValue();
int defaultViewSize = ((Integer) context.get("defaultViewSize")).intValue();
Timestamp introductionDateLimit = (Timestamp) context.get("introductionDateLimit");
Timestamp releaseDateLimit = (Timestamp) context.get("releaseDateLimit");
List<String> orderByFields = UtilGenerics.checkList(context.get("orderByFields"));
if (orderByFields == null) orderByFields = new LinkedList<String>();
String entityName = getCategoryFindEntityName(delegator, orderByFields, introductionDateLimit, releaseDateLimit);
String prodCatalogId = (String) context.get("prodCatalogId");
boolean useCacheForMembers = (context.get("useCacheForMembers") == null || ((Boolean) context.get("useCacheForMembers")).booleanValue());
boolean activeOnly = (context.get("activeOnly") == null || ((Boolean) context.get("activeOnly")).booleanValue());
// checkViewAllow defaults to false, must be set to true and pass the prodCatalogId to enable
boolean checkViewAllow = (prodCatalogId != null && context.get("checkViewAllow") != null &&
((Boolean) context.get("checkViewAllow")).booleanValue());
String viewProductCategoryId = null;
if (checkViewAllow) {
viewProductCategoryId = CatalogWorker.getCatalogViewAllowCategoryId(delegator, prodCatalogId);
}
Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
int viewIndex = 0;
try {
viewIndex = Integer.valueOf((String) context.get("viewIndexString")).intValue();
} catch (Exception e) {
viewIndex = 0;
}
int viewSize = defaultViewSize;
try {
viewSize = Integer.valueOf((String) context.get("viewSizeString")).intValue();
} catch (Exception e) {
viewSize = defaultViewSize;
}
GenericValue productCategory = null;
try {
productCategory = EntityQuery.use(delegator).from("ProductCategory").where("productCategoryId", productCategoryId).cache().queryOne();
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
productCategory = null;
}
int listSize = 0;
int lowIndex = 0;
int highIndex = 0;
if (limitView) {
// get the indexes for the partial list
lowIndex = ((viewIndex * viewSize) + 1);
highIndex = (viewIndex + 1) * viewSize;
} else {
lowIndex = 0;
highIndex = 0;
}
boolean filterOutOfStock = false;
try {
String productStoreId = (String) context.get("productStoreId");
if (UtilValidate.isNotEmpty(productStoreId)) {
GenericValue productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).queryOne();
if (productStore != null && "N".equals(productStore.getString("showOutOfStockProducts"))) {
filterOutOfStock = true;
}
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
List<GenericValue> productCategoryMembers = null;
if (productCategory != null) {
EntityListIterator pli = null;
try {
if (useCacheForMembers) {
productCategoryMembers = EntityQuery.use(delegator).from(entityName).where("productCategoryId", productCategoryId).orderBy(orderByFields).cache(true).queryList();
if (activeOnly) {
productCategoryMembers = EntityUtil.filterByDate(productCategoryMembers, true);
}
List<EntityCondition> filterConditions = new LinkedList<EntityCondition>();
if (introductionDateLimit != null) {
EntityCondition condition = EntityCondition.makeCondition(EntityCondition.makeCondition("introductionDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("introductionDate", EntityOperator.LESS_THAN_EQUAL_TO, introductionDateLimit));
filterConditions.add(condition);
}
if (releaseDateLimit != null) {
EntityCondition condition = EntityCondition.makeCondition(EntityCondition.makeCondition("releaseDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("releaseDate", EntityOperator.LESS_THAN_EQUAL_TO, releaseDateLimit));
filterConditions.add(condition);
}
if (!filterConditions.isEmpty()) {
productCategoryMembers = EntityUtil.filterByCondition(productCategoryMembers, EntityCondition.makeCondition(filterConditions, EntityOperator.AND));
}
// filter out of stock products
if (filterOutOfStock) {
try {
productCategoryMembers = ProductWorker.filterOutOfStockProducts(productCategoryMembers, dispatcher, delegator);
} catch (GeneralException e) {
Debug.logWarning("Problem filtering out of stock products :"+e.getMessage(), module);
}
}
// filter out the view allow before getting the sublist
if (UtilValidate.isNotEmpty(viewProductCategoryId)) {
productCategoryMembers = CategoryWorker.filterProductsInCategory(delegator, productCategoryMembers, viewProductCategoryId);
}
// set the index and size
listSize = productCategoryMembers.size();
if (limitView) {
// limit high index to (filtered) listSize
if (highIndex > listSize) {
highIndex = listSize;
}
// if lowIndex > listSize, the input is wrong => reset to first page
if (lowIndex > listSize) {
viewIndex = 0;
lowIndex = 1;
highIndex = Math.min(viewSize, highIndex);
}
// get only between low and high indexes
if (UtilValidate.isNotEmpty(productCategoryMembers)) {
productCategoryMembers = productCategoryMembers.subList(lowIndex-1, highIndex);
}
} else {
lowIndex = 1;
highIndex = listSize;
}
} else {
List<EntityCondition> mainCondList = new LinkedList<EntityCondition>();
mainCondList.add(EntityCondition.makeCondition("productCategoryId", EntityOperator.EQUALS, productCategory.getString("productCategoryId")));
if (activeOnly) {
mainCondList.add(EntityCondition.makeCondition("fromDate", EntityOperator.LESS_THAN_EQUAL_TO, nowTimestamp));
mainCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, nowTimestamp)));
}
if (introductionDateLimit != null) {
mainCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("introductionDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("introductionDate", EntityOperator.LESS_THAN_EQUAL_TO, introductionDateLimit)));
}
if (releaseDateLimit != null) {
mainCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("releaseDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("releaseDate", EntityOperator.LESS_THAN_EQUAL_TO, releaseDateLimit)));
}
EntityCondition mainCond = EntityCondition.makeCondition(mainCondList, EntityOperator.AND);
// set distinct on
// using list iterator
pli = EntityQuery.use(delegator).from(entityName).where(mainCond).orderBy(orderByFields).cursorScrollInsensitive().maxRows(highIndex).queryIterator();
// get the partial list for this page
if (limitView) {
if (viewProductCategoryId != null) {
// do manual checking to filter view allow
productCategoryMembers = new LinkedList<GenericValue>();
GenericValue nextValue;
int chunkSize = 0;
listSize = 0;
while ((nextValue = pli.next()) != null) {
String productId = nextValue.getString("productId");
if (CategoryWorker.isProductInCategory(delegator, productId, viewProductCategoryId)) {
if (listSize + 1 >= lowIndex && chunkSize < viewSize) {
productCategoryMembers.add(nextValue);
chunkSize++;
}
listSize++;
}
}
} else {
productCategoryMembers = pli.getPartialList(lowIndex, viewSize);
listSize = pli.getResultsSizeAfterPartialList();
}
} else {
productCategoryMembers = pli.getCompleteList();
if (UtilValidate.isNotEmpty(viewProductCategoryId)) {
// filter out the view allow
productCategoryMembers = CategoryWorker.filterProductsInCategory(delegator, productCategoryMembers, viewProductCategoryId);
}
listSize = productCategoryMembers.size();
lowIndex = 1;
highIndex = listSize;
}
// filter out of stock products
if (filterOutOfStock) {
try {
productCategoryMembers = ProductWorker.filterOutOfStockProducts(productCategoryMembers, dispatcher, delegator);
listSize = productCategoryMembers.size();
} catch (GeneralException e) {
Debug.logWarning("Problem filtering out of stock products :"+e.getMessage(), module);
}
}
// null safety
if (productCategoryMembers == null) {
productCategoryMembers = new LinkedList<GenericValue>();
}
if (highIndex > listSize) {
highIndex = listSize;
}
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
finally {
// close the list iterator, if used
if (pli != null) {
try {
pli.close();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
}
}
}
Map<String, Object> result = new HashMap<String, Object>();
result.put("viewIndex", Integer.valueOf(viewIndex));
result.put("viewSize", Integer.valueOf(viewSize));
result.put("lowIndex", Integer.valueOf(lowIndex));
result.put("highIndex", Integer.valueOf(highIndex));
result.put("listSize", Integer.valueOf(listSize));
if (productCategory != null) result.put("productCategory", productCategory);
if (productCategoryMembers != null) result.put("productCategoryMembers", productCategoryMembers);
return result;
}
2. 分析源码,找出主要的业务逻辑相关的代码。
分析CategoryDetail.groovy脚本中,andMap对象的包含的参数。
// get the product category & members
andMap = [productCategoryId : productCategoryId,
viewIndexString : viewIndex,
viewSizeString : viewSize,
defaultViewSize : defaultViewSize,
limitView : limitView]
andMap.put("prodCatalogId", currentCatalogId)
andMap.put("checkViewAllow", true)
// Prevents out of stock product to be displayed on site
productStore = ProductStoreWorker.getProductStore(request)
if (productStore) {
andMap.put("productStoreId", productStore.productStoreId)
}
if (context.orderByFields) {
andMap.put("orderByFields", context.orderByFields)
} else {
andMap.put("orderByFields", ["sequenceNum", "productId"])
}
catResult = runService('getProductCategoryAndLimitedMembers', andMap)
andMap的取值:
{
"productCategoryId":"PROMOTIONS",
"viewSizeString":"9",
"defaultViewSize":10,
"limitView":true,
"prodCatalogId":"DemoCatalog",
"checkViewAllow":true,
"productStoreId":"9000",
"orderByFields":["sequenceNum","productId"]
}
SELECT PC.*,pcm.*
FROM Product_Category pc
INNER JOIN Product_Category_Member PCM ON pc.product_Category_Id = PCM.product_Category_Id
WHERE pc.product_Category_Id = 'PROMOTIONS' ORDER BY pcm.sequence_Num,pcm.product_Id DESC
主要重点是参数"productCategoryId":"PROMOTIONS"是怎么传进来的。暂时不管了,知道特殊产品展示就是按上面的查询语句获取要展示的产品的。
3. 总结
为了获取andMap的值,引入了Gson包,方便调试。将gson-2.2.4.jar文件放入lib文件夹下,然后在CategoryDetail.groovy文件添加调试语句:
import com.google.gson.Gson;
gson = new Gson();
Debug.logInfo(gson.toJson(andMap), "CategoryDetailGroovy");
Debug.logInfo(gson.toJson(andMap), "CategoryDetailGroovy");
然后访问主页后(不用重启系统编译。修改文件后就生效了),可以去runtime/logs/ofbiz.log文件中找到对应日志。
查询指定分类下的推广产品分类
SELECT * FROM Prod_Catalog_Category WHERE prod_Catalog_Id = 'DemoCatalog' AND prod_Catalog_Category_Type_Id = 'PCCT_PROMOTIONS'
结果是:
SELECT PC.*,pcm.*
FROM Product_Category pc
INNER JOIN Product_Category_Member PCM ON pc.product_Category_Id = PCM.product_Category_Id
WHERE pc.product_Category_Id = 'PROMOTIONS' ORDER BY pcm.sequence_Num,pcm.product_Id DESC
根据查询结果的product_id字段可以关联product表获取产品信息。
SELECT p.*
FROM Product_Category pc
INNER JOIN Product_Category_Member PCM ON pc.product_Category_Id = PCM.product_Category_Id
INNER JOIN Product P ON p.product_id = PCM.product_id
WHERE pc.product_Category_Id = 'PROMOTIONS' ORDER BY pcm.sequence_Num,pcm.product_Id DESC
查询结果:
上一篇: 学习资源分享:某PHP培 训机 构的PHP学习导图
下一篇: phpstudy后门事件到底怎么回事