---
# System prepended metadata

title: B-CP-PRDS-02 販售產品詳細頁
tags: [CP頁]

---

# B-CP-PRDS-02 販售產品詳細頁
> [name=JasonWu]

###### tags: `CP頁`

## 網址
- https://{domain}/product/{型錄名稱}-{型錄ID}.html
    - ex: https://www.taiwantrade.com/product/font-color-red-salvia-miltiorrhiza-mouth-dissolving-font-pastilles-120-pastille-bottle-2-bottles-box-518429.html

## 原版程式
* com.hyweb.tt.cms.front.rest.ProductContentResource.java
* com.hyweb.tt.cms.front.service.pagedata.ProductContentPageData.java

## 頁面功能說明
- 透過 api 取得頁面所需資料
- 頁首部分共用![](https://i.imgur.com/zLb5CzO.jpg)
- 型錄內容說明 ![](https://i.imgur.com/6tREzfJ.jpg)
    - 上方需顯示麵包屑 > api 提供
    - 點選下面的小圖，上面會顯示對應大圖
    - 大圖須提供 zoom in 功能 ![](https://i.imgur.com/zzPjsYA.jpg)
    - 圖片下方的 facebook, twitter 等按鈕 ![](https://i.imgur.com/7OxuNt5.jpg)
請參考 https://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-585239dd7919d697
    - 當公司是 ep 類型時，Supplier 下方會出現 More About This Product，會連結至 ep 頁面 > 如果 api 有回傳 epUrl 時顯示
    - 如果有販售，顯示 Price、Payment 等相關訊息，api 會提供
    - 如果有販售，api 提供的資訊有折扣時，顯示的金額都會是 "折扣價"
    - 如果有販售，點選 Request for Quotation，會開新視窗，顯示 "RFQ商機頁"
    - 如果有販售，Quantity 可以變更，變更範圍需要參考上面的 Price table，決定對應的上下限 ![](https://i.imgur.com/jvpyd57.jpg)
參考上圖，Quantity 需介於 1~12 之間
    - 如果有販售，Quantity 變更時，需要從 price 表中找到對應的價格，並計算總額，以上圖為例，Quantity = 4，所以 Price 採用 900.00，並乘上數量後，顯示於 Total Price
    - 如果有販售，specInfoSelect 的資料需要做特殊效果處理
        - 以 https://www.ttstaging.com.tw/product/1560112 為例，當選擇 color 的時候，如果後台有設定 color = red 有圖片時![](https://i.imgur.com/bxtsWgb.jpg)
，型錄詳目頁需要顯示對應的圖片![](https://i.imgur.com/L1O68yk.jpg)
    - 如果有販售，會有 Buy Now 按鈕，點選 Buy Now 時，將會開啟視窗，進入 shopping cart 頁面
        - 點選 Buy Now 按鈕時，如果如上圖，有 Size, Color 這類的 SpecInfoSelect 資訊時，必須都要選擇後，才可以開啟 shopping cart 頁面
    - 點選 Contact Supplier 按鈕，頁面跳轉到下方的聯絡區塊
    - Add to cart 與 Add to favorite 請參考條列頁，點選後將此型錄加入 cart 或是 favorite，如果已經加入，購物車跟 favorite 的小圖示需要顯示對應的狀態
    - 下方的 line, skype 等資訊，依照 api 回傳值來判斷是否要顯示
---
- Product Detail![](https://i.imgur.com/H7p1BO4.jpg)
    - 型錄相關資訊，顯示 api 所回傳的資料
    - 點選認證圖片的燈箱效果參考 C-CP-COMS-2 認證燈箱
    - 如果 api 有回傳附加檔案，點選後可以下載 ![](https://i.imgur.com/v74aYmE.jpg)
---
- Company Profile
    - 公司相關資訊，顯示 api 所回傳的資料
    - 如果 api 有 other products 資料 ![](https://i.imgur.com/1qDYMW7.jpg)
        - 點選 product 連結，會 redirect 到該型錄詳目頁
        - 如果 api 有 All products 連結，代表該公司有 ep 網址，redirect 到對應的 url
    - Contact Us 需要判斷使用者是否登入，如果尚未登入，顯示的畫面會是 ![](https://i.imgur.com/5JhiZMQ.jpg)
    - 如果沒有登入，點選 Log in to view detail 時，需要 direct 到登入頁面，登入成功後會回到原本的 product cp 頁面
        - <font color="red">使用者提到要用燈箱來處理登入相關資訊，需要確認需求</font>
    - 如果使用者已登入，可以看到 Owner, Contact Person, Business Phone Number 等資料 ![](https://i.imgur.com/zCuJJIt.jpg)
    - 點選 Contact Supplier，跳轉至頁面下方的聯絡區塊
    - 如果 api 有回傳地址，需要顯示 google map 燈箱
---
- Shipping & Packaging ![](https://i.imgur.com/HbpdV0e.jpg)
    - 顯示 api 相關資料
    - 當切換國家、區域的時候，再次呼叫 api，並顯示 api 回傳的資料
---
- Payment Terms ![](https://i.imgur.com/EXOfJl2.jpg)
    - 顯示 api 相關資料
---
- Return Policy ![](https://i.imgur.com/1TwBRug.jpg)
    - 顯示 api 相關資料
---
- 聯絡人區塊 ![](https://i.imgur.com/4gVOp4C.jpg)
    - 參考 Inquiry Product 商機頁 (步驟一) 與 Inquiry Product 商機頁 (步驟二)
---
- 型錄推薦區塊 ![](https://i.imgur.com/T2BNMyZ.jpg)
    - 顯示 api 相關資料
    - 透過 slider 切換顯示項目
    - 點選型錄 url，redirect 至該型錄詳目頁

## 相關 api 分析
- 依照功能分類 api，可以分為以下幾類
    - 產品詳目頁 API
    - 公司內容 API
    - 認證 API
    - 如果有販售，需要有計算運費取得國家的 API
    - 如果有販售，需要有計算運費取得國家區域的 API
    - 如果有販售，需要有計算運費的 API
    - 推薦產品 API
    - Inquiry Product 新增商機 API
    - SEO ADM 設定 product cp 參數 API
- 參考 ep 設計，可參考的 API 可以分為以下幾個區塊
    - basicInfo > 取得產品名稱、型號、產品說明、產品認證等基本內容
    - sliderGallery > 取得產品圖片內容
    - videoInfo > 取得影片內容
    - multimedia > 取得 3d/360/video 的多媒體內容
    - specInfo > 取得產品設定的其他額外內容
    - specInfoSelect > 特殊規格內容，例如大小、顏色等內容
    - priceRangeInfo > 數量與價格對應表
    - attachInfo > 取得附加檔案
    - paymentTerm > 如果有販售，需取得 payment 相關內容
    - returnPolicy > 如果有販售，需取得退換貨相關內容

## 產品詳目頁 API
- 取得型錄相關資訊

### 規格
- path : ${TT-API網址}/product/info/{did}
- method : GET
- query : ?pid={pid}&langId={langId}

### API 邏輯
- 傳入 product id 與 language id
- 透過 sql 找出該型錄相關的資料並回傳
- 是否有販售，回傳資訊不同，顯示方式也不同

### Input
Column     | Type     | Require | Desc
-----------|----------|---------|---------
did        | number   | Y       | domain id
pid        | number   | Y       | 型錄id
langId     | number   | Y       | 語系id

### Output
- 回傳相關 json 內容，基本欄位參考 ep 相關功能
- 呼叫一次 api 回傳所有資訊，或者依區塊切開 api 內容，呼叫多次，這一段需要再討論
- 目前先依照一隻 api 回傳的方式來處理
- json 內容如下:
```=json
{ 
    "code" : {{ number }} , // 代碼，0：ok、 < 0: error 使用
    "errorMsg"  : {{ string }} , // 錯誤訊息
    // 型錄基本訊息
    "basicInfo" : {
        "productId" : {{ number }} , // 型錄
        "productName" : {{ string }} , // 型錄名稱
        "epUrl" : {{ string }} , // ep url
        "modelNo" : {{ string }} , // 型號
        "hasNewest" : {{ number }} , // 無(0)/有(1) newest tag
        "hasFeatured" : {{ number }} , // 無(0)/有(1) featured tag
        "hasSelling" : {{ number }} , // 無(0)/有(1) 販售
        "hasDiscount" : {{ number }} , // 無(0)/有(1) 折扣
        "hasFreeShipment" : {{ number }} , // 無(0)/有(1) 免運費
        "catalogStandardCid" : {{ number }} , // 標準 taitra code
        "fullCatalogName" : {{ string }} , // 標準 taitra code 名稱
        "madeIn" : {{ string }} , // 產地
        "priceCurrencyName" : {{ string }} , // 幣別
        "priceRange" : {{ string }} , // 價格區間，格式 min-max
        "discount" : {{ number }} , // 折扣，無折扣為 null
        "discountStartDate" : {{ string }} , // 折扣開始日期，無折扣為 ""
        "discountEndDate" : {{ string }} , // 折扣結束日期，無折扣為 ""
        "fullDiscountEndDate" : {{ string }} , // 折扣結束日期，無折扣為 ""
        "discountDayLeft" : {{ number }} , // 折扣剩餘天數，無折扣為 null
        "discountPriceRange" : {{ string }} , // 折扣價格區間，格式 min-max
        "unitName" : {{ string }} , // 單位
        "ezMinOrderCount" : {{ number }} , // 最小訂購數量
        "ezMaxOrderCount" : {{ number }} , // 最大訂購數量
        "contactSkype" : {{ string }} , // 聯絡人 skype 帳號
        "contactLine" : {{ string }} , // 聯絡人 line 帳號
        "contactQq" : {{ string }} , // 聯絡人 qq 帳號
        "contactWeChat" : {{ string }} , // 聯絡人 wechat 帳號
        "contactWhatsApp" : {{ string }} , // 聯絡人 whatsapp 帳號
        "contactFbMessenger" : {{ string }} , // 聯絡人 fb 帳號
        "videoId" : {{ number }} , // 影片 video id，沒有為 null
        "videoTypeName" : {{ string }} , // 影片 type
        "videoTitle" : {{ string }} , // 影片標題
        "videoUrl" : {{ string }} , // 影片 url
        "adSlogan" : {{ string }} , // 型錄廣告詞
        "logoType" : {{ number }} , // 1:MIC_logo, 2:DIC_logo, 其他:不顯示
        "keyFaturesHtml" : {{ string }} , // 型錄說明
        "paymentTerms" : {{ string }} , // 其他 Payment 說明
        "minOrderQuantityDesc" : {{ string }} , // 最小訂購數量說明
        "payCodeInfos" : {{ string }} , // 其他 Payment 圖示與排序資訊
        // "[{\"sort\": 1, \"code\": \"idealez_paypal\"},{\"sort\": 2, \"code\": \"idealez_card\"},...]"
    },
    // 圖片相關，array 中可以放多張
    "sliderGalleryInfos" : [
        {
            "seq" : {{ number }} , // 圖片順序
            "haspPrimary" : {{ number }} , // 是(1)/否(0) 為主圖
            "imgDesc" : {{ string }} , // 圖片說明
            "img360_360Url" : {{ string }} , // 圖片 360x360
            "img100_100Url" : {{ string }} , // 圖片 100x100
            "imgOriUrl" : {{ string }} , // 原始圖片 url
            "pcImgUrl" : {{ string }} , // pc 版本顯示圖片 url
            "mobileImgUrl" : {{ string }} // mobile 版本顯示圖片 url
        }
    ],
    // 影片相關
    "videoInfo" : {
        "id" : {{ number }} , // 影片 id
        "type" : {{ string }} , // 影片類型
        "title" : {{ string }} , // 影片標題
        "url" : {{ string }}  // 影片 url
    },
    // 3d/360 多媒體相關
    "multimedia" : {
        "multi_media_3d_title" : {{ string }} , // 多媒體 3d 標題
        "multimedia_3d_url" : {{ string }} , // 多媒體 3d url
        "multi_media_360_title" : {{ string }} , // 多媒體 360 標題
        "multimedia_360_url" : {{ string }} , // 多媒體 360 url
        "video_title" : {{ string }} , // 多媒體 video 標題
        "video_url" : {{ string }} // 多媒體 video url
    },
    // 規格相關，可能有多筆，顯示於說明文字
    "specInfo" : [
        {
            "name" : {{ string }} , // 規格名稱
            "value" : {{ string }} // 規格值
        },
    ],
    // 規格下拉相關，可能有多筆，選擇後有可能需要增加對應的圖片
    "specInfoSelect" : [
        {
            "sid" : {{ number }}, // 序號
            "name" : {{ string }}, // 名稱
            "specDatas" : [
                {
                    "specDetailId" : {{ number }}, // 序號
                    "name" : {{ string }}, // 名稱
                    "attachId" : {{ number }}, // 圖片 aid
                    "pic480" : {{ string }}, // 480x480 圖片
                    "pic50" : {{ string }}, // 50x50 圖片
                    "pic100" : {{ string }} // 100x100 圖片
                },
            ]
        }
    ],
    // 購買數量與價格匹配區間，可以多筆，對應的金額會用在計算上
    "priceRangeInfo" : [
        {
            "seq" : {{ number }}, // 序號
            "quantityRange" : {{ string }}, // 數量區間 min-max
            "price" : {{ string }}, // 本區間價格，格式: 幣別 + 金額，例如 USD 10.50
            "prepareDay" : {{ string }}, // 準備日
            "discount" : {{ number }}, // 折扣，無折扣為 0
            "isSelling" : {{ number }}, // 是(1)/否(0) 販售
            "discountPrice" : {{ string }} // 本區間折扣價格，格式: 幣別 + 金額，例如 USD 10.50
        }
    ],
    // 附加檔案，可能有多筆
    "attachInfo" : [
        {
            "fileUrl" : {{ string }}, // 檔案 url
            "fileName" : {{ string }}, // 檔案名稱
            "fileDesc" : {{ string }}, // 檔案說明
            "fileMbSize" : {{ string }} // 檔案大小            
        }
    ],
    // 如果有販售，需取得 payment 相關內容
    "paymentTerm" : [
        {
            "code" : {{ string }}, // payment code
            "allCurrency" : {{ string }} // payment 幣別
        }
    ],
    "returnPolicy" : {{ string }} // 退換貨內容文字
}
```

### 取值方式
- 透過 sql 取值
```=sql
```

---

## 公司內容 API
- 參考相關公司 API

### 規格
- path : ${TT-API網址}/product/company/{did}
- method : GET
- query : ?cid={cid}&langId={langId}&loginCheck={check}

### Input
Column     | Type     | Require | Desc
-----------|----------|---------|---------
did        | number   | Y       | domain id
cid        | number   | Y       | 公司 id
langId     | number   | Y       | 語系 id
loginCheck | string   | Y       | 是否已登入，決定是否要回傳公司聯絡人資訊，要定義一下作法

### Output
- 參考相關公司 API

### 取值方式
- 參考相關公司 API

---

## 販售國家 API
- 參考目前 ep 的販售國家取法

### 規格
- path : ${TT-API網址}/product/deliverycountry/{languageId}
- method : GET

### Input
Column         | Type     | Require | Desc
---------------|----------|---------|---------
languageId     | number   | Y       | 語系id

### Output
- json 內容如下:
```=json
{ 
    "code" : {{ number }} , // 代碼，0：ok、 < 0: error 使用
    "errorMsg"  : {{ string }} , // 錯誤訊息
    "rows" : [
        {
            "cid" : {{ number }} , // 國家 id
            "hasDefault" : {{ number }} , // 是否為預設選取
            "code" : {{ string }} , // 國家簡碼
            "name" : {{ string }}  // 國家名稱
        },...
    ]
}
```

### 取值方式
- 透過 sql 取值
```
```

---

## 販售區別 API
- 參考目前 ep 的販售區域取法
- 需要傳入國家id

### 規格
- path : ${TT-API網址}/product/deliverystate/{countryId}/{langId}
- method : GET

### Input
Column     | Type     | Require | Desc
-----------|----------|---------|---------
countryId  | number   | Y       | 運送國家id
langId     | number   | Y       | 語系id

### Output
- json 內容如下:
```=json
{ 
    "code" : {{ number }} , // 代碼，0：ok、 < 0: error 使用
    "errorMsg"  : {{ string }} , // 錯誤訊息
    "rows" : [
        {
            "cid" : {{ number }} , // 區域 id
            "name" : {{ string }}  // 區域名稱
        },...
    ]
}
```

### 取值方式
- 透過 sql 取值
```
```

---

## 販售運費計算 API
- 參考目前 ep 的販售運費算法
- 需要傳入國家id，不同國家取得的運費不同

### 規格
- path : ${TT-API網址}/product/sellinfo/{did}
- method : GET
- query : ?pid={pid}&countryId={countryId}&langId={langId}

### Input
Column     | Type     | Require | Desc
-----------|----------|---------|---------
did        | number   | Y       | domain id
pid        | number   | Y       | 型錄id
countryId  | number   | Y       | 運送國家id
langId     | number   | Y       | 語系id

### Output
- json 內容如下:
```=json
{ 
    "code" : {{ number }} , // 代碼，0：ok、 < 0: error 使用
    "errorMsg"  : {{ string }} , // 錯誤訊息
    "rows" : [
        {
            "code" : {{ string }} , // code
            "name" : {{ string }} , // name
            "shippingType" : {{ number }} , // 0: 免運費 1:自訂運費 2:固定運費 3:會員專屬優惠運費
            "customAmount" : {{ number }} , // 自訂運費單位數
            "customPortage" : {{ number }} , // 自訂運費
            "customOverAmount" : {{ number }} , // 自訂超過運費單位數
            "customOverPortage" : {{ number }} , // 自訂超過運費
            "forAllCountry" : {{ number }} , // 是否為全部國家(1: 是, 0: 否, default 為 0)
            "fixFee" : {{ number }} , // 固定運費
            "spType" : {{ number }} , // 優惠方案:1-貿協優惠運費,2-廠商自訂折扣
            "customDiscount" : {{ number }} , // 廠商自訂折扣折數
            "calculateRule" : {{ number }} , // 計價原則
            "productHeight" : {{ number }} , // 產品高
            "productLength" : {{ number }} , // 產品長
            "productWidth" : {{ number }} , // 產品寬
            "productWeight" : {{ number }} , // 產品重量
            "estimatedDeliveryTime" : {{ string }}  // 預計寄送時間
        }
    ]
}
```

### 取值方式
- 透過程式取值
```
```

---

## 推薦產品 API
- 透過 idol 取得該型錄推薦的未販售型錄
    - recommane > 未販售型錄
    - small order > 有販售型錄
- 參考現行邏輯，組出 idol url

### 規格
- 參考 https://hackmd.io/@jTFbLxrFR6qCyUF4lSdQCA/rJoPiGVI_
- path : ${TT-API網址}/products/detail/recommends/{did}
- method : GET
- query : ?id={id}&type={type}&cid={cid}

### Input
Column     | Type     | Require | Desc
-----------|----------|---------|---------
did        | number   | Y       | domain id
id         | number   | Y       | 型錄id
type       | string   | Y       | 固定傳入 'product'
cid        | number   | Y       | 公司id

### Output
- json 內容如下:
```=json
{ 
    "code" : {{ number }} , // 代碼，0：ok、 < 0: error 使用
    "errorMsg"  : {{ string }} , // 錯誤訊息
    "rows" : [
        {
            "productId" : {{ number }}, // 推薦型錄id
            "name" : {{ string }}, // 推薦型錄名稱
            "modelNo" : {{ string }}, // 推薦型錄型號
            "productUrl" : {{ string }}, // 推薦型錄url
            "imgUrl150" : {{ string }}, // 推薦型錄圖片 150x150
            "imgUrl220" : {{ string }}, // 推薦型錄圖片 220x220
            "imgUrl480" : {{ string }}, // 推薦型錄圖片 480x480
            "isFreeShipping" : {{ number }}, // 推薦型錄 是(1)/否(0) 免運費
            "isSelling" : {{ number }}, // 推薦型錄 是(1)/否(0) 販售
            "isDiscount" : {{ number }}, // 推薦型錄 是(1)/否(0) 折扣
            "quantity" : {{ number }}, // 推薦型錄數量
            "unitName" : {{ string }}, // 推薦型錄單位
            "priceRange" : {{ string }}, // 推薦型錄價格，USD 10.00-20.00
            "priceDiscountRange" : {{ string }}, // 推薦型錄折扣價格，USD 10.00-20.00
        }
    ]
}
```

### 取值方式
- 透過 idol 取值

---

## Inquiry Product 新增商機 API
- 參考 https://hackmd.io/-JgxZNPEQ2OCtJPxCYVLYw

---

## SEO ADM 設定 product cp 參數 API
- adm 可以設定相關頁面的標題等資訊，透過此 api 取得設定檔
- 相關頁面都有可能會用到此功能
- 透過 api 取得 adm 所設定的格式，例如 Product %productName% %companyName%
- 一併回傳其他頁面相關 meta tag

### 規格
- 參考 https://docs.google.com/spreadsheets/d/12U90GlZtqTFVemxzp5lFCv5l_eAZchVlOJN6xbRxDLI/edit#gid=0&range=A67
- path : ${TT-API網址}/domains/seo/{seoType}/{pageType}/{did}/{rowId}
- method : GET

### Input
Column     | Type     | Require | Desc
-----------|----------|---------|---------
seoType    | string   | Y       | normal
pageType   | string   | Y       | 固定為 productCp
did        | number   | Y       | domain id
rowId      | number   | Y       | 傳入 product id

### Output
- 參考 https://docs.google.com/spreadsheets/d/12U90GlZtqTFVemxzp5lFCv5l_eAZchVlOJN6xbRxDLI/edit#gid=0&range=A67

### 取值方式
- 參考 https://docs.google.com/spreadsheets/d/12U90GlZtqTFVemxzp5lFCv5l_eAZchVlOJN6xbRxDLI/edit#gid=0&range=A67
