Commit 54365ecc authored by GuanHua's avatar GuanHua

feat:对接商品交易评价和最近销售商品的接口

parent 68667aac
.nodata_wrap {
padding: 25px 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&>p {
color: #6B778C;
font-size: 14px;
margin-top: 16px;
margin-bottom: 0;
}
}
\ No newline at end of file
import React from 'react'
import noDataIcon from '@/assets/imgs/nodata_default.png'
import styles from './index.less'
interface NoDataPropsType {
content?: string
}
const NoData: React.FC<NoDataPropsType> = (props) => {
const { content = "暂无数据" } = props
return (
<div className={styles.nodata_wrap}>
<img src={noDataIcon} />
<p>{content}</p>
</div>
)
}
export default NoData
......@@ -31,7 +31,6 @@ const Exhibition: React.FC<ExhibitionPropsType> = (props) => {
let collectFlg = true
useEffect(() => {
if (commodityDetail) {
console.log(shopInfo)
getCollectState()
}
}, [commodityDetail])
......@@ -124,9 +123,7 @@ const Exhibition: React.FC<ExhibitionPropsType> = (props) => {
commodityId: commodityDetail.id,
type: getLayoutType()
}
console.log([3, 4, 5].includes(getLayoutType()))
if ([3, 4, 5].includes(getLayoutType())) {
console.log(shopInfo.memberId, " shopInfo.memberId")
param.channelMemberId = shopInfo.memberId
}
if (collectState) {
......
import React from 'react'
import { COMMODITY_TYPE } from '@/constants'
import React, { useEffect, useState } from 'react'
import { COMMODITY_TYPE, LAYOUT_TYPE } from '@/constants'
import cx from 'classnames'
import { PublicApi } from '@/services/api'
import ImageBox from '@/components/ImageBox'
import { GlobalConfig } from '@/global/config'
import { numFormat, priceFormat } from '@/utils/numberFomat'
import { GetSearchShopChannelGetLatelyCommodityResponse } from '@/services/SearchApi'
import styles from './index.less'
interface InterestedPropsType {
priceType: COMMODITY_TYPE
priceType: COMMODITY_TYPE,
layoutType?: LAYOUT_TYPE,
shopInfo?: any
}
const Interested: React.FC<InterestedPropsType> = (props) => {
const { priceType } = props
const { priceType, layoutType, shopInfo } = props
const [commodityList, setCommodityList] = useState<GetSearchShopChannelGetLatelyCommodityResponse>([])
useEffect(() => {
if (shopInfo && priceType) {
console.log(props)
getchLatelyCommodity()
}
}, [shopInfo, priceType])
const getchLatelyCommodity = () => {
let getFn
let param: any = {}
switch (layoutType) {
case LAYOUT_TYPE.shop:
case LAYOUT_TYPE.mall:
param.storeId = shopInfo.id
if (priceType === COMMODITY_TYPE.integral) {
param.isScore = true
} else {
param.isScore = false
}
getFn = PublicApi.getSearchShopStoreGetLatelyCommodity
break
case LAYOUT_TYPE.channel:
case LAYOUT_TYPE.ichannel:
param.channelMemberId = shopInfo.memberId
if (priceType === COMMODITY_TYPE.integral) {
param.isScore = true
} else {
param.isScore = false
}
getFn = PublicApi.getSearchShopChannelGetLatelyCommodity
break
default:
break;
}
getFn && getFn(param).then(res => {
if (res.code === 1000) {
setCommodityList(res.data)
}
})
}
const getCommodityDetailLink = (item) => {
let link = ""
switch (layoutType) {
case LAYOUT_TYPE.channel:
link = `${GlobalConfig.channelRootRoute}/commodity/detail?id=${item.id}&type=${item.priceType}&channelId=${btoa(JSON.stringify({ shopId: item.storeId, memberId: item.memberId }))}`
break
case LAYOUT_TYPE.ichannel:
link = `${GlobalConfig.ichannelRootRoute}/commodity/detail?id=${item.id}&type=${item.priceType}&channelId=${btoa(JSON.stringify({ shopId: item.storeId, memberId: item.memberId }))}`
break
default:
link = `/shop/commodity/detail?id=${item.id}&type=${item.priceType}&shopId=${btoa(JSON.stringify({ shopId: item.storeId, memberId: item.memberId }))}`
break
}
return link
}
return (
<div className={styles.interested}>
<div className={styles.interested_title}>最近销售</div>
<div className={styles.interested_product_list}>
<a href="/shop/commodity/detail?id=asdjflewjfe&type=prompt">
<div className={styles.interested_product_list_item}>
<div className={styles.interested_product_list_item_img_box}>
<img src="https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1-6.jpg" />
</div>
<div className={styles.interested_product_list_item_name}>0.8-1.0mm黑色手折纹胎…</div>
{
priceType === COMMODITY_TYPE.integral ? <div className={cx(styles.interested_product_list_item_price, styles.integral)}>2,000~3,000 积分</div> :
<div className={styles.interested_product_list_item_price}><span></span> 79.00</div>
}
</div>
</a>
<a href="/shop/commodity/detail?id=asdjflewjfe&type=prompt">
<div className={styles.interested_product_list_item}>
<div className={styles.interested_product_list_item_img_box}>
<img src="https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1-6.jpg" />
</div>
<div className={styles.interested_product_list_item_name}>0.8-1.0mm黑色手折纹胎…</div>
{
priceType === COMMODITY_TYPE.integral ? <div className={cx(styles.interested_product_list_item_price, styles.integral)}>2,000~3,000 积分</div> :
<div className={styles.interested_product_list_item_price}><span></span> 79.00</div>
}
</div>
</a>
{
commodityList && commodityList.map(item => (
<a href={getCommodityDetailLink(item)} key={item.id}>
<div className={styles.interested_product_list_item}>
<div className={styles.interested_product_list_item_img_box}>
<ImageBox width={150} height={150} imgUrl={item.mainPic} />
</div>
<div className={styles.interested_product_list_item_name}>{item.name}</div>
{
priceType === COMMODITY_TYPE.integral ? <div className={cx(styles.interested_product_list_item_price, styles.integral)}>{item.min === item.max ? `${numFormat(item.min)}积分` : `${numFormat(item.min)}~${numFormat(item.max)}积分`}</div> :
<div className={styles.interested_product_list_item_price}><span></span> {priceFormat(item.min)}</div>
}
</div>
</a>
))
}
</div>
</div>
)
......
import React from 'react'
import React, { useState, useEffect } from 'react'
import cx from 'classnames'
import { Rate, Pagination } from 'antd'
import { Rate, Pagination, Spin } from 'antd'
import ImageViewList from '../ImageViewList'
import defaultAvatar from '@/assets/imgs/default_avatar.png'
import { PublicApi } from '@/services/api'
import { GetMemberCommentMallTradeHistoryPageResponseDetail, GetMemberCommentMallTradeSummaryResponse } from '@/services/MemberApi'
import isEmpty from 'lodash/isEmpty'
import NoData from '@/components/NoData'
import moment from 'moment'
import styles from './index.less'
const Comment: React.FC = () => {
interface CommentPropsType {
productIds: number[],
setCount: Function
}
const Comment: React.FC<CommentPropsType> = (props) => {
const { productIds, setCount } = props
const [current, setCurrent] = useState<number>(1)
const [pageSize, setPageSize] = useState<number>(10)
const [totalCount, setTotalCount] = useState<number>(0)
const [summaryInfo, setSummaryInfo] = useState<GetMemberCommentMallTradeSummaryResponse>()
const [commentList, setCommentList] = useState<GetMemberCommentMallTradeHistoryPageResponseDetail[]>([])
const [commentCountList, setCommentCountList] = useState<any>([])
const [commentType, setCommentType] = useState<string>('all')
const [spinLoading, setSpinLoading] = useState<boolean>(true)
useEffect(() => {
if (productIds && !isEmpty(productIds)) {
fetchCommentList()
fetchCommentSummary()
}
}, [productIds])
useEffect(() => {
if (productIds && !isEmpty(productIds)) {
fetchCommentList(commentType)
}
}, [current])
const fetchCommentList = (type = '') => {
let param: any = {
current,
pageSize,
productIds: productIds.toString() // '2339'
}
if (type === 'good') {
param.starLevel = 3
} else if (type === 'middle') {
param.starLevel = 2
} else if (type === 'bad') {
param.starLevel = 1
}
setSpinLoading(true)
//@ts-ignore
PublicApi.getMemberCommentMallTradeHistoryPage(param).then(res => {
setSpinLoading(false)
if (res.code === 1000) {
setTotalCount(res.data.totalCount)
setCommentList(res.data.data)
}
}).catch(() => {
setSpinLoading(false)
})
}
const fetchCommentSummary = () => {
PublicApi.getMemberCommentMallTradeSummary({ productIds: productIds.toString() }).then(res => {
if (res.code === 1000) {
setSummaryInfo(res.data)
getCommentCountBySummary(res.data.rows)
}
})
}
/**
* 计算各种评价星级的数量
* @param data
*/
const getCommentCountBySummary = (data) => {
let goodCount = 0
let middleCount = 0
let badCount = 0
if (data) {
for (let item of data) {
switch (item.star) {
case 1:
case 2:
badCount += item.sum || 0
break
case 3:
middleCount += item.sum || 0
break
case 4:
case 5:
goodCount += item.sum || 0
break
default:
break
}
}
}
let allCount = goodCount + middleCount + badCount
let result = [{
title: '全部评价',
sum: allCount,
sumText: allCount > 200 ? `(200+)` : `(${allCount})`,
type: 'all'
}, {
title: '好评',
sum: goodCount,
sumText: goodCount > 100 ? `(100+)` : `(${goodCount})`,
type: 'good'
}, {
title: '中评',
sum: middleCount,
sumText: middleCount > 100 ? `(100+)` : `(${middleCount})`,
type: 'middle'
}, {
title: '差评',
sum: badCount,
sumText: badCount > 100 ? `(100+)` : `(${badCount})`,
type: 'bad'
}]
setCommentCountList(result)
setCount(allCount)
}
const handleFilterCommentType = (type: string) => {
setCommentType(type)
fetchCommentList(type)
}
const handlePageChange = (page) => {
setCurrent(page)
}
return (
<div id="comment" className={styles.comment}>
<div className={styles.comment_title}>交易评价</div>
<div className={styles.favorable_comments}>
<div className={styles.favorable_comments_title}>好评率</div>
<span>98</span>
<span>{summaryInfo?.avgStar || 0}</span>
<i>%</i>
</div>
<div className={styles.common_count}>
<div className={cx(styles.common_count_item, styles.active)}>全部评价(200+)</div>
<div className={styles.common_count_item}>好评(100+)</div>
<div className={styles.common_count_item}>中评(99)</div>
<div className={styles.common_count_item}>差评(5)</div>
</div>
<div className={styles.comment_list}>
<div className={styles.comment_list_item}>
<div className={styles.comment_list_item_left}>
<div className={styles.user_avatar}>
<img src={defaultAvatar} />
{
commentCountList.map((item, index) => (
<div
key={`common_count_item_${index}`}
className={cx(styles.common_count_item, commentType === item.type ? styles.active : '')}
onClick={() => handleFilterCommentType(item.type)}
>
{item.title}{item.sumText}
</div>
<div className={styles.user_name}>温州市****皮具有限公司</div>
<div className={styles.user_type}>VIP会员</div>
</div>
<div className={styles.comment_list_item_right}>
<Rate className={styles.comment_rate} value={4} disabled />
<div className={styles.comment_content}>买的京东那个叫什么三购买的,不错。9块9。洗完澡以后穿着这个再大。听你走来走去也没事,跟家人一起的话穿着这个既文明药物。可以。保持礼貌。</div>
<div className={styles.comment_date}>2020-05-20 15:58</div>
</div>
))
}
</div>
<Spin spinning={spinLoading}>
<div className={styles.comment_list}>
{
(commentList && commentList.length > 0) ? commentList.map(item => (
<div className={styles.comment_list_item} key={item.id}>
<div className={styles.comment_list_item_left}>
<div className={styles.user_avatar}>
<img src={defaultAvatar} />
</div>
<div className={styles.user_name}>{item.memberName}</div>
<div className={styles.user_type}>{item.levelTag}</div>
</div>
<div className={styles.comment_list_item_right}>
<Rate className={styles.comment_rate} value={item.star} disabled />
<div className={styles.comment_content}>{item.comment}</div>
{
(item.pics && item.pics.length > 0) && <ImageViewList imgList={item.pics} />
}
<div className={styles.comment_date}>{moment(item.createTime).format("YYYY-MM-DD HH:mm")}</div>
</div>
</div>
)) : <NoData content="暂无交易评价" />
}
</div>
<div className={styles.comment_list_item}>
<div className={styles.comment_list_item_left}>
<div className={styles.user_avatar}>
<img src={defaultAvatar} />
{
totalCount > 0 && (
<div className={styles.pagination_wrap}>
<Pagination showQuickJumper={false} showSizeChanger={false} onChange={handlePageChange} current={1} pageSize={pageSize} total={totalCount} />
</div>
<div className={styles.user_name}>温州市****皮具有限公司</div>
<div className={styles.user_type}>VIP会员</div>
</div>
<div className={styles.comment_list_item_right}>
<Rate className={styles.comment_rate} value={4} disabled />
<div className={styles.comment_content}>买的京东那个叫什么三购买的,不错。9块9。洗完澡以后穿着这个再大。听你走来走去也没事,跟家人一起的话穿着这个既文明药物。可以。保持礼貌。</div>
<ImageViewList />
<div className={styles.comment_date}>2020-05-20 15:58</div>
</div>
</div>
</div>
<div className={styles.pagination_wrap}>
<Pagination showQuickJumper={false} showSizeChanger={false} defaultCurrent={1} total={50} />
</div>
)
}
</Spin>
</div>
)
}
......
......@@ -3,24 +3,18 @@ import { VerticalRightOutlined, FullscreenOutlined, UndoOutlined, RedoOutlined }
import cx from 'classnames'
import styles from './index.less'
const ImageViewList = () => {
interface ImageViewListPropsType {
imgList: string[]
}
const ImageViewList: React.FC<ImageViewListPropsType> = (props) => {
const [previewImage, setPreviewImage] = useState<number>(-1)
const [rotateZ, setRotateZ] = useState<number>(0)
const imgList = [
{
url: "https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1.jpg"
},
{
url: "https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1-5.jpg"
},
{
url: "https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1-3.jpg"
},
{
url: "https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1-2.jpg"
},
"https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1.jpg",
"https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1-5.jpg",
"https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1-3.jpg"
]
const handlePreviewImg = (index: number) => {
......@@ -46,7 +40,7 @@ const ImageViewList = () => {
break
case 'preview':
let el = document.createElement('a')
el.href = imgList[previewImage].url;
el.href = imgList[previewImage];
el.target = '_blank';
el.click()
break
......@@ -59,13 +53,13 @@ const ImageViewList = () => {
<div className={styles.image_view_list}>
<div className={styles.thumb_img_list}>
{
imgList.map((item, index) => (
imgList.map((path, index) => (
<div
key={`thumb_img_list_item_${index}`}
className={cx(styles.thumb_img_list_item, previewImage === index ? styles.active : '')}
onClick={() => handlePreviewImg(index)}
>
<img src={item.url} />
<img src={path} />
</div>
))
}
......@@ -91,7 +85,7 @@ const ImageViewList = () => {
<span>右转</span>
</div>
</div>
<img src={imgList[previewImage].url} style={{ transform: `rotateZ(${rotateZ}deg)` }} />
<img src={imgList[previewImage]} style={{ transform: `rotateZ(${rotateZ}deg)` }} />
</div>
)
}
......
......@@ -21,6 +21,7 @@ const ProductDescription: React.FC<ProductDescriptionPropsType> = (props) => {
const [currentAnchor, setCurrentAnchor] = useState<string>("#introduction")
const [productIds, setProductIds] = useState<number[]>([])
const [tradeRecordCount, setTradeRecordCount] = useState<number>(0)
const [commentCount, setCommentCount] = useState<number>(0)
const handleAnchorChange = (currentActiveLink: string) => {
if (currentActiveLink) {
......@@ -44,13 +45,13 @@ const ProductDescription: React.FC<ProductDescriptionPropsType> = (props) => {
onChange={handleAnchorChange}
>
<Link className={cx(currentAnchor === "#introduction" ? 'active' : '')} href="#introduction" title="产品简介" />
<Link href="#trade_record" title={commodityDetail?.priceType === COMMODITY_TYPE.integral ? `兑换记录(2)` : `交易记录${tradeRecordCount ? `(${tradeRecordCount})` : `(0)`}`} />
<Link href="#comment" title="交易评价(96)" />
<Link href="#trade_record" title={commodityDetail?.priceType === COMMODITY_TYPE.integral ? `兑换记录${tradeRecordCount ? `(${tradeRecordCount})` : `(0)`}` : `交易记录${tradeRecordCount ? `(${tradeRecordCount})` : `(0)`}`} />
<Link href="#comment" title={`交易评价(${commentCount > 999 ? '999+' : commentCount})`} />
<BackTop className={styles.buy_now_btn} visibilityHeight={800} >立即订购</BackTop>
</Anchor>
<Introduction commodityDetail={commodityDetail} />
<TradeRecord productIds={productIds} setCount={(count) => setTradeRecordCount(count)} />
<Comment />
<Comment productIds={productIds} setCount={(count) => setCommentCount(count)} />
<Recommand dataList={dataList} {...props} />
</div>
)
......
......@@ -963,7 +963,7 @@ const CommodityDetail = (props) => {
{
layoutType === LAYOUT_TYPE.shop && <ShopInfo {...props} />
}
<Interested priceType={commodityDetail?.priceType} />
<Interested priceType={commodityDetail?.priceType} shopInfo={shopInfo} {...props} />
</div>
<div className={styles.commodity_detail_body_right}>
<ProductDescription commodityDetail={commodityDetail} dataList={commonCategoryCommodityList} {...props} />
......
......@@ -78,6 +78,21 @@
z-index: 999;
}
.user_type {
color: #F8EDAF;
display: inline-block;
background-color: #303133;
height: 16px;
font-size: 12px;
line-height: 16px;
padding: 0 3px;
text-align: center;
}
.credit_count {
line-height: 16px;
}
.userInfo_card {
display: none;
position: absolute;
......@@ -88,7 +103,7 @@
background: #FFFFFF;
z-index: 99;
box-shadow: 0px 2px 8px 0px rgba(48, 49, 51, 0.08), 0px 0px 1px 0px #EEF0F3;
border: 1px solid #EEF0F3;
// border: 1px solid #EEF0F3;
&_header {
display: flex;
......
import React from 'react'
import React, { useEffect } from 'react'
import { EnvironmentOutlined, CaretDownOutlined } from '@ant-design/icons'
import { inject, observer } from 'mobx-react'
import cx from 'classnames'
......@@ -27,6 +27,10 @@ const TopBar: React.FC<TopBarPropsType> = (props) => {
const { langComponent, name, type, shopUrlParam } = props
const { userInfo } = props.UserStore
useEffect(() => {
}, [])
const getHomePath = () => {
switch (type) {
case LAYOUT_TYPE.shop:
......@@ -74,8 +78,9 @@ const TopBar: React.FC<TopBarPropsType> = (props) => {
<div className={styles.userInfo_card_header}>
<ImageBox width={64} height={64} circle={true} direction="column" imgUrl={defaultAvatar} />
<div className={styles.userInfo_card_column}>
<div>信用积分:<span>{numFormat(1278)}</span></div>
<div className={cx(styles.userInfo_card_level, styles.level3)} />
<div className={styles.credit_count}>信用积分:<span>{numFormat(1278)}</span></div>
<div className={styles.user_type}>VIP会员</div>
{/* <div className={cx(styles.userInfo_card_level, styles.level3)} /> */}
</div>
<div className={styles.sign_out_btn} onClick={handleSignOut}>退出账号</div>
</div>
......
......@@ -617,6 +617,38 @@ const PurchaseOrder: React.FC<PurchaseOrderPropsType> = (props) => {
return linkUrl
}
const getLayoutType = () => {
switch (layoutType) {
case LAYOUT_TYPE.mall:
case LAYOUT_TYPE.shop:
return 1
case LAYOUT_TYPE.channel:
return 3
case LAYOUT_TYPE.ichannel:
return 4
default:
return 1
}
}
const handleCollect = (commodityId: number) => {
let param: any = {
commodityId: commodityId,
type: getLayoutType()
}
if ([3, 4, 5].includes(getLayoutType())) {
param.channelMemberId = shopInfo.memberId
}
PublicApi.postSearchShopCommodityCollectSaveCommodityCollect(param).then(res => {
if (res.code === 1000) {
message.destroy()
message.success('收藏成功')
}
})
}
return (
<div className={styles.purchase_order}>
<div className={styles.purchase_order_container}>
......@@ -700,7 +732,7 @@ const PurchaseOrder: React.FC<PurchaseOrderPropsType> = (props) => {
</div>
<div className={cx(styles.order_list_item_item, styles.opration)}>
<div className={styles.order_list_item_item_operation}>
<div className={styles.order_list_item_item_operation_item}>移入收藏夹</div>
<div className={styles.order_list_item_item_operation_item} onClick={() => handleCollect(childItem.commodityUnitPrice.commodity.id)}>移入收藏夹</div>
<div className={styles.order_list_item_item_operation_item} onClick={() => handleDeleteItem(childItem.id)}>删除</div>
</div>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment