Commit 18785ab4 authored by XieZhiXiong's avatar XieZhiXiong
parents e1cc477e c870f334
import React from 'react'
import React, { useEffect, useState } from 'react'
import { MinusOutlined, PlusOutlined } from '@ant-design/icons'
import cx from 'classnames'
import './index.less'
......@@ -6,14 +6,26 @@ import './index.less'
interface InputNumberPropsType {
value: number;
onChange: Function;
min?: number;
max?: number;
}
const InputNumber: React.FC<InputNumberPropsType> = (props) => {
const { value, onChange } = props
const { value, onChange, min, max } = props
const [minCount, setMinCount] = useState<number>(1)
const [maxCount, setMaxCount] = useState<number>()
useEffect(() => {
if (min) {
setMinCount(min)
onChange(min)
}
max && setMaxCount(max)
}, [min, max])
const handleReduce = () => {
if (value > 1) {
if (value > minCount) {
onChange(Number(value) - 1)
}
}
......@@ -34,15 +46,20 @@ const InputNumber: React.FC<InputNumberPropsType> = (props) => {
const handleBlur = (e) => {
const { value } = e.target;
if (value === "") {
onChange(1)
onChange(minCount)
} else {
Number(value) < minCount && onChange(minCount)
Number(value) > maxCount && onChange(maxCount)
}
}
return (
<div className="input_number">
<div className={cx("input_number_item reduce", value <= 1 ? 'disable' : '')} onClick={handleReduce}><MinusOutlined /></div>
<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="input_number_item add" onClick={handleAdd}><PlusOutlined /></div>
<div className={cx("input_number_item add", value >= maxCount ? 'disable' : '')} onClick={handleAdd}><PlusOutlined /></div>
</div>
)
}
......
......@@ -57,17 +57,23 @@
.delete_btn {
color: #fff;
position: absolute;
top:50%;
left:50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.upload_wrap{
.upload_wrap {
position: relative;
width: 104px;
height: 104px;
&.large {
width: 175px;
height: 120px;
}
&:hover {
.delete_wrap {
display: block;
......
......@@ -71,7 +71,7 @@ const UploadImage: React.FC<UploadImagePorpsType> = forwardRef((props, ref) => {
return (
<div className={styles.upload_image_wrap}>
<div className={styles.upload_wrap}>
<div className={cx(styles.upload_wrap, large ? styles.large : '')}>
<Upload {...uploadProps}>
{<div className={cx(styles.upload_btn, !imgUrl ? styles.isAdd : "", large ? styles.large : '')}>
{
......@@ -84,7 +84,7 @@ const UploadImage: React.FC<UploadImagePorpsType> = forwardRef((props, ref) => {
}
</div>
{
showDesc &&
showDesc &&
<div className={styles.size_require}>
<p>支持JPG/PNG/JPEG, <br />最大不超过 {fileMaxSize}K, <br />尺寸:{size}</p>
</div>
......
......@@ -71,7 +71,7 @@ const MenuSlider: React.FC<MenuSliderProps> = (props) => {
return <>
<OuterSider {...props} />
<Sider theme="light" collapsed={props.collapseState}>
<Sider theme="light" className="menu_sider" collapsed={props.collapseState}>
<div className={styles.logo}>LOGOLOGOGOG</div>
<div className={styles.menuTitle}>
{menuRouter?.name}
......
......@@ -4,6 +4,21 @@
margin: 16px;
}
:global {
.menu_sider.ant-layout-sider-collapsed {
flex: 0 !important;
max-width: 0 !important;
min-width: 0 !important;
width: 0 !important;
}
}
.menu_sider {
position: relative;
}
.menuTitle {
height: 64px;
font-size: 14px;
......@@ -25,7 +40,7 @@
}
.wrapperSilder {
background-color: #38414A!important;
background-color: #38414A !important;
.menuBox {
padding: 0;
......
......@@ -45,7 +45,6 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
const UserStore = useLocalStore(() => store.UserStore)
const FilterStore = useLocalStore(() => store.FilterStore)
const { userInfo } = UserStore
const inputRef = useRef()
const [modalVisible, setModalVisible] = useState<boolean>(false)
const [confirmLoading, setConfirmLoading] = useState<boolean>(false)
const [commonlyUsedName, setCommonlyUsedName] = useState<string>("")
......@@ -90,7 +89,7 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
return (() => {
onResetFilter()
})
}, [])
}, [layoutType])
const fetchCommodityList = () => {
let param: filterQuery = {
......
......@@ -52,7 +52,7 @@ const CommodityList: React.FC<CommodityListPropsType> = (props) => {
<a href={`/${layoutType === LAYOUT_TYPE.channel ? 'channelmall' : 'shop'}/commodity/detail?id=${item.id}&type=${item.priceType}&shopId=${btoa(JSON.stringify({ shopId: item.storeId, memberId: item.memberId }))}`} target="_blank">
<div className={styles.goods_img}>
{
item.commodityPic ? <img src={item.commodityPic} /> : <Skeleton.Image style={{ width: 220, height: 220 }} />
item.mainPic ? <img src={item.mainPic} /> : <Skeleton.Image style={{ width: 220, height: 220 }} />
}
</div>
<div className={styles.info_box}>
......@@ -85,7 +85,7 @@ const CommodityList: React.FC<CommodityListPropsType> = (props) => {
<a href={`/${layoutType === LAYOUT_TYPE.channel ? 'channelmall' : 'shop'}/commodity/detail?id=${item.id}&type=${item.priceType}&shopId=${btoa(JSON.stringify({ shopId: item.storeId, memberId: item.memberId }))}`} target="_blank">
<div className={styles.goods_img}>
{
item.commodityPic ? <img src={item.commodityPic} /> : <Skeleton.Image style={{ width: 120, height: 120 }} />
item.mainPic ? <img src={item.mainPic} /> : <Skeleton.Image style={{ width: 120, height: 120 }} />
}
</div>
<div className={styles.info_box}>
......
......@@ -42,7 +42,9 @@ interface filterQuery {
}
const CommoditySearch: React.FC<CommodityPropsType> = (props) => {
const UserStore = useLocalStore(() => store.UserStore)
const FilterStore = useLocalStore(() => store.FilterStore)
const { userInfo } = UserStore
const { filterList, filterUpdate, filterParam, onDeleteFilterItem, onResetFilter, onFilterParamChange } = FilterStore
const { layoutType, shopId, shopUrlParam } = props
const { query: { search = "" } } = props.location
......@@ -52,7 +54,9 @@ const CommoditySearch: React.FC<CommodityPropsType> = (props) => {
const [current, setCurrent] = useState<number>(1)
const [pageSize, setPageSize] = useState<number>(20)
const [totalCount, setTotalCount] = useState<number>(0)
const filterConfig = [FILTER_TYPE.commonlyUsed, FILTER_TYPE.category, FILTER_TYPE.brand, FILTER_TYPE.price, FILTER_TYPE.useArea, FILTER_TYPE.commodityType]
const [filterConfig, setFilterConfig] = useState([FILTER_TYPE.categoryAndAttr, FILTER_TYPE.brand, FILTER_TYPE.price, FILTER_TYPE.useArea, FILTER_TYPE.commodityType])
// const filterConfig = [FILTER_TYPE.commonlyUsed, FILTER_TYPE.category, FILTER_TYPE.brand, FILTER_TYPE.price, FILTER_TYPE.useArea, FILTER_TYPE.commodityType]
useEffect(() => {
fetchCommodityList()
......@@ -65,6 +69,17 @@ const CommoditySearch: React.FC<CommodityPropsType> = (props) => {
}
}, [filterList])
useEffect(() => {
if (userInfo && layoutType === LAYOUT_TYPE.mall) {
let temp = JSON.parse(JSON.stringify(filterConfig))
temp.unshift(FILTER_TYPE.commonlyUsed)
setFilterConfig(temp)
}
return (() => {
onResetFilter()
})
}, [layoutType])
const fetchCommodityList = () => {
let param: filterQuery = {
current,
......
......@@ -179,7 +179,6 @@ const CommodityDetail = (props) => {
price: initPriceRange[key]
})
})
console.log(tempPriceRange, "tempPriceRange")
setCommodityPriceInfo(tempPriceRange)
}
......@@ -230,10 +229,7 @@ const CommodityDetail = (props) => {
console.log(temp, "temp")
unitPrice = temp[0]?.price
}
}
console.log(unitPrice)
let amount = unitPrice * (Number(buyCount) || 0)
return amount
}
......@@ -314,7 +310,7 @@ 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}>20000</span>
<span className={styles.text}>{commodityPriceInfo && commodityPriceInfo[0]?.price}</span>
<Tooltip placement="top" title="可使用平台通用积分或商户积分进行兑换">
<QuestionCircleOutlined />
</Tooltip>
......@@ -334,7 +330,7 @@ const CommodityDetail = (props) => {
<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} onChange={(value) => setBuyCount(value)} />
<InputNumber value={buyCount} min={commodityDetail?.priceType === COMMODITY_TYPE.prompt ? commodityDetail?.minOrder : 1} max={20000} 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)}>(库存20,000{commodityDetail?.unitName})</span>
</div>
......@@ -342,6 +338,16 @@ const CommodityDetail = (props) => {
)
}
{
commodityDetail?.priceType !== COMMODITY_TYPE.integral && (
<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}>{commodityDetail?.minOrder} {commodityDetail?.unitName}</span>
</div>
</div>
)
}
{
commodityDetail?.priceType === COMMODITY_TYPE.prompt && (
<div className={styles.product_info_price}>
<div className={styles.product_info_price_text}>{buyCount || 0}<span>{commodityDetail?.unitName}</span></div>
......
......@@ -53,7 +53,6 @@
margin: 0;
&_item {
position: relative;
padding-left: 20px;
padding-top: 12px;
height: 56px;
......
......@@ -4,6 +4,7 @@ import { inject, observer } from 'mobx-react'
import { Link } from 'umi'
import cx from 'classnames'
import { LAYOUT_TYPE } from '@/constants'
import { PublicApi } from '@/services/api'
import isEmpty from 'lodash/isEmpty'
import styles from './index.less'
......@@ -11,19 +12,41 @@ interface CategoryPropsType {
CategoryStore?: any;
SiteStore?: any;
layoutType?: LAYOUT_TYPE;
type?: LAYOUT_TYPE
type?: LAYOUT_TYPE;
shopId?: number;
shopUrlParam?: string;
}
const Category: React.FC<CategoryPropsType> = (props) => {
const { type } = props
const { type, shopId, shopUrlParam } = props
const { mallTemplateId } = props.SiteStore
const { fetchCategoryList, categoryList } = props.CategoryStore
useEffect(() => {
if (isEmpty(categoryList)) {
fetchCategoryList({ templateId: mallTemplateId })
console.log(type, "type")
let getCategoryFn
let params: any = {}
switch (type) {
case LAYOUT_TYPE.mall:
params.templateId = mallTemplateId
getCategoryFn = PublicApi.getTemplatePlatformFindAllCategoryTree
fetchCategoryList(getCategoryFn, params, type)
break
case LAYOUT_TYPE.shop:
if (shopId) {
params.storeId = shopId
getCategoryFn = PublicApi.getSearchShopStoreGetCustomerCategoryTree
fetchCategoryList(getCategoryFn, params, type)
}
break
case LAYOUT_TYPE.channel:
break
default:
break
}
}, [])
}, [props])
return (
<div className={styles.category}>
......
......@@ -10,9 +10,6 @@ interface DialogModalModalPropsType {
const DialogModal: React.FC<DialogModalModalPropsType> = (props) => {
const { visible = false, title, children, onCancel } = props
useEffect(() => {
console.log(visible, "visible")
}, [visible])
return (
<Modal
......
......@@ -75,7 +75,7 @@ const Category: React.FC<CategoryPropsType> = (props) => {
useEffect(() => {
if (lastCategoryId) {
let param = {
let param: any = {
categoryId: lastCategoryId
}
let getAttributeFn
......@@ -84,6 +84,7 @@ const Category: React.FC<CategoryPropsType> = (props) => {
getAttributeFn = PublicApi.getSearchShopEnterpriseGetAttributeByCategoryId
break;
case LAYOUT_TYPE.shop:
param.storeId = shopId
getAttributeFn = PublicApi.getSearchShopStoreGetCustomerAttributeByCategoryId
break;
case LAYOUT_TYPE.channel:
......
......@@ -44,11 +44,13 @@ const CommodityType: React.FC<CommodityTypePropsType> = (props) => {
result = checkValue.filter(item => item !== selectKeys[0])
}
setSelectKeys(result)
onFilter({
type: FILTER_TYPE.commodityType,
key: result[0],
title: getItemText(result[0])
})
if (result[0]) {
onFilter({
type: FILTER_TYPE.commodityType,
key: result[0],
title: getItemText(result[0])
})
}
}
const getItemText = (key: number) => {
......
......@@ -6,16 +6,10 @@ import { useLocalStore, observer } from 'mobx-react'
import { store } from '@/store'
import isEmpty from 'lodash/isEmpty'
import styles from './index.less'
import { message } from 'god'
interface CommonlyUsedPropsType {
}
const CommonlyUsed: React.FC<CommonlyUsedPropsType> = (props) => {
const CommonlyUsed: React.FC = () => {
const FilterStore = useLocalStore(() => store.FilterStore)
const { commonlyUseFilter, deleteCommonlyUsedFilterItem, useCommonlyFilter } = FilterStore
console.log(JSON.stringify(commonlyUseFilter), "commonlyUseFilter")
const handleDeleteItem = (id: number) => {
deleteCommonlyUsedFilterItem(id)
......
......@@ -9,21 +9,22 @@ interface MainNavPropsType {
menuData: any;
pathname: string;
type: LAYOUT_TYPE,
shopId?: string
shopId?: number,
shopUrlParam?: string;
}
const MainNav: React.FC<MainNavPropsType> = (props) => {
const { menuData, pathname, type, shopId = "" } = props
const { menuData, pathname, type, shopId, shopUrlParam } = props
return (
<div className={cx(styles.main_nav, type === LAYOUT_TYPE.shop ? styles.shop : "")}>
<div className={styles.main_nav_container}>
<Category type={type} />
<Category type={type} shopId={shopId} shopUrlParam={shopUrlParam} />
<ul className={styles.nav}>
{
menuData && menuData.map(item => !item.hide && (
<li className={cx(styles.nav_item, item.path === pathname ? styles.active : '')} key={item.key}>
<Link to={type === LAYOUT_TYPE.shop ? `${item.path}?shopId=${shopId}` : item.path}>{item.name}</Link>
<Link to={type === LAYOUT_TYPE.shop ? `${item.path}?shopId=${shopUrlParam}` : item.path}>{item.name}</Link>
</li>
))
}
......
......@@ -45,13 +45,13 @@ const LXShopLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const { formatMessage } = useIntl();
const basicInfo = getMenuData(props.route.routes, { locale: true }, formatMessage)
const menuData = basicInfo.menuData ? basicInfo.menuData.filter(item => !item.redirect) : []
console.log(query.shopId, "query.shopId", shopId, "shopId")
return (
<div className={styles.lxmall_page}>
<TopBar />
<div className={styles.content}>
<ShopHeader shopId={query.shopId} shopUrlParam={shopId} />
<MainNav menuData={menuData} pathname={location.pathname} type={LAYOUT_TYPE.shop} shopId={shopId} />
<MainNav menuData={menuData} pathname={location.pathname} type={LAYOUT_TYPE.shop} shopId={query.shopId} shopUrlParam={shopId} />
{
children && React.Children.map(children, (child: any) => {
return React.cloneElement(child,
......
......@@ -18,11 +18,13 @@ const CommodityList: React.FC<CommodityListPropsType> = (props) => {
const getCommodityDetailUrl = () => {
switch (layoutType) {
case LAYOUT_TYPE.mall:
return "/"
return ""
case LAYOUT_TYPE.channel:
return "/channelmall"
case LAYOUT_TYPE.shop:
return "/shop"
default:
return ""
}
}
......@@ -34,7 +36,7 @@ const CommodityList: React.FC<CommodityListPropsType> = (props) => {
<a href={`${getCommodityDetailUrl()}/commodity/detail?id=${item.id}&type=${item.priceType}&shopId=${btoa(JSON.stringify({ shopId: item.storeId, memberId: item.memberId }))}`} target="_blank">
<div className={styles.goods_img}>
{
item.commodityPic ? <img src={item.commodityPic} /> : <Skeleton.Image style={{ width: 220, height: 220 }} />
item.mainPic ? <img src={item.mainPic} /> : <Skeleton.Image style={{ width: 220, height: 220 }} />
}
</div>
<div className={styles.info_box}>
......
......@@ -26,7 +26,7 @@ const PurchaseOnline: React.FC<PurchaseOnlinePropsType> = (props) => {
const [showType, setShowType] = useState<number>(1) // 展示方式:1:矩阵排列; 2:列表排列
const [filterList, setFilterList] = useState([])
const filterConfig = [FILTER_TYPE.commonlyUsed, FILTER_TYPE.category, FILTER_TYPE.useArea]
const filterConfig = [FILTER_TYPE.category, FILTER_TYPE.useArea]
const handleFilter = (filterValue: filterValueType) => {
let filteState = filterList.some(item => item.type === filterValue.type)
......
......@@ -11,7 +11,42 @@
display: flex;
&_item {
flex: 1;
&.auto_width {
flex: 1;
}
.shop_about_btn_group {
display: flex;
height: 100%;
align-items: center;
padding-left: 30px;
padding-right: 60px;
}
.shop_about_btn {
padding: 0 15px;
height: 32px;
line-height: 32px;
font-size: 12px;
background: #FFFFFF;
border: 1px solid #EEEEEE;
cursor: pointer;
&:hover {
opacity: .9;
}
&.primary {
background-color: var(--mall_main_color);
color: #FFFFFF;
}
&:not(:last-child) {
margin-right: 20px;
}
}
&_character {
position: relative;
......@@ -25,6 +60,7 @@
}
.shop_about_info_title {
padding-top: 15px;
font-size: 24px;
line-height: 24px;
color: #333333;
......@@ -228,7 +264,7 @@
height: 256px;
width: 100%;
display: flex;
margin-top: 20px;
margin: 40px 0;
align-items: center;
.exhibition_tool_item {
......@@ -287,5 +323,19 @@
}
}
.shop_workshopimg_list {
padding: 20px 0;
&_item {
margin-bottom: 20px;
&>img {
width: 100%;
}
}
}
}
}
\ No newline at end of file
......@@ -68,12 +68,19 @@ const ShopAbout: React.FC = () => {
</div>
</div>
</div>
<div className={styles.shop_about_info_item}>
<div className={cx(styles.shop_about_info_item)}>
<div className={styles.shop_about_btn_group}>
<div className={styles.shop_about_btn}>收藏本店</div>
<div className={cx(styles.shop_about_btn, styles.primary)}>申请成为本店会员</div>
</div>
</div>
<div className={cx(styles.shop_about_info_item, styles.auto_width)}>
<i className={styles.shop_about_info_item_character}></i>
<p>经营全粒面牛皮,修面皮,漆色皮,打腊皮,水腊皮,疯马皮,珠光变色,大小荔枝纹,打腊水腊皮生产销售</p>
</div>
</div>
<div className={styles.channel_info_about}>
{/* <div className={styles.channel_info_about}>
<div className={styles.channel_info_about_container}>
<div className={styles.channel_info_about_img}>
<Carousel className={styles.channel_info_about_img_list} pauseOnDotsHover>
......@@ -105,9 +112,9 @@ const ShopAbout: React.FC = () => {
</div>
</div>
</div>
</div> */}
<div className={styles.shop_about_card_list}>
{/* <div className={styles.shop_about_card_list}>
<div className={styles.shop_about_card_list_item}>
<div className={styles.shop_about_card_list_item_title}>店铺年龄</div>
<div className={styles.shop_about_card_list_item_content}>
......@@ -136,7 +143,7 @@ const ShopAbout: React.FC = () => {
<span>万元</span>
</div>
</div>
</div>
</div> */}
<div className={styles.shop_about_split}>
<div className={styles.shop_about_split_line}></div>
......@@ -159,8 +166,23 @@ const ShopAbout: React.FC = () => {
</div>
<div className={cx(styles.exhibition_tool_item, styles.next)} onClick={() => handleNext()}><RightOutlined /></div>
</div>
<div className={styles.shop_about_split}>
<div className={styles.shop_about_split_line}></div>
<div className={styles.shop_about_split_text}>公司 介绍</div>
<div className={styles.shop_about_split_line}></div>
</div>
<div className={styles.shop_workshopimg_list}>
<div className={styles.shop_workshopimg_list_item}>
<img src="https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1.jpg" />
</div>
<div className={styles.shop_workshopimg_list_item}>
<img src="https://woodmartcdn-cec2.kxcdn.com/wp-content/uploads/2016/09/product-furniture-1.jpg" />
</div>
</div>
</div>
</div>
)
}
......
import { action, computed, observable, runInAction } from 'mobx'
import { LAYOUT_TYPE } from '@/constants'
import { PublicApi } from '@/services/api'
const defaultCategory = [
......@@ -48,16 +49,19 @@ class CategoryStore {
@observable public categoryList: any = []; // 品类列表
@observable public enterpriseCategoryList: any = []
@observable public storeCategoryList: any = []
@observable public categoryType: LAYOUT_TYPE | null = null
/**
* 企业商城商品分类列表
*/
@action.bound
public async fetchCategoryList(param) {
let res = await PublicApi.getTemplatePlatformFindAllCategoryTree(param)
runInAction(() => {
this.categoryList = res.data || []
})
public async fetchCategoryList(getCategoryFn, params, type) {
if (this.categoryType !== type) {
this.categoryType = type
let res = await getCategoryFn(params)
runInAction(() => {
this.categoryList = res.data || []
})
}
}
/**
......
......@@ -79,6 +79,7 @@ class FilterStore {
}
this.filterUpdate = true
this.filterList = tempFilterList
this.commonlyUseFilterId = null
}
/**
* 重置筛选项
......@@ -87,6 +88,7 @@ class FilterStore {
public onResetFilter = () => {
this.filterList = []
this.filterUpdate = true
this.commonlyUseFilterId = null
}
/**
......@@ -105,6 +107,7 @@ class FilterStore {
})
this.filterList = tempFilterList
this.filterUpdate = true
this.commonlyUseFilterId = null
}
/**
......
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