Commit 629a6a16 authored by 前端-钟卫鹏's avatar 前端-钟卫鹏

fix:渠道商品添加物流相关信息,处理订单自提方式无法显示自提地址,处理采购下单多商品下价格运算异常,处理列表高级筛选后重置异常

parent fb7f5abb
......@@ -51,7 +51,7 @@
"bizcharts": "^4.0.14",
"copy-to-clipboard": "^3.3.1",
"crypto-js": "^4.0.0",
"god": "^0.2.1",
"god": "0.2.2",
"immutability-helper": "^3.1.1",
"lingxi-design": "^1.0.8",
"lingxi-design-ui": "^1.1.15",
......
......@@ -15,8 +15,8 @@ const Search = props => {
const [state, setState] = useFieldState({
filterSearch: false,
});
const {
align,
const {
align,
advanced = true, // 是否展示高级筛选
tip, // 搜索框悬浮提示
...rest
......@@ -55,6 +55,7 @@ const Search = props => {
)}
<Button
onClick={() => {
sessionStorage.setItem('tableRest', 'true')
props.form.reset();
props.form.submit();
}}
......
......@@ -207,4 +207,8 @@
z-index: 1;
}
}
\ No newline at end of file
.ant-input-textarea {
width: 100%;
}
}
......@@ -61,7 +61,7 @@ const Organ: React.FC<{}> = () => {
const handleSubmitAllSetting = () => {
formActions.submit()
}
// 保存设置提交
const handleSubmit = (value) => {
// 去掉模拟的key, 为true的时候是编辑
......@@ -86,7 +86,7 @@ const Organ: React.FC<{}> = () => {
<h3 className="commonPanelTitle mb-30">选择要编辑的项目</h3>
{
treeData && treeData.length > 0
? <TabTree
? <TabTree
fetchData = {params => fetchMenuData(params)}
treeData={treeData}
toolsRender={toolsRender}
......@@ -97,7 +97,7 @@ const Organ: React.FC<{}> = () => {
:
<Button block type='primary' onClick={() => handleSelect()}>暂无菜单, 开始新增</Button>
}
</Col>
<Col span={16}>
{treeStatus !== FormState.FREE && <>
......@@ -122,7 +122,7 @@ const Organ: React.FC<{}> = () => {
</Button>
<Popconfirm title="确定要删除吗?" okText="是" cancelText="否" onConfirm={handleDeleteMenu}>
<Button style={{ marginTop: 32, marginBottom: 16}}>
删除菜单
删除
</Button>
</Popconfirm>
</>
......
......@@ -32,4 +32,4 @@ export const menuSchema: ISchema = {
}
}
}
}
\ No newline at end of file
}
import React, { useState, useEffect, useRef } from 'react'
import { history } from 'umi'
import { Form, Select, Radio, Checkbox, InputNumber } from 'antd'
import { PublicApi } from '@/services/api'
import {
GetLogisticsSelectListCompanyResponse,
GetLogisticsSelectListShipperAddressResponse,
GetLogisticsSelectListFreightTemplateResponse
} from '@/services/LogisticsApi'
import { store } from '@/store'
const { ChannelProudctStore } = store
const layout = {
labelCol: {
span: 2,
},
wrapperCol: {
span: 12,
},
}
export interface Iprops {
onRef: (refs: any) => void;
}
const { Option } = Select
const SetLogistics: React.FC<Iprops> = (props) => {
const { onRef } = props
const [logisticsForm] = Form.useForm()
const [logisticsCompanyLists, setLogisticsCompanyLists] = useState<GetLogisticsSelectListCompanyResponse>()
const [logisticsAddressList, setLogisticsAddressList] = useState<GetLogisticsSelectListShipperAddressResponse>()
const [logisticsTemplateList, setLogisticsTemplateList] = useState<GetLogisticsSelectListFreightTemplateResponse>()
const [isTemplate, setIsTemplate] = useState<boolean>(false)
const [deliveryType, setDeliveryType] = useState<number>(1)
const [carriageType, setCarriageType] = useState<number>()
const [banCarriageType, setBanCarriageType] = useState(false)
const [template, setTemplate] = useState(false) // 是否必填运费模板
const { priceType } = ChannelProudctStore
useEffect(()=>{
//传入ref给父级
onRef(logisticsForm)
logisticsForm.setFieldsValue({deliveryType:1, carriageType:1})
// 获取发货地址 物流公司 运费模板
PublicApi.getLogisticsSelectListShipperAddress().then(res=>{
setLogisticsAddressList(res.data)
})
PublicApi.getLogisticsSelectListCompany({cooperateType: '2'}).then(res=>{
setLogisticsCompanyLists(res.data)
})
PublicApi.getLogisticsSelectListFreightTemplate().then(res=>{
setLogisticsTemplateList(res.data)
})
}, [])
useEffect(() => {
if(priceType === 3){
logisticsForm.setFieldsValue({carriageType: 1})
setCarriageType(1)
setBanCarriageType(true)
}else{
setBanCarriageType(false)
}
}, [priceType])
const changeDeliveryType = (e) => {
setDeliveryType(e.target.value)
setCarriageType(1)
setIsTemplate(false)
logisticsForm.resetFields()
logisticsForm.setFieldsValue({deliveryType: e.target.value})
logisticsForm.setFieldsValue({carriageType: 1})
}
const onChangeTemplate = (e) => {
setIsTemplate(e.target.checked)
logisticsForm.setFieldsValue({weight: null})
}
const changeCarriageType = (e) => {
setCarriageType(e.target.value)
if(e.target.value === 2) {
setTemplate(true)
setIsTemplate(true)
logisticsForm.setFieldsValue({useTemplate: true})
} else {
setTemplate(false)
setIsTemplate(false)
logisticsForm.setFieldsValue({useTemplate: false})
}
}
return (<>
<Form
{...layout}
form={logisticsForm}
name="logistic-form"
labelAlign="left"
colon={false}
autoComplete="off"
>
<Form.Item
name="deliveryType"
label="配送方式"
rules={[
{
required: true,
message: '请选择配送方式'
},
]}
>
<Radio.Group onChange={changeDeliveryType}>
<Radio value={1}>物流(默认)</Radio>
<Radio value={2}>自提</Radio>
<Radio value={3}>无需配送</Radio>
</Radio.Group>
</Form.Item>
{
deliveryType === 1 && <><Form.Item
name="carriageType"
label="运费方式"
rules={[
{
required: true,
message: '请选择运费方式'
},
]}
>
<Radio.Group onChange={changeCarriageType} disabled={banCarriageType}>
<Radio value={1}>卖家承担运费(默认)</Radio>
<Radio value={2}>买家承担运费</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label={<>重量<i style={{color:'red'}}>&nbsp;*</i></>}
style={{position: 'relative'}}
>
<Form.Item
name="weight"
rules={[
{
required: true,
message: '请正确输入重量',
},
{
pattern: /^\d+(\.\d{1,3})?$/,
message: '重量数值小数点后仅限三位',
}
]}
noStyle
>
<InputNumber min={0} style={{width:'100%'}} placeholder="请输入重量" />
</Form.Item>
<span style={{position:'absolute', right:5, top:5, opacity: 0.6}}>KG</span>
</Form.Item></>
}
{
carriageType === 2 && <Form.Item
name="useTemplate"
valuePropName="checked"
label=" "
>
<Checkbox disabled={template} onChange={onChangeTemplate}>使用运费模板(只有买家承担运费才能选择)</Checkbox>
</Form.Item>
}
{
isTemplate && <Form.Item
name="templateId"
label="运费模板"
rules={[
{
required: template,
message: '请正确输入重量',
}
]}
>
<Select
placeholder="请选择运费模板"
allowClear
>
{
logisticsTemplateList?.length>0 && logisticsTemplateList.map(_ => <Option key={_.id} value={_.id}>{_.name}</Option>)
}
</Select>
</Form.Item>
}
{
deliveryType !== 3 && <Form.Item
name="sendAddress"
label="发货地址"
>
<Select
placeholder="请选择发货地址"
allowClear
>
{
logisticsAddressList?.length > 0 && logisticsAddressList.map(_=><Option key={_.id} value={_.id}>{_.fullAddress}</Option>)
}
</Select>
</Form.Item>
}
{
deliveryType === 1 && <Form.Item
name="company"
label="物流公司"
>
<Select
placeholder="请选择物流公司"
allowClear
>
{
logisticsCompanyLists?.length > 0 && logisticsCompanyLists.map(_=><Option key={_.id} value={_.id}>{_.name}</Option>)
}
</Select>
</Form.Item>
}
</Form>
</>)
}
export default SetLogistics
......@@ -63,9 +63,9 @@ const SetPrice:React.FC<IProps> = (props) => {
const [loading, setLoading] = useState<boolean>(false)
const { ChannelProudctStore } = store
const {
priceType,
productName,
const {
priceType,
productName,
productSelectRowInStore,
selectedSource,
setTableDataInSetPrice
......@@ -73,7 +73,7 @@ const SetPrice:React.FC<IProps> = (props) => {
useEffect(() => {
onRef(formPrice)
}, [])
useEffect(() => {
......@@ -84,7 +84,7 @@ const SetPrice:React.FC<IProps> = (props) => {
if(visibleAddSpec)
fetchSpecData()
}, [visibleAddSpec])
// 获取商品规格列表
const fetchSpecData = (params?: any) => {
setLoading(true)
......@@ -105,36 +105,36 @@ const SetPrice:React.FC<IProps> = (props) => {
temp.push({title: _item.customerAttribute.name, dataIndex: [_item.customerAttribute.name, 'value'], key: _item.customerAttribute.name})
})
col.push({
title: 'ID',
dataIndex: 'id',
key: 'id'
},
title: 'ID',
dataIndex: 'id',
key: 'id'
},
{
title: 'GoodsId',
dataIndex: 'goodsId',
title: 'GoodsId',
dataIndex: 'goodsId',
key: 'id',
className: 'commonHide'
},
{
title: '索引',
dataIndex: '索引',
{
title: '索引',
dataIndex: '索引',
key: '索引',
className: 'commonHide'
},
{
title: '商品名称',
dataIndex: '商品名称',
{
title: '商品名称',
dataIndex: '商品名称',
key: '商品名称'
},
},
{
title: '对应货品',
dataIndex: '对应货品',
title: '对应货品',
dataIndex: '对应货品',
key: '对应货品'
},
...temp,
{
title: priceType === 3 ? '积分' : '单价',
dataIndex: '单价',
},
...temp,
{
title: priceType === 3 ? '积分' : '单价',
dataIndex: '单价',
key: '单价',
render: (text, record) => {
if (!text || JSON.stringify(text)==='{}') return null
......@@ -221,7 +221,7 @@ const SetPrice:React.FC<IProps> = (props) => {
let priceArray = Object.values(record['单价'])
let tempArr = []
numberArray.map((_item, _index) => {
tempArr.push({ numberPrice: priceArray[_index], numberRange: { numberMin: _item[0], numberMax: _item[1] } })
tempArr.push({ numberPrice: priceArray[_index], numberRange: { numberMin: _item[0], numberMax: _item[1] } })
})
setPriceForm.setFieldsValue({ladderPrice: true, ladderRange: tempArr})
}
......@@ -262,8 +262,8 @@ const SetPrice:React.FC<IProps> = (props) => {
let _data = selectData.map(item => {
let price = priceTableData.filter(_i => _i.id === item.id)[0]['单价']
let params: any = {
...item,
unitPrice: price,
...item,
unitPrice: price,
commodityUnitPriceAndPicId: item.id
}
delete params.id
......@@ -316,7 +316,7 @@ const SetPrice:React.FC<IProps> = (props) => {
<Form
{...layout}
form={formPrice}
name="add-channel-discount"
name="add-channel-discount"
labelAlign="left"
colon={false}
initialValues={{isMemberPrice: true}}
......@@ -340,7 +340,7 @@ const SetPrice:React.FC<IProps> = (props) => {
<PlusOutlined /> 选择商品规格
</Button>
{
priceTableData.length > 0 && priceType != 2 &&
priceTableData.length > 0 && priceType != 2 &&
<Button
type="text"
style={{float: 'right'}}
......@@ -351,7 +351,7 @@ const SetPrice:React.FC<IProps> = (props) => {
</Button>
}
<Table rowKey="id" dataSource={priceTableData} columns={priceColumn} style={{clear: 'both'}} />
<Modal
title="设置价格"
visible={modifyModal}
......@@ -365,7 +365,7 @@ const SetPrice:React.FC<IProps> = (props) => {
form={setPriceForm}
initialValues={{ladderPrice: false}}
>
{
{
priceType!==3 &&
<Form.Item
label=""
......@@ -434,7 +434,7 @@ const SetPrice:React.FC<IProps> = (props) => {
placeholder="~"
disabled
/>
<Form.Item
<Form.Item
name={[field.name, 'numberRange', 'numberMax']}
noStyle
rules={[
......@@ -518,19 +518,19 @@ const SetPrice:React.FC<IProps> = (props) => {
destroyOnClose={true}
width={704}
>
<Table
dataSource={specTableData}
columns={specColumn}
<Table
dataSource={specTableData}
columns={specColumn}
rowKey="id"
loading={loading}
rowSelection={{
type: 'checkbox',
...rowSelectionSetSpec,
}}
pagination={{ simple: true }}
pagination={{ simple: true, position: ['topRight'] }}
/>
</Modal>
</>)
}
export default observer(SetPrice)
\ No newline at end of file
export default observer(SetPrice)
......@@ -13,6 +13,7 @@ import styles from './index.less'
import SelectProduct from './addChannelItem/selectProduct'
import SelectChannel from './addChannelItem/selectChannel'
import SetPrice from './addChannelItem/setPrice'
import SetLogistics from './addChannelItem/setLogistics'
import { store } from '@/store'
import { inject, observer } from 'mobx-react'
......@@ -26,10 +27,10 @@ const AddDirectChannel:React.FC<{}> = (props) => {
let [formRefs, setFormRefs] = useState([]) //子form的ref数组
const { ChannelProudctStore } = store
const {
priceType,
productName,
productSelectRowInStore,
const {
priceType,
productName,
productSelectRowInStore,
tableDataInSetPrice,
selectedRole,
selectChannel,
......@@ -41,40 +42,55 @@ const AddDirectChannel:React.FC<{}> = (props) => {
const onSave = () => {
setIsDisabledSave(true)
let data = formRefs.map(async __ => {
return (
await __.validateFields()
)
})
Promise.all(data).then((values) => {
let params: any = {}
values.map(item => {
params = { ...params, ...item }
try {
let data = formRefs.map(async __ => {
return (
await __.validateFields()
)
})
params.unitPriceAndPicList = tableDataInSetPrice
params.commodityId = productSelectRowInStore.id
params.parentMemberId = productSelectRowInStore.memberId
params.parentMemberName = productSelectRowInStore.memberName
params.childMemberRoleName = selectedRole?.children || null
params.commodityMemberList = selectChannel.map(item => ({ memberId: item.memberId, memberName: item.name }))
Promise.all(data).then((values) => {
let params: any = {}
console.log(values, 'vvv')
values.map((item, index) => {
if(index !== 2)
params = { ...params, ...item }
else
params.logistics = { ...item }
})
params.unitPriceAndPicList = tableDataInSetPrice
params.commodityId = productSelectRowInStore.id
params.parentMemberId = productSelectRowInStore.memberId
params.parentMemberName = productSelectRowInStore.memberName
params.childMemberRoleName = selectedRole?.children || null
params.commodityMemberList = selectChannel.map(item => ({ memberId: item.memberId, memberName: item.name }))
if(!tableDataInSetPrice.length){
message.error('请选择商品规格!')
setIsDisabledSave(false)
return ;
}
if(!tableDataInSetPrice.length){
message.error('请选择商品规格!')
setIsDisabledSave(false)
return ;
}
if(params.childMemberRoleName)
PublicApi.postProductChannelCommoditySaveChannelCommodity(params).then(res=>{
if(params.childMemberRoleName)
PublicApi.postProductChannelCommoditySaveChannelCommodity(params).then(res=>{
setIsDisabledSave(false)
if(res.code === 1000)
history.goBack()
})
else{
message.error('暂无渠道角色数据!')
setIsDisabledSave(false)
if(res.code === 1000)
history.goBack()
})
else{
message.error('暂无渠道角色数据!')
}
}).catch(_e => {
setIsDisabledSave(false)
}
})
message.error(_e.errorFields[0].errors[0] || '请完善渠道商品必填信息!')
console.log(_e, _e.message, '_e')
})
} catch (e) {
setIsDisabledSave(false)
message.error(e.message || '请完善相关信息!')
console.log(e, 'error')
}
}
return (<PageHeaderWrapper
......@@ -99,6 +115,11 @@ const AddDirectChannel:React.FC<{}> = (props) => {
onRef={(refs)=>setFormRefs([...formRefs, refs])}
/>
</TabPane>
<TabPane tab="物流信息" key="4">
<SetLogistics
onRef={(refs)=>setFormRefs([...formRefs, refs])}
/>
</TabPane>
<TabPane tab="适用渠道" key="3">
<SelectChannel
onRef={(refs)=>setFormRefs([...formRefs, refs])}
......@@ -109,4 +130,4 @@ const AddDirectChannel:React.FC<{}> = (props) => {
</PageHeaderWrapper>)
}
export default observer(AddDirectChannel)
\ No newline at end of file
export default observer(AddDirectChannel)
import React, {useState, useRef, useEffect} from 'react'
import { history } from 'umi';
import { Button, Form, Card, Tabs, Modal, Checkbox, Table, InputNumber, Row, Col, Input } from 'antd'
import { Button, Form, Card, Tabs, Modal, Checkbox, Table, InputNumber, Row, Col, Input, Radio, Select } from 'antd'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import {
PlusOutlined,
......@@ -12,6 +12,7 @@ import ReutrnEle from '@/components/ReturnEle';
import styles from './index.less'
import { PublicApi } from '@/services/api';
import { GetLogisticsSelectListCompanyResponse, GetLogisticsSelectListFreightTemplateResponse, GetLogisticsSelectListShipperAddressResponse } from '@/services/LogisticsApi';
const layout = {
labelCol: {
......@@ -28,11 +29,13 @@ const layoutSetPrice = {
}
const { TabPane } = Tabs
const {Item}:any = Form
const { Item }: any = Form
const { Option } = Select
const ModifyDirectChannel:React.FC<{}> = () => {
const [formPrice] = Form.useForm()
const [setPriceForm] = Form.useForm()
const [logisticsForm] = Form.useForm()
const [queryId, setQueryId] = useState<any>()
const [isDisabledSave, setIsDisabledSave] = useState<boolean>(false)
const [modifyModal, setModifyModal] = useState(false)
......@@ -57,6 +60,15 @@ const ModifyDirectChannel:React.FC<{}> = () => {
const [originHasIds, setOriginHasIds] = useState<number[]>([])
const [loading, setLoading] = useState<boolean>(false)
const [logisticsCompanyLists, setLogisticsCompanyLists] = useState<GetLogisticsSelectListCompanyResponse>()
const [logisticsAddressList, setLogisticsAddressList] = useState<GetLogisticsSelectListShipperAddressResponse>()
const [logisticsTemplateList, setLogisticsTemplateList] = useState<GetLogisticsSelectListFreightTemplateResponse>()
const [isTemplate, setIsTemplate] = useState<boolean>(false)
const [deliveryType, setDeliveryType] = useState<number>(1)
const [carriageType, setCarriageType] = useState<number>()
const [banCarriageType, setBanCarriageType] = useState(false)
const [template, setTemplate] = useState(false) // 是否必填运费模板
useEffect(() => {
const { id } = history.location.query
......@@ -68,11 +80,30 @@ const ModifyDirectChannel:React.FC<{}> = () => {
setChannelDetails(data)
priceTypeRef.current = data.channelCommodity.commodity.priceType
formPrice.setFieldsValue({isMemberPrice: data?.isMemberPrice})
const { deliveryType, carriageType, useTemplate } = data.logistics
setDeliveryType(deliveryType)
setCarriageType(carriageType)
setIsTemplate(useTemplate)
setTemplate(useTemplate)
logisticsForm.setFieldsValue(data.logistics)
structureTable(data.unitPriceAndPicList, data.channelCommodity.commodity, true) // 初始已有规格
let hasIds = data.unitPriceAndPicList.map(item => item.id)
setOriginHasIds(hasIds)
}
})
// 获取发货地址 物流公司 运费模板
PublicApi.getLogisticsSelectListShipperAddress().then(res=>{
setLogisticsAddressList(res.data)
})
PublicApi.getLogisticsSelectListCompany({cooperateType: '2'}).then(res=>{
setLogisticsCompanyLists(res.data)
})
PublicApi.getLogisticsSelectListFreightTemplate().then(res=>{
setLogisticsTemplateList(res.data)
})
}, [])
useEffect(() => {
......@@ -88,7 +119,7 @@ const ModifyDirectChannel:React.FC<{}> = () => {
if(visibleAddSpec)
fetchSpecData()
}, [visibleAddSpec])
// 获取商品规格列表
const fetchSpecData = () => {
setLoading(true)
......@@ -112,42 +143,42 @@ const ModifyDirectChannel:React.FC<{}> = () => {
temp.push({title: _item.customerAttribute.name, dataIndex: [_item.customerAttribute.name, 'value'], key: _item.customerAttribute.name})
})
col.push({
title: 'ID',
dataIndex: 'id',
key: 'id'
},
title: 'ID',
dataIndex: 'id',
key: 'id'
},
{
title: 'GoodsId',
dataIndex: 'goodsId',
title: 'GoodsId',
dataIndex: 'goodsId',
key: 'goodsId',
className: 'commonHide'
},
{
title: '索引',
dataIndex: '索引',
{
title: '索引',
dataIndex: '索引',
key: '索引',
className: 'commonHide'
},
{
title: 'commodityUnitPriceAndPicId',
dataIndex: 'commodityUnitPriceAndPicId',
{
title: 'commodityUnitPriceAndPicId',
dataIndex: 'commodityUnitPriceAndPicId',
key: 'commodityUnitPriceAndPicId',
className: 'commonHide'
},
{
title: '商品名称',
dataIndex: '商品名称',
{
title: '商品名称',
dataIndex: '商品名称',
key: '商品名称'
},
},
{
title: '对应货品',
dataIndex: '对应货品',
title: '对应货品',
dataIndex: '对应货品',
key: '对应货品'
},
...temp,
{
title: priceTypeRef.current === 3 ? '积分' : '单价',
dataIndex: '单价',
},
...temp,
{
title: priceTypeRef.current === 3 ? '积分' : '单价',
dataIndex: '单价',
key: '单价',
render: (text, record) => {
if (!text || JSON.stringify(text)==='{}') return null
......@@ -236,7 +267,7 @@ const ModifyDirectChannel:React.FC<{}> = () => {
let priceArray = Object.values(record['单价'])
let tempArr = []
numberArray.map((_item, _index) => {
tempArr.push({ numberPrice: priceArray[_index], numberRange: { numberMin: _item[0], numberMax: _item[1] } })
tempArr.push({ numberPrice: priceArray[_index], numberRange: { numberMin: _item[0], numberMax: _item[1] } })
})
setPriceForm.setFieldsValue({ladderPrice: true, ladderRange: tempArr})
}
......@@ -310,7 +341,7 @@ const ModifyDirectChannel:React.FC<{}> = () => {
})
setSubmitParams(_data)
console.log(priceTableData, _priceTableData, _data, 'params')
// console.log(priceTableData, _priceTableData, _data, 'params')
}
const clickDelete = (record: any) => {
......@@ -376,6 +407,33 @@ const ModifyDirectChannel:React.FC<{}> = () => {
})
}
const changeDeliveryType = (e) => {
setDeliveryType(e.target.value)
setCarriageType(1)
setIsTemplate(false)
logisticsForm.resetFields()
logisticsForm.setFieldsValue({deliveryType: e.target.value})
logisticsForm.setFieldsValue({carriageType: 1})
}
const onChangeTemplate = (e) => {
setIsTemplate(e.target.checked)
logisticsForm.setFieldsValue({weight: null})
}
const changeCarriageType = (e) => {
setCarriageType(e.target.value)
if(e.target.value === 2) {
setTemplate(true)
setIsTemplate(true)
logisticsForm.setFieldsValue({useTemplate: true})
} else {
setTemplate(false)
setIsTemplate(false)
logisticsForm.setFieldsValue({useTemplate: false})
}
}
return (<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回"/>}
......@@ -388,7 +446,7 @@ const ModifyDirectChannel:React.FC<{}> = () => {
>
<Card>
<Tabs type="card">
<TabPane tab="渠道信息" key="1">
<TabPane tab="基本信息" key="1">
<Form
{...layout}
labelAlign="left"
......@@ -411,11 +469,11 @@ const ModifyDirectChannel:React.FC<{}> = () => {
</Form.Item>
</Form>
</TabPane>
<TabPane tab="修改商品价格" key="2">
<TabPane tab="商品规格" key="2">
<Form
{...layout}
form={formPrice}
name="add-channel-discount"
name="add-channel-discount"
labelAlign="left"
>
<Form.Item
......@@ -430,7 +488,7 @@ const ModifyDirectChannel:React.FC<{}> = () => {
<PlusOutlined /> 选择商品规格
</Button>
{
priceTableData.length > 0 && priceTypeRef.current != 2 &&
priceTableData.length > 0 && priceTypeRef.current != 2 &&
<Button
type="text"
style={{float: 'right'}}
......@@ -442,6 +500,132 @@ const ModifyDirectChannel:React.FC<{}> = () => {
}
<Table rowKey="id" dataSource={priceTableData} columns={priceColumn} style={{clear: 'both'}} />
</TabPane>
<TabPane tab="物流信息" key="3">
<Form
{...layout}
form={logisticsForm}
name="logistic-form"
labelAlign="left"
colon={false}
autoComplete="off"
>
<Form.Item
name="deliveryType"
label="配送方式"
rules={[
{
required: true,
message: '请选择配送方式'
},
]}
>
<Radio.Group onChange={changeDeliveryType}>
<Radio value={1}>物流(默认)</Radio>
<Radio value={2}>自提</Radio>
<Radio value={3}>无需配送</Radio>
</Radio.Group>
</Form.Item>
{
deliveryType === 1 && <><Form.Item
name="carriageType"
label="运费方式"
rules={[
{
required: true,
message: '请选择运费方式'
},
]}
>
<Radio.Group onChange={changeCarriageType} disabled={banCarriageType}>
<Radio value={1}>卖家承担运费(默认)</Radio>
<Radio value={2}>买家承担运费</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label={<>重量<i style={{color:'red'}}>&nbsp;*</i></>}
style={{position: 'relative'}}
>
<Form.Item
name="weight"
rules={[
{
required: true,
message: '请正确输入重量',
},
{
pattern: /^\d+(\.\d{1,3})?$/,
message: '重量数值小数点后仅限三位',
}
]}
noStyle
>
<InputNumber min={0} style={{width:'100%'}} placeholder="请输入重量" />
</Form.Item>
<span style={{position:'absolute', right:5, top:5, opacity: 0.6}}>KG</span>
</Form.Item></>
}
{
carriageType === 2 && <Form.Item
name="useTemplate"
valuePropName="checked"
label=" "
>
<Checkbox disabled={template} onChange={onChangeTemplate}>使用运费模板(只有买家承担运费才能选择)</Checkbox>
</Form.Item>
}
{
isTemplate && <Form.Item
name="templateId"
label="运费模板"
rules={[
{
required: template,
message: '请正确输入重量',
}
]}
>
<Select
placeholder="请选择运费模板"
allowClear
>
{
logisticsTemplateList?.length>0 && logisticsTemplateList.map(_ => <Option key={_.id} value={_.id}>{_.name}</Option>)
}
</Select>
</Form.Item>
}
{
deliveryType !== 3 && <Form.Item
name="sendAddress"
label="发货地址"
>
<Select
placeholder="请选择发货地址"
allowClear
>
{
logisticsAddressList?.length > 0 && logisticsAddressList.map(_=><Option key={_.id} value={_.id}>{_.fullAddress}</Option>)
}
</Select>
</Form.Item>
}
{
deliveryType === 1 && <Form.Item
name="company"
label="物流公司"
>
<Select
placeholder="请选择物流公司"
allowClear
>
{
logisticsCompanyLists?.length > 0 && logisticsCompanyLists.map(_=><Option key={_.id} value={_.id}>{_.name}</Option>)
}
</Select>
</Form.Item>
}
</Form>
</TabPane>
</Tabs>
</Card>
......@@ -459,7 +643,7 @@ const ModifyDirectChannel:React.FC<{}> = () => {
form={setPriceForm}
initialValues={{ladderPrice: false}}
>
{
{
priceTypeRef.current!==3 &&
<Form.Item
label=""
......@@ -528,7 +712,7 @@ const ModifyDirectChannel:React.FC<{}> = () => {
placeholder="~"
disabled
/>
<Form.Item
<Form.Item
name={[field.name, 'numberRange', 'numberMax']}
noStyle
rules={[
......@@ -612,9 +796,9 @@ const ModifyDirectChannel:React.FC<{}> = () => {
destroyOnClose={true}
width={704}
>
<Table
dataSource={specTableData}
columns={specColumn}
<Table
dataSource={specTableData}
columns={specColumn}
rowKey="id"
loading={loading}
rowSelection={{
......@@ -627,4 +811,4 @@ const ModifyDirectChannel:React.FC<{}> = () => {
</PageHeaderWrapper>)
}
export default ModifyDirectChannel
\ No newline at end of file
export default ModifyDirectChannel
......@@ -12,6 +12,9 @@ const ViewDriectChannel: React.FC<{}> = () => {
const [priceTableData, setPriceTableData] = useState<any[]>([])
const [priceTableDataColumn, setPrcieTableColumn] = useState<any[]>([])
const [shopList, setShopList] = useState<any[]>([])
const [logisticTemplateName, setLogisticTemplateName] = useState<string>()
const [logisticResourceCompanyName, setLogisticResourceCompanyName] = useState<string>()
const [logisticResourceSendAddress, setLogisticResourceSendAddress] = useState<string>()
useEffect(() => {
const { id } = history.location.query
......@@ -23,9 +26,24 @@ const ViewDriectChannel: React.FC<{}> = () => {
PublicApi.getProductChannelCommodityGetShop({ id: id }).then(res => {
setShopList(res.data)
})
}, [])
useEffect(() => {
if(channelDetails?.logistics?.templateId)
PublicApi.getLogisticsFreightTemplateGet({id: channelDetails?.logistics?.templateId + ''}).then(res => {
setLogisticTemplateName(res.data.name)
})
if(channelDetails?.logistics?.company)
PublicApi.getLogisticsCompanyGet({id: channelDetails?.logistics?.company + ''}).then(res => {
setLogisticResourceCompanyName(res.data.name)
})
if(channelDetails?.logistics?.sendAddress)
PublicApi.getLogisticsShipperAddressGet({id: channelDetails?.logistics?.sendAddress + ''}).then(res => {
const { provinceName, cityName, districtName, address } = res.data
setLogisticResourceSendAddress(provinceName + cityName + districtName + address)
})
}, [channelDetails])
const constructTable = (param: any) => {
const { unitPriceAndPicList, channelCommodity } = param
const { commodity } = channelCommodity
......@@ -138,6 +156,18 @@ const ViewDriectChannel: React.FC<{}> = () => {
</Descriptions>
</>
const renderDeliveryType = (type: number) => {
if(type === 1) return '物流(默认)'
else if(type === 2) return '自提'
else if(type === 3) return '无需配送'
else return null
}
const renderCarriageType = (type: number) => {
if(type === 1) return '卖家承担运费(默认)'
if(type === 2) return '买家承担运费'
}
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
......@@ -194,6 +224,80 @@ const ViewDriectChannel: React.FC<{}> = () => {
</Row>
</Card>
</Space>
<Space direction="vertical" style={{ width: '100%' }}>
<Card headStyle={{ borderBottom: 'none' }} title="物流信息">
<Row>
<Col span={24}>
{
renderDeliveryType(channelDetails?.logistics?.deliveryType) &&
<Row>
<Col span={4}>
<p>配送方式:</p>
</Col>
<Col span={20}>
<p>{renderDeliveryType(channelDetails?.logistics?.deliveryType)}</p>
</Col>
</Row>
}
{
renderCarriageType(channelDetails?.logistics?.carriageType) &&
<Row>
<Col span={4}>
<p>运送方式:</p>
</Col>
<Col span={20}>
<p>{renderCarriageType(channelDetails?.logistics?.carriageType)}</p>
</Col>
</Row>
}
{
channelDetails?.logistics?.weight &&
<Row>
<Col span={4}>
<p>重量:</p>
</Col>
<Col span={20}>
<p>{channelDetails.logistics.weight}KG(公斤)</p>
</Col>
</Row>
}
{
logisticTemplateName &&
<Row>
<Col span={4}>
<p>运费模版:</p>
</Col>
<Col span={20}>
<p>{logisticTemplateName}</p>
</Col>
</Row>
}
{
logisticResourceCompanyName &&
<Row>
<Col span={4}>
<p>物流公司:</p>
</Col>
<Col span={20}>
<p>{logisticResourceCompanyName}</p>
</Col>
</Row>
}
{
logisticResourceSendAddress &&
<Row>
<Col span={4}>
<p>发货地址:</p>
</Col>
<Col span={20}>
<p>{logisticResourceSendAddress}</p>
</Col>
</Row>
}
</Col>
</Row>
</Card>
</Space>
</PageHeaderWrapper>
)
}
......
......@@ -66,7 +66,8 @@ export const searchSchema: ISchema = {
style: {
width: 174
}
}
},
visible: false,
},
memberStatus: {
type: 'string',
......@@ -163,4 +164,4 @@ export const rechargeSchema: ISchema = {
}
}
}
}
\ No newline at end of file
}
......@@ -140,9 +140,9 @@ const AddBrand: React.FC<{}> = () => {
delete values.proveUrl.file
}
PublicApi.postProductBrandSaveOrUpdateBrand(values).then(res => {
setIsDisabledSave(true)
setIsEnableCheck(false)
setReponseId(res.data)
setIsDisabledSave(true)
setIsEnableCheck(false)
setReponseId(res.data)
})
})
}
......
......@@ -36,23 +36,63 @@ export enum SALE_ORDER_STATUS {
export const tableListSchema: ISchema = {
type: 'object',
properties: {
orderNo: {
type: 'string',
"x-component": 'SearchFilter',
'x-component-props': {
placeholder: '请输入订单编号',
align: 'flex-end',
},
},
[FORM_FILTER_PATH]: {
// orderNo: {
// type: 'string',
// "x-component": 'SearchFilter',
// 'x-component-props': {
// placeholder: '请输入订单编号',
// align: 'flex-end',
// },
// },
// [FORM_FILTER_PATH]: {
// type: 'object',
// 'x-component': 'flex-layout',
// 'x-component-props': {
// inline: true,
// colStyle: {
// marginLeft: 20
// }
// },
mageLayout: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
inline: true,
colStyle: {
marginLeft: 20
}
},
'x-component': 'mega-layout',
properties: {
topLayout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
grid: true,
},
properties: {
ctl: {
type: 'object',
'x-component': 'Children',
'x-component-props': {
children: '{{controllerBtns}}',
},
},
orderNo: {
type: 'string',
"x-component": 'Search',
'x-component-props': {
placeholder: '请输入订单编号',
align: 'flex-end',
},
}
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
},
colStyle: {
marginLeft: 20,
},
},
properties: {
orderThe: {
type: 'string',
......@@ -79,7 +119,7 @@ export const tableListSchema: ISchema = {
children: '查询',
},
},
},
},}}
},
}
}
......@@ -192,16 +192,16 @@ const CreateOrderElectronModal:React.FC<OrderElectronModalProps> = (props) => {
// useAsyncSelect('contractTemplateId', async () => (await PublicApi.getOrderSelectListContractTemplate()).data, ['name', 'id']).then(()=>{
// actions.setFieldValue("contractTemplateId", data.contractTemplateId)
// })
const { data } = await PublicApi.getOrderSelectListContractTemplate()
let options = data.map(item => ({
const res = await PublicApi.getOrderSelectListContractTemplate()
let options = res.data.map(item => ({
label: item.name,
value: item.id,
}))
actions.setFieldState('contractTemplateId', state => {
state.props.enum = options
})
if(options?.length && options.filter(_i => _i.value === data.contractTemplateId).length) {
actions.setFieldValue("contractTemplateId", data.contractTemplateId)
if(options?.length && options.filter(_i => _i.value === data['contractTemplateId']).length) {
actions.setFieldValue("contractTemplateId", data['contractTemplateId'])
}
} else {
actions.setFieldState('usingElectronicContracts', state => {
......
......@@ -95,4 +95,4 @@ const OrderMergeInfo: React.FC<OrderMergeInfoProps> = (props) => {
OrderMergeInfo.defaultProps = {}
export default OrderMergeInfo
\ No newline at end of file
export default OrderMergeInfo
import React, { useState, useEffect, useContext, useRef } from 'react'
import { Modal, Steps, Row, Col, Spin, message, Upload, Button, Input } from 'antd'
import style from './index.less'
import { OrderDetailContext } from '../../_public/order/context'
import cx from 'classnames'
import { ScanOutlined, UploadOutlined } from '@ant-design/icons'
import { UPLOAD_TYPE } from '@/constants'
import { usePageStatus } from '@/hooks/usePageStatus'
import { PublicApi } from '@/services/api'
import { history } from 'umi'
import { useHttpRequest } from '@/hooks/useHttpRequest'
import { encryptedByAES } from '@/utils/cryptoAes'
import QRCode from 'qrcode'
export interface OrderPayModalProps {
currentRef: any,
confirm?()
}
const HeaderTitle = ({ current }) => {
return <div style={{ padding: '0 40px' }}>
<Steps size='small' current={current}>
<Steps.Step title='选择支付方式'></Steps.Step>
<Steps.Step title='进行支付'></Steps.Step>
</Steps>
</div>
}
const transformPayData = (originData, data): any => {
console.log(originData, data, 'transformPayData')
const result = originData.reduce((prev, next) => {
const findItem = data.find(v => v.id === next.channel) || null
if (!findItem) {
return prev
}
if (prev[next.payWay]) {
prev[next.payWay].push({ label: next.way, value: next.id })
} else {
prev[next.payWay] = [
{ label: findItem.way, value: next.id, channel: next.channel }
]
}
return prev
}, {})
return result
}
const formatting = (data, property) => {
let nweData = data.reduce(function (acc, obj) {
let key = obj[property];
if (!acc[key]) {
acc[key] = []
}
acc[key].push(obj)
return acc
}, {})
for(let i in nweData){
nweData[i] = nweData[i].map(item => ({ value: item.id, label: item.way, channel: item.payType }))
}
return nweData
}
const payTextList = ["",
'线上支付',
'线下支付',
'授信支付',
'货到付款'
]
const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
const formRef = useRef<any>({})
const { id } = usePageStatus()
const { data, payList, currentPayInfoId } = useContext(OrderDetailContext)
// const transformPayList: any = data ? transformPayData(data.paymentInformationResponses, payList) : []
const transformPayList: any = data ? formatting(payList, "payType") : []
const { run, loading } = useHttpRequest(PublicApi.postOrderPendingOrderPay)
const [visible, setVisible] = useState(false)
const [checked, setChecked] = useState<any>({})
const [current, setCurrent] = useState(0) // 0选择方式 1线下支付方式 2授信支付 3余额支付 4微信支付 5货到付款 1000清除
const [payStep, setPayStep] = useState(0) // 支付模态框的步骤 0选方式 1下一步的具体操作 2输入支付密码
const mobilePayFlag = useRef(0) // 用于判断移动支付类型 4微信
const [code, setCode] = useState('')
const [qrCodeInfo, setQrCodeInfo] = useState({ generateCharacter: '', qrUrl: '' })
const [number, setNumber] = useState([0,1,2,3,4,5])
const { currentRef, confirm } = props
const [isSpin, setIsSpin] = useState<boolean>(false)
const [creditInfo, setCreditInfo] = useState<any>()
const [balanceInfo, setBalanceInfo] = useState<any>()
useEffect(() => {
if (currentRef) {
currentRef.current = {
visible,
setVisible
}
}
}, [])
useEffect(() => {
if (!visible) {
setCurrent(0)
setPayStep(0)
setChecked(null)
}
}, [visible])
useEffect(() => {
if(qrCodeInfo.generateCharacter){
generateQrCode()
}
}, [qrCodeInfo.generateCharacter])
const generateQrCode = () => {
// 生成二维码
QRCode.toDataURL(qrCodeInfo.generateCharacter).then((url:any) => {
setQrCodeInfo({...qrCodeInfo, qrUrl: url})
// 轮询支付结果
// setOpenTimer(1)
})
.catch((err:any) => {
console.error(err)
})
}
const handleConfirm = () => {
console.log(data,'data')
if (current === 0) {
if (checked.id) {
if (checked.id === 5) { // 线下支付
setCurrent(1)
setPayStep(1)
} else if (checked.id === 6) { // 授信额度支付
console.log('选择了授信支付')
setIsSpin(true)
PublicApi.getPayCreditGetCredit({
parentMemberId: data.supplyMembersId,
parentMemberRoleId: data.supplyMembersRoleId
}).then(res => {
if(res.code === 1000) {
setCreditInfo(res.data)
} else {
message.error(res.message)
}
setIsSpin(false)
})
setCurrent(2)
setPayStep(1)
} else if (checked.id === 4) { // 余额支付
console.log('选择了余额支付')
setIsSpin(true)
PublicApi.getPayAssetAccountGetUserBalance({
parentMemberId: data.supplyMembersId,
parentMemberRoleId: data.supplyMembersRoleId,
payType: data.ruleConfigurationId
}).then(res => {
if(res.code === 1000) {
setBalanceInfo(res.data)
} else {
message.error(res.message)
}
setIsSpin(false)
})
setCurrent(3)
setPayStep(1)
} else if(checked.id === 7) {
console.log('选择了货到付款')
setCurrent(5)
setPayStep(1)
} else if(checked.id === 2) {
console.log('选择了微信支付')
// 跳转扫码支付
history.push(`/pay?orderId=${btoa(JSON.stringify({ orderId: id, memberId: data.supplyMembersId, memberRoleId: data.supplyMembersRoleId }))}`)
// mobilePayFlag.current = 4
// setCurrent(4)
// setPayStep(1)
// handleSubmitPay()
}
else {
message.error('暂只支持线下支付、授信额度支付、余额支付方式、货到付款')
}
} else {
message.error('请先选择支付方式')
}
return;
}
let payPrice = data.paymentInformationResponses.filter(item => item.id === Number(currentPayInfoId))[0].payPrice
// 开始提交线下支付数据
if(current === 1) {
const payOrderUrls = formRef.current.urlList
const checkedId = checked.id
if (!payOrderUrls || payOrderUrls.length === 0) {
message.error('请先上传凭证')
return;
}
if (!checkedId) {
message.error('未选择支付方式')
return;
}
handleSubmitPay()
} else if (current === 2) {
// 开始提交授信支付数据 (需要输入支付密码)
console.log('开始提交授信支付数据', payPrice)
if(payPrice <= creditInfo.canUseQuota){
setPayStep(2)
setCurrent(1000)
} else {
message.error('您的授信可用额度不足')
}
} else if(current === 3) {
// 开始提交余额支付数据 (需要输入支付密码)
console.log('开始提交余额支付数据', payPrice)
if(payPrice <= balanceInfo){
setPayStep(2)
setCurrent(1000)
} else {
message.error('您的账户余额不足')
}
} else if(current === 5) {
// 开始提交货到付款数据
console.log('开始提交货到付款数据', payPrice)
handleSubmitPay()
}
confirm && confirm()
}
const handleCancel = () => {
if (current === 0) {
setVisible(false)
} else {
setCurrent(0)
setPayStep(0)
}
}
const handleSubmitPay = async () => {
const payOrderUrls = formRef.current.urlList
// 当前选中的支付信息
let PayInfoObj = data.paymentInformationResponses.filter(item => item.id === Number(currentPayInfoId))[0]
let params: any = {
id: Number(id),
paymentInformationId: PayInfoObj.id,
payTypeId: checked.id,
}
if(payStep === 2) {
if(code.length != number.length){
return message.error('请输入支付密码')
}
params.payPassword = encryptedByAES(code)
} else if(current === 1) {
params.payOrderUrls = payOrderUrls.join(',')
}
console.log(current, payStep,'666',mobilePayFlag)
const res = await run(params)
if (res.code === 1000) {
if(mobilePayFlag.current !== 4) {
history.goBack()
} else {
console.log(res, '二维码信息')
setQrCodeInfo({ ...qrCodeInfo, generateCharacter: res.data })
}
}
}
const handleUploadChange = (e) => {
const { fileList } = e
const urlList = fileList.map(v => v.response && v.response.code === 1000 ? v.response.data : '')
formRef.current.urlList = urlList
}
const handleBack = () => {
setCurrent(0)
setPayStep(0)
}
const handleOk = () => {
console.log('ODEK')
handleCancel()
}
const onChange = (e) => {
let v = e.target.value
setCode(v)
}
const renderModalFooter = () => {
let footer = null;
if(current){
if(payStep === 1){
footer = [
<Button key="back" onClick={handleBack}>
上一步
</Button>,
<Button key="submit" type="primary" loading={loading} onClick={handleConfirm}>
确认
</Button>,
]
} else if (payStep === 2) {
footer = [
<Button key="submit" type="primary" loading={loading} onClick={handleSubmitPay} style={{width: '100%'}}>
确认支付
</Button>
]
}
} else {
footer = [
<Button key="back" onClick={handleCancel}>
取消
</Button>,
<Button key="submit" type="primary" loading={loading} onClick={handleConfirm}>
下一步
</Button>,
]
}
return footer;
}
return (
<Modal
width={704}
title={<HeaderTitle current={current} />}
visible={visible}
onOk={handleConfirm}
onCancel={handleCancel}
footer={renderModalFooter()}
destroyOnClose={true}
maskClosable={false}
// cancelText={current === 0 ? '取消' : '上一步'}
// okText={current === 0 ? '下一步' : '确认'}
// confirmLoading={loading}
>
{current === 0 &&
transformPayList && Object.entries(transformPayList).map(([key, value]) => <Row key={key} style={{ marginBottom: 24 }}>
<Col span={6} style={{ color: '#909399', fontSize: 12 }}>{payTextList[key]}</Col>
<Col style={{ flex: 1 }}>
<div className={style.radioBox}>
{
(value as any[]).map(v =>
<div key={v.value} className={cx(style.payRadio, (checked && v.value === checked.id) ? style.active : '')} onClick={() => setChecked({ id: v.value, channel: v.channel })}>{v.label}</div>
)
}
</div>
</Col>
</Row>)
}
{/* 线下支付线上确认 */}
{
current === 1 &&
<div>
<p style={{fontWeight: "bold"}}>上传支付凭证</p>
<Upload
name='file'
action='/api/file/file/upload'
headers={{
authorization: 'authorization-text'
}}
data={{
fileType: UPLOAD_TYPE
}}
onChange={handleUploadChange}
showUploadList
>
<Button icon={<UploadOutlined />} type='dashed'>上传凭证</Button>
</Upload>
</div>
}
{/* 授信支付 */}
{
current === 2 &&
<Spin spinning={isSpin}>
<p style={{fontWeight: "bold"}}>授信额度</p>
<p>
<span className={style.title}>
可用授信额度(元):
</span>
<span className={style.amount}>
{creditInfo?.canUseQuota?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
总授信额度(元):
</span>
<span className={cx(style.amount, style.amount1)}>
{creditInfo?.quota?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
已用授信额度(元):
</span>
<span className={cx(style.amount, style.amount1)}>
{creditInfo?.useQuota?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
本次需支付(元):
</span>
<span className={cx(style.amount, style.amount2)}>
{data?.paymentInformationResponses?.filter(item => item.id === Number(currentPayInfoId))[0]?.payPrice?.toFixed(2)}
</span>
</p>
</Spin>
}
{/* 余额支付 */}
{
current === 3 &&
<Spin spinning={isSpin}>
<p style={{fontWeight: "bold"}}>账户余额</p>
<p>
<span className={style.title}>
账户可用余额(元):
</span>
<span className={style.amount}>
{balanceInfo?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
本次需支付(元):
</span>
<span className={cx(style.amount, style.amount2)}>
{data?.paymentInformationResponses?.filter(item => item.id === Number(currentPayInfoId))[0]?.payPrice?.toFixed(2)}
</span>
</p>
</Spin>
}
{/* 货到付款 */}
{
current === 5 &&
<div>
<p style={{fontWeight: "bold"}}>货到付款支付确认</p>
<p>
<span className={style.title}>
支付方式:
</span>
<span className={style.amount}>
货到付款
</span>
</p>
<p>
<span className={style.title}>
支付金额(元):
</span>
<span className={cx(style.amount, style.amount2)}>
{data?.paymentInformationResponses?.filter(item => item.id === Number(currentPayInfoId))[0]?.payPrice?.toFixed(2)}
</span>
</p>
</div>
}
{/* 微信扫码支付 */}
{
current === 4 &&
<div>
<div className={style.qrCodeImage}>
<img src={qrCodeInfo.qrUrl} alt=""/>
<div className={style.scanTips}>
<ScanOutlined className={style.scanIcon} />
<span>打开 {mobilePayFlag.current === 4 ? '微信' : '支付宝'}App<br />扫码完成支付</span>
</div>
</div>
</div>
}
{/* 输入支付密码 payStep===2 */}
{
payStep === 2 &&
<div className={style.payContainer}>
<p className={style.title}>请输入支付密码</p>
<div className={style.inputBox}>
{
number.map((item, index) => <div
className={style.codeItem}
key={index}
>
{code[index]?.replace(/[0-9]/g, '·')}
</div>)
}
<Input.Password
className={style.codeInput}
value={code}
maxLength={number.length}
onChange={onChange}
visibilityToggle={false}
/>
</div>
</div>
}
</Modal>
)
}
OrderPayModal.defaultProps = {}
export default OrderPayModal
import React, { useState, useEffect, useContext, useRef } from 'react'
import { Modal, Steps, Row, Col, Spin, message, Upload, Button, Input } from 'antd'
import style from './index.less'
import { OrderDetailContext } from '../../_public/order/context'
import cx from 'classnames'
import { ScanOutlined, UploadOutlined } from '@ant-design/icons'
import { UPLOAD_TYPE } from '@/constants'
import { usePageStatus } from '@/hooks/usePageStatus'
import { PublicApi } from '@/services/api'
import { history } from 'umi'
import { useHttpRequest } from '@/hooks/useHttpRequest'
import { encryptedByAES } from '@/utils/cryptoAes'
import QRCode from 'qrcode'
export interface OrderPayModalProps {
currentRef: any,
confirm?()
}
const HeaderTitle = ({ current }) => {
return <div style={{ padding: '0 40px' }}>
<Steps size='small' current={current}>
<Steps.Step title='选择支付方式'></Steps.Step>
<Steps.Step title='进行支付'></Steps.Step>
</Steps>
</div>
}
const transformPayData = (originData, data): any => {
console.log(originData, data, 'transformPayData')
const result = originData.reduce((prev, next) => {
const findItem = data.find(v => v.id === next.channel) || null
if (!findItem) {
return prev
}
if (prev[next.payWay]) {
prev[next.payWay].push({ label: next.way, value: next.id })
} else {
prev[next.payWay] = [
{ label: findItem.way, value: next.id, channel: next.channel }
]
}
return prev
}, {})
return result
}
const formatting = (data, property) => {
let nweData = data.reduce(function (acc, obj) {
let key = obj[property];
if (!acc[key]) {
acc[key] = []
}
acc[key].push(obj)
return acc
}, {})
for(let i in nweData){
nweData[i] = nweData[i].map(item => ({ value: item.id, label: item.way, channel: item.payType }))
}
return nweData
}
const payTextList = ["",
'线上支付',
'线下支付',
'授信支付',
'货到付款'
]
const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
const formRef = useRef<any>({})
const { id } = usePageStatus()
const { data, payList, currentPayInfoId } = useContext(OrderDetailContext)
// const transformPayList: any = data ? transformPayData(data.paymentInformationResponses, payList) : []
const transformPayList: any = data ? formatting(payList, "payType") : []
const { run, loading } = useHttpRequest(PublicApi.postOrderPendingOrderPay)
const [visible, setVisible] = useState(false)
const [checked, setChecked] = useState<any>({})
const [current, setCurrent] = useState(0) // 0选择方式 1线下支付方式 2授信支付 3余额支付 4微信支付 5货到付款 1000清除
const [payStep, setPayStep] = useState(0) // 支付模态框的步骤 0选方式 1下一步的具体操作 2输入支付密码
const mobilePayFlag = useRef(0) // 用于判断移动支付类型 4微信
const [code, setCode] = useState('')
const [qrCodeInfo, setQrCodeInfo] = useState({ generateCharacter: '', qrUrl: '' })
const [number, setNumber] = useState([0,1,2,3,4,5])
const { currentRef, confirm } = props
const [isSpin, setIsSpin] = useState<boolean>(false)
const [creditInfo, setCreditInfo] = useState<any>()
const [balanceInfo, setBalanceInfo] = useState<any>()
useEffect(() => {
if (currentRef) {
currentRef.current = {
visible,
setVisible
}
}
}, [])
useEffect(() => {
if (!visible) {
setCurrent(0)
setPayStep(0)
setChecked(null)
}
}, [visible])
useEffect(() => {
if(qrCodeInfo.generateCharacter){
generateQrCode()
}
}, [qrCodeInfo.generateCharacter])
const generateQrCode = () => {
// 生成二维码
QRCode.toDataURL(qrCodeInfo.generateCharacter).then((url:any) => {
setQrCodeInfo({...qrCodeInfo, qrUrl: url})
// 轮询支付结果
// setOpenTimer(1)
})
.catch((err:any) => {
console.error(err)
})
}
const handleConfirm = () => {
console.log(data,'data')
if (current === 0) {
if (checked.id) {
if (checked.id === 5) { // 线下支付
setCurrent(1)
setPayStep(1)
} else if (checked.id === 6) { // 授信额度支付
console.log('选择了授信支付')
setIsSpin(true)
PublicApi.getPayCreditGetCredit({
parentMemberId: data.supplyMembersId,
parentMemberRoleId: data.supplyMembersRoleId
}).then(res => {
if(res.code === 1000) {
setCreditInfo(res.data)
} else {
message.error(res.message)
}
setIsSpin(false)
})
setCurrent(2)
setPayStep(1)
} else if (checked.id === 4) { // 余额支付
console.log('选择了余额支付')
setIsSpin(true)
PublicApi.getPayAssetAccountGetUserBalance({
parentMemberId: data.supplyMembersId,
parentMemberRoleId: data.supplyMembersRoleId,
payType: data.ruleConfigurationId
}).then(res => {
if(res.code === 1000) {
setBalanceInfo(res.data)
} else {
message.error(res.message)
}
setIsSpin(false)
})
setCurrent(3)
setPayStep(1)
} else if(checked.id === 7) {
console.log('选择了货到付款')
setCurrent(5)
setPayStep(1)
} else if(checked.id === 2) {
console.log('选择了微信支付')
// 跳转扫码支付
history.push(`/pay?orderId=${btoa(JSON.stringify({ orderId: id, memberId: data.supplyMembersId, memberRoleId: data.supplyMembersRoleId }))}`)
// mobilePayFlag.current = 4
// setCurrent(4)
// setPayStep(1)
// handleSubmitPay()
}
else {
message.error('暂只支持线下支付、授信额度支付、余额支付方式、货到付款')
}
} else {
message.error('请先选择支付方式')
}
return;
}
let payPrice = data.paymentInformationResponses.filter(item => item.id === Number(currentPayInfoId))[0].payPrice
// 开始提交线下支付数据
if(current === 1) {
const payOrderUrls = formRef.current.urlList
const checkedId = checked.id
if (!payOrderUrls || payOrderUrls.length === 0) {
message.error('请先上传凭证')
return;
}
if (!checkedId) {
message.error('未选择支付方式')
return;
}
handleSubmitPay()
} else if (current === 2) {
// 开始提交授信支付数据 (需要输入支付密码)
console.log('开始提交授信支付数据', payPrice)
if(payPrice <= creditInfo.canUseQuota){
setPayStep(2)
setCurrent(1000)
} else {
message.error('您的授信可用额度不足')
}
} else if(current === 3) {
// 开始提交余额支付数据 (需要输入支付密码)
console.log('开始提交余额支付数据', payPrice)
if(payPrice <= balanceInfo){
setPayStep(2)
setCurrent(1000)
} else {
message.error('您的账户余额不足')
}
} else if(current === 5) {
// 开始提交货到付款数据
console.log('开始提交货到付款数据', payPrice)
handleSubmitPay()
}
confirm && confirm()
}
const handleCancel = () => {
if (current === 0) {
setVisible(false)
} else {
setCurrent(0)
setPayStep(0)
}
}
const handleSubmitPay = async () => {
const payOrderUrls = formRef.current.urlList
// 当前选中的支付信息
let PayInfoObj = data.paymentInformationResponses.filter(item => item.id === Number(currentPayInfoId))[0]
let params: any = {
id: Number(id),
paymentInformationId: PayInfoObj.id,
payTypeId: checked.id,
payType: checked.channel,
}
if(payStep === 2) {
if(code.length != number.length){
return message.error('请输入支付密码')
}
params.payPassword = encryptedByAES(code)
} else if(current === 1) {
params.payOrderUrls = payOrderUrls.join(',')
}
const res = await run(params)
if (res.code === 1000) {
if(mobilePayFlag.current !== 4) {
history.goBack()
} else {
console.log(res, '二维码信息')
setQrCodeInfo({ ...qrCodeInfo, generateCharacter: res.data })
}
}
}
const handleUploadChange = (e) => {
const { fileList } = e
const urlList = fileList.map(v => v.response && v.response.code === 1000 ? v.response.data : '')
formRef.current.urlList = urlList
}
const handleBack = () => {
setCurrent(0)
setPayStep(0)
}
const handleOk = () => {
console.log('ODEK')
handleCancel()
}
const onChange = (e) => {
let v = e.target.value
setCode(v)
}
const renderModalFooter = () => {
let footer = null;
if(current){
if(payStep === 1){
footer = [
<Button key="back" onClick={handleBack}>
上一步
</Button>,
<Button key="submit" type="primary" loading={loading} onClick={handleConfirm}>
确认
</Button>,
]
} else if (payStep === 2) {
footer = [
<Button key="submit" type="primary" loading={loading} onClick={handleSubmitPay} style={{width: '100%'}}>
确认支付
</Button>
]
}
} else {
footer = [
<Button key="back" onClick={handleCancel}>
取消
</Button>,
<Button key="submit" type="primary" loading={loading} onClick={handleConfirm}>
下一步
</Button>,
]
}
return footer;
}
return (
<Modal
width={704}
title={<HeaderTitle current={current} />}
visible={visible}
onOk={handleConfirm}
onCancel={handleCancel}
footer={renderModalFooter()}
destroyOnClose={true}
maskClosable={false}
// cancelText={current === 0 ? '取消' : '上一步'}
// okText={current === 0 ? '下一步' : '确认'}
// confirmLoading={loading}
>
{current === 0 &&
transformPayList && Object.entries(transformPayList).map(([key, value]) => <Row key={key} style={{ marginBottom: 24 }}>
<Col span={6} style={{ color: '#909399', fontSize: 12 }}>{payTextList[key]}</Col>
<Col style={{ flex: 1 }}>
<div className={style.radioBox}>
{
(value as any[]).map(v =>
<div key={v.value} className={cx(style.payRadio, (checked && v.value === checked.id) ? style.active : '')} onClick={() => setChecked({ id: v.value, channel: v.channel })}>{v.label}</div>
)
}
</div>
</Col>
</Row>)
}
{/* 线下支付线上确认 */}
{
current === 1 &&
<div>
<p style={{fontWeight: "bold"}}>上传支付凭证</p>
<Upload
name='file'
action='/api/file/file/upload'
headers={{
authorization: 'authorization-text'
}}
data={{
fileType: UPLOAD_TYPE
}}
onChange={handleUploadChange}
showUploadList
>
<Button icon={<UploadOutlined />} type='dashed'>上传凭证</Button>
</Upload>
</div>
}
{/* 授信支付 */}
{
current === 2 &&
<Spin spinning={isSpin}>
<p style={{fontWeight: "bold"}}>授信额度</p>
<p>
<span className={style.title}>
可用授信额度(元):
</span>
<span className={style.amount}>
{creditInfo?.canUseQuota?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
总授信额度(元):
</span>
<span className={cx(style.amount, style.amount1)}>
{creditInfo?.quota?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
已用授信额度(元):
</span>
<span className={cx(style.amount, style.amount1)}>
{creditInfo?.useQuota?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
本次需支付(元):
</span>
<span className={cx(style.amount, style.amount2)}>
{data?.paymentInformationResponses?.filter(item => item.id === Number(currentPayInfoId))[0]?.payPrice?.toFixed(2)}
</span>
</p>
</Spin>
}
{/* 余额支付 */}
{
current === 3 &&
<Spin spinning={isSpin}>
<p style={{fontWeight: "bold"}}>账户余额</p>
<p>
<span className={style.title}>
账户可用余额(元):
</span>
<span className={style.amount}>
{balanceInfo?.toFixed(2)}
</span>
</p>
<p>
<span className={style.title}>
本次需支付(元):
</span>
<span className={cx(style.amount, style.amount2)}>
{data?.paymentInformationResponses?.filter(item => item.id === Number(currentPayInfoId))[0]?.payPrice?.toFixed(2)}
</span>
</p>
</Spin>
}
{/* 货到付款 */}
{
current === 5 &&
<div>
<p style={{fontWeight: "bold"}}>货到付款支付确认</p>
<p>
<span className={style.title}>
支付方式:
</span>
<span className={style.amount}>
货到付款
</span>
</p>
<p>
<span className={style.title}>
支付金额(元):
</span>
<span className={cx(style.amount, style.amount2)}>
{data?.paymentInformationResponses?.filter(item => item.id === Number(currentPayInfoId))[0]?.payPrice?.toFixed(2)}
</span>
</p>
</div>
}
{/* 微信扫码支付 */}
{
current === 4 &&
<div>
<div className={style.qrCodeImage}>
<img src={qrCodeInfo.qrUrl} alt=""/>
<div className={style.scanTips}>
<ScanOutlined className={style.scanIcon} />
<span>打开 {mobilePayFlag.current === 4 ? '微信' : '支付宝'}App<br />扫码完成支付</span>
</div>
</div>
</div>
}
{/* 输入支付密码 payStep===2 */}
{
payStep === 2 &&
<div className={style.payContainer}>
<p className={style.title}>请输入支付密码</p>
<div className={style.inputBox}>
{
number.map((item, index) => <div
className={style.codeItem}
key={index}
>
{code[index]?.replace(/[0-9]/g, '·')}
</div>)
}
<Input.Password
className={style.codeInput}
value={code}
maxLength={number.length}
onChange={onChange}
visibilityToggle={false}
/>
</div>
</div>
}
</Modal>
)
}
OrderPayModal.defaultProps = {}
export default OrderPayModal
......@@ -74,15 +74,17 @@ const orderProductShopTypeMaps = {
export const AddressPop = (props) => {
const { pickInfo = null, children } = props
let receiveInfo = pickInfo?.render && JSON.parse(pickInfo.render).props.pickInfo
return pickInfo && pickInfo.deliveryType === 2 ? <Space>
<EnvironmentOutlined style={{marginRight: 8}}/>
<Popover content={
<Row>
<EnvironmentOutlined/>
<div>
<h3>自提地址</h3>
<p>{pickInfo.receiverName} / {pickInfo.phone}</p>
<p>{pickInfo.fullAddress}</p>
<h3><EnvironmentOutlined/> 自提地址</h3>
{/* <p>{pickInfo.receiverName} / {pickInfo.phone}</p>
<p>{pickInfo.fullAddress}</p> */}
<p>{receiveInfo.shipperName} / {receiveInfo.phone}</p>
<p>{receiveInfo.provinceName + receiveInfo.cityName + receiveInfo.districtName + receiveInfo.address}</p>
</div>
</Row>
}>
......
......@@ -52,7 +52,7 @@ export const MoneyTotalBox = registerVirtualBox('moneyTotalBox', props => {
const { form } = useFormSpy({ selector: [['onFieldValueChange', 'orderProductRequests']], reducer: v => v })
const data = form.getFieldValue('orderProductRequests')
const receiverAddressId = form.getFieldValue('deliveryAddresId')
const sum = data.reduce((prev, next) => prev + (next.money || 0), 0)
const sum = data.reduce((prev, next) => (prev*100 + (next.money || 0)*100)/100, 0)
const [freePrice, setFreePrice] = useState<number>(0)
useEffect(() => {
......@@ -60,6 +60,7 @@ export const MoneyTotalBox = registerVirtualBox('moneyTotalBox', props => {
form.notify('sumPrice', sum + freePrice)
}
}, [sum, freePrice])
useEffect(() => {
// 存在商品 并且有选择收货地址,则开始计算运费
if (data && data.length > 0 && receiverAddressId) {
......
import React, { useState } from 'react'
import React, { useRef, useState } from 'react'
import { Card, Button, Modal } from 'antd'
import { StandardTable } from 'god'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
......@@ -12,19 +12,24 @@ import { FORM_FILTER_PATH } from '@/formSchema/const'
import DateRangePickerUnix from '@/components/NiceForm/components/DateRangePickerUnix'
import Submit from '@/components/NiceForm/components/Submit'
import moment from 'moment'
import NiceForm from '@/components/NiceForm'
import { createFormActions } from '@formily/antd'
// 销售订单查询
export interface SaleOrderProps { }
const fetchTableData = async (params) => {
console.log(params, 'ppp')
const { data } = await PublicApi.getOrderPurchaseOrderList(params)
return data
}
const formActions = createFormActions();
// 最后一步开始调试 TODO
const SaleOrder: React.FC<SaleOrderProps> = (props) => {
const ref = useRef<any>({})
const [saleVisible, setSaleVisible] = useState<any>(false)
// 售后唤起弹窗 @todo
......@@ -35,7 +40,7 @@ const SaleOrder: React.FC<SaleOrderProps> = (props) => {
const handleEvaluate = (id) => {
history.push(`/memberCenter/tranactionAbility/supplierEvaluation/unevaluated`)
}
const secondColumns: any[] = baseOrderListColumns.concat([
{
title: '操作',
......@@ -50,41 +55,38 @@ const SaleOrder: React.FC<SaleOrderProps> = (props) => {
}
])
const controllerBtns = <Button style={{width: 140}} onClick={() => {}} type='default'>导出</Button>
return <PageHeaderWrapper>
<Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
columns={secondColumns}
rowKey={'orderNo'}
formilyLayouts={{
justify: 'space-between'
}}
formilyChilds={{
layouts: {
order: 2
},
children: <Button style={{width: 140}} onClick={() => {}} type='default'>导出</Button>
}}
formilyProps={{
layouts: {
order: 3
},
ctx: {
inline: false,
schema: tableListSchema,
effects: ($, actions) => {
currentRef={ref}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => ref.current.reload(values)}
expressionScope={{
controllerBtns,
}}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'orderNo',
FORM_FILTER_PATH,
);
},
components: {
)
}}
schema={tableListSchema}
components={{
DateRangePickerUnix,
Submit
}
}
}}
/>
}
tableProps={{
rowKey: 'orderNo',
}}
/>
</Card>
......@@ -93,4 +95,4 @@ const SaleOrder: React.FC<SaleOrderProps> = (props) => {
SaleOrder.defaultProps = {}
export default SaleOrder
\ No newline at end of file
export default SaleOrder
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