1. 程式人生 > >品優購專案記錄:day12

品優購專案記錄:day12

今日目標:

(1)掌握 Freemarker常用的指令與內建函式

(2)完成商品詳細頁的資料顯示

(3)完成商品詳細頁的動態顯示

(4)完成商品詳細頁讀取SKU資訊的業務邏輯

(5)完成商品稽核呼叫功能

目錄

1.1 配置

3、對接

1、商品詳細頁-資料顯示

準備工作:搭建工程(page-interface、page-service),並編寫相關配置和引入相關依賴

1.1 配置

(1)配置Freemarker的bean,在WEB-INF下建立ftl資料夾

	<!-- 配置freemarker-bean -->
	<bean id="freeMarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
		<!-- 模板檔案位置 -->
		<property name="templateLoaderPath" value="/WEB-INF/ftl/"/>
		<!-- 預設編碼 -->
		<property name="defaultEncoding" value="UTF-8"/>
	</bean>

(2)配置存放商品詳細頁的位置,注意保證資料夾存在,還需要將樣式檔案拷入該目錄

## 商品詳細頁存放位置
PAGE_DIR=D:\\item\\

1.2 服務層

(1)page-interface,編寫ItemPageService介面

package com.pinyougou.page.service;

/**
 * 商品詳細頁靜態化
 * Author xushuai
 * Description
 */
public interface ItemPageService {

    /**
     * 生成商品詳細頁
     *
     * @param goodsId 商品id
     * @return boolean
     */
    boolean genItemPage(Long goodsId);
}

(2)page-service,編寫ItemPageServiceImpl實現

package com.pinyougou.page.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.pinyougou.mapper.TbGoodsDescMapper;
import com.pinyougou.mapper.TbGoodsMapper;
import com.pinyougou.page.service.ItemPageService;
import com.pinyougou.pojo.TbGoods;
import com.pinyougou.pojo.TbGoodsDesc;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * 商品詳情頁靜態化實現
 * Author xushuai
 * Description
 */
@Service
@Transactional
public class ItemPageServiceImpl implements ItemPageService {

    @Autowired
    private FreeMarkerConfigurer FreeMarkerConfigurer;
    @Autowired
    private TbGoodsMapper goodsMapper;
    @Autowired
    private TbGoodsDescMapper goodsDescMapper;

    @Value("PAGE_DIR")
    private String PAGE_DIR;

    @Override
    public boolean genItemPage(Long goodsId) {
        try {
            // 查詢商品基本資訊和商品擴充套件資訊
            TbGoods tbGoods = goodsMapper.selectByPrimaryKey(goodsId);
            TbGoodsDesc tbGoodsDesc = goodsDescMapper.selectByPrimaryKey(goodsId);
            // 將查詢到的資料封裝到Map
            Map<String, Object> data = new HashMap<>();
            data.put("goods", tbGoods);
            data.put("goodsDesc", tbGoodsDesc);

            // 建立檔案輸出流
            Writer out = new FileWriter(PAGE_DIR + goodsId + ".html");

            // 使用模板生成商品詳細頁
            Configuration configuration = FreeMarkerConfigurer.getConfiguration();
            Template template = configuration.getTemplate("item.ftl");
            template.process(data, out);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}

1.3 基本測試

(1)拷貝靜態原型的item.html作為模板

(2)修改模板中的商品標題為插值:${goods.goodsName}

(3)測試

1.4 替換模板基本資訊為插值

(1)將item.ftl中的頭部和尾部分別放入另外兩個模板中,在item.ftl中使用<#include>匯入

(2)將商品基本資訊使用插值替換到模板中

1.5 替換模板圖片列表

(1)因為圖片列表為json串,我們需要將json串轉換為物件

<#-- 處理圖片列表Json串 -->
<#assign imageList = goodsDesc.itemImages?eval>

(2)遍歷生成的物件,展示圖片,注意限制圖片放大鏡的最大寬高

(3)效果

1.6 生成擴充套件屬性列表

(1)將擴充套件資訊的json串轉換為物件

<#-- 處理擴充套件屬性Json串 -->
<#if goodsDesc.customAttributeItems??>
    <#assign attrList = goodsDesc.customAttributeItems?eval>
</#if>

(2)遍歷展示擴充套件資訊

(3)效果

1.7 生成規格列表

(1)將規格列表資訊的json串轉換為物件

<#-- 處理規格列表Json串 -->
<#if goodsDesc.specificationItems??>
    <#assign specList = goodsDesc.specificationItems?eval>
</#if>

(2)展示規格資訊

(3)效果

1.8 生成商品型別麵包屑

(1)服務層實現(page-interface),修改ItemPageServiceImpl中的程式碼,主要為:查詢分類資訊

package com.pinyougou.page.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.pinyougou.mapper.TbGoodsDescMapper;
import com.pinyougou.mapper.TbGoodsMapper;
import com.pinyougou.mapper.TbItemCatMapper;
import com.pinyougou.page.service.ItemPageService;
import com.pinyougou.pojo.TbGoods;
import com.pinyougou.pojo.TbGoodsDesc;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * 商品詳情頁靜態化實現
 * Author xushuai
 * Description
 */
@Service
@Transactional
public class ItemPageServiceImpl implements ItemPageService {

    @Autowired
    private FreeMarkerConfigurer FreeMarkerConfigurer;
    @Autowired
    private TbGoodsMapper goodsMapper;
    @Autowired
    private TbGoodsDescMapper goodsDescMapper;
    @Autowired
    private TbItemCatMapper itemCatMapper;

    @Value("${PAGE_DIR}")
    private String PAGE_DIR;

    @Override
    public boolean genItemPage(Long goodsId) {
        try {
            // 獲取資料
            Map<String, Object> data = getDataMap(goodsId);

            // 建立檔案輸出流
            Writer out = new FileWriter(PAGE_DIR + goodsId + ".html");

            // 使用模板生成商品詳細頁
            Configuration configuration = FreeMarkerConfigurer.getConfiguration();
            Template template = configuration.getTemplate("item.ftl");
            template.process(data, out);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 獲取模板需要的資料
     * 
     * @param goodsId 商品ID
     * @return java.util.Map<java.lang.String,java.lang.Object> 
     */
    private Map<String, Object> getDataMap(Long goodsId) {
        Map<String, Object> data = new HashMap<>();
        // 查詢商品基本資訊和商品擴充套件資訊
        TbGoods tbGoods = goodsMapper.selectByPrimaryKey(goodsId);
        TbGoodsDesc tbGoodsDesc = goodsDescMapper.selectByPrimaryKey(goodsId);
        // 查詢商品分類資訊
        String category1 = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory1Id()).getName();
        String category2 = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory2Id()).getName();
        String category3 = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory3Id()).getName();

        // 將查詢到的資料封裝到Map
        data.put("goods", tbGoods);
        data.put("goodsDesc", tbGoodsDesc);
        data.put("category1", category1);
        data.put("category2", category2);
        data.put("category3", category3);

        return data;
    }
}

(2)替換模板中的文字

(3)效果

2、商品詳細頁-前端邏輯

2.1 數量的加減

(1)拷貝相關的JS檔案到存放商品詳情頁的目錄中

(2)在js目錄中新建controller資料夾,編寫itemController.js檔案

app.controller('itemController', function ($scope) {
    
    // 數量
	$scope.num = 1;

	// 增加數量
	$scope.incrNum = function() {
		$scope.num ++;
	}

	// 減少數量
	$scope.decrNum = function() {
		if($scope.num > 1) {
			$scope.num --;
		}
	}
});

(2)修改模板,在模板中引入相關JS檔案和基本指令

(3)數量輸入框繫結變數,+號和-號繫結單擊事件

2.2 規格選擇

(1)在itemController.js中新增方法

