Commit 436f70b1 authored by GuanHua's avatar GuanHua

feat:修改文件名,添加搜索结果页面样式

parent bf330b42
This diff is collapsed.
......@@ -64,12 +64,15 @@ const config: any = {
plugins: [], // 配置项的名字通常是插件名去掉 umi-plugin- 或 @umijs/plugin 前缀。
proxy,
// ssr: {},
// exportStatic: {},
/**
* 配置 webpack 的 publicPath。当打包的时候,webpack 会在静态文件路径前面添加 publicPath 的值
* 当你需要修改静态文件地址时,比如使用 CDN 部署,把 publicPath 的值设为 CDN 的值就可以
*/
publicPath: '/',
targets: {
ie: 10,
},
/**
* https://umijs.org/zh-CN/config#theme
* 配置主题,实际上是配 less 变量。
......
......@@ -13,26 +13,9 @@ export interface UseType {
businessType: BusinessType[];
}
export interface Element {
id: number;
fieldName: string;
fieldCNName: string;
fieldType: string;
fieldLength: number;
fieldEmpty: number;
fieldOrder: number;
fieldRemark: string;
checkRules: any[];
}
export interface UseDetail {
groupName: string;
elements: Element[];
}
export interface UserRegister {
useType: UseType;
useDetail: UseDetail[];
useDetail?: any;
}
export interface CountryList {
......
......@@ -70,7 +70,7 @@ export default {
// 店铺能力
'menu.shopAbility': '店铺',
'menu.shopAbility.shopInfoManage': '店铺信息',
'menu.shopAbility.shopInfoManage': '创建店铺',
'menu.shopAbility.shopTemplate': '店铺装修模板',
// 交易能力
......
......@@ -14,6 +14,7 @@ body {
.banner {
height: 160px;
overflow: hidden;
margin-bottom: 20px;
&>img {
width: 100%;
......@@ -25,7 +26,7 @@ body {
display: flex;
height: 48px;
width: 100%;
margin-top: 20px;
.tool_bar_left {
display: flex;
......@@ -179,4 +180,48 @@ body {
}
}
}
}
.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
......@@ -3,23 +3,75 @@ import { CaretUpOutlined, CaretDownOutlined, UnorderedListOutlined, AppstoreOutl
import Filter from '../components/Filter'
import cx from 'classnames'
import { Pagination } from 'antd'
import CommodityList from './list';
import CommodityList from './list'
import NoResult from './noresult'
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 './index.less'
const Commodity: React.FC = () => {
interface filterValueType {
key: string;
title: string;
type: FILTER_TYPE;
}
enum FILTER_TYPE {
category = 'category', // 分类
brand = 'brand', // 品牌
style = 'style', // 风格
price = 'price', // 价格
area = 'area', // 适用地区
commodityType = 'commodityType', // 商品类型
}
interface CommodityPropsType {
location: any
}
const Commodity: React.FC<CommodityPropsType> = (props) => {
const { query: { search = "" } } = props.location
const [showType, setShowType] = useState<number>(1) // 展示方式:1:矩阵排列; 2:列表排列
const [filterList, setFilterList] = useState([])
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)
}
const handleDeleteFilterItem = (key: string) => {
let tempFilterList = [...filterList]
tempFilterList = tempFilterList.filter(item => String(item.key) !== String(key))
setFilterList(tempFilterList)
}
/**
* 重置筛选
*/
const handleResetFilter = () => {
setFilterList([])
}
return (
<div className="commodity">
<div className="mall_container">
<div className="commodity_container">
<Filter />
<Filter onFilter={handleFilter} />
<div className="commodity_main">
<div className="banner">
{/* <div className="banner">
<img src={bannerImg} />
</div>
</div> */}
<div className="tool_bar">
<div className="tool_bar_left">
<div className="tool_bar_filter_item">
......@@ -56,28 +108,32 @@ const Commodity: React.FC = () => {
<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">重置</div>
<div className="filter_bar_left_text" onClick={handleResetFilter}>重置</div>
</div>
<div className="filter_bar_list">
<div className="filter_bar_list_item">
<span className="filter_bar_list_item_text">黄牛皮</span>
<CloseOutlined className="filter_bar_list_item_icon" />
</div>
<div className="filter_bar_list_item">
<span className="filter_bar_list_item_text">3M</span>
<CloseOutlined className="filter_bar_list_item_icon" />
</div>
<div className="filter_bar_list_item">
<span className="filter_bar_list_item_text">最低<b>¥179</b></span>
<CloseOutlined className="filter_bar_list_item_icon" />
</div>
{
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>
{
<CommodityList showType={showType} />
<div className="pagination_wrap">
<Pagination showQuickJumper showSizeChanger={false} defaultCurrent={1} total={100} />
</div>
}
{
!!search ? <NoResult search={search} /> : (
<>
<CommodityList showType={showType} />
<div className="pagination_wrap">
<Pagination showQuickJumper showSizeChanger={false} defaultCurrent={1} total={100} />
</div>
</>
)
}
</div>
</div>
</div>
......
.commodity_list {
margin-top: 20px;
display: flex;
flex-wrap: wrap;
&.column {
flex-direction: column;
margin-top: 20px;
}
&.row {
......
import React from 'react'
import styles from './index.less'
interface NoResultPropsType {
search?: string
}
const NoResult: 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>
”相关的商品
</div>
</div>
<div className={styles.no_result_suggest}>
<ul className={styles.no_result_suggest_list}>
<li>建议您:</li>
<li>1、尝试其他关键字</li>
<li>2、适当减少筛选条件</li>
<li>3、调整价格区间</li>
</ul>
</div>
</div>
)
}
export default NoResult
......@@ -264,4 +264,39 @@
}
}
}
}
.add_success {
display: flex;
height: 150px;
align-items: center;
&_info {
flex: 1;
}
&_btn {
width: 100px;
height: 30px;
background: rgba(211, 47, 47, 0.05);
border: 1px solid rgba(211, 47, 47, 0.2);
font-size: 12px;
line-height: 28px;
text-align: center;
color: #D32F2F;
cursor: pointer;
&:not(:last-child) {
margin-right: 20px;
}
&:hover {
opacity: .8;
}
&.primary {
background: rgba(211, 47, 47, 1);
color: #FFF;
}
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ import React, { useState } from 'react'
import { QuestionCircleOutlined } from '@ant-design/icons'
import { Tooltip } from 'antd'
import cx from 'classnames'
import DialogModal from '../components/DialogModal'
import Exhibition from './components/Exhibition'
import BrowseRecords from './components/BrowseRecords'
import Interested from './components/Interested'
......@@ -226,7 +227,26 @@ const CommodityDetail = (props) => {
</div>
</div>
</div>
<DialogModal
title="添加成功"
visible={false}
>
<div className="add_success">
<div className="add_success_info">
<div className="add_success_info_title">
<i className="add_success_info_icon"></i>
<span>货品已添加到进货单!</span>
</div>
<div className="add_success_info_text">
<span>当前进货单共</span>
<b>3</b>
<span>种商品</span>
</div>
</div>
<div className="add_success_btn primary">去结算</div>
<div className="add_success_btn">继续购物</div>
</div>
</DialogModal>
</div>
)
}
......
.add_success_modal {
position: relative;
:global {
.ant-modal-header {
background-color: #FAFAFA;
}
}
}
\ No newline at end of file
import React from 'react'
import { Modal } from 'antd'
import styles from './index.less'
interface DialogModalModalPropsType {
visible: boolean;
title?: string;
}
const DialogModal: React.FC<DialogModalModalPropsType> = (props) => {
const { visible = false, title, children } = props
return (
<Modal
className={styles.add_success_modal}
title={title}
visible={visible}
footer={null}
centered
width={600}
>
<div>
{children}
</div>
</Modal>
)
}
export default DialogModal
......@@ -2,7 +2,43 @@ import React from 'react'
import FilterBox from '../FilterBox'
import './index.less'
const Brand: React.FC = () => {
interface BrandPropsType {
onFilter?: Function;
}
const Brand: React.FC<BrandPropsType> = (props) => {
const { onFilter } = props
let mock_brand_list = [
{
id: 1,
name: '1M',
brandUrl: 'https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp'
},
{
id: 2,
name: '2M',
brandUrl: 'https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp'
},
{
id: 3,
name: '3M',
brandUrl: 'https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp'
},
{
id: 4,
name: '4M',
brandUrl: 'https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp'
},
]
const handleSelectBrand = (brandInfo) => {
onFilter({
type: 'brand',
key: brandInfo.id,
title: brandInfo.name
})
}
return (
<FilterBox
......@@ -10,26 +46,16 @@ const Brand: React.FC = () => {
>
<div className="filter_brand">
<ul className="filter_brand_list">
<li className="filter_brand_list_item">
<div className="brand_img">
<img src="https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
</li>
<li className="filter_brand_list_item">
<div className="brand_img">
<img src="https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
</li>
<li className="filter_brand_list_item">
<div className="brand_img">
<img src="https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
</li>
<li className="filter_brand_list_item">
<div className="brand_img">
<img src="https://img.alicdn.com/i2/2/TB1GJzSbQfb_uJjSsrbXXb6bVXa?abtest=&pos=1&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
</li>
{
mock_brand_list.map(item => (
<li className="filter_brand_list_item" key={item.id} onClick={() => handleSelectBrand(item)}>
<div className="brand_img">
<img src={item.brandUrl} />
</div>
</li>
))
}
</ul>
</div>
</FilterBox>
......
......@@ -3,7 +3,12 @@ import { Tree } from 'antd'
import FilterBox from '../FilterBox'
import './index.less'
const Category: React.FC = () => {
interface CategoryPropsType {
onFilter?: Function
}
const Category: React.FC<CategoryPropsType> = (props) => {
const { onFilter } = props
const treeData = [
{
......@@ -58,14 +63,14 @@ const Category: React.FC = () => {
},
];
const onSelect = (selectedKeys, info) => {
console.log('selected', selectedKeys, info);
};
const onCheck = (checkedKeys, info) => {
console.log('onCheck', checkedKeys, info);
};
const handleSelect = (selectedKeys, info) => {
const { title } = info.node
onFilter({
type: 'category',
key: selectedKeys,
title
})
}
return (
<FilterBox
......@@ -74,9 +79,7 @@ const Category: React.FC = () => {
<div className="filter_category">
<Tree
defaultExpandedKeys={['0-0-0', '0-0-0']}
// defaultSelectedKeys={['0-0-0', '0-0-1']}
onSelect={onSelect}
onCheck={onCheck}
onSelect={handleSelect}
treeData={treeData}
/>
</div>
......
......@@ -3,9 +3,13 @@ import { Checkbox } from 'antd'
import FilterBox from '../FilterBox'
import './index.less'
interface CommodityTypePropsType {
}
const CheckboxGroup = Checkbox.Group
const CommodityType: React.FC = () => {
const CommodityType: React.FC<CommodityTypePropsType> = (props) => {
const styleOptions = [
{ label: '只看现价商品', value: '1' },
......
......@@ -4,7 +4,11 @@ import { CaretDownOutlined } from '@ant-design/icons'
import FilterBox from '../FilterBox'
import '../../index.less'
const CommonlyUsed: React.FC = () => {
interface CommonlyUsedPropsType {
}
const CommonlyUsed: React.FC<CommonlyUsedPropsType> = (props) => {
return (
<FilterBox
......
......@@ -3,7 +3,11 @@ import { Slider } from 'antd'
import FilterBox from '../FilterBox'
import './index.less'
const Price: React.FC = () => {
interface PricePropsType {
}
const Price: React.FC<PricePropsType> = (props) => {
const [priceRange, setPriceRange] = useState<any>([0, 1000])
const handlePriceChange = (value) => {
......
......@@ -9,6 +9,35 @@
}
.ant-checkbox-wrapper {
font-size: 12px;
}
.ant-checkbox-checked::after {
border: 1px solid var(--mall_main_color);
}
.ant-checkbox-input {
&:active,
&:hover,
&:focus {
+.ant-checkbox-inner {
border-color: var(--mall_main_color);
}
}
}
.ant-checkbox-group-item {
&:hover,
&:active {
.ant-checkbox-inner {
border-color: var(--mall_main_color);
}
}
}
.ant-checkbox-checked .ant-checkbox-inner {
background-color: var(--mall_main_color);
border-color: var(--mall_main_color);
......
......@@ -5,7 +5,12 @@ import './index.less'
const CheckboxGroup = Checkbox.Group
const Style: React.FC = () => {
interface StylePropsType {
onFilter?: Function;
}
const Style: React.FC<StylePropsType> = (props) => {
const { onFilter } = props
const styleOptions = [
{ label: '荔枝纹', value: '1' },
......@@ -13,8 +18,8 @@ const Style: React.FC = () => {
{ label: '自然摔纹', value: '3' },
];
const handleChange = () => {
const handleChange = (e) => {
console.log(e)
}
return (
......
......@@ -3,7 +3,12 @@ import FilterBox from '../FilterBox'
import cx from 'classnames'
import './index.less'
const UseArea: React.FC = () => {
interface UseAreaPropsType {
onFilter?: Function;
}
const UseArea: React.FC<UseAreaPropsType> = (props) => {
const { onFilter } = props
const [selectCity, setSelectCity] = useState<string[]>([])
......@@ -77,12 +82,18 @@ const UseArea: React.FC = () => {
]
const handleSelect = (key: string, type: number) => {
const handleSelect = (item: any, type: number) => {
if (type === 1) {
setSelectCity([key])
setSelectCity([item.value])
} else {
setSelectCity([selectCity[0], key])
setSelectCity([selectCity[0], item.value])
}
onFilter({
type: 'area',
title: item.label,
key: item.value
})
}
return (
......@@ -94,15 +105,14 @@ const UseArea: React.FC = () => {
{
mockData.map(item => (
<div key={item.value} className={cx("filter_usearea_list_item", selectCity.includes(item.value) ? "active" : '')}>
<span className="text" onClick={() => handleSelect(item.value, 1)}>{item.label}</span>
<span className="text" onClick={() => handleSelect(item, 1)}>{item.label}</span>
{
(selectCity.includes(item.value) && !!item.children) && (
<div className="more_panel">
<div className="sub_area_list">
{
item.children.map(childItem => (
<div onClick={() => handleSelect(childItem.value, 2)} className={cx("sub_area_list_item", selectCity.includes(childItem.value) ? 'active' : '')}>
<div key={childItem.value} onClick={() => handleSelect(childItem, 2)} className={cx("sub_area_list_item", selectCity.includes(childItem.value) ? 'active' : '')}>
{childItem.label}
</div>
))
......
......@@ -8,16 +8,25 @@ import UseArea from './components/UseArea'
import CommodityType from './components/CommodityType'
import './index.less'
const Filter: React.FC = () => {
interface FilterPropsType {
onFilter?: Function;
}
const Filter: React.FC<FilterPropsType> = (props) => {
const { onFilter } = props
const handleFilter = (filterValue: any) => {
onFilter(filterValue)
}
return (
<div className="filter">
<CommonlyUsed />
<Category />
<Style />
<Brand />
<Category onFilter={handleFilter} />
<Style onFilter={handleFilter} />
<Brand onFilter={handleFilter} />
<Price />
<UseArea />
<UseArea onFilter={handleFilter} />
<CommodityType />
</div>
)
......
@import '../../../../theme/style/common.less';
@mall_main_color: var(--mall_main_color);
.shop_header {
position: relative;
background-color: #FFF;
width: 100%;
padding-top: 10px;
.shop_header_container {
.common_page_container();
height: 110px;
display: flex;
align-items: center;
.logo {
padding-left: 14px;
&>img {
width: 145px;
height: 50px;
}
}
.shop_header_split {
width: 1px;
height: 32px;
background-color: #F5F5F5;
margin: 0 20px;
}
.shop_header_info {
position: relative;
height: 48px;
display: flex;
&:hover {
.shop_info {
display: block;
}
}
&_logo {
border-radius: 4px;
overflow: hidden;
width: 48px;
height: 48px;
margin-right: 8px;
&>img {
width: 48px;
height: 48px;
}
}
&_content {
position: relative;
&_name {
font-size: 14px;
color: #333333;
font-weight: 500;
}
&_about {
display: flex;
margin-top: 4px;
&_item {
flex: 1;
display: flex;
align-items: center;
&>span {
font-size: 14px;
color: #333333;
line-height: 20px;
&.red {
color: #D32F2F;
margin-right: 4px;
}
}
&>.icon {
position: relative;
top: -1px;
overflow: hidden;
margin-right: 5px;
&>img {
width: 20px;
height: 20px;
}
}
}
}
&_icon {
color: #cccccc;
font-size: 12px;
margin-left: 6px;
}
}
.shop_info {
position: absolute;
display: none;
top: 48px;
width: 214px;
padding: 0 10px;
padding-bottom: 15px;
margin-bottom: 20px;
border: 1px solid rgba(245, 245, 245, 1);
background: linear-gradient(180deg, rgba(255, 245, 203, 1) 0%, rgba(255, 253, 244, 1) 100%);
z-index: 8;
left: 0;
.shop_info_title {
display: flex;
align-items: center;
justify-content: center;
height: 47px;
&_split {
width: 40px;
height: 1px;
background-color: #F2C17C;
}
&_text {
color: #EA8000;
margin: 0 15px;
}
}
.shop_name {
font-size: 12px;
color: #333333;
margin-bottom: 10px;
font-weight: bold;
}
.shop_about {
display: flex;
&_item {
flex: 1;
display: flex;
align-items: center;
&>span {
font-size: 14px;
color: #333333;
line-height: 20px;
&.red {
color: #D32F2F;
margin-right: 4px;
}
}
&>.icon {
position: relative;
top: -1px;
overflow: hidden;
margin-right: 5px;
&>img {
width: 20px;
height: 20px;
}
}
}
}
.dashed_split {
margin: 15px 0;
width: 100%;
border-top: 1px dashed #F2C17C;
height: 0;
}
.shop_info_list {
margin-top: 10px;
&_item {
display: flex;
font-size: 12px;
color: #333333;
align-items: center;
&:not(:last-child) {
margin-bottom: 5px;
}
&>.breif {
.star {
font-size: 15px;
line-height: 15px;
}
.certified {
color: #00B37A;
}
}
&>.label {
width: 60px;
}
}
}
.shop_info_btn_group {
display: flex;
.shop_info_btn {
flex: 1;
height: 32px;
background-color: #FFFFFF;
border: 1px solid rgba(229, 229, 229, 1);
color: #333333;
font-size: 12px;
line-height: 32px;
text-align: center;
cursor: pointer;
&:hover {
background-color: #f5f5f5;
}
&:last-child {
margin-left: 6px;
}
}
}
.apply_member_btn {
margin-top: 15px;
width: 100%;
height: 32px;
background-color: #D32F2F;
color: #FFF;
line-height: 32px;
text-align: center;
font-size: 12px;
cursor: pointer;
&:hover {
opacity: .9;
}
}
}
}
.mall_search {
width: 528px;
margin-left: auto;
.mall_search_tags {
.mall_search_tags_item {
display: inline-block;
height: 24px;
line-height: 24px;
color: @mall_main_color;
font-size: 12px;
padding: 0 9px;
cursor: pointer;
&.active {
background-color: @mall_main_color;
color: #FFF;
}
}
}
.mall_search_box {
.commone_input_placeholder();
position: relative;
width: 100%;
border: 2px solid @mall_main_color;
height: 40px;
.mall_search_input {
display: inline-block;
width: 521px;
height: 36px;
line-height: 36px;
outline: none;
border: none;
text-indent: 12px;
}
.search_btn {
position: absolute;
background-color: @mall_main_color;
color: #FFF;
width: 120px;
height: 100%;
line-height: 36px;
text-align: center;
font-size: 14px;
z-index: 1;
right: 0;
top: 0;
cursor: pointer;
&:hover {
opacity: .9;
}
}
}
}
.shopping_cart {
position: relative;
vertical-align: top;
margin-left: 66px;
display: inline-block;
width: 110px;
height: 40px;
border: 1px solid rgba(204, 204, 204, 1);
line-height: 38px;
color: @mall_main_color;
text-align: center;
cursor: pointer;
&.mall {
margin-top: 24px;
}
.card_icon {
margin-right: 14px;
}
.badge {
position: absolute;
width: 16px;
height: 16px;
left: 26px;
top: 4px;
border-radius: 50%;
overflow: hidden;
line-height: 16px;
font-size: 12px;
color: #FFF;
background-color: @mall_main_color;
}
}
}
}
\ No newline at end of file
import React, { useState } from 'react'
import { CaretDownOutlined } from '@ant-design/icons'
import { Rate } from 'antd'
import { Link, history } from 'umi'
import logo from '@/theme/imgs/logo_w.png'
import shop_icon from '@/assets/imgs/shop_icon.png'
import credit_icon from '@/assets/imgs/credit_icon.png'
import shopLogo from '@/assets/imgs/shop_logo.png'
import './index.less'
interface ShopHeaderPropsType {
}
const ShopHeader: React.FC<ShopHeaderPropsType> = (props) => {
const { query } = history.location
return (
<div className="shop_header">
<div className="shop_header_container">
<div className="logo">
<Link to="/">
<img src={logo} />
</Link>
</div>
<div className="shop_header_split"></div>
<div className="shop_header_info">
<div className="shop_header_info_logo">
<img src={shopLogo} />
</div>
<div className="shop_header_info_content">
<div className="shop_header_info_content_name">
<span>广州白马灯具有限公司</span>
<CaretDownOutlined className="shop_header_info_content_icon" />
</div>
<div className="shop_header_info_content_about">
<div className="shop_header_info_content_about_item">
<i className="icon"><img src={shop_icon} /></i>
<span className="red">2</span>
<span></span>
</div>
<div className="shop_header_info_content_about_item">
<i className="icon"><img src={credit_icon} /></i>
<span>1288</span>
</div>
</div>
</div>
<div className="shop_info">
<div className="shop_info_title">
<div className="shop_info_title_split"></div>
<div className="shop_info_title_text">会员认证</div>
<div className="shop_info_title_split"></div>
</div>
<div className="shop_info_list">
<div className="shop_info_list_item">
<div className="label">满意度:</div>
<div className="breif"><Rate className="star" count={4} disabled defaultValue={4} /></div>
</div>
<div className="shop_info_list_item">
<div className="label">注册资本:</div>
<div className="breif">5000万元</div>
</div>
<div className="shop_info_list_item">
<div className="label">成立日期:</div>
<div className="breif">2014-09-09</div>
</div>
<div className="shop_info_list_item">
<div className="label">营业执照:</div>
<div className="breif"><span className="certified">[已认证]</span></div>
</div>
</div>
<div className="dashed_split"></div>
<div className="shop_info_btn_group">
<div className="shop_info_btn">进入店铺</div>
<div className="shop_info_btn">收藏本店</div>
</div>
<div className="apply_member_btn">申请成为本店会员</div>
</div>
</div>
<div className="mall_search">
<div className="mall_search_box">
<input className="mall_search_input" placeholder="请输入关键词" />
<div className="search_btn">搜本店</div>
</div>
</div>
</div>
</div>
)
}
export default ShopHeader
......@@ -5,6 +5,7 @@
height: 30px;
width: 100%;
background-color: #FFF;
border-bottom: 1px solid #F5F5F5;
.topbar_container {
.common_page_container();
......
......@@ -10,7 +10,6 @@ const Category: React.FC = () => {
<div className="category_type">
<MenuOutlined className="icon" />
<span>全部商品分类</span>
</div>
<div className="category_content">
<div className="category_type_panel">
......
......@@ -5,6 +5,7 @@
position: relative;
background-color: #FFF;
width: 100%;
padding-top: 10px;
.header_container {
.common_page_container();
......
import React, { useState } from 'react'
import cx from 'classnames'
import { Link } from 'umi'
import { FileTextOutlined } from '@ant-design/icons'
import logo from '@/theme/imgs/logo_w.png'
import './index.less'
interface HeaderPropsType {
type: string;
}
const Header: React.FC<HeaderPropsType> = (props) => {
const { type } = props // type: shop: 店铺; mall:商城
const [searchType, setSearchType] = useState<number>(1) // 1:商品; 2:店铺
const handleChangeSearchType = (type: number) => {
......@@ -22,31 +22,25 @@ const Header: React.FC<HeaderPropsType> = (props) => {
<div className="header">
<div className="header_container">
<div className="logo">
<img src={logo} />
<Link to="/">
<img src={logo} />
</Link>
</div>
<div className="mall_search">
{
type === 'mall' && (
<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>
)
}
<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>
<div className="mall_search_box">
<input className="mall_search_input" placeholder="请输入关键词" />
<div className="search_btn">搜索</div>
</div>
</div>
{
type === 'mall' && (
<div className="shopping_cart mall">
<div className="badge">0</div>
<FileTextOutlined className="card_icon" />
<span>进货单</span>
</div>
)
}
<div className="shopping_cart mall">
<div className="badge">0</div>
<FileTextOutlined className="card_icon" />
<span>进货单</span>
</div>
</div>
</div>
)
......
......@@ -8,6 +8,8 @@
border-bottom: 2px solid @mall_main_color;
background-color: #FFF;
&_container {
.common_page_container();
height: 40px;
......@@ -41,4 +43,20 @@
}
}
}
&.shop {
background-color: @mall_main_color;
.main_nav_container>.nav .nav_item {
&.active {
a {
color: #FFF;
}
}
a {
color: #FFF;
}
}
}
}
\ No newline at end of file
......@@ -7,12 +7,15 @@ import './index.less'
interface MainNavPropsType {
menuData: any;
pathname: string;
type: "shop" | "mall"
}
const MainNav: React.FC<MainNavPropsType> = (props) => {
const { menuData, pathname } = props
const { menuData, pathname, type } = props
console.log(type, "type")
return (
<div className="main_nav">
<div className={cx("main_nav", type === "shop" ? "shop" : "")}>
<div className="main_nav_container">
<Category />
<ul className="nav">
......
......@@ -5,6 +5,7 @@ import FloorLine from '../components/FloorLine'
import Information from '../components/Information'
import FindMore from '../components/FindMore'
import FloorAnchor from '../components/FloorAnchor'
import { PublicApi } from '@/services/api'
import analyze from 'rgbaster'
import './index.less'
......@@ -12,8 +13,20 @@ const MallIndex: React.FC = () => {
useEffect(() => {
getImgRGB()
fetchMallHome()
}, [])
const fetchMallHome = () => {
//@ts-ignore
PublicApi.getTemplatePlatformFindMallHome({ templateId: 707 }).then(res => {
if (res.code === 1000) {
}
})
}
const getImgRGB = async () => {
// 获取图片主题色
const result = await analyze('https://img.alicdn.com/tps/i4/TB1ICgYL.H1gK0jSZSySuttlpXa.jpg')
......
......@@ -6,7 +6,6 @@ import {
import SelectLang from '@/layouts/components/SelectLang'
import { useIntl } from 'umi';
import TopBar from '../components/TopBar'
import Advert from '../components/Advert'
import Header from '../components/Header'
import MainNav from '../components/MainNav'
import SideNav from '../components/SideNav'
......@@ -40,10 +39,9 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
return (
<div className={styles.lxmall_page}>
<TopBar langComponent={<SelectLang />} />
<Advert type="top" />
<div className={styles.content}>
<Header type="mall" />
<MainNav menuData={menuData} pathname={location.pathname} />
<Header />
<MainNav menuData={menuData} pathname={location.pathname} type="mall" />
{children}
</div>
<Footer />
......
......@@ -6,7 +6,7 @@ import {
import { useIntl } from 'umi';
import TopBar from '../components/TopBar'
import Advert from '../components/Advert'
import Header from '../components/Header'
import ShopHeader from '../components/ShopHeader'
import MainNav from '../components/MainNav'
import SideNav from '../components/SideNav'
import Footer from '../components/Footer'
......@@ -37,10 +37,9 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
return (
<div className={styles.lxmall_page}>
<TopBar />
<Advert />
<div className={styles.content}>
<Header type="shop" />
<MainNav menuData={menuData} pathname={location.pathname} />
<ShopHeader />
<MainNav menuData={menuData} pathname={location.pathname} type="shop" />
{children}
</div>
<Footer />
......
......@@ -4,6 +4,7 @@ import { PlusOutlined, MinusOutlined } from '@ant-design/icons'
import { PublicApi } from '@/services/api'
import cx from 'classnames'
import styles from './index.less'
import { isEmpty } from '@formily/antd/esm/shared'
interface CitySelectPropsType {
selectData: Array<{
......@@ -47,9 +48,9 @@ const CityCascader: React.FC<CitySelectPropsType> = (props) => {
return result
}
const getCityById = (id: number) => {
const getCityById = (id: number, provinceCode: string) => {
let result: number = 0
cities && cities.map(item => {
!isEmpty(cityData) && cityData[provinceCode].map(item => {
if (item.value === id) {
result = item
}
......@@ -94,7 +95,7 @@ const CityCascader: React.FC<CitySelectPropsType> = (props) => {
const handleProvinceChange = (value: number, index: number) => {
let newData = JSON.parse(JSON.stringify(selectData))
let proviceById: any = getProviceById(value)
console.log(cityData[proviceById.value], "cityData[proviceById.value]")
setCities(cityData[proviceById.value])
newData.map((item: any) => {
if (item.index === index) {
......@@ -108,10 +109,10 @@ const CityCascader: React.FC<CitySelectPropsType> = (props) => {
onChange(newData)
}
const onSecondCityChange = (value: number, index: number) => {
const onSecondCityChange = (value: number, provinceCode: string, index: number) => {
let newData = JSON.parse(JSON.stringify(selectData))
const cityById: any = getCityById(value)
const cityById: any = getCityById(value, provinceCode)
newData.map((item: any) => {
if (item.index === index) {
item.cityCode = cityById.value
......@@ -150,12 +151,12 @@ const CityCascader: React.FC<CitySelectPropsType> = (props) => {
<Select
style={{ width: 278, marginLeft: 16, marginRight: 24 }}
value={item.cityCode ? item.cityCode : undefined}
onChange={(value) => onSecondCityChange(value, item.index)}
onChange={(value) => onSecondCityChange(value, item.provinceCode, item.index)}
placeholder="请选择"
>
{cities.map((item: any) => (
{(item.provinceCode && !isEmpty(cityData)) ? cityData[item.provinceCode].map((item: any) => (
<Option value={item.value} key={item.value}>{item.lable}</Option>
))}
)) : null}
</Select>
{
index === selectData.length - 1 && (
......
......@@ -55,7 +55,7 @@ const TemplateItem: React.FC<TemplateItemPropsType> = (props) => {
<span>{templateInfo.shopName}</span>
</div>
</div>
<div className={cx(styles.template_item_btn, templateInfo.isUse ? styles.active : '')}>
<div className={cx(styles.template_item_btn, templateInfo.use === 1 ? styles.active : '')}>
<PlayCircleOutlined />
<label>{templateInfo.use === 1 ? '启用中' : '启用'}</label>
</div>
......
......@@ -21,16 +21,19 @@ interface ShopInfoPropsType {
}
}
const defaultCityData = { index: 0, provinceCode: 0, province: '', cityCode: 0, city: '' }
const ShopInfo: React.FC<ShopInfoPropsType> = (props) => {
const { siteUrl, siteId } = props.SiteStore
const [formIsHalfFilledOut, setFormIsHalfFilledOut] = useState(false)
const [form] = Form.useForm()
const [allMallList, setAllMallList] = useState([])
const [storeUrl, setStoreUrl] = useState<string>('')
const [selectCityData, setSelectCityData] = useState([{ index: 0, provinceCode: 0, province: '', cityCode: 0, city: '' }])
const [selectCityData, setSelectCityData] = useState<any>([defaultCityData])
const [workshopPics, setWorkshopPics] = useState([]) // 厂房照片
const [honorPics, setHonorPics] = useState([]) // 资质荣誉
const [logo, setLogo] = useState<string>("")
const [shopId, setShopId] = useState<number>()
useEffect(() => {
fetchShopInfo()
......@@ -51,7 +54,35 @@ const ShopInfo: React.FC<ShopInfoPropsType> = (props) => {
* 获取店铺信息
*/
const fetchShopInfo = () => {
PublicApi.getTemplateShopFindShop()
PublicApi.getTemplateShopFindShop().then(res => {
const data = res.data
if (res.code === 1000) {
setSelectCityData(initMemberShopArea(data.memberShopAreas) || defaultCityData)
setLogo(data.logo)
setShopId(data.shopId)
setWorkshopPics(data.workshopPics || [])
setHonorPics(data.honorPics || [])
setStoreUrl(data.storeUrl || "")
form.setFieldsValue({
describe: data.describe,
customerUrl: data.customerUrl,
logo: data.logo,
memberShopAreas: initMemberShopArea(data.memberShopAreas) || defaultCityData,
workshopPics: data.workshopPics || [],
honorPics: data.honorPics || []
})
}
})
}
const initMemberShopArea = (data) => {
if (!!data) {
return data.map((item, index) => {
item.index = index
return item
})
}
return data
}
const handleAddNewCitySelect = (item: any) => {
......@@ -83,26 +114,38 @@ const ShopInfo: React.FC<ShopInfoPropsType> = (props) => {
let result = [...workshopPics]
result = result.filter(item => item !== itemInfo)
setWorkshopPics(result)
form.setFieldsValue({
workshopPics: result
})
}
const handleDeleteHonorPicsItem = (itemInfo: any) => {
let result = [...honorPics]
result = result.filter(item => item !== itemInfo)
setHonorPics(result)
form.setFieldsValue({
honorPics: result
})
}
const handleSave = (e: any) => {
e.preventDefault()
console.log(selectCityData)
form.validateFields().then(value => {
console.log(value)
if (checkMemberShopAreas(value.memberShopAreas)) {
if (!checkMemberShopAreas(value.memberShopAreas)) {
return
}
if (!shopId) {
message.error("店铺链接不能为空")
return
}
value.storeUrl = storeUrl
value.shopId = shopId
//@ts-ignore
PublicApi.postTemplateShopSaveShop(value).then(res => {
if (res.code === 1000) {
fetchShopInfo()
setFormIsHalfFilledOut(false)
}
})
......@@ -160,7 +203,18 @@ const ShopInfo: React.FC<ShopInfoPropsType> = (props) => {
const handleMallSelectChange = (mallId: number) => {
let selectItem = allMallList.filter(item => item.id === mallId)
setStoreUrl(`${siteUrl}/B2B?id=${1}`)
setShopId(mallId)
if (mallId) {
setStoreUrl(`${siteUrl}/${selectItem[0].url}?id=${1}`)
} else {
setStoreUrl(null)
}
}
const handleFormValueChange = () => {
console.log('handleFormValueChange')
setFormIsHalfFilledOut(true)
}
return (
......@@ -171,6 +225,7 @@ const ShopInfo: React.FC<ShopInfoPropsType> = (props) => {
form={form}
className={styles.add_template_form}
hideRequiredMark={true}
onValuesChange={handleFormValueChange}
>
<Form.Item
labelAlign="left"
......@@ -271,7 +326,7 @@ const ShopInfo: React.FC<ShopInfoPropsType> = (props) => {
label={<RequireItem label="店铺链接" />}
// rules={[{ required: true, message: "请输入客服链接" }]}
>
<Select allowClear className={styles.form_item} onChange={handleMallSelectChange}>
<Select allowClear value={shopId} className={styles.form_item} onChange={handleMallSelectChange}>
{
allMallList.map(item => (
<Select.Option key={item.id} value={item.id}>{MALL_TYPE[item.type]}</Select.Option>
......
import React, { useEffect, useState } from 'react'
import { Row, Col } from 'antd'
import { Row, Col, message } from 'antd'
import { history } from 'umi'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import TemplateItem from '../components/templateItem'
import { PublicApi } from '@/services/api'
......@@ -16,7 +17,12 @@ const ShopTemplate: React.FC = () => {
const fetchAllShelfShopTemplate = () => {
PublicApi.getTemplateShopFindAllShelfShopTemplate().then(res => {
setTemplateList(res.data)
if (res.code === 1000) {
setTemplateList(res.data)
} else if (res.code === 47001) {
message.info("您还未创建店铺,请先创建店铺")
history.push('/memberCenter/shopAbility/infoManage')
}
})
}
......
......@@ -95,7 +95,7 @@ const TemplateDetail: React.FC<TemplateDetailPropsType> = (props) => {
<LayoutOutlined />
<label>店铺装修</label>
</div>
<div className={cx(styles.btn, detailInfo?.use === 1 ? styles.use : '')} onClick={() => setUseModalVisible(true)}>
<div className={cx(styles.btn, detailInfo?.use === 1 ? styles.use : '')} onClick={() => detailInfo?.use !== 1 ? setUseModalVisible(true) : {}}>
<PushpinOutlined />
<label>{detailInfo?.use === 1 ? '使用中' : '使用'}</label>
</div>
......
import { action, computed, observable, runInAction } from 'mobx'
import { ILoginModule } from '@/module/userModule';
import { localStorage } from '@/utils/storage'
// import { userDetailGet } from '@/services/user'
const userInfo = localStorage.getItem('userInfo')
// const userInfo = localStorage.getItem('userInfo')
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 = {} //userInfo ? JSON.parse(userInfo) : {}
// 可以改变对应的状态值
// @todo 接入更新用户信息接口
......
......@@ -30,7 +30,7 @@
height: 460px;
background-color: var(--category_content_bg);
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.05);
top: 40px;
top: 42px;
left: 0;
z-index: 5;
......
......@@ -9,11 +9,11 @@
// 店铺科技类模板颜色配置
&.theme-shop-science {
--mall_main_color: #464552;
--mall_sub_color: #FFFFFF;
--mall_main_color: #D32F2F;
--mall_sub_color: rgba(211, 47, 47, 0.1);
--category_content_bg: #464552;
--category_content_title_text: #FFFFFF;
--category_content_sub_title_text: rgba(255, 255, 255, .45);
--category_content_bg: #FFFFFF;
--category_content_title_text: #333333;
--category_content_sub_title_text: #666666;
}
}
\ No newline at end of file
import { extend, ResponseError, OnionOptions, RequestOptionsInit, ResponseInterceptor, OnionMiddleware, Context, RequestMethod } from 'umi-request';
import responseCode from '@/constants/responseCode'
import { IRequestError, IRequestSuccess } from '..';
import { history } from 'umi'
import { message } from 'antd'
import { getAuth } from './auth';
......@@ -106,6 +107,11 @@ class ApiRequest {
options.ctlType === 'message' && message.success(res.message)
resolve(res)
} else {
// 未登录
if (res.code === 1101) {
history.push('/user/login')
reject()
}
message.error(res.message)
}
}).catch((err: IRequestError) => {
......
let targetWin = null
if (window) targetWin = window
let proxyWindow = new Proxy(targetWin, {
get: function (target, key, receiver) {
if (!targetWin) {
return Reflect.get({ nothing: function () { } }, 'nothing', receiver);
}
return Reflect.get(target, key, receiver);
}
});
export const localStorage = proxyWindow.localStorage
export const sessionStorage = proxyWindow.sessionStorage
export default proxyWindow
\ No newline at end of file
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