Commit 94813c1e authored by GuanHua's avatar GuanHua

feat:商品详情和渠道商首页

parent b0f26dbf
import React, { useEffect, useState } from 'react'
import { MinusOutlined, PlusOutlined } from '@ant-design/icons'
import cx from 'classnames'
import './index.less'
import styles from './index.less'
interface InputNumberPropsType {
value: number;
onChange: Function;
min?: number;
max?: number;
disabled?: boolean;
}
const InputNumber: React.FC<InputNumberPropsType> = (props) => {
const { value, onChange, min, max } = props
const { value, onChange, min, max, disabled = false } = props
const [minCount, setMinCount] = useState<number>(1)
const [maxCount, setMaxCount] = useState<number>()
......@@ -21,7 +22,12 @@ const InputNumber: React.FC<InputNumberPropsType> = (props) => {
setMinCount(min)
onChange(min)
}
max && setMaxCount(max)
if (max || max === 0) {
setMaxCount(max)
if (value > max) {
onChange(max)
}
}
}, [min, max])
const handleReduce = () => {
......@@ -31,8 +37,9 @@ const InputNumber: React.FC<InputNumberPropsType> = (props) => {
}
const handleAdd = () => {
onChange(Number(value) + 1)
if (value < maxCount) {
onChange(Number(value) + 1)
}
}
const handleChange = (e) => {
......@@ -56,10 +63,10 @@ const InputNumber: React.FC<InputNumberPropsType> = (props) => {
}
return (
<div className="input_number">
<div className={cx("input_number_item reduce", value <= minCount ? 'disable' : '')} onClick={handleReduce}><MinusOutlined /></div>
<input className="input_number_input" value={value} onChange={handleChange} onBlur={handleBlur} />
<div className={cx("input_number_item add", value >= maxCount ? 'disable' : '')} onClick={handleAdd}><PlusOutlined /></div>
<div className={styles.input_number}>
<div className={cx(styles.input_number_item, styles.reduce, value <= minCount ? styles.disable : '')} onClick={handleReduce}><MinusOutlined /></div>
<input disabled={disabled} className={styles.input_number_input} value={value} onChange={handleChange} onBlur={handleBlur} />
<div className={cx(styles.input_number_item, styles.add, value >= maxCount ? styles.disable : '')} onClick={handleAdd}><PlusOutlined /></div>
</div>
)
}
......
......@@ -212,7 +212,7 @@ const ChannelInfo: React.FC<ShopInfoPropsType> = (props) => {
let selectItem = allMallList.filter(item => item.id === mallId)
setShopId(mallId)
if (mallId) {
setStoreUrl(`${siteUrl}/channelMall?id=${btoa(JSON.stringify({ shopId: shopInfo.shopId, memberId: shopInfo.memberId }))}`)
setStoreUrl(`${siteUrl}/channelmall?id=${btoa(JSON.stringify({ shopId: shopInfo.shopId, memberId: shopInfo.memberId }))}`)
// setStoreUrl(`${siteUrl}/${selectItem[0].url}?id=${1}`)
} else {
setStoreUrl(null)
......
......@@ -123,7 +123,7 @@ const ChannelIndex: React.FC<ChannelIndexPropsType> = (props) => {
<div className={styles.channel_index}>
<div className={styles.banner}>
{
useMemo(() => <Advert type="banner" advertList={firstAdvertList} hasQuickNav={false} />, [firstAdvertList])
useMemo(() => <Advert visible={firstAdvertList.length > 0} type="banner" advertList={firstAdvertList} hasQuickNav={false} />, [firstAdvertList])
}
</div>
<FloorAnchor anchorList={categoryList} type="shop" />
......@@ -133,7 +133,7 @@ const ChannelIndex: React.FC<ChannelIndexPropsType> = (props) => {
}
<Advert type="service" advertList={secondAdvertList} />
<CommonTitle title="关于我们" type="primary" />
<AboutUs shopInfo={shopInfo} shopUrlParam={shopUrlParam} />
<AboutUs shopInfo={shopInfo} shopUrlParam={shopUrlParam} type={LAYOUT_TYPE.channel} />
<Information />
</div >
)
......
......@@ -243,13 +243,25 @@
align-items: center;
font-size: 16px;
color: #D32F2F;
border-radius: 0;
cursor: pointer;
&[disabled] {
cursor: not-allowed;
}
&.buy {
background-color: #D32F2F;
color: #FFF;
border: 1px solid #D32F2F;
;
&[disabled] {
color: rgba(0, 0, 0, 0.25);
background: #f5f5f5;
border-color: #d9d9d9;
text-shadow: none;
box-shadow: none;
}
}
&:hover {
......
import React, { useState, useEffect } from 'react'
import { QuestionCircleOutlined } from '@ant-design/icons'
import { Tooltip, message } from 'antd'
import { Tooltip, message, Button } from 'antd'
import cx from 'classnames'
import { history } from 'umi'
import DialogModal from '../components/DialogModal'
......@@ -253,6 +253,7 @@ const CommodityDetail = (props) => {
memberDiscount: parameter,
category: commodityDetail.customerCategory.name,
brand: commodityDetail.brand.name,
stockCount: commodityDetail.stockCount,
commodityPic: attrAndValList.commodityPic[0],
attribute: attrAndValList.attributeAndValueList
}
......@@ -287,7 +288,7 @@ const CommodityDetail = (props) => {
case COMMODITY_TYPE.prompt:
return (
<>
<div className={cx(styles.product_info_btn_item, styles.buy)} onClick={() => handleToBuy()}>立即订购</div>
<Button disabled={buyCount <= 0} className={cx(styles.product_info_btn_item, styles.buy)} onClick={() => handleToBuy()}>立即订购</Button>
<div className={cx(styles.product_info_btn_item, styles.add)} onClick={() => handleAddToPurchase()} >
<img className={styles.btn_icon} src={jinhuodanIcon} />
<span>加入进货单</span>
......@@ -581,16 +582,16 @@ const CommodityDetail = (props) => {
<div className={styles.product_info_line}>
<div className={styles.product_info_line_label}>库存数量</div>
<div className={styles.product_info_line_brief}>
<span className={styles.text}>20,000{commodityDetail?.unitName}</span>
<span className={styles.text}>{numFormat(commodityDetail?.stockCount)}{commodityDetail?.unitName}</span>
</div>
</div>
) : (
<div className={styles.product_info_line}>
<div className={styles.product_info_line_label}>{commodityDetail?.priceType === COMMODITY_TYPE.prompt ? '购买数量' : '兑换数量'}</div>
<div className={cx(styles.product_info_line_brief, styles.row)}>
<InputNumber value={buyCount} min={commodityDetail?.priceType === COMMODITY_TYPE.prompt ? commodityDetail?.minOrder : 1} max={20000} onChange={(value) => setBuyCount(value)} />
<InputNumber disabled={commodityDetail?.stockCount === 0} value={buyCount} min={commodityDetail?.priceType === COMMODITY_TYPE.prompt ? commodityDetail?.minOrder : 1} max={commodityDetail?.stockCount} onChange={(value) => setBuyCount(value)} />
<span className={cx(styles.text, styles.mar_left_10)}>{commodityDetail?.unitName}</span>
<span className={cx(styles.text, styles.mar_left_10)}>(库存{numFormat(20000)}{commodityDetail?.unitName})</span>
<span className={cx(styles.text, styles.mar_left_10)}>(库存{numFormat(commodityDetail?.stockCount)}{commodityDetail?.unitName})</span>
</div>
</div>
)
......
......@@ -3,6 +3,7 @@ import cx from 'classnames'
import { Link } from 'umi'
import { ArrowRightOutlined } from '@ant-design/icons'
import { Carousel } from 'antd'
import { LAYOUT_TYPE } from '@/constants'
import { GetTemplateShopFindShopResponse, GetTemplateChannelFindChannelResponse } from '@/services/TemplateApi'
import styles from './index.less'
......@@ -13,11 +14,12 @@ enum TAB_TYPE {
interface AboutUsPropsType {
shopInfo: GetTemplateShopFindShopResponse | GetTemplateChannelFindChannelResponse,
shopUrlParam?: string
shopUrlParam?: string,
type: LAYOUT_TYPE
}
const AboutUs: React.FC<AboutUsPropsType> = (props) => {
const { shopInfo, shopUrlParam } = props
const { shopInfo, shopUrlParam, type } = props
const [aboutTab, setAboutTab] = useState<number>(TAB_TYPE.introduction) //1:公司简介 2:资质荣誉
const handleChangeAboutTab = (tab: number) => {
......@@ -26,6 +28,19 @@ const AboutUs: React.FC<AboutUsPropsType> = (props) => {
}
}
const getMoreLink = () => {
let link = ''
switch (type) {
case LAYOUT_TYPE.shop:
link = `/shop/about?shopId=${shopUrlParam}`
break
case LAYOUT_TYPE.channel:
link = `/channelmall/about?id=${shopUrlParam}`
break
}
return link
}
return (
<div className={styles.channel_info_about} id="about_us">
<div className={styles.channel_info_about_container}>
......@@ -71,7 +86,7 @@ const AboutUs: React.FC<AboutUsPropsType> = (props) => {
}
<div className={styles.channel_info_about_info_more}>
<Link to={`/shop/about?shopId=${shopUrlParam}`}>查看更多</Link>
<Link to={getMoreLink()}>查看更多</Link>
<ArrowRightOutlined />
</div>
</div>
......
import React, { useState } from 'react'
import cx from 'classnames'
import { Link, history } from 'umi'
import { FileTextOutlined } from '@ant-design/icons'
import React, { useState, useEffect } from 'react'
import { GetTemplateChannelFindChannelResponse } from '@/services/TemplateApi'
import logo from '@/theme/imgs/logo_w.png'
import './index.less'
interface HeaderPropsType {
shopInfo: GetTemplateChannelFindChannelResponse
}
const Header: React.FC<HeaderPropsType> = (props) => {
const { shopInfo } = props
const [searchType, setSearchType] = useState<number>(1) // 1:商品; 2:店铺
const handleChangeSearchType = (type: number) => {
if (searchType !== type) {
setSearchType(type)
}
}
useEffect(() => {
console.log(shopInfo, "shopInfo")
}, [shopInfo])
return (
<div className="header">
<div className="header_container">
<div className="logo">
<img src={logo} />
<img src={shopInfo?.logo} />
</div>
<div className="mall_search">
<div className="mall_search_box">
......
......@@ -64,9 +64,17 @@
cursor: pointer;
margin: 0 10px;
&>a {
color: var(--mall_main_color);
}
&.primary {
background-color: var(--mall_main_color);
color: #FFFFFF;
&>a {
color: #FFFFFF;
}
}
&:hover,
......
import React, { useState, useEffect } from 'react'
import cx from 'classnames'
import editIcon from './edit_icon.png'
import './index.less'
import { inject, observer } from 'mobx-react'
import { Link } from 'umi'
import styles from './index.less'
const QuickNav: React.FC = (props) => {
interface QuickNavPropsType {
UserStore?: any;
}
const QuickNav: React.FC<QuickNavPropsType> = (props) => {
const { userInfo } = props.UserStore
const [tabType, setTabType] = useState<number>(1) // 1; 卖家服务;2:买家服务
const handleChangeTabType = (type: number) => {
if (tabType !== type) {
setTabType(type)
}
}
// 卖家服务快捷导航
const sell_quick_nav_list = [
{
path: '/memberCenter/home',
path: '/memberCenter/commodityAbility/commodity/products/addProducts',
title: '上传商品',
},
{
path: '/memberCenter/home',
path: '/memberCenter/tranactionAbility/enquirySubmit/addEnquiry',
title: '报价',
},
{
......@@ -30,10 +34,11 @@ const QuickNav: React.FC = (props) => {
title: '接单',
},
]
// 买家服务快捷导航
const buy_quick_nav_list = [
{
path: '/memberCenter/home',
path: '/purchaseOnline',
title: '我要求购',
},
{
......@@ -41,7 +46,7 @@ const QuickNav: React.FC = (props) => {
title: '报价信息',
},
{
path: '/memberCenter/home',
path: '/memberCenter/tranactionAbility/purchaseOrder/orderList',
title: '我的订单',
},
]
......@@ -60,57 +65,61 @@ const QuickNav: React.FC = (props) => {
title: '去求购',
},
{
path: '/memberCenter/home',
path: '/shops',
title: '找店铺',
},
{
path: '/memberCenter/home',
path: '/pointsMall',
title: '换积分',
},
{
path: '/memberCenter/home',
path: '/infomation',
title: '看资讯',
},
]
return (
<div className="quikc_nav">
<div className="quikc_nav_right">
<div className="member_card">
<div className="member_no_login">
<div className="welcome">
<div className="welcome_avatar">Hi</div>
<span className="welcome_text">Hi,欢迎来到XX商城</span>
</div>
<div className="btn_group">
<div className="btn_item primary">登陆</div>
<div className="btn_item">注册</div>
<div className={styles.quikc_nav}>
<div className={styles.quikc_nav_right}>
<div className={styles.member_card}>
<div className={styles.member_no_login}>
<div className={styles.welcome}>
<div className={styles.welcome_avatar}>Hi</div>
<span className={styles.welcome_text}>Hi,欢迎来到XX商城</span>
</div>
{
!userInfo && (
<div className={styles.btn_group}>
<div className={cx(styles.btn_item, styles.primary)}><Link to="/user/login">登陆</Link></div>
<div className={styles.btn_item}><Link to="/user/register">注册</Link></div>
</div>
)
}
</div>
</div>
<div className="quick_tab">
<div className={cx("quick_tab_item", tabType === 1 ? 'active' : '')} onClick={() => handleChangeTabType(1)}>卖家服务</div>
<div className={cx("quick_tab_item", tabType === 2 ? 'active' : '')} onClick={() => handleChangeTabType(2)}>买家服务</div>
<div className={styles.quick_tab}>
<div className={cx(styles.quick_tab_item, tabType === 1 ? styles.active : '')} onClick={() => handleChangeTabType(1)}>卖家服务</div>
<div className={cx(styles.quick_tab_item, tabType === 2 ? styles.active : '')} onClick={() => handleChangeTabType(2)}>买家服务</div>
</div>
<div className="quick_nav_list">
<div className={styles.quick_nav_list}>
{
tabType === 1 ? sell_quick_nav_list.map((item, index) => (
<a href={item.path} className="quick_nav_list_item bb" key={`sell_quick_nav_list_item-${index}`}>
<img className="quick_nav_list_item_icon" src={editIcon} />
<span className="quick_nav_list_item_text">{item.title}</span>
<a href={item.path} className={cx(styles.quick_nav_list_item, styles.bb)} key={`sell_quick_nav_list_item-${index}`}>
<img className={styles.quick_nav_list_item_icon} src={editIcon} />
<span className={styles.quick_nav_list_item_text}>{item.title}</span>
</a>
)) : buy_quick_nav_list.map((item, index) => (
<a href={item.path} className="quick_nav_list_item bb" key={`buy_quick_nav_list_item-${index}`}>
<img className="quick_nav_list_item_icon" src={editIcon} />
<span className="quick_nav_list_item_text">{item.title}</span>
<a href={item.path} className={cx(styles.quick_nav_list_item, styles.bb)} key={`buy_quick_nav_list_item-${index}`}>
<img className={styles.quick_nav_list_item_icon} src={editIcon} />
<span className={styles.quick_nav_list_item_text}>{item.title}</span>
</a>
))
}
{
quick_nav_list.map((item, index) => (
<a href={item.path} className="quick_nav_list_item" key={`quick_nav_list_item-${index}`}>
<img className="quick_nav_list_item_icon" src={editIcon} />
<span className="quick_nav_list_item_text">{item.title}</span>
<a href={item.path} className={styles.quick_nav_list_item} key={`quick_nav_list_item-${index}`}>
<img className={styles.quick_nav_list_item_icon} src={editIcon} />
<span className={styles.quick_nav_list_item_text}>{item.title}</span>
</a>
))
}
......@@ -120,4 +129,4 @@ const QuickNav: React.FC = (props) => {
)
}
export default QuickNav
export default inject('UserStore')(observer(QuickNav))
......@@ -48,7 +48,9 @@ const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
}, [])
useEffect(() => {
console.log(query)
if (query.memberId) {
fetchShopInfo(query.memberId)
}
}, [query])
......@@ -64,9 +66,11 @@ const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
}
useEffect(() => {
let body = document.getElementsByTagName('body')[0];
if (shopInfo) {
let body = document.getElementsByTagName('body')[0];
body.className = shopInfo.fileName ? `theme-shop-${shopInfo.fileName}` : templateName;
} else {
body.className = templateName
}
}, [shopInfo])
......@@ -77,7 +81,7 @@ const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
{
!menuRouter?.hideHeader && (
<>
<ChannelHeader />
<ChannelHeader shopInfo={shopInfo} />
<MainNav menuData={menuData} pathname={location.pathname} type={LAYOUT_TYPE.channel} shopId={query.shopId} shopUrlParam={id} />
</>
)
......
......@@ -81,6 +81,8 @@
flex-direction: column;
.stock {
width: 120px;
text-align: center;
margin-top: 10px;
}
}
......
......@@ -7,19 +7,16 @@ import cx from 'classnames'
import { Checkbox, Affix, message, Modal, Button } from 'antd'
import styles from './index.less'
import { PublicApi } from '@/services/api'
import { priceFormat } from "@/utils/numberFomat"
import { priceFormat, numFormat } from "@/utils/numberFomat"
import { useLocalStore, observer } from 'mobx-react'
import { store } from '@/store'
import { GetProductPurchaseGetPurchaseListResponse } from '@/services/ProductApi'
interface PurchaseOrderPropsType {
}
interface PurchaseOrderPropsType { }
const PurchaseOrder: React.FC<PurchaseOrderPropsType> = (props) => {
const OrderStore = useLocalStore(() => store.OrderStore)
const { updateOrderInfo } = OrderStore
const [buyCount, setBuyCount] = useState<number>(1)
const [indeterminate, setIndeterminate] = useState<boolean>(false)
const [checkAll, setCheckAll] = useState<boolean>(false)
const [checkedList, setCheckedList] = useState([])
......@@ -421,7 +418,8 @@ const PurchaseOrder: React.FC<PurchaseOrderPropsType> = (props) => {
category: item.commodityUnitPrice.commodity.customerCategory.name,
brand: item.commodityUnitPrice.commodity.brand.name,
commodityPic: item.commodityUnitPrice.commodityPic[0],
attribute: item.commodityUnitPrice.attributeAndValueList
attribute: item.commodityUnitPrice.attributeAndValueList,
stockCount: item.stockCount || 0
}
if (item.commodityUnitPrice.commodity.isMemberPrice) {
buyCommodityInfo.memberDiscount = await getMemberCredit(item.commodityUnitPrice.commodity.memberId, item.commodityUnitPrice.commodity.memberRoleId)
......@@ -541,8 +539,8 @@ const PurchaseOrder: React.FC<PurchaseOrderPropsType> = (props) => {
}
</div>
<div className={cx(styles.order_list_item_item, styles.count)}>
<InputNumber value={childItem.count} onChange={(value) => handleCountChange(value, childItem.id)} />
<div className={styles.stock}>(库存20,000{childItem.commodityUnitPrice.commodity.unitName})</div>
<InputNumber disabled={!childItem.stockCount} max={childItem.stockCount || 0} min={1} value={childItem.count} onChange={(value) => handleCountChange(value, childItem.id)} />
<div className={styles.stock}>(库存{numFormat(childItem.stockCount)}{childItem.commodityUnitPrice.commodity.unitName})</div>
</div>
<div className={cx(styles.order_list_item_item, styles.amount)}>
<span className={styles.order_list_item_item_price}>{priceFormat(computeItemPrice(childItem.commodityUnitPrice?.priceRange, childItem.count))}</span>
......
......@@ -10,6 +10,7 @@ import { PublicApi } from '@/services/api'
import { LAYOUT_TYPE } from '@/constants'
import { GetTemplateShopFindShopResponse, GetTemplatePlatformFindAllFirstCategoryResponse } from '@/services/TemplateApi'
import styles from './index.less'
import { LaptopOutlined } from '@ant-design/icons'
interface ChannelIndexPropsType {
SiteStore?: any;
......@@ -128,7 +129,7 @@ const ShopIndex: React.FC<ChannelIndexPropsType> = (props) => {
</div>
<FloorAnchor anchorList={categoryList} type="shop" />
<CommonTitle title="关于我们" type="primary" />
<AboutUs shopInfo={shopInfo} shopUrlParam={shopUrlParam} />
<AboutUs shopInfo={shopInfo} shopUrlParam={shopUrlParam} type={LAYOUT_TYPE.shop} />
<CommonTitle title="热销商品" type="primary" />
{
categoryComponents ? categoryComponents : <FloorSkeleton type={LAYOUT_TYPE.shop} />
......
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