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

merge

parents d9c1940d fe199fdc
import React from 'react'
export interface CouponBoxProps {}
const CouponBox:React.FC<CouponBoxProps> = (props) => {
return (
<div>优惠券</div>
)
}
CouponBox.defaultProps = {}
export default CouponBox
\ No newline at end of file
......@@ -3,7 +3,7 @@ import { Input, Space, Button, Table } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
const MultTable = (props) => {
const { columns, prefix, suffix, rowKey } = props.props['x-component-props']
const { columns, prefix, suffix, rowKey, ...restProps } = props.props['x-component-props']
const value = props.value || []
return (
<div style={{width: '100%'}}>
......@@ -12,6 +12,7 @@ const MultTable = (props) => {
rowKey={rowKey || 'id'}
columns={columns}
dataSource={value}
{...restProps}
/>
{suffix}
</div>
......
......@@ -12,6 +12,8 @@ export default {
'menu.shopHome': '首页',
'menu.mallCommodity': '商品商城',
'menu.shopCommodity': '商品',
'menu.shopCommoditySearch': '商品搜索',
'menu.shopCommodityDetail': '商品详情',
'menu.purchaseOnline': '在线求购',
'menu.pointsMall': '积分商城',
'menu.shopPointsMall': '积分兑换',
......@@ -19,6 +21,8 @@ export default {
'menu.shopAbout': '关于我们',
'menu.infomation': '资讯',
'menu.shopInfomation': '资讯',
'menu.infomationDetail': '资讯详情',
'menu.infomationSearch': '资讯搜索',
'menu.admin': '管理页',
'menu.admin.sub-page': '二级管理页',
'menu.login': '登录',
......
......@@ -28,7 +28,7 @@ const Introduction: React.FC<IntroductionPropsType> = (props) => {
let templateName = commodityTemplateInfo.fileName || 'science'
switch (templateName) {
case 'science':
return <ScienceTemplate />
return <ScienceTemplate {...commodityDetail?.commodityRemark} />
}
}
......
......@@ -2,8 +2,8 @@
* 科技类商品描述模板
* @Author: ghua
* @Date: 2020-08-01 10:59:17
* @Last Modified by: ghua
* @Last Modified time: 2020-08-01 10:59:17
* @Last Modified by: ghua
* @Last Modified time: 2020-09-09 11:07:52
*/
import React, { Fragment } from 'react'
......@@ -12,24 +12,35 @@ import "video-react/dist/video-react.css"
import './index.less'
interface ScienceTemplatePropsType {
image: string[],
video: string[],
word: string[]
}
const ScienceTemplate: React.FC<ScienceTemplatePropsType> = () => {
const ScienceTemplate: React.FC<ScienceTemplatePropsType> = (props) => {
const { image, video, word } = props
return (
<Fragment>
<div className="video_box">
<Player
poster="https://img.alicdn.com/imgextra/i1/2200692764442/O1CN01OQ5Y9q1igTvAGTpsB_!!2200692764442.jpg"
src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4"
>
<BigPlayButton position="center" />
<ControlBar autoHide={true} />
</Player>
{
video && video.map((video, index) => (
<Player
key={`video_box_item${index}`}
// poster="https://img.alicdn.com/imgextra/i1/2200692764442/O1CN01OQ5Y9q1igTvAGTpsB_!!2200692764442.jpg"
src={video}
>
<BigPlayButton position="center" />
<ControlBar autoHide={true} />
</Player>
))
}
</div>
<div className="img_list">
<img src="https://img.alicdn.com/imgextra/i1/2200692764442/O1CN01OQ5Y9q1igTvAGTpsB_!!2200692764442.jpg" />
{
image && image.map((url, index) => <img key={`img_list_item_${index}`} src={url} />)
}
</div>
</Fragment>
)
......
......@@ -52,9 +52,14 @@ interface imgItemType {
const CommodityDetail = (props) => {
const { query: { id } } = props.location
const { shopInfo = {} } = props
const OrderStore = useLocalStore(() => store.OrderStore)
const { updateOrderInfo } = OrderStore
const [addSuccessVisible, setAddSuccessVisible] = useState<boolean>(false)
const [attributeList, setAttributeList] = useState([])
const [commodityDetail, setCommodityDetail] = useState<GetSearchShopStoreGetCommodityDetailResponse>()
const [attrAndValList, setAttrAndValList] = useState<any>({})
const [selectAttrVal, setSelectAttrVal] = useState<selectAttrValType[]>([])
const [commodityImgList, setCommodityImgList] = useState<imgItemType[]>([])
const [commodityPriceInfo, setCommodityPriceInfo] = useState([])
......@@ -62,12 +67,19 @@ const CommodityDetail = (props) => {
const [selectCommodityId, setSelectCommodityId] = useState<number>()
const [buyCount, setBuyCount] = useState<number>(1)
const [purchaseCount, setPurchaseCount] = useState<number>(0)
const [payWayList, setPayWayList] = useState([])
let clickFlag = true
useEffect(() => {
fetchDetail()
}, [])
useEffect(() => {
if (shopInfo) {
console.log(shopInfo, "shopInfo")
}
}, [shopInfo])
const fetchDetail = () => {
PublicApi.getSearchShopStoreGetCommodityDetail({ commodityId: id }).then(res => {
if (res.code === 1000) {
......@@ -85,11 +97,52 @@ const CommodityDetail = (props) => {
}
//@ts-ignore
PublicApi.getPayPayWayList({ memberId }).then(res => {
if (res.code === 1000) {
initPayWayList(res.data)
}
})
}
const initPayWayList = (data) => {
if (!data) {
return []
}
let result = []
for (let item of data) {
if (result.some(tempItem => tempItem.payType === item.payType)) {
result = result.map(resItem => {
if (resItem.payType === item.payType) {
resItem.payList = [...resItem.payList, item]
}
return resItem
})
} else {
let payVal = ""
switch (item.payType) {
case 1:
payVal = "线上支付"
break
case 2:
payVal = "线下支付"
break
case 3:
payVal = "授信支付"
break
case 4:
payVal = "货到付款"
break
}
result.push({
payVal,
payType: item.payType,
payList: [item]
})
}
}
setPayWayList(result)
}
const getMemberCredit = (memberId, memberRoleId) => {
let param = {
parentMemberId: memberId,
......@@ -122,6 +175,7 @@ const CommodityDetail = (props) => {
if (judgeArrisCommon(temp, selectAttrVal)) {
setSelectCommodityId(item.id)
setCurrentPriceRange(item.unitPrice)
setAttrAndValList(item)
}
}
}
......@@ -172,12 +226,47 @@ const CommodityDetail = (props) => {
message.info("请选择商品属性")
return
}
PublicApi.postOrderIsWorkFlow({ productIds: [selectCommodityId] }).then(res => {
if (res.code === 1000) {
message.destroy()
history.push(`/order?commodityId=${selectCommodityId}&scence=buy`)
}
})
if (clickFlag) {
clickFlag = false
PublicApi.postOrderIsWorkFlow({ productIds: [selectCommodityId] }).then(res => {
if (res.code === 1000) {
message.destroy()
let buyCommodityInfo = {
id: commodityDetail.id,
count: buyCount,
unitName: commodityDetail.unitName,
unitPrice: getUnitPrice(),
logistics: commodityDetail.logistics,
name: commodityDetail.name,
priceRange: commodityPriceInfo,
memberDiscount: parameter,
commodityPic: attrAndValList.commodityPic[0],
attribute: attrAndValList.attributeAndValueList
}
let buyOrderInfo = {
logistics: commodityDetail.logistics,
payWayList,
supplyMembersId: commodityDetail.memberId,
orderList: [{
id: shopInfo.id,
shopname: shopInfo.company,
orderList: [buyCommodityInfo]
}]
}
updateOrderInfo(buyOrderInfo).then(() => {
history.push(`/order?id=${selectCommodityId}&scence=prompt`)
})
clickFlag = true
} else {
}
}).catch(() => {
clickFlag = true
})
}
}
const renderBtn = () => {
......@@ -248,7 +337,6 @@ const CommodityDetail = (props) => {
setCurrentPriceRange(unitPriceAndPicList[0].unitPrice)
setCommodityImgList(tempImgList)
console.log(tempAttrList, "tempAttrList")
setAttributeList(tempAttrList)
}
......@@ -299,6 +387,24 @@ const CommodityDetail = (props) => {
}
}
const getUnitPrice = () => {
let unitPrice = 0
if (!commodityPriceInfo) {
return 0
}
if (commodityDetail?.priceType === COMMODITY_TYPE.prompt) {
if (commodityPriceInfo.length <= 1) {
unitPrice = commodityPriceInfo[0]?.price
} else {
let temp = commodityPriceInfo.filter(item => {
return Number(buyCount) >= Number(item.min) && Number(buyCount) < Number(item.max)
})
unitPrice = temp[0]?.price
}
}
return unitPrice
}
const getAmount = () => {
let unitPrice = 0
......@@ -453,10 +559,9 @@ const CommodityDetail = (props) => {
<div className={styles.product_info_line}>
<div className={styles.product_info_line_label}>支付方式</div>
<div className={styles.product_info_line_brief}>
<span className={styles.text}>线上支付</span>
<span className={styles.text}>线下支付</span>
<span className={styles.text}>授信支付</span>
<span className={styles.text}>货到付款</span>
{
payWayList.map((item, index) => <span key={`pay_way_item_${index}`} className={styles.text}>{item.payVal}</span>)
}
</div>
</div>
<div className={cx(styles.product_info_line, styles.mar_top_10)}>
......
......@@ -49,6 +49,17 @@ const Category: React.FC<CategoryPropsType> = (props) => {
}, [props, mallTemplateId])
const getNavLink = (item) => {
switch (type) {
case LAYOUT_TYPE.shop:
return `/shop/commodity?categoryId=${item.id}&categoryName=${btoa(encodeURIComponent(item.title))}&shopId=${shopUrlParam}`
case LAYOUT_TYPE.channel:
return `/channelmall/commodity?categoryId=${item.id}&categoryName=${btoa(encodeURIComponent(item.title))}&id=${shopUrlParam}`
default:
return `/commodity?categoryId=${item.id}&categoryName=${btoa(encodeURIComponent(item.title))}`
}
}
return (
<div className={styles.category}>
<div className={styles.category_type}>
......@@ -65,7 +76,7 @@ const Category: React.FC<CategoryPropsType> = (props) => {
<div className={styles.sub_category}>
{
item.children.map((childCategory, childIndex) => childIndex < 3 && (
<Link to={`/commodity`} key={childCategory.id}>{childCategory.title}</Link>
<Link to={getNavLink(childCategory)} key={childCategory.id}>{childCategory.title}</Link>
))
}
</div>
......@@ -77,14 +88,14 @@ const Category: React.FC<CategoryPropsType> = (props) => {
item.children.map(childCategory => (
<div className={styles.second_category_type} key={childCategory.id}>
<div className={styles.title}>
<Link to={`/commodity`}>
<Link to={getNavLink(childCategory)}>
{childCategory.title} <RightOutlined />
</Link>
</div>
<ul className={styles.third_category_type_list}>
{
childCategory.children.map(thirdChildItem => (
<li key={thirdChildItem.id}><Link to={`/commodity`}>{thirdChildItem.title}</Link></li>
<li key={thirdChildItem.id}><Link to={getNavLink(thirdChildItem)}>{thirdChildItem.title}</Link></li>
))
}
</ul>
......
......@@ -16,9 +16,7 @@ const CommonHeader: React.FC<ShopHeaderPropsType> = (props) => {
<div className={styles.common_header}>
<div className={styles.common_header_container}>
<div className="logo">
<Link to="/">
<img src={logo} />
</Link>
<img src={logo} />
</div>
<div className={styles.common_header_split}></div>
<div className={styles.common_header_title}>{title}</div>
......
......@@ -105,28 +105,4 @@
}
}
}
}
.mallComfirm {
position: relative;
:global {
.ant-modal-confirm-btns {
.ant-btn {
&:hover {
color: var(--mall_main_color);
border-color: var(--mall_main_color);
}
}
.ant-btn-primary {
background-color: var(--mall_main_color);
border-color: var(--mall_main_color);
&:hover {
color: #ffffff;
}
}
}
}
}
\ No newline at end of file
......@@ -6,7 +6,12 @@ import { PublicApi } from '@/services/api'
import { GetLogisticsReceiverAddressPageResponseDetail, GetLogisticsReceiverAddressGetResponse } from '@/services/LogisticsApi'
import styles from './index.less'
const Address: React.FC = () => {
interface AddressPropsType {
onChange: Function
}
const Address: React.FC<AddressPropsType> = (props) => {
const { onChange } = props
const [selectKey, setSelectKey] = useState<number>()
const [expand, setExpand] = useState<boolean>(false)
const [addressFormVisible, setAddressFormVisible] = useState<boolean>(false)
......@@ -34,18 +39,32 @@ const Address: React.FC = () => {
})
}
const initDefaultAddress = (addressList: GetLogisticsReceiverAddressPageResponseDetail[]) => {
let defaultAddrKey
const initDefaultAddress = async (addressList: GetLogisticsReceiverAddressPageResponseDetail[]) => {
let selectItem
for (let item of addressList) {
if (item.isDefault === 1) {
defaultAddrKey = item.id
selectItem = item
}
}
defaultAddrKey && setSelectKey(defaultAddrKey)
if (selectItem) {
setSelectKey(selectItem.id)
let res = await PublicApi.getLogisticsReceiverAddressGet({ id: selectItem.id })
onChange(res.data)
}
}
const handleSelect = (e: any) => {
const handleSelect = async (e: any) => {
setSelectKey(e.target.value)
let selectItem
for (let item of addressList) {
if (item.id === e.target.value) {
selectItem = item
}
}
if (selectItem) {
let res = await PublicApi.getLogisticsReceiverAddressGet({ id: selectItem.id })
onChange(res.data)
}
}
/**
......@@ -55,6 +74,7 @@ const Address: React.FC = () => {
Modal.confirm({
className: styles.mallComfirm,
content: "是否确认删除该收货地址",
centered: true,
onOk: () => {
return new Promise((resolve, reject) => {
PublicApi.postLogisticsReceiverAddressDelete({ id }).then(res => {
......@@ -81,7 +101,6 @@ const Address: React.FC = () => {
fetchAddressList()
}
})
}
return (
......
......@@ -77,4 +77,28 @@
transition: all .2s;
}
}
}
.mallComfirm {
position: relative;
:global {
.ant-modal-confirm-btns {
.ant-btn {
&:hover {
color: var(--mall_main_color);
border-color: var(--mall_main_color);
}
}
.ant-btn-primary {
background-color: var(--mall_main_color);
border-color: var(--mall_main_color);
&:hover {
color: #ffffff;
}
}
}
}
}
\ No newline at end of file
......@@ -94,11 +94,7 @@ const AddAddress: React.FC<AddAddressPropsType> = (props) => {
{ label: <><img src={us} key='5' style={{ width: _width, height: _height }} /> +86</>, value: '5' }
]
let _Options: any = [], TelCodeList: any = []
/**
* @description: formilyjs表单赋值方法 actions.setFieldState(key,state=> {state.value= **})
* @param {type}
* @return:
*/
useEffect(() => {
PublicApi.getManageGetTelCode().then(res => {
......
......@@ -6,9 +6,12 @@ import {
createFormActions,
FormEffectHooks,
FormPath,
createAsyncFormActions,
} from '@formily/antd'
import { Input, Switch, Select, FormMegaLayout, Radio } from '@formily/antd-components'
import styles from './index.less'
import { PublicApi } from '@/services/api'
import { postSettleAccountsInvoiceMessageUpdate } from '@/services/SettlementApi'
//列表带来的参数
export interface ListProps {
......@@ -23,14 +26,17 @@ interface AddAddressPropsType {
onOk?: any;
onCancel?: any;
title?: string;
editItem?: any;
type: 'add' | 'edit'
}
const actions = createFormActions()
const { onFieldValueChange$ } = FormEffectHooks
const actions = createAsyncFormActions()
const AddInvoice: React.FC<AddAddressPropsType> = (props) => {
const { visible = false, title, onOk, onCancel } = props
const { visible = false, title, onOk, onCancel, editItem, type } = props
const [state, setState] = useState({ editable: true })
const [confirmLoading, setConfirmLoading] = useState<boolean>(false)
/**
* @description: Form保存
......@@ -38,7 +44,25 @@ const AddInvoice: React.FC<AddAddressPropsType> = (props) => {
* @return:
*/
const formSubmit = (values) => {
console.log(values)
values.isDefault ? values.isDefault = 1 : values.isDefault = 0
setConfirmLoading(true)
let postLogisticsFn
if (type === 'edit') {
values.id = editItem.id
postLogisticsFn = PublicApi.postSettleAccountsInvoiceMessageUpdate
} else {
postLogisticsFn = PublicApi.postSettleAccountsInvoiceMessageAdd
}
postLogisticsFn(values).then(res => {
if (res.code === 1000) {
onOk()
}
setConfirmLoading(false)
}).catch(() => {
setConfirmLoading(false)
})
}
const handleOk = () => {
......@@ -52,15 +76,16 @@ const AddInvoice: React.FC<AddAddressPropsType> = (props) => {
onOk={handleOk}
width={600}
centered
confirmLoading={confirmLoading}
className={styles.common_add_modal}
onCancel={onCancel}
maskClosable={false}
>
<SchemaForm editable={state.editable}
actions={actions} // 要传递
initialValues={{
Radio2: '1',
fapiao: '1'
initialValues={type === 'edit' ? editItem : {
type: 1,
kind: 1
}}
components={{
Input, Select, TextArea: Input.TextArea, Switch,
......@@ -73,21 +98,21 @@ const AddInvoice: React.FC<AddAddressPropsType> = (props) => {
<Field
required
title="开具类型"
name="Radio2"
name="type"
x-component="RadioGroup"
enum={[
{ label: '企业(默认)', value: '1' },
{ label: '个人', value: '2' },
{ label: '企业', value: 1 },
{ label: '个人', value: 2 },
]}
/>
<Field
required
title="发票种类"
name="fapiao"
name="kind"
x-component="RadioGroup"
enum={[
{ label: '增值税普通发票(默认)', value: '1' },
{ label: '增值税专用发票', value: '2' },
{ label: '增值税普通发票', value: 1 },
{ label: '增值税专用发票', value: 2 },
]}
/>
<Field
......@@ -96,7 +121,7 @@ const AddInvoice: React.FC<AddAddressPropsType> = (props) => {
message: '请输入发票抬头',
}}
title="发票抬头"
name="receiverName"
name="invoiceTitle"
maxLength={40}
x-component="Input"
x-component-props={{
......@@ -109,7 +134,7 @@ const AddInvoice: React.FC<AddAddressPropsType> = (props) => {
message: '请输入纳税号',
}}
title="纳税号"
name="receiverName2"
name="taxNo"
maxLength={40}
x-component="Input"
x-component-props={{
......@@ -118,25 +143,25 @@ const AddInvoice: React.FC<AddAddressPropsType> = (props) => {
/>
<Field
title="开户行"
name="receiverName3"
name="bankOfDeposit"
maxLength={40}
x-component="Input"
/>
<Field
title="账号"
name="receiverName4"
name="account"
maxLength={40}
x-component="Input"
/>
<Field
title="地址"
name="receiverName5"
name="addres"
maxLength={40}
x-component="Input"
/>
<Field
title="电话号码"
name="receiverName6"
name="tel"
maxLength={40}
x-component="Input"
/>
......
......@@ -3,8 +3,14 @@ import { Tooltip, Checkbox } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import styles from './index.less'
const Contract: React.FC = () => {
interface ContractPropsType {
state: boolean;
onChange: Function;
}
const Contract: React.FC<ContractPropsType> = (props) => {
const { state, onChange } = props
return (
<div className={styles.contract}>
<div className={styles.common_title}>
......@@ -14,7 +20,7 @@ const Contract: React.FC = () => {
</Tooltip>
</div>
<div className={styles.checkbox}>
<Checkbox>
<Checkbox checked={state} onChange={(e) => onChange(e.target.checked)}>
<span>我同意签订:</span>
</Checkbox>
<span className={styles.checkbox_contract_text}> 《广州白马皮具交易中心商品购销合同.pdf》</span>
......
......@@ -12,13 +12,13 @@ const Delivery: React.FC = () => {
<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}>
<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> */}
</div>
)
}
......
......@@ -16,7 +16,7 @@
&_item {
flex: 1;
text-align: center;
// text-align: center;
}
}
......@@ -31,19 +31,35 @@
font-weight: 500;
}
.order_list_item_logistics {
padding-left: 40px;
padding-bottom: 15px;
font-size: 12px;
&>label {
color: #999999;
}
&>span {
color: #333333;
margin-right: 12px;
}
}
&_item {
display: flex;
height: 130px;
height: 120px;
align-items: center;
font-size: 12px;
&_item {
display: flex;
padding-left: 25px;
flex: 1;
// padding-left: 25px;
&.goods_info {
padding-left: 40px;
width: 360px;
text-align: left;
}
&_imgbox {
......@@ -58,24 +74,11 @@
}
}
&.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;
......@@ -92,6 +95,18 @@
}
}
.goods_info {
padding-left: 40px;
width: 390px;
text-align: center;
flex: none;
}
.count {
width: 350px;
flex: none;
}
.settlement_box {
height: 50px;
margin-top: 30px;
......@@ -127,8 +142,10 @@
text-align: center;
color: #FFF;
height: 50px;
line-height: 50px;
outline: none;
font-size: 16px;
border-color: #D32F2F;
border-radius: 0;
background-color: #D32F2F;
cursor: pointer;
......
This diff is collapsed.
import React, { useState } from 'react'
import { Checkbox, Radio } from 'antd'
import React, { useState, useEffect } from 'react'
import { Checkbox, Radio, Modal } from 'antd'
import AddInvoice from '../components/addInvoice'
import { PublicApi } from '@/services/api'
import { getAuth } from '@/utils/auth';
import { GetSettleAccountsInvoiceMessageListResponse } from '@/services/SettlementApi'
import cx from 'classnames'
import styles from './index.less'
const Invoice: React.FC = () => {
interface InvoicePropsType {
state: boolean;
onChange: Function;
onSelect: Function;
}
const Invoice: React.FC<InvoicePropsType> = (props) => {
const { state, onChange, onSelect } = props
const [selectKey, setSelectKey] = useState<number>()
const [invoiceFormVisible, setInvoiceFormVisible] = useState<boolean>(false)
const [invoiceList, setInvoiceList] = useState<GetSettleAccountsInvoiceMessageListResponse>([])
const [editItem, setEditItem] = useState<any>()
const [type, setType] = useState<'add' | 'edit'>('add')
useEffect(() => {
fetchInvoiceList(true)
}, [])
const fetchInvoiceList = (init = false) => {
const { memberId } = getAuth() || {}
//@ts-ignore
PublicApi.getSettleAccountsInvoiceMessageList().then(res => {
if (res.code === 1000) {
setInvoiceList(res.data)
if (init) {
initDefaultInvoice(res.data)
}
}
})
}
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 initDefaultInvoice = (data: GetSettleAccountsInvoiceMessageListResponse) => {
let selectItem
for (let item of data) {
if (item.isDefault === 1) {
selectItem = item
}
}
]
if (selectItem) {
setSelectKey(selectItem.id)
onSelect(selectItem)
}
}
const handleSelect = (e: any) => {
setSelectKey(e.target.value)
let selectItem
for (let item of invoiceList) {
if (item.id === e.target.value) {
selectItem = item
}
}
if (selectItem) {
onSelect(selectItem)
}
}
const handleAddSuccess = () => {
fetchInvoiceList()
setInvoiceFormVisible(false)
setEditItem(null)
}
/**
* 删除发票
*/
const handleDelteInvoice = (id: number) => {
Modal.confirm({
className: styles.mallComfirm,
content: "是否确认删除该发票信息",
centered: true,
onOk: () => {
return new Promise((resolve, reject) => {
PublicApi.postSettleAccountsInvoiceMessageDelete({ id }).then(res => {
if (res.code === 1000) {
resolve()
fetchInvoiceList()
}
}).catch(() => {
reject()
})
})
}
})
}
/**
* 设置为默认
* @param item
*/
const handleSetDefault = (item) => {
let param = item
param.isDefault = 1
//@ts-ignore
PublicApi.postSettleAccountsInvoiceMessageUpdate(param).then(res => {
if (res.code === 1000) {
fetchInvoiceList()
}
})
}
const handleStateChange = (e) => {
onChange(e.target.checked)
}
return (
<div className={styles.invoice}>
<div className={styles.common_title}>
<span>发票信息</span>
<div className={styles.common_title_btn} onClick={() => setInvoiceFormVisible(true)}>新增发票信息</div>
<div className={styles.common_title_btn} onClick={() => {
setInvoiceFormVisible(true)
setType('add')
setEditItem(null)
}}>新增发票信息</div>
</div>
<div className={styles.checkbox}>
<Checkbox>需要发票</Checkbox>
<Checkbox checked={state} onChange={handleStateChange}>需要发票</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>
{
state && (
<Radio.Group className={styles.raido_group} value={selectKey} onChange={handleSelect}>
<div className={styles.invoice_list}>
{
invoiceList.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.kind !== 1 ? styles.special : '')}>{item.kind === 1 ? '增值税普通发票' : '增值税专用发票'}</div>
<div className={styles.invoice_list_item_content_name}>
<span>{item.invoiceTitle}</span>
<span>{item.type === 1 ? '(企业)' : '(个人)'}</span>
{
item.isDefault === 1 ? <div className={styles.default}>默认</div> :
<div className={styles.set_default} onClick={() => handleSetDefault(item)}>设为默认</div>
}
</div>
</div>
{
item.isDefault === 1 ? <div className={styles.default}>默认</div> :
<div className={styles.set_default}>设为默认</div>
selectKey === item.id && (
<div className={styles.invoice_list_item_btn_group}>
<div className={styles.invoice_list_item_btn} onClick={() => {
setEditItem(item)
setType('edit')
setInvoiceFormVisible(true)
}}>编辑</div>
<div className={styles.invoice_list_item_btn} onClick={() => handleDelteInvoice(item.id)}>删除</div>
</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>
))
}
</Radio>
))
}
</div>
</Radio.Group>
</div>
</Radio.Group>
)
}
<AddInvoice
title="新增发票信息"
title={type === 'add' ? "新增发票信息" : "编辑发票信息"}
type={type}
editItem={editItem}
visible={invoiceFormVisible}
onOk={() => handleAddSuccess()}
onCancel={() => setInvoiceFormVisible(false)}
/>
</div>
......
......@@ -6,7 +6,14 @@ 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 = () => {
interface PayWayProps {
payWayList: any;
onChange: Function;
selectItem: any;
}
const PayWay: React.FC<PayWayProps> = (props) => {
const { payWayList = [], onChange, selectItem = {} } = props
const [expand, setExpand] = useState<boolean>(false)
const PayWay = [
......@@ -56,23 +63,27 @@ const PayWay: React.FC = () => {
},
]
const handleSelectWay = (item) => {
onChange(item)
}
return (
<div className={styles.payway}>
<div className={styles.common_title}>
<span>支付方式</span>
</div>
{
PayWay.map((item, index) => (!expand ? index < 1 : true) && (
payWayList.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>
<div className={styles.payway_line_label}>{item.payVal}</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>
item.payList.map((childItem, childIndex) => (
<li className={cx(styles.payway_pay_list_item, childItem.id === selectItem.id ? styles.active : '')} key={`payway_pay_list_item_${childIndex}`} onClick={() => handleSelectWay(childItem)}>
{childItem.way === '支付宝' && <img src={alipayIcon} />}
{childItem.way === '微信' && <img src={wechatIcon} />}
{childItem.way === '银联' && <img src={bankIcon} />}
<span>{childItem.way}</span>
</li>
))
}
......
......@@ -31,7 +31,6 @@ const AddressModal:React.FC<AddressModalProps> = (props) => {
if (selfInitValue) {
selfInitValue.isDefault = !!selfInitValue.isDefault
}
const resetForm = () => {
addressSchemaAction.reset({validate: false})
}
......@@ -63,6 +62,7 @@ const AddressModal:React.FC<AddressModalProps> = (props) => {
}
const fn = mode === 'edit' ? PublicApi.postLogisticsReceiverAddressUpdate : PublicApi.postLogisticsReceiverAddressAdd
await fn(params)
resetForm()
props.currentRef.current.setVisible(false)
props.reloadAddress && props.reloadAddress()
}
......
.noMarbottom {
margin-bottom: 0 !important;
}
\ No newline at end of file
import React, { useRef, useEffect, useMemo } from 'react'
import ModalForm from '@/components/ModalForm'
import { createFormActions } from '@formily/antd'
import addressSchema from './schema'
import './index.less'
import { PublicApi } from '@/services/api'
export interface InvoiceModalProps {
mode: 'add' | 'edit' | 'default',
currentRef?: any,
formInitValue?: any,
reload?()
}
const schemaActions = createFormActions()
const InvoiceModal:React.FC<InvoiceModalProps> = (props) => {
const { mode, formInitValue } = props
const selfInitValue = useMemo(() => mode === 'add' ? null : formInitValue, [mode, formInitValue])
// 由于默认是number类型, 但switch组件只接收boolean
if (selfInitValue) {
selfInitValue.isDefault = !!selfInitValue.isDefault
}
const resetForm = () => {
schemaActions.reset({validate: false})
}
const handleConfirm = () => {
schemaActions.submit()
}
const handleSubmit = async (value) => {
const params = {
...value,
isDefault: value.isDefault ? 1 : 0
}
const fn = mode === 'edit' ? PublicApi.postSettleAccountsInvoiceMessageUpdate : PublicApi.postSettleAccountsInvoiceMessageAdd
await fn(params)
resetForm()
props.currentRef.current.setVisible(false)
props.reload && props.reload()
}
return (
<ModalForm
modalTitle={mode === 'add' ? '新建发票信息' : '编辑发票信息'}
confirm={handleConfirm}
cancel={resetForm}
value={selfInitValue}
effects={($, { setFieldState }) => {
$('onFormMount').subscribe(() => {
})
}}
currentRef={props.currentRef}
actions={schemaActions}
schema={addressSchema}
onSubmit={handleSubmit}
/>
)
}
InvoiceModal.defaultProps = {}
export default InvoiceModal
\ No newline at end of file
import { ISchema } from "@formily/antd";
import { PATTERN_MAPS } from '@/constants/regExp';
import { PublicApi } from '@/services/api';
const addressSchema: ISchema = {
type: 'object',
properties: {
NO_SUBMIT_LAYOUT_ADDRESS: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
labelAlign: 'left',
labelCol: 4,
wrapperCol: 20,
full: true
},
properties: {
type: {
type: 'radio',
title: '开具类型',
enum: [
{
label: '企业(默认)',
value: 1
},
{
label: '个人',
value: 2
}
],
default: 1,
"x-rules": [
{
required: true,
message: '请选择开具类型'
}
]
},
kind: {
type: 'radio',
title: '发票种类',
enum: [
{
label: '增值税普通发票(默认)',
value: 1
},
{
label: '增值税专用发票',
value: 2
}
],
default: 1,
"x-rules": [
{
required: true,
message: '请选择开具类型'
}
]
},
invoiceTitle: {
type: 'string',
title: '发票抬头',
"x-rules": [
{
limitByte: true,
maxByte: 40
},
{
required: true,
message: '请输入发票抬头'
}
]
},
taxNo: {
type: 'string',
title: '纳税号',
"x-rules": [
{
limitByte: true,
maxByte: 20
},
{
required: true,
message: '请输入纳税号'
}
]
},
bankOfDeposit: {
type: 'string',
title: '开户行',
"x-rules": [
{
limitByte: true,
maxByte: 40
}
]
},
account: {
type: 'string',
title: '账号',
maxLength: 20
},
address: {
type: 'string',
title: '地址',
"x-rules": [
{
limitByte: true,
maxByte: 80
}
]
},
tel: {
type: 'string',
title: '电话号码',
"x-rules": [
{
pattern: PATTERN_MAPS.phone,
message: '请输入正确的电话号码'
}
]
},
isDefault: {
title: '是否默认',
type: 'boolean',
"x-mega-props": {
wrapperWidth: 36
}
}
}
}
}
}
export default addressSchema
\ No newline at end of file
......@@ -14,7 +14,7 @@ export interface MemberModalTableProps extends ModalTableProps {
const MemberModalTable:React.FC<MemberModalTableProps> = (props) => {
const { type = 'radio', schemaAction, confirmModal, currentRef, ...restProps } = props
const { visible, setVisible, rowSelection, rowSelectionCtl } = useModalTable({type})
const { visible, setVisible, rowSelection, rowSelectionCtl } = useModalTable({type, customKey: 'memberId'})
useEffect(() => {
if (currentRef) {
......@@ -27,7 +27,10 @@ const MemberModalTable:React.FC<MemberModalTableProps> = (props) => {
}, [])
const handleConfirm = () => {
schemaAction.setFieldValue('supplyMembersName', rowSelectionCtl.selectRow)
const rowItem = rowSelectionCtl.selectRow[0]
if (rowItem) {
schemaAction.setFieldValue('supplyMembersName', rowItem.name)
}
confirmModal && confirmModal()
setVisible(false)
}
......@@ -42,7 +45,7 @@ const MemberModalTable:React.FC<MemberModalTableProps> = (props) => {
rowSelection={rowSelection}
modalType='memberByDefault'
tableProps={{
rowKey: 'id'
rowKey: 'memberId'
}}
{...restProps}
/>
......
import React, { useState, useRef, useContext, useEffect } from 'react'
import { Form, Input, Select } from 'antd';
export interface PayInfoCellProps {
title: React.ReactNode;
editable: boolean;
children: React.ReactNode;
dataIndex: string;
record: any;
handleSave: (record: any) => void;
forceEdit: boolean,
formItem: string,
formItemProps: any
}
const EditableContext = React.createContext<any>({});
export const EditableRow: React.FC<any> = ({ index, ...props }) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
export const PayInfoCell:React.FC<PayInfoCellProps> = ({
title,
editable,
children,
dataIndex,
record,
handleSave,
forceEdit,
formItem,
formItemProps={},
...restProps
}) => {
const [editing, setEditing] = useState(false);
const formItemRef = useRef<any>();
const form = useContext(EditableContext);
useEffect(() => {
if (editing) {
formItemRef.current.focus();
}
}, [editing]);
const toggleEdit = () => {
setEditing(!editing);
form.setFieldsValue({ [dataIndex]: record[dataIndex] });
};
const save = async e => {
try {
const values = await form.validateFields();
toggleEdit();
handleSave({ ...record, ...values });
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
};
const chooseFormItem = (type) => {
switch(type) {
case 'input': {
return <Input ref={formItemRef} onPressEnter={save} onBlur={save} {...formItemProps}/>
}
case 'select': {
return <Select ref={formItemRef} onChange={save} {...formItemProps}/>
}
}
}
let childNode = children;
if (editable) {
childNode = (forceEdit || editing) ? (
<Form.Item
style={{ margin: 0 }}
name={dataIndex}
rules={[
{
required: true,
message: `${title}必须填写`,
},
]}
>
{chooseFormItem(formItem)}
</Form.Item>
) : (
<div className="editable-cell-value-wrap" style={{ paddingRight: 24 }} onClick={toggleEdit}>
{children}
</div>
);
}
return <td {...restProps}>{childNode}</td>;
}
PayInfoCell.defaultProps = {}
export default PayInfoCell
\ 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: 100%;
align-items: center;
height: 72px;
background-color: #FAFAFA;
margin: 10px;
padding-left: 16px;
}
.ant-radio-wrapper.ant-radio-wrapper-checked {
border: 1px solid @main-color;
&::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: 12px solid @main-color;
border-left: 12px solid transparent;
bottom: 0;
right: 0;
z-index: 5;
}
}
}
}
}
}
\ No newline at end of file
import React, { useState, useRef, useEffect } from 'react'
import styled from 'styled-components'
import { ISchemaFormProps, ISchemaFieldProps, ISchemaFieldComponentProps, createFormActions, useFieldState } from '@formily/antd'
import { Button, Space, Row, Col, Tag, Radio } from 'antd'
import { PlusOutlined, DeleteColumnOutlined, EditOutlined, DeleteOutlined, CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons'
import cx from 'classnames'
import { fetchOrderApi } from '../../readyAddOrder/apis'
import { PublicApi } from '@/services/api'
import InvoiceModal from '../invoiceModal'
import styles from './index.less'
const SelectStyles = styled((props) => <div className='select-list' {...props}></div>)`
.select_style_border {
border: 1px solid #EBECF0;
margin-top: 20px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 14px;
cursor: pointer;
line-height: 28px;
position:relative;
}
.select_style_border.active {
border: 1px solid #00B382;
}
.select_style_border.active::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: 12px solid #00B37A;
border-left: 12px solid transparent;
bottom: 0;
right: 0;
z-index: 5;
}
`
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 transformDefaultData = (data: any[]) => {
if (data.length === 0) return data
const hasDefault = data.some(v => v.isDefault === 1)
return hasDefault ? data : data.map((v,i) => {
if (i === 0) {
v.isDefault = 1
}
return v
})
}
const TheInvoiceList = (props: ISchemaFieldComponentProps) => {
const [formInitValue, setFormInitValue] = useState<any>(null)
const [mode, setMode] = useState<'add' | 'edit' | 'default'>('default')
const [state, setFieldState] = useFieldState({
dataSource: [],
showMore: false
})
const modalRef = useRef<any>({})
const { dataSource, showMore } = state
const { value, mutators, form } = props
const transformData = transformDefaultData(dataSource)
const showDataSource = showMore ? [...transformData].splice(0, 3) : transformData
const handleAdd = () => {
setMode('add')
modalRef.current.setVisible(true)
}
const handleCheck = (id) => {
// 选中的id
mutators.change(id)
}
const reload = () => {
fetchOrderApi.getInvoicesList().then(data => {
setFieldState({
dataSource: data,
showMore
})
})
}
const toogleMore = () => {
setFieldState({
dataSource,
showMore: !showMore
})
}
const handleDelete = async (id, e) => {
e.stopPropagation()
try {
const result = await PublicApi.postSettleAccountsInvoiceMessageDelete({id})
reload()
} catch (error) {
}
}
const handleEdit = async (item, e) => {
e.stopPropagation()
const { data } = await PublicApi.getSettleAccountsInvoiceMessageDetails({id: item.id})
setFormInitValue({...data, isDefault: item.isDefault})
setMode('edit')
modalRef.current.setVisible(true)
}
const handleSetDefault = async (item, e) => {
e.stopPropagation()
const { data } = await PublicApi.postSettleAccountsInvoiceMessageUpdate({...item, isDefault: item.isDefault ? 0 : 1})
reload()
}
return (
<div style={{width: '100%'}} className={styles.invoice}>
<Button block onClick={handleAdd} icon={<PlusOutlined/>}>新增发票</Button>
<Radio.Group className={styles.raido_group} value={value} onChange={e => handleCheck(e)}>
<div className={styles.invoice_list}>
{
showDataSource.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.kind !== 1 ? styles.special : '')}>{item.kind === 1 ? '增值税普通发票' : '增值税专用发票'}</div>
<div className={styles.invoice_list_item_content_name}>
<span>{item.invoiceTitle}</span>
<span>({item.type === 1 ? '企业' : '个人'})</span>
{
item.isDefault === 1 ? <div className={styles.default}>默认</div> :
<div className={styles.set_default} onClick={e => handleSetDefault(item, e)}>设为默认</div>
}
</div>
</div>
{
value === item.id && (
<div className={styles.invoice_list_item_btn_group}>
<div className={styles.invoice_list_item_btn} onClick={(e) => handleEdit(item, e)}>编辑</div>
<div className={styles.invoice_list_item_btn} onClick={(e) => handleDelete(item.id, e)}>删除</div>
</div>
)
}
</div>
</Radio>
))
}
</div>
</Radio.Group>
{ transformData.length > 3 &&
<div onClick={toogleMore} style={{textAlign: 'center', cursor: 'pointer'}}>
显示更多{showMore ? <CaretDownOutlined /> : <CaretUpOutlined/>}
</div>
}
<InvoiceModal mode={mode} formInitValue={formInitValue} currentRef={modalRef} reload={reload}/>
</div>
)
}
TheInvoiceList.defaultProps = {}
TheInvoiceList.isFieldComponent = true;
export default TheInvoiceList
\ No newline at end of file
......@@ -3,7 +3,7 @@ import { PublicApi } from '@/services/api'
export const fetchOrderApi = {
// 弹窗获取商品列表
async getProductList(params) {
const { data } = await PublicApi.getProductCommodityGetCommodityDetailList(params)
const { data } = await PublicApi.getProductCommodityGetCommodityDetailList({...params, shopType: 1})
return data
},
......@@ -40,5 +40,15 @@ export const fetchOrderApi = {
async getProductAddressAll() {
const { data } = await PublicApi.getLogisticsSelectListReceiverAddress()
return data
},
// 获取发票列表
async getInvoicesList() {
const { data } = await PublicApi.getSettleAccountsInvoiceMessageList()
return data
},
// 获取支付信息列表
async getPayInfoList(params) {
const { data } = await PublicApi.getOrderInitializationPaymentInformation(params)
return data
}
}
\ No newline at end of file
......@@ -86,12 +86,32 @@ export const orderTypeLabel = ['',
'渠道积分兑换'
]
// 支付方式
export const payTypeLabel = [
{
label: '线上支付',
value: 1
},
{
label: '线下支付',
value: 2
},
{
label: '授信支付',
value: 3
},
{
label: '货到付款',
value: 4
},
]
export const memberColumns: any[] = [
{
title: '会员ID',
dataIndex: 'id',
dataIndex: 'memberId',
align: 'center',
key: 'id',
key: 'memberId',
},
{
title: '会员名称',
......@@ -100,10 +120,22 @@ export const memberColumns: any[] = [
key: 'name',
},
{
title: '公司地址',
dataIndex: 'address',
title: '公司类型',
dataIndex: 'memberTypeName',
align: 'center',
key: 'address',
key: 'memberTypeName',
},
{
title: '公司角色',
dataIndex: 'roleName',
align: 'center',
key: 'roleName',
},
{
title: '公司等级',
dataIndex: 'levelTag',
align: 'center',
key: 'levelTag',
},
]
......@@ -163,8 +195,14 @@ export const paymentInformationColumns: any[] = [
{
title: '支付比例',
dataIndex: 'payRatio',
align: 'center',
key: 'payRatio'
key: 'payRatio',
editable: true,
forceEdit: true,
formItem: 'input',
formItemProps: {
addonAfter: '%'
},
width: 200
},
{
title: '支付金额',
......@@ -175,13 +213,22 @@ export const paymentInformationColumns: any[] = [
{
title: '支付方式',
dataIndex: 'payWay',
align: 'center',
key: 'payWay'
key: 'payWay',
formItem: 'select',
editable: true,
forceEdit: true,
formItemProps: {
options: payTypeLabel
},
width: 200
},
{
title: '支付渠道',
dataIndex: 'channel',
align: 'center',
key: 'channel'
key: 'channel',
formItem: 'select',
editable: true,
forceEdit: true,
width: 200
},
]
\ No newline at end of file
......@@ -7,22 +7,18 @@ import { Button, Card } from 'antd'
import { createFormActions } from '@formily/antd'
import { SaveOutlined, LinkOutlined, PlusOutlined } from '@ant-design/icons'
import NiceForm from '@/components/NiceForm'
import { orderDetailSchema } from './schema'
import { useDetailOrder } from './model/useDetailOrder'
import ModalTable from '@/components/ModalTable'
import { useModelTypeChange, useEditHideField, useOrderFormInitEffect } from './effects'
import { OrderModalType, orderTypeLabel, memberColumns, orderCombination, paymentInformationColumns } from './constant'
import { useLinkageUtils } from '@/utils/formEffectUtils'
import { useModalTable } from './model/useModalTable'
import { memberSchema } from './schema/modal'
import { fetchOrderApi } from './apis'
import { orderDetailSchema, orderAddSchema } from './schema'
import { useModelTypeChange, useEditHideField, useOrderFormInitEffect, useProductTableChangeForPay } from './effects'
import { OrderModalType, orderTypeLabel, orderCombination, paymentInformationColumns } from './constant'
import ProductModalTable, { productColumns } from '../components/productModalTable'
import MemberModalTable from '../components/memberModalTable'
import InquiryModalTable from '../components/inquiryModalTable'
import DemandModalTable from '../components/demandModalTable'
import { useLinkComponentProps } from '@/components/NiceForm/linkages/linkComponentProps'
import CirculationRecord from '../components/circulationRecord'
import SelectAddress from '../components/selectAddress'
import TheInvoiceList from '../components/theInvoiceList'
import moment from 'moment'
import { usePaymentInfo } from './model/usePaymentInfo'
export interface PurchaseOrderDetailProps {}
......@@ -33,14 +29,20 @@ const PurchaseOrderDetail:React.FC<PurchaseOrderDetailProps> = (props) => {
const memberRef = useRef<any>({})
const inquiryRef = useRef<any>({})
const demandRef = useRef<any>({})
const [paymentColumns, paymentComponents, paymentSave] = usePaymentInfo(addSchemaAction)
const {setShowProBtn, showProBtn } = useDetailOrder({
addSchemaAction
})
// 页面进入时, 当前所处的下单模式
const { pageStatus } = usePageStatus()
const handleSubmit = (value) => {
const params = {
...value,
deliveryTime: moment(value.deliveryTime).valueOf()
}
console.log(params)
}
// 唤起报价单弹窗
const handleOrderNo = () => {
// @todo 未完整实现功能, 缺少商品接口
......@@ -67,6 +69,25 @@ const PurchaseOrderDetail:React.FC<PurchaseOrderDetailProps> = (props) => {
// 新增收货地址
const addNewAddress = <Button block icon={<PlusOutlined/>}>新增收货地址</Button>
const paymentEditColumns = paymentColumns.map(col => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
formItem: col.formItem,
formItemProps: col.formItemProps,
forceEdit: col.forceEdit,
handleSave: paymentSave,
}),
};
})
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
......@@ -82,10 +103,11 @@ const PurchaseOrderDetail:React.FC<PurchaseOrderDetailProps> = (props) => {
<Card className=''>
<NiceForm
actions={addSchemaAction}
schema={orderDetailSchema}
className='useConnectBtnWrapper'
schema={pageStatus === PageStatus.ADD ? orderAddSchema : orderDetailSchema}
onSubmit={handleSubmit}
components={{
SelectAddress
SelectAddress,
TheInvoiceList
}}
effects={($, ctx) => {
// useLinkComponentProps()
......@@ -119,18 +141,24 @@ const PurchaseOrderDetail:React.FC<PurchaseOrderDetailProps> = (props) => {
// 选择某种类型时, 需显示对应的订单类型
ctx.setFieldValue('type', orderTypeLabel[value - 4]) // -4 获得对应的数组下标, 由于id是固定的
// 切换过下单模式, 需重置受下单模式影响的字段
ctx.reset({
validate: false,
selector: '*(quotationNo,supplyMembersName,orderProductRequests)'
})
productRef.current.rowSelectionCtl.setSelectRow([])
productRef.current.rowSelectionCtl.setSelectedRowKeys([])
})
useEditHideField()
// 商品信息的改动 驱动支付信息变化
useProductTableChangeForPay(ctx)
}}
expressionScope={{
orderNoPrice,
orderMember,
paymentInformationColumns,
paymentColumns: paymentEditColumns,
paymentComponents,
productColumns,
productAddButton,
couponAddButton,
......
......@@ -29,6 +29,24 @@ export const useEditHideField = () => {
})
}
export const useProductTableChangeForPay = (ctx: ISchemaFormActions | ISchemaFormAsyncActions) => {
FormEffectHooks.onFieldValueChange$('orderProductRequests').subscribe(state => {
const payInfoData = ctx.getFieldValue('paymentInformationResponses')
// 已经存在数据 无需请求
if (payInfoData && payInfoData.length > 0) {
} else if (state.value && state.value.length > 0){
// 请求一次并复制给支付信息
const productItem = state.value[0]
fetchOrderApi.getPayInfoList({
productId: productItem.id
}).then(data => {
ctx.setFieldValue('paymentInformationResponses', data)
})
}
})
}
// 表单初始化时,对应操作
export const useOrderFormInitEffect = (ctx: ISchemaFormActions | ISchemaFormAsyncActions) => {
const { orderModel = 0 } = history.location.query
......@@ -48,9 +66,16 @@ export const useOrderFormInitEffect = (ctx: ISchemaFormActions | ISchemaFormAsyn
// 写入收货地址数据
useProductAddress(ctx)
})
FormEffectHooks.onFieldValueChange$('needTheInvoice').subscribe(state => {
if (state.value) {
useInvoiceList(ctx)
}
})
}
export const useProductAddress = (ctx: ISchemaFormActions | ISchemaFormAsyncActions) => {
fetchOrderApi.getProductAddressAll().then(data => {
ctx.setFieldState('deliveryAddresId', state => {
if (data.length > 0 && !state.value) {
......@@ -62,3 +87,17 @@ export const useProductAddress = (ctx: ISchemaFormActions | ISchemaFormAsyncActi
})
})
}
// 获取发票信息
export const useInvoiceList = (ctx: ISchemaFormActions | ISchemaFormAsyncActions) => {
fetchOrderApi.getInvoicesList().then(data => {
ctx.setFieldState('theInvoiceId', state => {
if (data.length > 0 && !state.value) {
// 初始化时存在数据, 默认帮用户选中第一个
state.value = data[0].id
}
state.dataSource = data
state.showMore = data.length > 3
})
})
}
import { paymentInformationColumns } from '../constant'
import { PayInfoCell, EditableRow } from '../../components/payInfoTableCell'
import { ISchemaFormActions } from '@formily/antd'
export const usePaymentInfo = (ctx: ISchemaFormActions): any => {
const columns = paymentInformationColumns
const components = {
body: {
row: EditableRow,
cell: PayInfoCell
},
}
const handleSave = row => {
const newData = [...ctx.getFieldValue('paymentInformationResponses')];
const index = newData.findIndex(item => row.key === item.key);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
ctx.setFieldValue('paymentInformationResponses', newData)
};
return [
columns,
components,
handleSave
]
}
\ No newline at end of file
......@@ -64,7 +64,8 @@ const basicInfo: ISchema = {
type: 'object',
"x-component": 'tabpane',
"x-component-props": {
tab: '基本信息'
tab: '基本信息',
className: 'useConnectBtnWrapper'
},
properties: {
NO_SUBMIT_LAYOUT: {
......@@ -213,18 +214,18 @@ const orderProduct: ISchema = {
"x-component-props": {
rowKey: 'id',
columns: "{{productColumns}}",
prefix: "{{productAddButton}}",
suffix: "{{couponAddButton}}"
// @todo 第一版本暂不做优惠券
// suffix: "{{couponAddButton}}"
}
}
}
}
// 支付信息
const payInfo = {
const payInfo: ISchema = {
type: 'object',
"x-component": 'tabpane',
"x-component-props": {
tab: '支付信息'
tab: '支付信息',
},
properties: {
paymentInformationResponses: {
......@@ -232,8 +233,16 @@ const payInfo = {
"x-component": 'MultTable',
"x-component-props": {
rowKey: 'id',
columns: "{{paymentInformationColumns}}",
}
columns: "{{paymentColumns}}",
components: "{{paymentComponents}}"
},
default: [
{
payCount: 1,
id: 1,
payRatio: 123
}
]
}
}
}
......@@ -271,38 +280,6 @@ const submitInfo: ISchema = {
}
}
},
// deliveryType: {
// type: 'string',
// enum: DELIVERY_TYPE_ENUM,
// title: '提货方式',
// required: true,
// "x-linkages": [
// {
// type: 'value:visible',
// target: 'selfAddress',
// condition: "{{$value === 2}}"
// },
// {
// type: 'value:visible',
// target: 'money',
// condition: "{{$value === 1}}"
// }
// ]
// },
// selfAddress: {
// type: 'string',
// "x-component": 'text',
// title: '自提地址',
// default: 'xxx',
// visible: false
// },
// money: {
// type: 'string',
// "x-component": 'text',
// title: '运费',
// default: 10,
// visible: false
// }
}
},
deliveryAddresId: {
......@@ -346,6 +323,27 @@ const ortherInfo: ISchema = {
wrapperCol: 10
},
properties: {
needTheInvoice: {
type: 'number',
"x-component": 'CheckboxSingle',
"x-component-props": {
children: '需要发票'
},
title: '发票',
default: 0,
"x-linkages": [
{
type: 'value:visible',
target: 'theInvoiceId',
condition: "{{!!$value}}"
}
]
},
theInvoiceId: {
type: 'number',
title: ' ',
"x-component": "theInvoiceList",
},
pageRequire: {
type: 'string',
"x-component": 'textarea',
......@@ -403,12 +401,30 @@ export const orderDetailSchema: ISchema = {
type: 'object',
"x-component": 'tab',
properties: {
NO_SUBMIT_TABPANE1: basicInfo,
NO_SUBMIT_TABPANE2: orderProduct,
NO_SUBMIT_TABPANE3: payInfo,
NO_SUBMIT_TABPANE4: submitInfo,
NO_SUBMIT_TABPANE5: ortherInfo,
NO_SUBMIT_TABPANE6: transformRecord,
basicInfo,
orderProduct,
payInfo,
submitInfo,
ortherInfo,
transformRecord,
}
}
}
}
// 新增时使用的schema
export const orderAddSchema: ISchema = {
type: 'object',
properties: {
NO_SUBMIT_TABS: {
type: 'object',
"x-component": 'tab',
properties: {
basicInfo,
orderProduct,
payInfo,
submitInfo,
ortherInfo,
}
}
}
......
import React, { useState } from 'react'
import { history } from 'umi'
import { Form, Row, Col, Input, Button } from 'antd'
import { Form, Row, Col, Input, Button, message } from 'antd'
import {
UserOutlined,
LockOutlined,
......@@ -18,6 +18,8 @@ const LoginWrap: React.FC = () => {
PublicApi.postMemberLogin(value).then(res => {
const { data, code } = res
if (code === 1000) {
message.destroy()
message.success("登录成功")
setAuth(data)
setRouters(data.urls)
// 此处需使用href跳转, 否则无法触发app.ts中的路由初始化校验
......
......@@ -13,7 +13,7 @@ import * as SettleApi from './SettleApi'
* 可在这里写入自定义的接口
*/
export const CustomApi = {
}
// 公共的接口,从yapi拉下
......
......@@ -3,6 +3,7 @@ import { Provider } from 'mobx-react'
import UserStore from './user'
import ThemeStore from './theme'
import ProductStroe from './product'
import OrderStore from './order'
import ChannelProudctStore from './channelProduct'
import SiteStore from './site'
import CategoryStore from './category'
......@@ -45,8 +46,9 @@ export const store = {
ChannelProudctStore: new ChannelProudctStore,
SiteStore: new SiteStore,
CategoryStore: new CategoryStore,
FilterStore: new FilterStore,
MemberStore: new MemberStore,
FilterStore: new FilterStore,
MemberStore: new MemberStore,
OrderStore: new OrderStore
}
const MobxProvider: React.FC = (props) => {
......
import { action, computed, observable, runInAction } from 'mobx'
const sessionOrderInfo = sessionStorage.getItem("tempOrderInfo")
class OrderStore {
@observable orderInfo = sessionOrderInfo ? JSON.parse(sessionOrderInfo) : null
@action.bound
public updateOrderInfo = (orderInfo) => {
return new Promise((resolve) => {
this.orderInfo = orderInfo
sessionStorage.setItem("tempOrderInfo", JSON.stringify(this.orderInfo))
resolve()
})
}
@action.bound
public clearOrderInfo = () => {
this.orderInfo = null
sessionStorage.removeItem("tempOrderInfo")
}
}
export default OrderStore
\ No newline at end of file
......@@ -115,8 +115,8 @@ class ApiRequest {
// 登录验证
if (res.code === 1101) {
removeAuth()
history.replace(`/user/login?redirect=${btoa(encodeURIComponent(String(window.location)))}`)
// window.location.href = `/user/login?redirect=${btoa(encodeURIComponent(String(window.location)))}`
// history.replace(`/user/login?redirect=${btoa(encodeURIComponent(String(window.location)))}`)
window.location.replace(`/user/login?redirect=${btoa(encodeURIComponent(String(window.location)))}`)
message.destroy()
message.error(res.message)
return false
......
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