Commit f7ab0e52 authored by 前端-许佳敏's avatar 前端-许佳敏

merge

parents 47b40454 de69ff87
import React, { useState } from 'react';
import { Input, Space, Select, Button } from 'antd';
import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons';
import { useFieldState, FormPath, FormEffectHooks } from '@formily/antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { PublicApi } from '@/services/api';
const { Option } = Select
// export interface SearchProps {
// value: string;
// mutators: any;
// props: any;
// }
const CustomInputSearch = props => {
console.log(props);
// const [state, setState] = useFieldState({
// filterSearch: false,
// });
const justifyAlign = props.props['x-component-props'].align || 'flex-end';
// const changeFilterVisible = () => {
// if (state.filterSearch) {
// props.form.reset({
// // 清除FILTER_PARAMS下所有字段
// selector: `*.${FORM_FILTER_PATH}.*`,
// });
// }
// setState({
// filterSearch: !state.filterSearch,
// });
// };
const [brandData, setBrandData] = useState<any>([])
const [brandValue, setBrandValue] = useState(undefined)
const handleBrandSearch = (value: any) => { // end value
console.log(value, 'handleBrandSearch')
if (value) {
PublicApi.getProductSelectGetSelectBrand({ name: value }).then(res => {
if (res.code === 1000)
setBrandData(res.data)
})
} else {
setBrandData([])
}
}
return (
<Space size={20} style={{ justifyContent: justifyAlign, width: '100%' }}>
<Select
showSearch={true}
showArrow={true}
placeholder="品牌"
value={brandValue}
defaultActiveFirstOption={false}
filterOption={false}
onSearch={value => handleBrandSearch(value)}
onChange={v => props.mutators.change(v)}
notFoundContent={null}
style={{ width: '174px', lineHeight: '32px' }}
{...props.props['x-component-props']}
>
{brandData.map(d => <Option value={d.id} key={d.id}>{d.name}</Option>)}
</Select>
{/* <Input.Search
value={props.value || ''}
onChange={e => props.mutators.change(e.target.value)}
onSearch={(_, e) => {
e.preventDefault();
props.form.submit();
}}
{...props.props['x-component-props']}
/> */}
</Space>
);
};
CustomInputSearch.defaultProps = {};
CustomInputSearch.isFieldComponent = true;
export default CustomInputSearch;
......@@ -9,6 +9,7 @@ import CustomStatus from './components/CustomStatus';
import CustomAddArray from './components/CustomAddArray';
import CustomSlider from './components/CustomSlider';
import Search from './components/Search';
import CustomInputSearch from './components/CustomInputSearch'
import Submit from './components/Submit';
import Text from './components/Text';
import CardCheckBox from './components/CardCheckBox';
......@@ -82,6 +83,7 @@ const NiceForm: React.FC<NiceFormProps> = props => {
CustomAddArray,
CustomSlider,
Search,
CustomInputSearch,
Submit,
Text,
CardCheckBox,
......
......@@ -108,7 +108,10 @@ const AddGoods = () => {
}
const onFinish = (values:any) => {
PublicApi.postProductGoodsSaveOrUpdateGoods({...values})
PublicApi.postProductGoodsSaveOrUpdateGoods({...values}).then(res => {
if(res.code === 1000)
history.goBack()
})
};
return (<PageHeaderWrapper
......
......@@ -314,9 +314,9 @@ const Goods: React.FC<{}> = () => {
console.log('取消删除')
}
const handleSearch = (val: string) => {
const handleSearch = (val?: string) => {
console.log(val)
let obj = { ...filterParams, name: val }
let obj = val ? { ...filterParams, name: val } : { ...filterParams }
setFilterParams(obj)
//@ts-ignore
ref.current.reload(obj)
......@@ -402,6 +402,28 @@ const Goods: React.FC<{}> = () => {
tableProps={{ rowKey: "id" }}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
// <NiceForm
// actions={formActions}
// onSubmit={values => ref.current.reload(values)}
// expressionScope={{
// controllerBtns,
// }}
// effects={($, actions) => {
// useStateFilterSearchLinkageEffect(
// $,
// actions,
// 'name',
// FORM_FILTER_PATH,
// );
// // useAsyncInitSelect(
// // ['memberType', 'roleId', 'level', 'source'],
// // fetchSearchItems,
// // );
// }}
// schema={goodsSchema}
// />
<Row>
<Col span={24}>
<Row gutter={[16,16]} justify="space-between" style={{marginBottom:0}}>
......@@ -475,6 +497,9 @@ const Goods: React.FC<{}> = () => {
<Col span={4}>
<Input name="batch" value={filterParams.batch} onChange={(e)=>setFilterParams({...filterParams, batch: e.target.value})} placeholder="导入批次"></Input>
</Col>
<Col>
<Button type="primary" onClick={()=>handleSearch()}>查询</Button>
</Col>
</Col>
</Row>
</Col>
......
......@@ -51,15 +51,9 @@ export const goodsSchema: ISchema = {
},
brandId: {
type: 'string',
enum: [],
'x-component': 'CustomInputSearch',
'x-component-props': {
placeholder: '品牌',
showSearch: true,
showArrow: true,
filterOption: false,
defaultActiveFirstOption: false,
notFoundContent: false,
style: { width: '100%' },
},
},
customerCategoryId: {
......
......@@ -128,10 +128,12 @@ const AddProducts: React.FC<{}> = (props) => {
_params.id = id ? id : null
console.log(_params,'_params')
PublicApi.postProductCommoditySaveOrUpdateCommodity(_params).then(res => {
console.log(res, 'res')
setIsEnableCheck(false)
//@ts-ignore
setReponseId(res.data)
if(res.code === 1000){
setIsEnableCheck(false)
//@ts-ignore
setReponseId(res.data)
history.goBack()
}
})
}).catch(error => {
message.error("请完善表单必填项!")
......
......@@ -8,17 +8,16 @@
padding: 0;
li{
padding-left: 24px;
height: 32px;
line-height: 32px;
// height: 32px;
// line-height: 32px;
color: #172B4D;
display: flex;
justify-content: space-between;
margin: 8px 0;
cursor: pointer;
// span{
// padding-top: 12px;
// padding-bottom: 12px;
// }
span{
padding-right: 16px;
}
a{
color: #97A0AF;
float: right;
......
......@@ -48,6 +48,8 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
const [attributeObjArr, setAttributeObjArr] = useState<any[]>([])
const [attributeValObjArr, setAttributeValObjArr] = useState<any[]>([])
const [validatorArray, setValidatorArray] = useState<any>([])
const [colums, setColumns] = useState<ColumnType<any>[]>()
const { ProductStore } = store
const {
......@@ -339,6 +341,19 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
priceForm.setFieldsValue({unitName: option.children})
}
// 校验数值范围
const validatorNumberRange = (rule, value, callback) => {
try {
setValidatorArray([...validatorArray, value])
console.log(value, [...validatorArray, value], 'rule')
if(value.numberMin >= value.numberMax){
throw new Error('请正确输入数值范围')
}
} catch (err) {
// callback(err)
}
}
return (<>
<Form
{...layout}
......@@ -347,7 +362,7 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
labelAlign="left"
ref={priceFormRef}
colon={false}
initialValues={productInfoByEdit?.id ? getPriceAttributeFormParamsByEdit : {}}
initialValues={productInfoByEdit?.id ? getPriceAttributeFormParamsByEdit : {isMemberPrice: false}}
autoComplete="off"
>
<Form.Item
......@@ -407,7 +422,7 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
transform: (value) => Number(value)
}]}
>
<Input placeholder="请输入最小起订数" />
<InputNumber style={{width: '100%'}} min={0} placeholder="请输入最小起订数" />
</Form.Item>
<Form.Item
name="priceType"
......@@ -441,10 +456,10 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
</Tooltip>
</span>
}
rules={[{
required: true,
message: '请选择会员折扣'
}]}
// rules={[{
// required: true,
// message: '请选择会员折扣'
// }]}
valuePropName="checked"
>
<Checkbox>允许使用会员折扣价购买</Checkbox>
......@@ -499,10 +514,24 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
fieldKey={[field.fieldKey, 'numberRange']}
key={'_' + field.fieldKey}
noStyle
// rules={[
// {
// validator: validatorNumberRange
// }
// ]}
>
<Input.Group compact>
<Form.Item name={[field.name, 'numberRange', 'numberMin']} noStyle>
<Input style={{ width: 100, textAlign: 'center' }} placeholder="最小数量" />
<Form.Item
name={[field.name, 'numberRange', 'numberMin']}
noStyle
rules={[
{
pattern: /^\d+(\.\d{1,3})?$/,
message: '小数点后仅限三位',
}
]}
>
<InputNumber style={{ width: 100, textAlign: 'center' }} placeholder="最小数量" />
</Form.Item>
<Input
style={{
......@@ -514,8 +543,17 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
placeholder="~"
disabled
/>
<Form.Item name={[field.name, 'numberRange', 'numberMax']} noStyle>
<Input
<Form.Item
name={[field.name, 'numberRange', 'numberMax']}
noStyle
rules={[
{
pattern: /^\d+(\.\d{1,3})?$/,
message: '小数点后仅限三位',
}
]}
>
<InputNumber
className={styles.siteInputRight}
style={{
width: 100,
......@@ -532,8 +570,14 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
fieldKey={[field.fieldKey, 'numberPrice']}
key={'__' + field.fieldKey}
noStyle
rules={[
{
pattern: /^\d+(\.\d{1,4})?$/,
message: '小数点后仅限四位',
}
]}
>
<Input style={{ width: '50%', marginLeft: 24 }} placeholder="请输入单价" />
<InputNumber style={{ width: '50%', marginLeft: 24 }} placeholder="请输入单价" />
</Item>
</Col>
<Col span={4}>
......@@ -549,9 +593,18 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
</Form.Item> : <Form.Item
label={planPrice===3?"所需积分":"单价"}
name="uniquePrice"
rules={[{ required: true, message: planPrice===3?'请输入积分!':'请输入价格!' }]}
rules={[
{
required: true,
message: planPrice===3?'请输入积分!':'请输入价格!'
},
{
pattern: planPrice!==3 && /^\d+(\.\d{1,4})?$/,
message: planPrice!==3 && '小数点后仅限四位',
}
]}
>
<Input placeholder={planPrice===3?"请输入积分":"请输入价格"} />
<InputNumber style={{width: '100%'}} placeholder={planPrice===3?"请输入积分":"请输入价格"} />
</Form.Item>
}
</Form>
......
......@@ -109,16 +109,39 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
}
const beforeUpload = (file: UploadFile) => {
console.log(file,'file')
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg';
if (!isJpgOrPng) {
message.error('仅支持上传JPEG/JPG/PNG文件!')
}
const isLt2M = file.size / 1024 / 1024 < 2;
const isLt2M = file.size / 1024 < 600;
if (!isLt2M) {
message.error('上传图片不超过2MB!');
}
return isJpgOrPng && isLt2M;
return isJpgOrPng && isLt2M && isSize(file, 800, 800);
}
//检测尺寸
const isSize = (file, w, h) => {
return new Promise((resolve, reject) => {
let width = w;
let height = h;
let _URL = window.URL || window.webkitURL;
let img = new Image();
img.onload = function() {
let valid = img.width < width && img.height < height;
valid ? resolve() : reject();
};
img.src = _URL.createObjectURL(file);
}).then(
() => {
return file;
},
() => {
message.error(file.name + "图片尺寸不符合要求,请修改后重新上传!");
return Promise.reject();
}
);
};
const handlePreview = async file => {
if (!file.url && !file.preview) {
......
......@@ -126,7 +126,7 @@ const FastModifyPrice: React.FC<{}> = () => {
else if (record.status === 3)
component = (<><span className="commonStatusValid"></span>审核通过</>)
else if (record.status === 4)
component = (<><span className="commonStatusInvalid">审核不通过</span></>)
component = (<><span className="commonStatusInvalid"></span>审核不通过</>)
else if (record.status === 5)
component = (<span style={{ color: '#00B37A', padding: '2px 5px', background: 'rgba(235,247,242,1)', borderRadius: '4px' }}>已上架</span>)
else if (record.status === 6)
......
......@@ -524,9 +524,9 @@ const Products: React.FC<{}> = () => {
console.log(value, 'handleClassChange')
}
const handleSearch = (val: string) => {
const handleSearch = (val?: string) => {
console.log(val)
let obj = {...filterParams, name: val}
let obj = val ? {...filterParams, name: val} : { ...filterParams }
setFilterParams(obj)
//@ts-ignore
ref.current.reload(obj)
......@@ -682,6 +682,9 @@ const Products: React.FC<{}> = () => {
/>
</Input.Group>
</Col>
<Col>
<Button type="primary" onClick={()=>handleSearch()}>查询</Button>
</Col>
</Col>
</Row>
</Col>
......
......@@ -202,7 +202,7 @@ const viewProducts: React.FC<{}> = () => {
const content = <>
<Descriptions colon={true} style={{paddingLeft:128}}>
<Descriptions.Item label="商品品牌">{productDetail?.brand?.name}</Descriptions.Item>
<Descriptions.Item label="商品品类">{productDetail?.customerCategoryFullName}</Descriptions.Item>
<Descriptions.Item label="商品品类">{productDetail?.customerCategory?.fullName}</Descriptions.Item>
<Descriptions.Item label="上架商城">
{
productDetail?.commodityShopList?.length>0 && productDetail.commodityShopList.map((item, index)=><span key={index}>{item.name}&nbsp;</span>)
......
import React from 'react'
import React, { useState, useEffect } from 'react'
import { MenuOutlined, RightOutlined } from '@ant-design/icons'
import { PublicApi } from '@/services/api'
import { inject, observer } from 'mobx-react'
import './index.less'
import { Link } from 'umi'
import { isEmpty } from '@formily/antd/esm/shared'
const Category: React.FC = () => {
interface CategoryPropsType {
CategoryStore?: any;
}
const Category: React.FC<CategoryPropsType> = (props) => {
const { fetchCategoryList, categoryList } = props.CategoryStore
useEffect(() => {
if (isEmpty(categoryList)) {
fetchCategoryList()
}
}, [])
return (
<div className="category">
......@@ -14,78 +28,60 @@ const Category: React.FC = () => {
<div className="category_content">
<div className="category_type_panel">
<ul className="category_nav_list">
<li className="category_nav_list_item">
<div className="main_category">成品皮</div>
<div className="sub_category">
<Link to="/">牛皮</Link>
<Link to="/">羊皮</Link>
<Link to="/">猪皮</Link>
</div>
<RightOutlined className="right_icon" />
<div className="category_type_content">
<div className="category_type_list">
<div className="title">成品皮</div>
<div className="second_category_type">
<div className="title">
<Link to="/">
牛皮 <RightOutlined />
</Link>
</div>
<ul className="third_category_type_list">
<li><Link to="/">黄牛皮</Link></li>
<li><Link to="/">水牛皮</Link></li>
<li>奶牛皮</li>
<li>牦牛皮</li>
<li>黄牛皮</li>
<li>水牛皮</li>
<li>奶牛皮</li>
<li>牦牛皮</li>
<li>黄牛皮</li>
<li>水牛皮</li>
<li>奶牛皮</li>
<li>牦牛皮</li>
</ul>
</div>
<div className="second_category_type">
<div className="title">猪皮 <RightOutlined /></div>
<ul className="third_category_type_list">
<li>头层</li>
<li>二层</li>
</ul>
{
categoryList.map(item => (
<li className="category_nav_list_item" key={item.id}>
<div className="main_category">{item.name}</div>
<div className="sub_category">
{
item.categoryTree.map((childCategory, childIndex) => childIndex < 3 && (
<Link to={`/commodity`} key={childCategory.id}>{childCategory.title}</Link>
))
}
</div>
<div className="second_category_type">
<div className="title">猪皮 <RightOutlined /></div>
<ul className="third_category_type_list">
<li>头层</li>
<li>二层</li>
</ul>
</div>
<div className="second_category_type">
<div className="title">马皮 <RightOutlined /></div>
<ul className="third_category_type_list">
<li>头层</li>
<li>二层</li>
</ul>
</div>
</div>
<div className="category_type_right_wrap">
<div className="category_advert">
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
<RightOutlined className="right_icon" />
<div className="category_type_content">
<div className="category_type_list">
<div className="title">{item.name}</div>
{
item.categoryTree.map(childCategory => (
<div className="second_category_type" key={childCategory.id}>
<div className="title">
<Link to={`/commodity`}>
{childCategory.title} <RightOutlined />
</Link>
</div>
<ul className="third_category_type_list">
{
childCategory.children.map(thirdChildItem => (
<li key={thirdChildItem.id}><Link to={`/commodity`}>{thirdChildItem.title}</Link></li>
))
}
</ul>
</div>
))
}
</div>
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
<div className="category_type_right_wrap">
<div className="category_advert">
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
<div className="category_advert_item">
<img src="https://img.alicdn.com/i2/2/TB1pwpNhfBNTKJjy1zdXXaScpXa?abtest=&pos=13&abbucket=&acm=09042.1003.1.1200415&scm=1007.13029.131809.100200300000000_200x200q100.jpg_.webp" />
</div>
</div>
</div>
</div>
</div>
</div>
</li>
</li>
))
}
</ul>
</div>
......@@ -94,4 +90,4 @@ const Category: React.FC = () => {
)
}
export default Category
\ No newline at end of file
export default inject('CategoryStore')(observer(Category))
......@@ -30,7 +30,7 @@
.common_header_title {
font-size: 24px;
font-weight: 600;
font-weight: bold;
color: #333333;
}
}
......
......@@ -19,50 +19,57 @@
}
}
.ant-tree {
font-size: 12px;
}
:global {
.ant-tree {
font-size: 12px;
}
.ant-tree-treenode {
height: 32px;
line-height: 32px;
display: flex;
align-items: center;
}
.ant-tree .ant-tree-treenode {
background: none !important;
border: none !important;
}
.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected {
background-color: #F5F5F5;
.ant-tree-treenode {
height: 32px;
line-height: 32px;
display: flex;
align-items: center;
}
.sub_category_title {
&::before {
background-color: var(--mall_main_color);
.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected {
background-color: #F5F5F5;
.sub_category_title {
&::before {
background-color: var(--mall_main_color);
}
}
}
}
.ant-tree-treenode.ant-tree-treenode-switcher-close.ant-tree-treenode-selected {
background-color: #F5F5F5;
}
.ant-tree-treenode.ant-tree-treenode-switcher-close.ant-tree-treenode-selected {
background-color: #F5F5F5 !important;
}
.ant-tree .ant-tree-treenode {
padding: 0 0 0 8px;
width: 100%;
}
.ant-tree .ant-tree-treenode {
padding: 0 0 0 8px;
width: 100%;
}
.ant-tree .ant-tree-node-content-wrapper {
line-height: 32px;
flex: 1;
}
.ant-tree .ant-tree-node-content-wrapper {
line-height: 32px;
flex: 1;
}
.ant-tree-treenode.ant-tree-treenode-switcher-open.ant-tree-treenode-selected {
background-color: #F5F5F5;
}
.ant-tree-treenode.ant-tree-treenode-switcher-open.ant-tree-treenode-selected {
background-color: #F5F5F5 !important;
}
.ant-tree-treenode {
transition: all .3s;
.ant-tree-treenode {
transition: all .3s;
&:hover {
background-color: #F5F5F5;
&:hover {
background-color: #F5F5F5;
}
}
}
}
\ No newline at end of file
import React from 'react'
import React, { useEffect, useState } from 'react'
import { Tree } from 'antd'
import FilterBox from '../FilterBox'
import './index.less'
import { inject, observer } from 'mobx-react'
import styles from './index.less'
interface CategoryPropsType {
onFilter?: Function
onFilter?: Function;
CategoryStore: any;
}
const Category: React.FC<CategoryPropsType> = (props) => {
const { onFilter } = props
const { onFilter, CategoryStore: { categoryList } } = props
const [treeData, setTreeData] = useState<any>([])
const treeData = [
{
title: '成品皮',
key: '0-0',
children: [
{
title: '牛皮',
key: '0-0-0',
children: [
{
title: <span className="sub_category_title">黄牛皮</span>,
key: '0-0-0-0',
},
{
title: <span className="sub_category_title" >水牛皮</span >,
key: '0-0-0-1',
},
],
},
{
title: '羊皮',
key: '0-0-1',
children: [{ title: <span style={{ color: '#1890ff' }}>sss</span>, key: '0-0-1-0' }],
},
],
},
{
title: '鞣制皮/皮胚',
key: '0-1',
children: [
{
title: '牛皮',
key: '0-1-0',
children: [
{
title: '黄牛皮',
key: '0-1-0-0',
},
{
title: '水牛皮',
key: '0-1-0-1',
},
],
},
{
title: '羊皮',
key: '0-1-1',
children: [{ title: <span style={{ color: '#1890ff' }}>sss</span>, key: '0-1-1-0' }],
},
],
},
];
useEffect(() => {
if (categoryList && categoryList.length > 0) {
initTreeData(categoryList)
}
}, [categoryList])
const initTreeData = (list: any) => {
let result: any = list.map(item => {
return {
title: item.name,
key: item.id,
children: item.categoryTree.map(secondCategoryItem => {
return {
title: secondCategoryItem.title,
key: secondCategoryItem.id,
children: secondCategoryItem.children.map(thirdCategoryItem => {
return {
title: <span className={styles.sub_category_title}>{thirdCategoryItem.title}</span>,
key: thirdCategoryItem.id,
children: []
}
})
}
})
}
})
setTreeData(result)
}
const handleSelect = (selectedKeys, info) => {
const { title } = info.node
......@@ -76,9 +55,9 @@ const Category: React.FC<CategoryPropsType> = (props) => {
<FilterBox
title="分类"
>
<div className="filter_category">
<div className={styles.filter_category}>
<Tree
defaultExpandedKeys={['0-0-0', '0-0-0']}
defaultExpandedKeys={[2, "4"]}
onSelect={handleSelect}
treeData={treeData}
/>
......@@ -87,4 +66,4 @@ const Category: React.FC<CategoryPropsType> = (props) => {
)
}
export default Category
export default inject('CategoryStore')(observer(Category))
@import '../common.less';
.address {
padding-bottom: 16px;
.address_raido_group {
display: block;
width: 100%;
}
&_list {
&_radio {
position: relative;
display: flex;
height: 36px;
align-items: center;
......@@ -16,22 +20,6 @@
border: 1px solid #ffffff;
padding-left: 17px;
:global {
.ant-radio-inner {
&:hover {
border-color: var(--mall_main_color);
}
}
.ant-radio-checked .ant-radio-inner {
border-color: var(--mall_main_color);
}
.ant-radio-inner::after {
background-color: var(--mall_main_color);
}
}
&:hover {
background-color: #FAFAFA;
......@@ -61,6 +49,17 @@
color: #666666;
}
.address_item_btn_group {
margin-left: auto;
display: flex;
.address_item_btn {
margin: 0 10px;
cursor: pointer;
}
}
&>span,
&>div {
display: block;
......@@ -69,5 +68,41 @@
}
}
:global {
span.ant-radio+* {
display: block;
width: 100%;
}
.ant-radio-inner {
&:hover {
border-color: var(--mall_main_color);
}
}
.ant-radio-wrapper.ant-radio-wrapper-checked {
border: 1px solid var(--mall_main_color);
&::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: 12px solid var(--mall_main_color);
border-left: 12px solid transparent;
bottom: 0;
right: 0;
z-index: 5;
}
}
.ant-radio-checked .ant-radio-inner {
border-color: var(--mall_main_color);
}
.ant-radio-inner::after {
background-color: var(--mall_main_color);
}
}
}
}
\ No newline at end of file
import React from 'react'
import React, { useState } from 'react'
import { Radio } from 'antd'
import { DownOutlined } from '@ant-design/icons'
import styles from './index.less'
const Address: React.FC = () => {
const [selectKey, setSelectKey] = useState<number>()
const [expand, setExpand] = useState<boolean>(false)
const mock_data = [
{
......@@ -25,20 +28,45 @@ const Address: React.FC = () => {
address: '广东省广州市海珠区新港东路1068号中洲中心北塔6楼',
mobile: '185 2929 6758',
isDefault: 0,
},
{
id: 4,
name: '蒯美政',
address: '广东省广州市海珠区新港东路1068号中洲中心北塔6楼',
mobile: '185 2929 6758',
isDefault: 0,
},
{
id: 5,
name: '蒯美政',
address: '广东省广州市海珠区新港东路1068号中洲中心北塔6楼',
mobile: '185 2929 6758',
isDefault: 0,
},
{
id: 6,
name: '蒯美政',
address: '广东省广州市海珠区新港东路1068号中洲中心北塔6楼',
mobile: '185 2929 6758',
isDefault: 0,
}
]
const handleSelect = (e: any) => {
setSelectKey(e.target.value)
}
return (
<div className={styles.address}>
<div className={styles.common_title}>
<span>收货地址</span>
<div className={styles.common_title_btn}>新增收货地址</div>
</div>
<Radio.Group className={styles.address_raido_group} >
<Radio.Group className={styles.address_raido_group} value={selectKey} onChange={handleSelect}>
<div className={styles.address_list}>
{
mock_data.map(item => (
<Radio className={styles.address_list_radio} value={item.id}>
mock_data.map((item, index) => (!expand ? index < 3 : true) && (
<Radio className={styles.address_list_radio} value={item.id} key={`address_list_radio_${item.id}`}>
<div className={styles.adderss_list_radio_line}>
<span>{item.name}</span>
<span>{item.address}</span>
......@@ -47,12 +75,26 @@ const Address: React.FC = () => {
item.isDefault === 1 ? <div className={styles.default_address}>默认地址</div> :
<div className={styles.set_default_address}>设为默认地址</div>
}
{
selectKey === item.id && (
<div className={styles.address_item_btn_group}>
<div className={styles.address_item_btn}>编辑</div>
<div className={styles.address_item_btn}>删除</div>
</div>
)
}
</div>
</Radio>
))
}
</div>
</Radio.Group>
<div className={styles.more_btn} onClick={() => setExpand(!expand)}>
<span>{expand ? '收起' : '更多地址'}</span>
<div className={styles.more_btn_icon}>
<DownOutlined rotate={expand ? 180 : 0} />
</div>
</div>
</div>
)
}
......
......@@ -7,6 +7,12 @@
display: flex;
margin-bottom: 5px;
&_icon {
color: #999999;
margin-left: 6px;
cursor: pointer;
}
&>span {
font-weight: 500;
......@@ -20,4 +26,55 @@
opacity: .8;
}
}
}
.checkbox {
padding: 10px 0;
&_contract_text {
cursor: pointer;
color: #D32F2F;
}
:global {
.ant-checkbox-checked .ant-checkbox-inner {
background-color: var(--mall_main_color);
border-color: var(--mall_main_color);
}
}
}
.more_btn {
padding-left: 40px;
font-size: 12px;
color: #999999;
margin-top: 12px;
display: inline-block;
cursor: pointer;
&.pad_l_40 {
padding-left: 100px;
}
&.pad_l_100 {
padding-left: 100px;
}
&_icon {
display: inline-block;
width: 16px;
height: 16px;
background-color: #EEEEEE;
border-radius: 50%;
margin-left: 5px;
font-size: 8px;
line-height: 16px;
text-align: center;
color: #999999;
svg {
transition: all .2s;
}
}
}
\ No newline at end of file
import React from 'react'
import { Tooltip, Checkbox } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import styles from './index.less'
const Contract: React.FC = () => {
......@@ -7,8 +9,16 @@ const Contract: React.FC = () => {
<div className={styles.contract}>
<div className={styles.common_title}>
<span>电子合同信息</span>
<Tooltip placement="top" title="勾选则表示同意签署电子合同,电子合同与纸质合同一样具备同等法律效力。">
<QuestionCircleOutlined className={styles.common_title_icon} />
</Tooltip>
</div>
<div className={styles.checkbox}>
<Checkbox>
<span>我同意签订:</span>
</Checkbox>
<span className={styles.checkbox_contract_text}> 《广州白马皮具交易中心商品购销合同.pdf》</span>
</div>
Contract
</div>
)
}
......
@import '../common.less';
.delivery {
padding-bottom: 16px;
&_list {
display: flex;
padding-top: 16px;
&_item {
position: relative;
list-style: none;
width: 130px;
height: 32px;
border: 1px solid rgba(238, 238, 238, 1);
text-align: center;
line-height: 30px;
margin-right: 15px;
cursor: pointer;
&.active {
border: 1px solid rgba(211, 47, 47, 1);
&::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: 12px solid var(--mall_main_color);
border-left: 12px solid transparent;
bottom: 0;
right: 0;
z-index: 5;
}
}
}
}
&_info {
display: flex;
align-items: center;
margin-top: 15px;
&_label {
color: #999999;
margin-right: 19px;
}
&_brief {
&>span {
margin-right: 20px;
}
}
}
}
\ No newline at end of file
import React from 'react'
import cx from 'classnames'
import styles from './index.less'
const Delivery: React.FC = () => {
return (
<div className={styles.delivery}>
<div className={styles.common_title}>
<span>配送方式</span>
</div>
<div className={styles.delivery_list}>
<div className={cx(styles.delivery_list_item, styles.active)}>自提</div>
</div>
<div className={styles.delivery_info}>
<div className={styles.delivery_info_label}>自提地址:</div>
<div className={styles.delivery_info_brief}>
<span>广东省广州市海珠区新港东路1068号中洲中心北塔6楼</span>
<span>蒯美政 / 185 2929 6758</span>
</div>
</div>
</div>
)
}
export default Delivery
@import '../common.less';
.distributionway {}
\ No newline at end of file
import React from 'react'
import styles from './index.less'
const DistributionWay: React.FC = () => {
return (
<div className={styles.distributionWay}>
<div className={styles.common_title}>
<span>配送方式</span>
</div>
DistributionWay
</div>
)
}
export default DistributionWay
@import './common.less';
.order {
&_container {
width: 1200px;
margin: 0 auto;
.order_tb_title {
display: flex;
padding: 20px 0;
font-size: 14px;
color: #999999;
&_item {
flex: 1;
text-align: center;
}
}
.order_list {
border: 1px solid #EEEEEE;
&_shop_name {
height: 50px;
line-height: 50px;
padding-left: 40px;
background-color: #FAFAFA;
font-weight: 500;
}
&_item {
display: flex;
height: 130px;
align-items: center;
font-size: 12px;
&_item {
display: flex;
padding-left: 25px;
&.goods_info {
padding-left: 40px;
width: 360px;
}
&_imgbox {
margin-right: 10px;
&_img {
width: 80px;
height: 80px;
background-position: center center;
background-size: 100% auto;
background-repeat: no-repeat;
}
}
&.count {
width: 330px;
flex-direction: column;
.stock {
margin-top: 10px;
}
}
&_price {
color: #D32F2F;
font-size: 16px;
}
&_unitprice {
width: 280px;
}
&_name {
color: #333333;
margin-bottom: 12px;
}
&_category {
color: #666666;
&>span {
margin-right: 20px;
}
}
}
}
}
.settlement_box {
height: 50px;
margin-top: 30px;
background-color: #F5F5F5;
display: flex;
justify-content: flex-end;
&_item {
&_btn {
width: 160px;
text-align: center;
color: #FFF;
height: 50px;
line-height: 50px;
font-size: 16px;
background-color: #D32F2F;
cursor: pointer;
&:hover {
opacity: .9;
}
}
}
}
}
}
\ No newline at end of file
import React from 'react'
import React, { useState } from 'react'
import CommonHeader from '../components/CommonHeader'
import cx from 'classnames'
import InputNumber from '@/components/InputNumber'
import Address from './address'
import PayWay from './payway'
import DistributionWay from './distributionway'
import Delivery from './delivery'
import Contract from './contract'
import Invoice from './invoice'
import styles from './index.less'
......@@ -12,16 +14,85 @@ interface OrderPropsType {
}
const Order: React.FC<OrderPropsType> = (props) => {
const [buyCount, setBuyCount] = useState<number>(1)
return (
<div className={styles.order}>
<CommonHeader title="订单结算" />
<div className={styles.order_container}>
<Address />
{/* <Address />
<PayWay />
<DistributionWay />
<Delivery />
<Invoice />
<Contract />
<Contract /> */}
<div className={styles.common_title}>
<span>订单信息</span>
</div>
<div className={styles.order_tb_title}>
<div className={styles.order_tb_title_item}>商品</div>
<div className={styles.order_tb_title_item}>单价(元)</div>
<div className={styles.order_tb_title_item}>数量</div>
<div className={styles.order_tb_title_item}>小计(元)</div>
</div>
<div className={styles.order_list}>
<div className={styles.order_list_shop_name}>
<span>温州市龙昌皮业有限公司</span>
</div>
<div className={styles.order_list_item}>
<div className={cx(styles.order_list_item_item, styles.goods_info)}>
<div className={styles.order_list_item_item_imgbox}>
<div className={styles.order_list_item_item_imgbox_img} style={{ backgroundImage: `url(https://img.alicdn.com/bao/uploaded/i1/691602756/O1CN013mdkHl1WEI92iLR75_!!691602756.jpg_400x400q60.jpg)` }}></div>
</div>
<div>
<div className={styles.order_list_item_item_name}>荔枝纹牛皮二层移膜</div>
<div className={styles.order_list_item_item_category}>
<span>颜色:红色</span>
<span>尺码:XXL</span>
</div>
</div>
</div>
<div className={styles.order_list_item_item}>
<span className={styles.order_list_item_item_unitprice}>1-20平方英尺:20.00</span>
</div>
<div className={cx(styles.order_list_item_item, styles.count)}>
<InputNumber value={buyCount} onChange={(value) => setBuyCount(value)} />
<div className={styles.stock}>(库存20,000平方英尺)</div>
</div>
<div className={styles.order_list_item_item}>
<span className={styles.order_list_item_item_price}>20.00</span>
</div>
</div>
<div className={styles.order_list_item}>
<div className={cx(styles.order_list_item_item, styles.goods_info)}>
<div className={styles.order_list_item_item_imgbox}>
<div className={styles.order_list_item_item_imgbox_img} style={{ backgroundImage: `url(https://img.alicdn.com/bao/uploaded/i1/691602756/O1CN013mdkHl1WEI92iLR75_!!691602756.jpg_400x400q60.jpg)` }}></div>
</div>
<div>
<div className={styles.order_list_item_item_name}>荔枝纹牛皮二层移膜</div>
<div className={styles.order_list_item_item_category}>
<span>颜色:红色</span>
<span>尺码:XXL</span>
</div>
</div>
</div>
<div className={styles.order_list_item_item}>
<span className={styles.order_list_item_item_unitprice}>1-20平方英尺:20.00</span>
</div>
<div className={cx(styles.order_list_item_item, styles.count)}>
<InputNumber value={buyCount} onChange={(value) => setBuyCount(value)} />
<div className={styles.stock}>(库存20,000平方英尺)</div>
</div>
<div className={styles.order_list_item_item}>
<span className={styles.order_list_item_item_price}>20.00</span>
</div>
</div>
</div>
<div className={styles.settlement_box}>
<div className={styles.settlement_box_item}>
<div className={styles.settlement_box_item_btn}>提交订单</div>
</div>
</div>
</div>
</div>
)
......
@import '../common.less';
.invoice {}
\ No newline at end of file
.invoice {
padding-bottom: 16px;
.raido_group {
position: relative;
display: block;
width: 100%;
.list_radio {
border: 1px solid #FFF;
}
.invoice_list {
position: relative;
display: flex;
margin: 0 -10px;
flex-wrap: wrap;
.invoice_list_item {
display: flex;
align-items: center;
&_content {
padding-left: 10px;
&_tag {
display: inline-block;
background-color: #6B778C;
padding: 0 6px;
height: 16px;
line-height: 16px;
color: #FFF;
font-size: 12px;
&.special {
background-color: #5377CE;
}
}
&_name {
display: flex;
align-items: center;
.default {
width: 64px;
height: 16px;
line-height: 16px;
text-align: center;
background: rgba(238, 238, 238, 1);
font-size: 12px;
color: #666666;
}
&>span {
margin-right: 20px;
}
}
}
&_btn_group {
display: flex;
margin-left: auto;
line-height: 14px;
// height: 14px;
.invoice_list_item_btn {
margin: 0 10px;
}
}
}
:global {
span.ant-radio+* {
display: block;
width: 100%;
}
.ant-radio-wrapper {
display: flex;
width: 48%;
align-items: center;
height: 72px;
background-color: #FAFAFA;
margin: 10px;
padding-left: 16px;
}
.ant-radio-inner {
&:hover {
border-color: var(--mall_main_color);
}
}
.ant-radio-wrapper.ant-radio-wrapper-checked {
border: 1px solid var(--mall_main_color);
&::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: 12px solid var(--mall_main_color);
border-left: 12px solid transparent;
bottom: 0;
right: 0;
z-index: 5;
}
}
.ant-radio-checked .ant-radio-inner {
border-color: var(--mall_main_color);
}
.ant-radio-inner::after {
background-color: var(--mall_main_color);
}
}
}
}
}
\ No newline at end of file
import React from 'react'
import React, { useState } from 'react'
import { Checkbox, Radio } from 'antd'
import cx from 'classnames'
import styles from './index.less'
const Invoice: React.FC = () => {
const [selectKey, setSelectKey] = useState<number>()
const MockData = [
{
id: 1,
type: 1,
name: '温州市龙昌皮业有限公司',
userType: 1,
isDefault: 1
},
{
id: 2,
type: 2,
name: '温州市龙昌皮业有限公司',
userType: 1,
isDefault: 0
},
{
id: 3,
type: 2,
name: '温州市龙昌皮业有限公司',
userType: 1,
isDefault: 0
}
]
const handleSelect = (e: any) => {
setSelectKey(e.target.value)
}
return (
<div className={styles.invoice}>
<div className={styles.common_title}>
<span>发票信息</span>
</div>
Invoice
<div className={styles.checkbox}>
<Checkbox>需要发票</Checkbox>
</div>
<Radio.Group className={styles.raido_group} value={selectKey} onChange={handleSelect}>
<div className={styles.invoice_list}>
{
MockData.map((item, index) => (
<Radio className={styles.list_radio} value={item.id} key={`address_list_radio_${item.id}`}>
<div className={styles.invoice_list_item} key={`invoice_list_item_${index}`}>
<div className={styles.invoice_list_item_content}>
<div className={cx(styles.invoice_list_item_content_tag, item.type !== 1 ? styles.special : '')}>{item.type === 1 ? '增值税普通发票' : '增值税专用发票'}</div>
<div className={styles.invoice_list_item_content_name}>
<span>{item.name}</span>
<span>(企业)</span>
{
item.isDefault === 1 ? <div className={styles.default}>默认</div> :
<div className={styles.set_default}>设为默认</div>
}
</div>
</div>
{
selectKey === item.id && (
<div className={styles.invoice_list_item_btn_group}>
<div className={styles.invoice_list_item_btn}>编辑</div>
<div className={styles.invoice_list_item_btn}>删除</div>
</div>
)
}
</div>
</Radio>
))
}
</div>
</Radio.Group>
</div>
)
}
......
@import '../common.less';
.payway {}
\ No newline at end of file
.payway {
padding-bottom: 16px;
.payway_line {
display: flex;
align-items: center;
margin-top: 15px;
&_label {
color: #999999;
}
.payway_pay_list {
display: flex;
padding: 0;
margin: 0;
padding-left: 32px;
&_item {
position: relative;
list-style: none;
width: 130px;
height: 32px;
border: 1px solid rgba(238, 238, 238, 1);
text-align: center;
line-height: 30px;
margin-right: 15px;
cursor: pointer;
&>img {
width: 20px;
height: 20px;
margin-right: 8px;
}
&.active {
border: 1px solid rgba(211, 47, 47, 1);
&::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: 12px solid var(--mall_main_color);
border-left: 12px solid transparent;
bottom: 0;
right: 0;
z-index: 5;
}
}
}
}
}
}
\ No newline at end of file
import React from 'react'
import React, { useState } from 'react'
import cx from 'classnames'
import { DownOutlined } from '@ant-design/icons'
import alipayIcon from '@/assets/imgs/alipay_icon.png'
import wechatIcon from '@/assets/imgs/wechat_icon.png'
import bankIcon from '@/assets/imgs/bank_icon.png'
import styles from './index.less'
const PayWay: React.FC = () => {
const [expand, setExpand] = useState<boolean>(false)
const PayWay = [
{
name: '线上支付',
payway: [
{
type: 'alipay',
name: '支付宝',
},
{
type: 'wechat',
name: '微信支付'
},
{
type: 'bank',
name: '银联'
},
]
},
{
name: '线下支付',
payway: [
{
type: 'pay',
name: '线下支付'
}
]
},
{
name: '授信额度',
payway: [
{
type: 'pay',
name: '授信额度支付'
}
]
},
{
name: '货到付款',
payway: [
{
type: 'pay',
name: '货到付款支付'
}
]
},
]
return (
<div className={styles.payway}>
<div className={styles.common_title}>
<span>支付方式</span>
</div>
PayWay
{
PayWay.map((item, index) => (!expand ? index < 1 : true) && (
<div className={styles.payway_line} key={`payway_line_${index}`}>
<div className={styles.payway_line_label}>{item.name}</div>
<ul className={styles.payway_pay_list}>
{
item.payway.map((childItem, childIndex) => (
<li className={cx(styles.payway_pay_list_item, childItem.type === 'alipay' ? styles.active : '')} key={`payway_pay_list_item_${childIndex}`}>
{childItem.type === 'alipay' && <img src={alipayIcon} />}
{childItem.type === 'wechat' && <img src={wechatIcon} />}
{childItem.type === 'bank' && <img src={bankIcon} />}
<span>{childItem.name}</span>
</li>
))
}
</ul>
</div>
))
}
<div className={cx(styles.more_btn, styles.pad_l_100)} onClick={() => setExpand(!expand)}>
<span>{expand ? '收起' : '展开'}</span>
<div className={styles.more_btn_icon}>
<DownOutlined rotate={expand ? 180 : 0} />
</div>
</div>
</div>
)
}
......
import { action, computed, observable, runInAction } from 'mobx'
import { GlobalConfig } from '@/global/config'
import { PublicApi } from '@/services/api'
import { GetSearchCommodityTemplateGetCategoryListResponse } from '@/services'
class CategoryStore {
@observable public categoryList: GetSearchCommodityTemplateGetCategoryListResponse = []; // 品类列表
@action.bound
public async fetchCategoryList() {
let res = await PublicApi.getSearchCommodityTemplateGetCategoryList()
runInAction(() => {
this.categoryList = res.data || []
})
}
}
export default CategoryStore
......@@ -2,11 +2,13 @@ import UserStore from './user'
import ThemeStore from './theme'
import ProductStroe from './product'
import SiteStore from './site'
import CategoryStore from './category'
import React from 'react';
import { Provider } from 'mobx-react'
import { ILoginModule } from '@/module/userModule';
import { IProductModule } from '@/module/productModule'
// import { ProductContext } from '@/pages/commodity/products/addProducts';
/**
......@@ -33,7 +35,8 @@ export const store = {
userStore: new UserStore,
ThemeStore: new ThemeStore,
ProductStore: new ProductStroe,
SiteStore: new SiteStore
SiteStore: new SiteStore,
CategoryStore: new CategoryStore
}
const MobxProvider: React.FC = (props) => {
......
......@@ -29,7 +29,7 @@
height: 460px;
background-color: var(--category_content_bg);
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.05);
top: 42px;
top: 41px;
left: 0;
z-index: 5;
......
......@@ -9,7 +9,9 @@ const tokens = [
'efe99e20ed1375dc0db3e809e4fc7692f42ecebaf60cd77e65c50ed65d6ba6c4', // 商品服务
'7ec923520215c7e2f771867cb4d29cafbf823daf0fb2d3d9fa70b57a523c8bfb', // 店铺服务
'c789e0e56ee8a8cc2fbd85f930eb2928c58fc1014583c6643acf29cff954da49', // 支付服务
'ca19f532efba91f7773cbfbd526b798c6ac83df670071e97d72c50dca1d53a48', // 搜索服务
]
const genMap = (tokens) => {
return tokens.map(v => {
return {
......
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