Commit 6093e60f authored by 前端-许佳敏's avatar 前端-许佳敏
parents 4bd58fd4 3128934e
......@@ -18,6 +18,14 @@ const mallRoute = {
component: '@/pages/lxMall/commodity',
},
{
// 商品搜索
path: `/commodity/search`,
name: 'mallCommoditySearch',
key: 'mallCommoditySearch',
hide: true,
component: '@/pages/lxMall/commodity/search',
},
{
// 订单
path: `/order`,
name: 'order',
......
......@@ -26,6 +26,7 @@ const whiteLists = [
...userLoginLists,
'/',
'/channelmall',
'/shop',
'/purchaseOnline',
'/pointsMall',
'/memberCenter',
......@@ -34,7 +35,6 @@ const whiteLists = [
'/shops',
'/shop/commodity/detail',
'/shop/commodity',
'/shop',
'/infomation',
'/403',
'/404',
......@@ -74,7 +74,7 @@ export function render(oldRender: Function) {
// 白名单页面不进行权限校验
if (whiteLists.includes(pathname)) {
oldRender()
return ;
return;
}
const authInfo = getAuth()
if (authInfo) {
......@@ -118,7 +118,7 @@ export function onRouteChange({ routes, matchedRoutes, location, action }) {
if (userLoginLists.includes(pathname)) {
// 当登录过, 并且尝试访问登录相关页面, 需重定向到首页
history.replace('/memberCenter/home')
return ;
return;
}
// 固定配置, 出现此参数说明需携带参数校验权限路由
if (query.page_type && routeAuthUrls.find(authPath => {
......
......@@ -8,6 +8,12 @@ export const MALL_TYPE = {
5: '渠道积分商城'
}
export enum LAYOUT_TYPE {
mall = 'mall',
shop = 'shop',
channel = 'channel'
}
// 本地环境跳过权限校验
export const isDev = process.env.NODE_ENV === "development"
// export const isDev = false
......@@ -19,6 +25,53 @@ export const Environment_Status = {
3: "APP"
}
export enum FILTE_RTYPE {
/**
* 常用筛选
*/
commonlyUsed = 'commonlyUsed',
/**
* 分类
*/
category = 'category',
/**
* 风格
*/
style = 'style',
/**
* 品牌
*/
brand = 'brand',
/**
* 价格
*/
price = 'price',
/**
* 发货地
*/
useArea = 'useArea',
/**
* 商品类型
*/
commodityType = 'commodityType',
/**
* 活跃店铺
*/
activeStores = 'activeStores',
/**
* 最新加入
*/
newJoin = 'newJoin',
/**
* 所需积分
*/
points = 'points',
/**
* 商品名称
*/
name = 'name'
}
// 商城类型
export const SHOP_TYPES = [
{
......
import React from 'react'
import { ArrowLeftOutlined } from '@ant-design/icons'
import { history } from 'umi'
import { Modal } from 'antd'
import styles from './index.less'
const ToolBar: React.FC = () => {
const handleGoBack = () => {
Modal.confirm({
content: "是否确认离开模板装修页面?",
okText: "确认",
cancelText: "取消",
onOk: () => {
history.goBack()
}
})
}
return (
<div className={styles.toolbar}>
<div className={styles.toolbar_back_btn} onClick={() => history.goBack()}>
<div className={styles.toolbar_back_btn} onClick={() => handleGoBack()}>
<ArrowLeftOutlined />
</div>
<div className={styles.toolbar_title}>
......
......@@ -174,7 +174,7 @@ const ShopEdit: React.FC<ShopEditPropsType> = (props) => {
...InformationConfig,
...FooterConfig
}
console.log(config)
setComponentConfigs(config)
setLoading(false)
}
......
......@@ -188,48 +188,4 @@
}
}
}
}
.no_result {
padding-top: 120px;
padding-left: 287px;
&_tip {
font-size: 14px;
color: #D32F2F;
font-weight: 500;
display: flex;
&_search {
color: #333333;
}
&_img {
width: 30px;
height: 30px;
overflow: hidden;
margin-right: 16px;
&>img {
width: 30px;
height: 30px;
}
}
}
&_suggest {
margin-top: 12px;
font-size: 12px;
color: #999999;
padding-left: 46px;
&_list {
padding: 0;
margin: 0;
&>li {
list-style: none;
}
}
}
}
\ No newline at end of file
......@@ -4,34 +4,26 @@ import Filter, { FilterType } from '../components/Filter'
import cx from 'classnames'
import { Pagination } from 'antd'
import CommodityList from './list'
import NoResult from './noResult'
import SearchNoResult from '../components/SearchNoResult'
import isEmpty from 'lodash/isEmpty'
import { Spin } from 'antd'
import { PublicApi } from '@/services/api'
import { GetSearchCommodityShopGetCommodityListResponseDetail } from '@/services'
import { LAYOUT_TYPE } from '@/constants'
import { GetSearchShopEnterpriseGetCommodityListResponseDetail } from '@/services'
import bannerImg from '@/assets/imgs/banner_2.png'
import arrowDownIcon from '@/assets/imgs/arrow_down.png'
import arrowDownActiveIcon from '@/assets/imgs/arrow_down_active.png'
import styles from './index.less'
interface filterValueType {
key: string;
key: string | string[];
title: string;
type: FILTER_TYPE;
}
enum FILTER_TYPE {
category = 'category', // 分类
brand = 'brand', // 品牌
style = 'style', // 风格
price = 'price', // 价格
area = 'area', // 适用地区
commodityType = 'commodityType', // 商品类型
type: FilterType;
}
interface CommodityPropsType {
location: any,
layoutType: 'mall' | 'shop' | 'channel'
layoutType: LAYOUT_TYPE.mall | LAYOUT_TYPE.shop | LAYOUT_TYPE.channel
}
interface filterQuery {
......@@ -52,11 +44,11 @@ interface filterQuery {
const Commodity: React.FC<CommodityPropsType> = (props) => {
const { layoutType } = props
const { query: { search = "" } } = props.location
const { query: { categoryId, categoryName } } = props.location
const [loading, setLoading] = useState<boolean>(true)
const [showType, setShowType] = useState<number>(1) // 展示方式:1:矩阵排列; 2:列表排列
const [filterList, setFilterList] = useState([])
const [commodityList, setCommodityList] = useState<GetSearchCommodityShopGetCommodityListResponseDetail[]>([])
const [commodityList, setCommodityList] = useState<GetSearchShopEnterpriseGetCommodityListResponseDetail[]>([])
const [current, setCurrent] = useState<number>(1)
const [pageSize, setPageSize] = useState<number>(20)
const [totalCount, setTotalCount] = useState<number>(0)
......@@ -65,24 +57,31 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
useEffect(() => {
fetchCommodityList()
}, [filterParam, current])
useEffect(() => {
if (categoryId && categoryName) {
handleFilter({
key: [categoryId],
title: decodeURIComponent(atob(categoryName)),
type: FilterType.category,
})
}
}, [filterParam, current, search])
}, [props.location.query])
const fetchCommodityList = () => {
let param: filterQuery = {
current,
pageSize
}
if (!!search) {
param.name = search
}
if (!isEmpty(filterParam)) {
param = Object.assign(param, filterParam)
}
setLoading(true)
//@ts-ignore
PublicApi.getSearchCommodityShopGetCommodityList(param).then(res => {
PublicApi.getSearchShopEnterpriseGetCommodityList(param).then(res => {
setLoading(false)
if (res.code === 1000) {
setCommodityList(res.data.data)
......@@ -105,14 +104,29 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
} else {
tempFilterList = [...tempFilterList, filterValue]
}
console.log(tempFilterList, "tempFilterList")
setFilterList(tempFilterList)
handleFilterChange(tempFilterList)
}
const handleFilterChange = (newFilterList: any) => {
let tempFilterParam: any = {}
for (let filterItem of newFilterList) {
switch (filterItem.type) {
case FilterType.category:
tempFilterParam.categoryId = filterItem.key[0]
break
default:
break
}
}
setFilterParam(tempFilterParam)
}
const handleDeleteFilterItem = (key: string) => {
let tempFilterList = [...filterList]
tempFilterList = tempFilterList.filter(item => String(item.key) !== String(key))
setFilterList(tempFilterList)
handleFilterChange(tempFilterList)
}
/**
......@@ -120,6 +134,7 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
*/
const handleResetFilter = () => {
setFilterList([])
handleFilterChange([])
}
const handlePageChange = (page) => {
......@@ -130,7 +145,7 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
<div className={styles.commodity}>
<div className={styles.mall_container}>
<div className={styles.commodity_container}>
<Filter onFilter={handleFilter} filterConfig={filterConfig} />
<Filter onFilter={handleFilter} filterConfig={filterConfig} layoutType={layoutType} />
<div className={styles.commodity_main}>
<div className={styles.banner}>
<img src={bannerImg} />
......@@ -185,7 +200,7 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
</div>
</div>
{
(commodityList.length === 0 || !commodityList) ? <NoResult search={search} /> : (
(commodityList.length === 0 || !commodityList) ? <SearchNoResult search="" /> : (
<>
<Spin spinning={loading}>
<CommodityList showType={showType} commodityList={commodityList} layoutType={layoutType} />
......
import React, { useState, useEffect } from 'react'
import { CaretUpOutlined, CaretDownOutlined, UnorderedListOutlined, AppstoreOutlined, CloseOutlined } from '@ant-design/icons'
import Filter, { FilterType } from '../components/Filter'
import cx from 'classnames'
import { history } from 'umi'
import { Pagination } from 'antd'
import CommodityList from './list'
import SearchNoResult from '../components/SearchNoResult'
import isEmpty from 'lodash/isEmpty'
import { Spin } from 'antd'
import { PublicApi } from '@/services/api'
import { GetSearchShopEnterpriseGetCommodityListResponseDetail } from '@/services'
import arrowDownIcon from '@/assets/imgs/arrow_down.png'
import arrowDownActiveIcon from '@/assets/imgs/arrow_down_active.png'
import styles from './index.less'
interface filterValueType {
key: string;
title: string;
type: FilterType;
}
interface CommodityPropsType {
location: any,
layoutType: 'mall' | 'shop' | 'channel'
}
interface filterQuery {
current: number;
pageSize: number;
name?: string;
categoryId?: number;
customerCategoryId?: number;
provinceCode?: number;
cityCode?: number;
brandId?: number;
customerAttributeList?: any;
Min?: number;
Max?: number;
priceType?: number;
}
const CommoditySearch: React.FC<CommodityPropsType> = (props) => {
const { layoutType } = props
const { query: { search = "" } } = props.location
const [loading, setLoading] = useState<boolean>(true)
const [showType, setShowType] = useState<number>(1) // 展示方式:1:矩阵排列; 2:列表排列
const [filterList, setFilterList] = useState([])
const [commodityList, setCommodityList] = useState<GetSearchShopEnterpriseGetCommodityListResponseDetail[]>([])
const [current, setCurrent] = useState<number>(1)
const [pageSize, setPageSize] = useState<number>(20)
const [totalCount, setTotalCount] = useState<number>(0)
const [filterParam, setFilterParam] = useState<filterQuery | {}>({})
const filterConfig = [FilterType.commonlyUsed, FilterType.category, FilterType.style, FilterType.brand, FilterType.price, FilterType.useArea, FilterType.commodityType]
useEffect(() => {
fetchCommodityList()
}, [filterParam, current, search])
const fetchCommodityList = () => {
let param: filterQuery = {
current,
pageSize
}
if (!!search) {
param.name = search
}
if (!isEmpty(filterParam)) {
param = Object.assign(param, filterParam)
}
setLoading(true)
//@ts-ignore
PublicApi.getSearchShopEnterpriseGetCommodityList(param).then(res => {
setLoading(false)
if (res.code === 1000) {
setCommodityList(res.data.data)
setTotalCount(res.data.totalCount)
}
})
}
const handleFilter = (filterValue: filterValueType) => {
let filteState = filterList.some(item => item.type === filterValue.type)
let tempFilterList = [...filterList]
if (filteState) {
tempFilterList = tempFilterList.map(item => {
if (item.type === filterValue.type) {
return filterValue
}
return item
})
} else {
tempFilterList = [...tempFilterList, filterValue]
}
setFilterList(tempFilterList)
handleFilterChange(tempFilterList)
}
const handleFilterChange = (newFilterList: any) => {
let tempFilterParam: any = {}
for (let filterItem of newFilterList) {
switch (filterItem.type) {
case FilterType.category:
tempFilterParam.categoryId = filterItem.key[0]
break
default:
break
}
}
setFilterParam(tempFilterParam)
}
const handleDeleteFilterItem = (key: string) => {
let tempFilterList = [...filterList]
tempFilterList = tempFilterList.filter(item => String(item.key) !== String(key))
setFilterList(tempFilterList)
handleFilterChange(tempFilterList)
}
/**
* 重置筛选
*/
const handleResetFilter = () => {
if (search) {
setFilterList([])
history.push('/commodity/search')
} else {
setFilterList([])
handleFilterChange([])
}
}
const handlePageChange = (page) => {
setCurrent(page)
}
/**
* 清除搜索
*/
const handleClearSearch = () => {
history.push('/commodity/search')
}
return (
<div className={styles.commodity}>
<div className={styles.mall_container}>
<div className={styles.commodity_container}>
<Filter onFilter={handleFilter} filterConfig={filterConfig} />
<div className={styles.commodity_main}>
<div className={styles.tool_bar}>
<div className={styles.tool_bar_left}>
<div className={styles.tool_bar_filter_item}>
<span>销量</span>
<i className={styles.icon}>
<img src={arrowDownIcon} />
</i>
</div>
<div className={styles.tool_bar_filter_item}>
<span>信用</span>
<i className={styles.icon}>
<img src={arrowDownIcon} />
</i>
</div>
<div className={styles.tool_bar_filter_item}>
<span>价格</span>
<div className={styles.price_filter_box}>
<CaretUpOutlined className={styles.icon} />
<CaretDownOutlined className={styles.icon} />
</div>
</div>
</div>
<div className={styles.tool_bar_right}>
<div className={styles.count}>
<span></span>
<label>{totalCount}</label>
<span>个商品</span>
</div>
<AppstoreOutlined className={cx(styles.icon, showType === 1 ? styles.active : '')} onClick={() => setShowType(1)} />
<UnorderedListOutlined className={cx(styles.icon, showType === 2 ? styles.active : '')} onClick={() => setShowType(2)} />
</div>
</div>
<div className={styles.filter_bar}>
<div className={styles.filter_bar_left}>
<div className={styles.filter_bar_left_text1}>当前搜索:</div>
{/* <div className={styles.filter_bar_left_split}></div>
<div className={styles.filter_bar_left_text} onClick={handleResetFilter}>重置</div> */}
</div>
<div className={styles.filter_bar_list}>
{
search && (
<div className={styles.filter_bar_list_item}>
<span className={styles.filter_bar_list_item_text}>{search}</span>
<CloseOutlined className={styles.filter_bar_list_item_icon} onClick={() => handleClearSearch()} />
</div>
)
}
{
filterList.map(item => (
<div className={styles.filter_bar_list_item} key={item.key}>
<span className={styles.filter_bar_list_item_text}>{item.title}</span>
<CloseOutlined className={styles.filter_bar_list_item_icon} onClick={() => handleDeleteFilterItem(item.key)} />
</div>
))
}
{
(search || filterList.length > 0) && <div className={styles.filter_bar_reset} onClick={handleResetFilter}>重置</div>
}
</div>
</div>
{
(commodityList.length === 0 || !commodityList) ? <SearchNoResult search={search} /> : (
<>
<Spin spinning={loading}>
<CommodityList showType={showType} commodityList={commodityList} layoutType={layoutType} />
</Spin>
<div className={styles.pagination_wrap}>
<Pagination showQuickJumper showSizeChanger={false} onChange={handlePageChange} current={current} pageSize={pageSize} total={totalCount} />
</div>
</>
)
}
</div>
</div>
</div>
</div>
)
}
export default CommoditySearch
import React, { useEffect } from 'react'
import { MenuOutlined, RightOutlined } from '@ant-design/icons'
import { inject, observer } from 'mobx-react'
import './index.less'
import { Link } from 'umi'
import { isEmpty } from '@formily/antd/esm/shared'
import { LAYOUT_TYPE } from '@/constants'
import isEmpty from 'lodash/isEmpty'
import './index.less'
interface CategoryPropsType {
CategoryStore?: any;
layoutType?: LAYOUT_TYPE.mall | LAYOUT_TYPE.shop | LAYOUT_TYPE.channel
}
const Category: React.FC<CategoryPropsType> = (props) => {
......@@ -14,7 +16,7 @@ const Category: React.FC<CategoryPropsType> = (props) => {
useEffect(() => {
if (isEmpty(categoryList)) {
fetchCategoryList()
// fetchCategoryList()
}
}, [])
......
import React, { useEffect, useState } from 'react'
import { Tree } from 'antd'
import FilterBox from '../FilterBox'
import { LAYOUT_TYPE } from '@/constants'
import { inject, observer } from 'mobx-react'
import isEmpty from 'lodash/isEmpty'
import styles from './index.less'
interface CategoryPropsType {
onFilter?: Function;
CategoryStore?: any;
layoutType?: LAYOUT_TYPE.mall | LAYOUT_TYPE.shop | LAYOUT_TYPE.channel
}
const Category: React.FC<CategoryPropsType> = (props) => {
const { onFilter, CategoryStore: { categoryList } } = props
const { onFilter, CategoryStore: { enterpriseCategoryList, storeCategoryList, fetchEnterpriseCategoryList, fetchStoreCategoryList }, layoutType = LAYOUT_TYPE.mall } = props
const [expandedKeys, setExpandedKeys] = useState<string[]>([])
const [treeData, setTreeData] = useState<any>([])
useEffect(() => {
if (categoryList && categoryList.length > 0) {
initTreeData(categoryList)
switch (layoutType) {
case LAYOUT_TYPE.mall:
fetchEnterpriseCategoryList()
break
case LAYOUT_TYPE.shop:
break
case LAYOUT_TYPE.channel:
fetchStoreCategoryList()
break
}
}, [categoryList])
}, [layoutType])
useEffect(() => {
if (!isEmpty(enterpriseCategoryList) || !isEmpty(storeCategoryList)) {
switch (layoutType) {
case LAYOUT_TYPE.mall:
initTreeData(enterpriseCategoryList)
break
case LAYOUT_TYPE.shop:
break
case LAYOUT_TYPE.channel:
initTreeData(storeCategoryList)
break
}
}
}, [enterpriseCategoryList, storeCategoryList])
const initTreeData = (list: any) => {
let initExpandKeys = []
let result: any = list.map(item => {
initExpandKeys.push(item.id)
return {
title: item.title,
key: item.id,
children: item.children.map(secondCategoryItem => {
initExpandKeys.push(secondCategoryItem.id)
return {
title: secondCategoryItem.title,
key: secondCategoryItem.id,
......@@ -39,6 +69,8 @@ const Category: React.FC<CategoryPropsType> = (props) => {
})
}
})
// setExpandedKeys(initExpandKeys)
setTreeData(result)
}
......@@ -51,15 +83,20 @@ const Category: React.FC<CategoryPropsType> = (props) => {
})
}
const handleExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys)
}
return (
<FilterBox
title="分类"
>
<div className={styles.filter_category}>
<Tree
defaultExpandedKeys={[2, "4"]}
expandedKeys={expandedKeys}
onSelect={handleSelect}
treeData={treeData}
onExpand={handleExpand}
/>
</div>
</FilterBox>
......
......@@ -10,11 +10,13 @@ import CommodityType from './components/CommodityType'
import ActiveStores from './components/ActiveStores'
import NewJoin from './components/NewJoin'
import Points from './components/Points'
import { LAYOUT_TYPE } from '@/constants'
import './index.less'
interface FilterPropsType {
onFilter?: Function;
filterConfig?: string[]
filterConfig?: string[],
layoutType?: LAYOUT_TYPE.mall | LAYOUT_TYPE.shop | LAYOUT_TYPE.channel
}
export enum FilterType {
......@@ -57,11 +59,15 @@ export enum FilterType {
/**
* 所需积分
*/
points = 'points'
points = 'points',
/**
* 商品名称
*/
name = 'name'
}
const Filter: React.FC<FilterPropsType> = (props) => {
const { onFilter, filterConfig = [] } = props
const { onFilter, filterConfig = [], layoutType = LAYOUT_TYPE.mall } = props
const handleFilter = (filterValue: any) => {
onFilter(filterValue)
......@@ -74,7 +80,7 @@ const Filter: React.FC<FilterPropsType> = (props) => {
case FilterType.commonlyUsed:
return <CommonlyUsed key={type} />
case FilterType.category:
return <Category onFilter={handleFilter} key={type} />
return <Category onFilter={handleFilter} key={type} layoutType={layoutType} />
case FilterType.style:
return <Style onFilter={handleFilter} key={type} />
case FilterType.brand:
......
......@@ -5,7 +5,7 @@ import { Link, history } from 'umi'
import { FileTextOutlined } from '@ant-design/icons'
import logo from '@/theme/imgs/logo_w.png'
import isEmpty from 'lodash/isEmpty'
import './index.less'
import styles from './index.less'
interface HeaderPropsType {
......@@ -14,13 +14,14 @@ interface HeaderPropsType {
const Header: React.FC<HeaderPropsType> = (props) => {
const [searchType, setSearchType] = useState<number>(1) // 1:商品; 2:店铺
const [searchValue, setSearchValue] = useState<string>("")
const { search } = history.location.query
useEffect(() => {
const { search } = history.location.query
if (!!search) {
setSearchValue(search)
} else {
setSearchValue("")
}
}, [])
}, [search])
const handleChangeSearchType = (type: number) => {
if (searchType !== type) {
......@@ -30,34 +31,40 @@ const Header: React.FC<HeaderPropsType> = (props) => {
const handleSearchCommodity = () => {
if (!isEmpty(searchValue)) {
history.push(`/commodity?search=${encodeURIComponent(searchValue)}`)
if (searchType === 1) {
history.push(`/commodity/search?search=${encodeURIComponent(searchValue)}`)
} else {
history.push(`/shops?search=${encodeURIComponent(searchValue)}`)
}
} else {
history.push(`/commodity`)
if (searchType === 1) {
history.push(`/commodity`)
} else {
history.push(`/shops`)
}
}
}
return (
<div className="header">
<div className="header_container">
<div className="logo">
<Link to="/">
<img src={logo} />
</Link>
<div className={styles.header}>
<div className={styles.header_container}>
<div className={styles.logo}>
<img src={logo} />
</div>
<div className="mall_search">
<div className="mall_search_tags">
<div className={cx("mall_search_tags_item", searchType === 1 ? 'active' : '')} onClick={() => handleChangeSearchType(1)}>商品</div>
<div className={cx("mall_search_tags_item", searchType === 2 ? 'active' : '')} onClick={() => handleChangeSearchType(2)}>店铺</div>
<div className={styles.mall_search}>
<div className={styles.mall_search_tags}>
<div className={cx(styles.mall_search_tags_item, searchType === 1 ? styles.active : '')} onClick={() => handleChangeSearchType(1)}>商品</div>
<div className={cx(styles.mall_search_tags_item, searchType === 2 ? styles.active : '')} onClick={() => handleChangeSearchType(2)}>店铺</div>
</div>
<div className="mall_search_box">
<Input className="mall_search_input" value={searchValue} placeholder="请输入关键词" onChange={e => setSearchValue(e.target.value)} onPressEnter={() => handleSearchCommodity()} />
<div className="search_btn" onClick={() => handleSearchCommodity()}>搜索</div>
<div className={styles.mall_search_box}>
<Input className={styles.mall_search_input} value={searchValue} placeholder="请输入关键词" onChange={e => setSearchValue(e.target.value)} onPressEnter={() => handleSearchCommodity()} />
<div className={styles.search_btn} onClick={() => handleSearchCommodity()}>搜索</div>
</div>
</div>
<div className="shopping_cart mall" onClick={() => history.push('/purchaseOrder')}>
<div className="badge">0</div>
<FileTextOutlined className="card_icon" />
<div className={cx(styles.shopping_cart, styles.mall)} onClick={() => history.push('/purchaseOrder')}>
<div className={styles.badge}>0</div>
<FileTextOutlined className={styles.card_icon} />
<span>进货单</span>
</div>
</div>
......
.no_result {
padding-top: 120px;
padding-left: 287px;
&_tip {
font-size: 14px;
color: #D32F2F;
font-weight: 500;
display: flex;
&_search {
color: #333333;
}
&_img {
width: 30px;
height: 30px;
overflow: hidden;
margin-right: 16px;
&>img {
width: 30px;
height: 30px;
}
}
}
&_suggest {
margin-top: 12px;
font-size: 12px;
color: #999999;
padding-left: 46px;
&_list {
padding: 0;
margin: 0;
&>li {
list-style: none;
}
}
}
}
\ No newline at end of file
......@@ -5,16 +5,26 @@ interface NoResultPropsType {
search?: string
}
const NoResult: React.FC<NoResultPropsType> = (props) => {
const SearchNoResult: React.FC<NoResultPropsType> = (props) => {
const { search } = props
return (
<div className={styles.no_result}>
<div className={styles.no_result_tip}>
<div className={styles.no_result_tip_img}></div>
<div className={styles.no_result_tip_text}>
抱歉,没有找到与“
<span className={styles.no_result_tip_search}>{search}</span>
”相关的商品
{
search ? (
<>
抱歉,没有找到与“
<span className={styles.no_result_tip_search}>{search}</span>
”相关的商品
</>
) : (
<>
抱歉,没有找到相关的商品
</>
)
}
</div>
</div>
<div className={styles.no_result_suggest}>
......@@ -29,4 +39,4 @@ const NoResult: React.FC<NoResultPropsType> = (props) => {
)
}
export default NoResult
export default SearchNoResult
import React from 'react'
import { EnvironmentOutlined } from '@ant-design/icons'
import './index.less'
import { inject, observer } from 'mobx-react'
import cx from 'classnames'
import styles from './index.less'
interface TopBarPropsType {
langComponent?: React.ReactNode
langComponent?: React.ReactNode;
UserStore?: any;
}
const TopBar: React.FC<TopBarPropsType> = (props) => {
const { langComponent } = props
const { userInfo } = props.UserStore
return (
<div className="topbar">
<div className="topbar_container">
<ul className="topbar_menu left">
<li className="topbar_menu_item pad_left_0">
<div className={styles.topbar}>
<div className={styles.topbar_container}>
<ul className={cx(styles.topbar_menu, styles.left)}>
<li className={cx(styles.topbar_menu_item, styles.pad_left_0)}>
<span>XX商城欢迎你!</span>
</li>
<li className="topbar_menu_item">
<EnvironmentOutlined className="icon" />
<li className={styles.topbar_menu_item}>
<EnvironmentOutlined className={styles.icon} />
<span>广州</span>
</li>
</ul>
<ul className="topbar_menu right">
<li className="topbar_menu_item">
<a href="/user/login">请登录</a>
</li>
<li className="topbar_menu_item">
<a href="/user/register">注册</a>
</li>
<li className="topbar_menu_item">
<ul className={cx(styles.topbar_menu, styles.right)}>
{
userInfo ? (
<li className={styles.topbar_menu_item}>
<span>{userInfo?.name}</span>
</li>
) : (
<>
<li className={styles.topbar_menu_item}>
<a href="/user/login">请登录</a>
</li>
<li className={styles.topbar_menu_item}>
<a href="/user/register">注册</a>
</li>
</>
)
}
<li className={styles.topbar_menu_item}>
<a href="/memberCenter/home">会员中心</a>
</li>
<li className="topbar_menu_item">我的消息</li>
<li className="topbar_menu_item">客户服务</li>
<li className={styles.topbar_menu_item}>我的消息</li>
<li className={styles.topbar_menu_item}>
<a href="http://p.qiao.baidu.com/cps/chat?siteId=11220066&userId=24534830&siteToken=49f62d4365e46c0f2c81538e4d168ab9" target="_blank">客户服务</a>
</li>
{
langComponent && (<li className="topbar_menu_item nopad">{langComponent}</li>)
langComponent && (<li className={cx(styles.topbar_menu_item, styles.nopad)}>{langComponent}</li>)
}
</ul>
</div>
......@@ -42,4 +57,4 @@ const TopBar: React.FC<TopBarPropsType> = (props) => {
)
}
export default TopBar
\ No newline at end of file
export default inject('UserStore')(observer(TopBar))
\ No newline at end of file
......@@ -92,6 +92,7 @@ const MallIndex: React.FC<MallIndexPropsType> = (props) => {
let categoryDetail: any = await fetchCategoryById(item.id)
result.push(
<FloorLine
linkUrl={`/commodity?categoryId=${item.id}&categoryName=${btoa(encodeURIComponent(item.name))}`}
anchor={`floorline_${item.id}`}
key={item.id}
title={item.name}
......
......@@ -13,6 +13,12 @@
.information_focus {
display: flex;
.information_focus_carousel {
width: 598px;
height: 444px;
}
&_left {
position: relative;
margin-right: 4px;
......@@ -22,7 +28,9 @@
&_img {
width: 598px;
height: 444px;
.common_background()
cursor: pointer;
transition: all 1s;
.common_background();
}
}
}
......
import React, { Fragment } from 'react'
import cx from 'classnames'
import { Input, Pagination } from 'antd'
import { Carousel, Pagination } from 'antd'
import { Link } from 'umi'
import { ClockCircleOutlined, EyeOutlined } from '@ant-design/icons'
import informationImg1 from '@/assets/imgs/information_1.png'
......@@ -16,92 +16,92 @@ interface InformationPropsType {
const MockList = [
{
id: new Date().getTime(),
id: new Date().getTime() + 1,
title: '今日热点',
list: [
{
id: new Date().getTime()
id: new Date().getTime() + 11
},
{
id: new Date().getTime()
id: new Date().getTime() + 12
},
{
id: new Date().getTime()
id: new Date().getTime() + 13
},
{
id: new Date().getTime()
id: new Date().getTime() + 14
},
]
},
{
id: new Date().getTime(),
id: new Date().getTime() + 2,
title: '今日热点',
list: [
{
id: new Date().getTime()
id: new Date().getTime() + 21
},
{
id: new Date().getTime()
id: new Date().getTime() + 22
},
{
id: new Date().getTime()
id: new Date().getTime() + 23
},
{
id: new Date().getTime()
id: new Date().getTime() + 24
},
]
},
{
id: new Date().getTime(),
id: new Date().getTime() + 3,
title: '行业头条',
list: [
{
id: new Date().getTime()
id: new Date().getTime() + 31
},
{
id: new Date().getTime()
id: new Date().getTime() + 32
},
{
id: new Date().getTime()
id: new Date().getTime() + 33
},
{
id: new Date().getTime()
id: new Date().getTime() + 34
},
]
},
{
id: new Date().getTime(),
id: new Date().getTime() + 4,
title: '专题报道',
list: [
{
id: new Date().getTime()
id: new Date().getTime() + 41
},
{
id: new Date().getTime()
id: new Date().getTime() + 42
},
{
id: new Date().getTime()
id: new Date().getTime() + 43
},
{
id: new Date().getTime()
id: new Date().getTime() + 44
},
]
},
{
id: new Date().getTime(),
id: new Date().getTime() + 5,
title: '政策法规',
list: [
{
id: new Date().getTime()
id: new Date().getTime() + 51
},
{
id: new Date().getTime()
id: new Date().getTime() + 52
},
{
id: new Date().getTime()
id: new Date().getTime() + 53
},
{
id: new Date().getTime()
id: new Date().getTime() + 54
},
]
},
......@@ -115,9 +115,18 @@ const Information: React.FC<InformationPropsType> = (props) => {
<BreadCrumbs />
<div className={styles.information_focus}>
<div className={styles.information_focus_left}>
<div className={styles.information_focus_imgbox_main}>
<div className={styles.information_focus_imgbox_main_img} style={{ backgroundImage: `url(${informationImg1})` }} />
</div>
<Carousel className={styles.information_focus_carousel} pauseOnDotsHover>
<div className={styles.information_focus_carousel_item}>
<div className={styles.information_focus_imgbox_main}>
<div className={styles.information_focus_imgbox_main_img} style={{ backgroundImage: `url(${informationImg1})` }} />
</div>
</div>
<div className={styles.information_focus_carousel_item}>
<div className={styles.information_focus_imgbox_main}>
<div className={styles.information_focus_imgbox_main_img} style={{ backgroundImage: `url(${informationImg2})` }} />
</div>
</div>
</Carousel>
</div>
<div className={styles.information_focus_right}>
<div className={styles.information_focus_imgbox_sub_1}>
......
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import {
BasicLayoutProps as ProLayoutProps,
getMenuData
} from '@ant-design/pro-layout';
} from '@ant-design/pro-layout'
import SelectLang from '@/layouts/components/SelectLang'
import { useIntl } from 'umi';
import { useIntl } from 'umi'
import { inject, observer } from 'mobx-react'
import TopBar from '../components/TopBar'
import ChannelHeader from '../components/ChannelHeader'
import MainNav from '../components/MainNav'
......@@ -18,10 +19,12 @@ interface LXMallLayoutPropsType {
routes: Array<any>
};
location: any;
SiteStore?: any;
}
const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const { children, location } = props
const [templateName] = useState<string>('theme-channel-science')
const getMenuRouter = (routes: any, pathname: any) => {
let list = routes.filter((item: any) => pathname.indexOf(item.key) > -1)
......@@ -33,8 +36,8 @@ const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const menuRouter = getMenuRouter(menuData, location.pathname)
useEffect(() => {
let body = document.getElementsByTagName('body')[0];
body.className = `theme-channel-science`;
let body = document.getElementsByTagName('body')[0]
body.className = templateName
}, [])
return (
......@@ -65,4 +68,4 @@ const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
)
}
export default LXChannelLayout
export default inject("SiteStore")(observer(LXChannelLayout))
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import {
BasicLayoutProps as ProLayoutProps,
getMenuData
} from '@ant-design/pro-layout';
} from '@ant-design/pro-layout'
import SelectLang from '@/layouts/components/SelectLang'
import { useIntl } from 'umi';
import { useIntl } from 'umi'
import { inject, observer } from 'mobx-react'
import TopBar from '../components/TopBar'
import Header from '../components/Header'
import MainNav from '../components/MainNav'
......@@ -18,10 +19,13 @@ interface LXMallLayoutPropsType {
routes: Array<any>
};
location: any;
SiteStore?: any;
}
const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const { children, location } = props
const [templateName] = useState<string>('theme-mall-science')
const { siteId } = props.SiteStore
const getMenuRouter = (routes: any, pathname: any) => {
let list = routes.filter((item: any) => pathname.indexOf(item.key) > -1)
......@@ -31,10 +35,10 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const basicInfo = getMenuData(props.route.routes, { locale: true }, formatMessage)
const menuData = basicInfo.menuData ? basicInfo.menuData.filter(item => !item.redirect) : []
const menuRouter = getMenuRouter(menuData, location.pathname)
useEffect(() => {
console.log(`tempalteName=theme-mall-science`)
let body = document.getElementsByTagName('body')[0];
body.className = `theme-mall-science`;
body.className = templateName;
}, [])
return (
......@@ -65,4 +69,4 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
)
}
export default LXMallLayout
export default inject("SiteStore")(observer(LXMallLayout))
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import {
BasicLayoutProps as ProLayoutProps,
getMenuData
} from '@ant-design/pro-layout';
import { useIntl } from 'umi';
import TopBar from '../components/TopBar'
import Advert from '../components/Advert'
import { inject, observer } from 'mobx-react'
import ShopHeader from '../components/ShopHeader'
import MainNav from '../components/MainNav'
import SideNav from '../components/SideNav'
......@@ -18,16 +18,17 @@ interface LXMallLayoutPropsType {
routes: Array<any>
};
location: any;
SiteStore?: any;
}
const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const LXShopLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const { children, location } = props
const [templateName] = useState<string>('theme-shop-science')
useEffect(() => {
console.log('当前使用店铺模板')
let body = document.getElementsByTagName('body')[0];
body.className = `${body.className} theme-shop-science`;
body.className = templateName;
}, [])
const { formatMessage } = useIntl();
......@@ -56,4 +57,5 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
)
}
export default LXMallLayout
export default inject("SiteStore")(observer(LXShopLayout))
......@@ -88,23 +88,6 @@ const ShopList: React.FC<ShopListPropsType> = (props) => {
</div>
</div>
</div>
{/* <div className="filter_bar">
<div className="filter_bar_left">
<div className="filter_bar_left_text">保存为常用筛选</div>
<div className="filter_bar_left_split"></div>
<div className="filter_bar_left_text" onClick={handleResetFilter}>重置</div>
</div>
<div className="filter_bar_list">
{
filterList.map(item => (
<div className="filter_bar_list_item" key={item.key}>
<span className="filter_bar_list_item_text">{item.title}</span>
<CloseOutlined className="filter_bar_list_item_icon" onClick={() => handleDeleteFilterItem(item.key)} />
</div>
))
}
</div>
</div> */}
{
!!search ? <NoResult search={search} /> : (
<>
......
import { action, computed, observable, runInAction } from 'mobx'
import { GlobalConfig } from '@/global/config'
import { PublicApi } from '@/services/api'
import { GetSearchCommodityGetCategoryTreeResponse } from '@/services'
import { GetSearchShopEnterpriseGetCategoryTreeResponse, GetSearchShopStoreGetCustomerCategoryTreeResponse } from '@/services'
const defaultCategory = [
{
......@@ -47,16 +46,45 @@ const defaultCategory = [
]
class CategoryStore {
@observable public categoryList: GetSearchCommodityGetCategoryTreeResponse = []; // 品类列表
@observable public categoryList: any = []; // 品类列表
@observable public enterpriseCategoryList: GetSearchShopEnterpriseGetCategoryTreeResponse = []
@observable public storeCategoryList: GetSearchShopStoreGetCustomerCategoryTreeResponse = []
/**
* 企业商城商品分类列表
*/
@action.bound
public async fetchCategoryList() {
let res = await PublicApi.getSearchCommodityGetCategoryTree()
let res = await PublicApi.getSearchShopEnterpriseGetCategoryTree()
runInAction(() => {
this.enterpriseCategoryList = res.data || []
})
}
/**
* 企业商城商品分类列表
*/
@action.bound
public async fetchEnterpriseCategoryList() {
let res = await PublicApi.getSearchShopEnterpriseGetCategoryTree()
runInAction(() => {
this.enterpriseCategoryList = res.data || []
})
}
/**
* 店铺商城商品分类列表
*/
@action.bound
public async fetchStoreCategoryList() {
let res = await PublicApi.getSearchShopStoreGetCustomerCategoryTree()
runInAction(() => {
this.categoryList = res.data || []
this.storeCategoryList = res.data || []
})
}
}
export default CategoryStore
import { action, computed, observable, runInAction } from 'mobx'
import { FILTE_RTYPE } from '@/constants'
interface filterValueType {
key: string | string[];
title: string;
type: FILTE_RTYPE;
}
class FilterStore {
/**
* 筛选条件列表
*/
@observable filterList = []
@action
public handleFilter = (filterValue: filterValueType) => {
}
}
export default FilterStore
\ No newline at end of file
......@@ -27,12 +27,12 @@ import { IProductModule } from '@/module/productModule'
*/
export interface IStore {
userStore: ILoginModule;
UserStore: ILoginModule;
ProductStore: IProductModule;
}
export const store = {
userStore: new UserStore,
UserStore: new UserStore,
ThemeStore: new ThemeStore,
ProductStore: new ProductStroe,
SiteStore: new SiteStore,
......
import { action, computed, observable, runInAction } from 'mobx'
import { ILoginModule } from '@/module/userModule';
import { ILoginModule } from '@/module/userModule'
import { getAuth } from '@/utils/auth'
import { localStorage } from '@/utils/storage'
// import { userDetailGet } from '@/services/user'
......@@ -9,7 +10,7 @@ class LoginStore implements ILoginModule {
@observable public username: string = 'admin';
@observable public password: string = "123456";
@observable public res: object = {};
@observable public userInfo = {} //userInfo ? JSON.parse(userInfo) : {}
@observable public userInfo = getAuth()
// 可以改变对应的状态值
// @todo 接入更新用户信息接口
......
......@@ -47,9 +47,10 @@
margin: 0;
&_item {
position: relative;
padding-left: 20px;
padding: 12px 19px 8px 20px;
padding-top: 12px;
height: 56px;
list-style: none;
cursor: pointer;
......
......@@ -3,6 +3,7 @@ import { isDev } from '@/constants'
export interface AuthInfo {
userId: number,
memberId: number,
name: string,
token: string
}
......
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