	// 選中的規格資料
	$scope.specificationItems = {};

	// 點選選中規格
	$scope.selectSpec = function(name, value) {
		// 設定給規格資料
		$scope.specificationItems[name] = value;
	}

	// 判斷當前規格是否被選中
	$scope.isSelected = function(name, value) {
		if ($scope.specificationItems[name] == value) {
			return true;
		} else {
			return false;
		}
	}

(2)模板中繫結變數和單擊事件

(3)效果

3、商品詳細頁-讀取SKU資訊

3.1 服務層實現(page-service)

(1)修改ItemPageServiceImpl中的getDataMap方法,新增獲取SKU列表資料的邏輯

(2)在頁面中將獲取到的SKU列表資料,生成變數,以後訪問都通過訪問這個變數

    <script>
        var skuList = [
            <#list itemList as item>
            {
                "id" : ${item.id?c},
                "title" : "${item.title!''}",
                "price" : ${item.price?c},
                "spec" : ${item.spec}
            },
            </#list>
        ];
    </script>

(3)測試效果

3.2 載入預設的SKU標題和價格

(1)在itemController.js中新增方法

	// 當前選擇SKU資訊
	$scope.sku={};

	// 載入預設的SKU資訊
	$scope.loadSku = function() {
		// 將skuList中的預設SKU資訊賦給當前選擇的SKU資訊
		$scope.sku = skuList[0];
	}

(2)在模板標題和價格處,繫結變數

(3)預設選中預設的規格,修改loadSku方法

(4)效果

3.3 選擇規格載入對應的標題和價格

(1)在itemController.js中新增方法

	// 判斷兩個物件是否內容相同
	$scope.matchObject = function(object1, object2) {
		for (var key in object1) {
			// 校驗當前鍵的值是否一致
			if (object1[key] != object2[key]) {
				return false;
			}
		}
		for (var key in object2) {
			// 校驗當前鍵的值是否一致
			if (object2[key] != object1[key]) {
				return false;
			}
		}
		// 內容相同
		return true;
	}

	// 獲取當前選中的SKU
	findSku = function() {
		for (var i = 0; i < skuList.length; i++) {
			if ($scope.matchObject($scope.specificationItems,skuList[i].spec)) {// 規格匹配
				// 當前迴圈到的sku為選中的sku
				$scope.sku = skuList[i];
				return ;
			}
		}
	}

(2)在選擇規格時,改變標題和價格,即在selectSpec中呼叫findSku方法

(3)效果

3.4 預留加入購物車方法

(1)在itemController.js中新增方法

	// 加入商品到購物車
	$scope.addToCart = function() {
		alert("SKU:" + $scope.sku.id + "加入購物車成功,購買數量為:" + $scope.num);
	}

(2)加入購物車按鈕,繫結事件

(3)效果

4、稽核商品生成商品詳細頁

4.1 控制層(manager-web)

(1)修改GoodsController中的updateStatus方法,新增邏輯

其他:與搜尋模組對接

1、配置Nginx

(1)修改生成靜態網頁的位置(page-service)

## 商品詳細頁存放位置
PAGE_DIR=E:\\temp\\freemarker\\

(2)將資原始檔放入該資料夾中

(3)配置nginx.conf配置檔案(windows版,測試用)

3、對接

(1)修改圖片連結地址