Commit 78056ada authored by GuanHua's avatar GuanHua

merge

parents b5a89cc6 d2ce1e22
......@@ -9,12 +9,17 @@ import React from 'react';
import { Card } from 'antd';
import { CardProps } from 'antd/lib/card';
import styles from './index.less';
import cx from 'classnames'
const MellowCard: React.FC<CardProps> = props => {
const { children, ...rest } = props;
export interface MellowCardProps extends CardProps {
blockClassName?: string
}
const MellowCard: React.FC<MellowCardProps> = props => {
const { children, blockClassName, ...rest } = props;
return (
<div className={styles.mellow}>
<div className={cx(styles.mellow, blockClassName)}>
<Card {...rest}>
{children}
</Card>
......
......@@ -57,7 +57,7 @@ const RowStyleLayout = styled(props => <div {...props} />)`
`
const CardCheckBox = (props) => {
const { dataSource = [] } = props.props['x-component-props']
const { dataSource = [], type = 'checkbox' } = props.props['x-component-props']
const value: number[] = props.value || []
const handleChange = (id) => {
......@@ -69,7 +69,8 @@ const CardCheckBox = (props) => {
const newValue = findItemAndDelete(value, id)
props.mutators.change(newValue)
} else {
props.mutators.change([...value, id])
// 扩展单选模式
type === 'radio' ? props.mutators.change([id]) : props.mutators.change([...value, id])
}
}
......
......@@ -222,12 +222,12 @@ const AddGoods = () => {
<Form.Item
name={['brand', 'id']}
label="品牌"
rules={[
{
required: true,
message: '请填入品牌'
},
]}
// rules={[
// {
// required: true,
// message: '请填入品牌'
// },
// ]}
>
{/* <Input placeholder="最长40个字符、20个汉字" /> */}
<Select
......
......@@ -319,9 +319,7 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
// console.log('生成传输数据', combineAttributeArray, attributeObjArr, attributeValObjArr, tableDataSource)
Array.isArray(combineAttributeArray) ? combineAttributeArray.map((item, index)=>{ // 非数组情况下默认无组合 从table数据中获取 // 当属性减少的时候 这个combine数组还是之前的 /* code1 */
let _tempArr: any = []
console.log(item, '0')
Array.isArray(item) ? item.map((_item, _index) => { /* code2 */
console.log(item, _item, '1')
let _tempObject: any = {};
_tempObject.customerAttribute = {
......@@ -507,8 +505,9 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
[]
)
let result = range.reduce((a, b) => { if(a<b) return b })
// console.log(result, 'result')
// console.log(result, range, 'result')
if(!result) throw new Error('请正确输入阶梯数量范围');
if(range[0]!==minOrderNumber) throw new Error('阶段的起始值必须为最小起订数');
callback()
}
} catch (err) {
......@@ -521,6 +520,7 @@ const PriceAttributeForm: React.FC<Iprops> = (props) => {
setPriceForm.resetFields() // 先清空
setIsBatchSetting(true) // 点击置为true
setSetPriceModal(true)
setLadderPrice(false)
}
/**
......
......@@ -42,10 +42,10 @@ const OrderDetailHeader:React.FC<OrderDetailHeaderProps> = ({headerTitle, extraR
<Row>
{detailList.map(v => {
const { label, render, name, ...colProps } = v
return <Col key={label} {...colProps} className={style.detailCol}>
return detailData[name] ? <Col key={label} {...colProps} className={style.detailCol}>
<span className={style.colLabel}>{label}:</span>
{render ? render(detailData[name], detailData) : <span>{detailData[name]}</span>}
</Col>
</Col> : null
})}
</Row>
</Col>
......
.wrapper {
padding: 24px;
}
\ No newline at end of file
import React from 'react'
import style from './index.less'
export interface OrderDetailWrapperProps {}
const OrderDetailWrapper:React.FC<OrderDetailWrapperProps> = (props) => {
return (
<div className={style.wrapper}>{props.children}</div>
)
}
OrderDetailWrapper.defaultProps = {}
export default OrderDetailWrapper
\ No newline at end of file
......@@ -66,9 +66,9 @@ const SelectAddress = (props: ISchemaFieldComponentProps) => {
setMode('add')
modalRef.current.setVisible(true)
}
const handleCheck = (id) => {
const handleCheck = (item) => {
if (editable) {
mutators.change(id)
mutators.change(item)
}
}
......@@ -111,7 +111,7 @@ const SelectAddress = (props: ISchemaFieldComponentProps) => {
{ editable && <Button block onClick={handleAdd} icon={<PlusOutlined/>}>新建地址</Button> }
<SelectStyles>
{
showDataSource.map(v => <div key={v.id} onClick={() => handleCheck(v.id)} className={cx('select_style_border', value === v.id ? 'active' : '')}>
showDataSource.map(v => <div key={v.id} onClick={() => handleCheck(v)} className={cx('select_style_border', value.id === v.id ? 'active' : '')}>
<div>
<Row style={{color: '#172B4D'}}>
<Col>{v.receiverName}</Col>
......
......@@ -141,7 +141,7 @@ export const useProductAddress = (ctx: ISchemaFormActions | ISchemaFormAsyncActi
ctx.setFieldState('deliveryAddresId', state => {
if (data.length > 0 && !state.value) {
// 初始化时存在数据, 默认帮用户选中第一个(默认地址)
state.value = data[0].id
state.value = data[0]
}
state.dataSource = data
state.showMore = data.length > 3
......
......@@ -24,7 +24,7 @@ import { useProductTable } from './model/useProductTable'
import styled from 'styled-components'
import { useUpdate } from '@umijs/hooks'
import { PublicApi } from '@/services/api'
import { formatTimeString } from '@/utils'
import { formatTimeString, omit } from '@/utils'
import { changeRouterTitleByStatus, findLastIndexFlowState } from '../utils'
import { ReadyAddOrderDetailContext } from '../context'
......@@ -144,7 +144,10 @@ const PurchaseOrderDetail:React.FC<PurchaseOrderDetailProps> = (props) => {
v.memberPrice = parseInt(v.memberPrice)
return v
}),
needTheInvoice: Number(value.needTheInvoice)
needTheInvoice: Number(value.needTheInvoice),
// 冗余交付信息
deliveryAddresId: value.deliveryAddresId.id,
...omit(value.deliveryAddresId, ['id'])
}
fnResult = id ? await PublicApi.postOrderProcurementOrderUpdate({...params, id}) : await PublicApi.postOrderProcurementOrderAdd(params)
break;
......@@ -198,7 +201,7 @@ const PurchaseOrderDetail:React.FC<PurchaseOrderDetailProps> = (props) => {
history.goBack()
}
} catch (error) {
console.log(error)
}
}
......
import React from 'react'
import { Modal } from 'antd'
import NiceForm from '@/components/NiceForm'
import { createFormActions } from '@formily/antd'
export interface OrderElectronModalProps {}
const schemaActions = createFormActions()
//@todo 尚未完成
const OrderElectronModal:React.FC<OrderElectronModalProps> = (props) => {
return (
<Modal>
<NiceForm
actions={schemaActions}
schema={{
type: 'object',
properties: {
NO_SUBMIT: {
type: 'object',
"x-component": "mega-layout",
"x-component-props": {
labelAlign: 'top'
},
properties: {
}
}
}
}}
/>
</Modal>
)
}
OrderElectronModal.defaultProps = {}
export default OrderElectronModal
\ No newline at end of file
.card-list {
font-size: 14px;
line-height: 20px;
margin-top: 24px;
}
.card-list_title {
font-size: 14px;
color: #909399;
}
.fullHeight {
height: 100%;
}
\ No newline at end of file
import React, { useContext, useEffect, useState, useMemo } from 'react'
import { Row, Col, Tag } from 'antd'
import MellowCard from '@/components/MellowCard'
import { OrderDetailContext } from '../../context'
import { formatTimeString } from '@/utils'
import { DELIVERY_TYPE } from '@/constants'
import style from './index.less'
import { PublicApi } from '@/services/api'
export interface OrderMergeInfoProps {}
const payInfo = [
{ title: '交付日期', name: 'deliveryTime', render: (text) => formatTimeString(text) },
{ title: '交付地址', name: 'deliveryAddresId', render: (_, record) =>
<div>
<Row>
<Col>{record.receiverName}</Col>
<Col> / </Col>
<Col>{record.phone}</Col>
{record.isDefault && <Col style={{marginLeft: 6}}><Tag color='default'>默认</Tag></Col>}
</Row>
<div style={{color: '#6B778C'}}>{record.fullAddress}</div>
</div>
},
{ title: '提货方式', name: 'deliveryType', render: (text) => DELIVERY_TYPE[text] },
{ title: '自提地址', name: 'pickUpAddress' },
{ title: '运费', name: 'freight' }
]
const otherInfo = [
{ title: '包装要求', name: 'pageRequire' },
{ title: '其他要求', name: 'restsRequire' },
]
const electronInfo = [
{ title: '电子合同', name: 'none' },
]
const RenderCard = ({infoList, dataSource}) => infoList.map(v => dataSource[v.name] ? <Row key={v.name} className={style['card-list']}>
<Col span={6} className={style['card-list_title']}>{v.title}</Col>
<Col flex={1}>{v.render ? v.render(dataSource[v.name], dataSource) : dataSource[v.name]}</Col>
</Row> : null)
const OrderMergeInfo:React.FC<OrderMergeInfoProps> = (props) => {
const orderDetailCtx = useContext(OrderDetailContext)
const address = useMemo(async () => {
const { data } = await PublicApi.getLogisticsSelectListReceiverAddress()
return data
}, [])
const { data, ctl } = orderDetailCtx
useEffect(() => {
if (data.deliveryAddresId && !data.receiverName) {
asyncSetAddress()
}
}, [data, address])
const asyncSetAddress = async () => {
const res = await address
ctl.setData({
...data,
...(res.find(v => v.id === data.deliveryAddresId) || {})
})
}
return (
<Row style={{marginTop: 24}}>
<Col span={12}>
<MellowCard title='交易信息' blockClassName={style.fullHeight} className={style.fullHeight}>
<RenderCard infoList={payInfo} dataSource={data}/>
</MellowCard>
</Col>
<Col span={6} push={1}>
<MellowCard title='其他信息' blockClassName={style.fullHeight} className={style.fullHeight}>
<RenderCard infoList={otherInfo} dataSource={data}/>
</MellowCard>
</Col>
<Col span={4} push={2}>
<MellowCard title='电子合同' blockClassName={style.fullHeight} className={style.fullHeight}>
<RenderCard infoList={electronInfo} dataSource={data}/>
</MellowCard>
</Col>
</Row>
)
}
OrderMergeInfo.defaultProps = {}
export default OrderMergeInfo
\ No newline at end of file
.fontGray {
font-size: 12px;
color: #909399;
margin-bottom: 10px;
}
.bignumber {
font-size: 24px;
color: #303133;
margin-bottom: 10px;
}
.smallnumber {
font-size: 16px;
color: #303133;
line-height: 24px;
}
\ No newline at end of file
import React, { useContext } from 'react'
import style from './index.less'
import { Tabs, Row, Col } from 'antd'
import { OrderDetailContext } from '../../context'
import MellowCard from '@/components/MellowCard'
import StatusColors from '../../../components/StatusColors'
export interface OrderPayTabsProps {}
const TabPane = Tabs.TabPane
const TabHeader = ({dataSource}) => {
return <Row justify='space-between'>
<Col>
<div className={style.fontGray}>支付比例</div>
<div className={style.bignumber}>30%</div>
<div className={style.smallnumber}>¥48,000.00</div>
</Col>
<Col>
<StatusColors status={5} type='out'/>
</Col>
</Row>
}
// 支付信息
const OrderPayTabs:React.FC<OrderPayTabsProps> = (props) => {
const { data } = useContext(OrderDetailContext)
return (
<MellowCard style={{marginTop: 24}} bordered={false}>
<Tabs defaultActiveKey='1'>
<TabPane tab={<TabHeader dataSource={data}/>} key='1'>
<Row>
<Col className={style.fontGray} span={4}>支付环节: </Col>
<Col>订单确认后支付</Col>
</Row>
<Row>
<Col className={style.fontGray} span={4}>支付方式: </Col>
<Col>订单确认后支付</Col>
</Row>
<Row>
<Col className={style.fontGray} span={4}>支付渠道: </Col>
<Col>订单确认后支付</Col>
</Row>
</TabPane>
</Tabs>
</MellowCard>
)
}
OrderPayTabs.defaultProps = {}
export default OrderPayTabs
\ No newline at end of file
.cancel {
color: #909399;
font-size: 12px;
cursor: pointer;
margin: 0 4px;
}
.confirm {
color: #00B37A;
font-size: 12px;
cursor: pointer;
}
\ No newline at end of file
import React, { useContext, useState, useRef, useEffect } from 'react'
import { StandardTable } from 'god'
import { Card, Table, Form, Input, Row, Col, Button, Modal } from 'antd'
import { OrderDetailContext } from '../../context'
import ProductTableCell, { ProductEditableRow } from '../productTableCell'
import { EditOutlined, SettingOutlined } from '@ant-design/icons'
import style from './index.less'
import { PublicApi } from '@/services/api'
import styled from 'styled-components'
import ModalForm from '@/components/ModalForm'
import { createFormActions } from '@formily/antd'
import MellowCard from '@/components/MellowCard'
export interface OrderProductTableProps {}
// 订单商品cell切换
const EditableContext = React.createContext<any>({});
interface Item {
key: string;
name: string;
age: string;
address: string;
}
interface EditableRowProps {
index: number;
}
const RowStyle = styled(props => <Row style={{marginTop: 12}} justify='end' {...props}>
{props.children}
</Row>)`
.ant-col {
text-align: center
}
.ant-col div {
margin-bottom: 12px;
}
`
const modalPriceActions = createFormActions()
// 总计金额联动框
export const MoneyTotalBox = ({ dataSource }) => {
const { orderProductRequests = [], receiverAddressId } = dataSource || {}
const sum = orderProductRequests.reduce((prev, next) => prev + parseInt((next.price || 0)), 0)
const modelRef = useRef<any>({})
const [freePrice, setFreePrice] = useState<number>(0)
const handleSetting = () => {
modelRef.current.setVisible(true)
}
const handleConfirm = () => {
setFreePrice(parseInt(modalPriceActions.getFieldValue('freePrice') || 0))
modelRef.current.setVisible(false)
}
useEffect(() => {
// 存在商品 并且有选择收货地址,则开始计算运费
if (orderProductRequests && orderProductRequests.length > 0 && receiverAddressId) {
// 筛选配送方式为物流的商品并且使用了运费模板
const logsiticsDataMaps = orderProductRequests.filter(v => v.logistics && v.logistics.useTemplate && v.logistics.deliveryType === 1)
if (logsiticsDataMaps.length > 0) {
PublicApi.postLogisticsFreightRemoteAddDetail({
orderProductList: logsiticsDataMaps.map(v => ({
templateId: v.templateId,
weight: v.weight
})),
receiverAddressId
}, {ttl: 10 * 1000, useCache: true, ctlType: 'none'}).then(res => {
if (res.code === 1000) {
setFreePrice(res.data)
}
})
}
}
}, [orderProductRequests])
return <RowStyle>
<Col span={2}>
<div>合计金额</div>
<div>{sum}</div>
</Col>
<Col span={2}>
<div>运费 <SettingOutlined style={{marginLeft: 8}} onClick={handleSetting}/></div>
<div>{freePrice}</div>
</Col>
<Col span={2}>
<div>总计金额</div>
<div>{sum + freePrice}</div>
</Col>
<ModalForm
modalTitle='设置运费'
currentRef={modelRef}
initialValues={freePrice}
schema={{
type: 'object',
properties: {
NO_SUBMIT_LAYOUT: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
labelAlign: 'top'
},
properties: {
freePrice: {
type: 'string',
title: '设置运费',
"x-props": {
addonBefore: '¥'
}
}
}
}
}
}}
actions={modalPriceActions}
confirm={handleConfirm}
>
</ModalForm>
</RowStyle>
}
const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
interface EditableCellProps {
title: React.ReactNode;
editable: boolean;
children: React.ReactNode;
dataIndex: string;
record: Item;
handleSave: (record: Item) => void;
}
const EditableCell: React.FC<EditableCellProps> = ({
title,
editable,
children,
dataIndex,
record,
handleSave,
...restProps
}) => {
const [editing, setEditing] = useState(false);
const inputRef = useRef<any>({});
const form = useContext(EditableContext);
useEffect(() => {
if (editing) {
inputRef.current.focus();
}
}, [editing]);
const toggleEdit = () => {
setEditing(!editing);
form.setFieldsValue({ [dataIndex]: record[dataIndex] });
};
const save = async e => {
try {
const values = await form.validateFields();
values.price = parseInt(values.price)
toggleEdit();
handleSave({ ...record, ...values });
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
};
const cancel = () => {
console.log('cancel')
setEditing(false)
}
let childNode = children;
if (editable) {
childNode = editing ? (
<Form.Item
style={{ margin: 0, width: 140 }}
name={dataIndex}
rules={[
{
required: true,
message: `单价是必填的`,
},
]}
>
<Input type='number' ref={inputRef} onBlur={save} onPressEnter={save}/>
</Form.Item>
) : (
<div className="editable-cell-value-wrap" style={{ paddingRight: 24 }} onClick={toggleEdit}>
{children}
<EditOutlined/>
</div>
);
}
return <td {...restProps}>{childNode}</td>;
};
const OrderProductTable:React.FC<OrderProductTableProps> = (props) => {
const { ctl, data } = useContext(OrderDetailContext)
const { orderProductRequests = [] } = data || {}
const productComponents = {
body: {
row: EditableRow,
cell: EditableCell
}
}
const asyncGetMemberPrice = async (asyncData: any[]) => {
return await Promise.all(asyncData.filter(v => v.memberPrice === undefined).map(async v => {
const {code, data} = await PublicApi.getMemberManageUpperCreditParamGet({
parentMemberId: v.memberId,
parentMemberRoleId: v.memberRoleId
}, {ttl: 60 * 1000, useCache: true})
return code === 1000 ? { value: (data.parameter * 100) + '%', id: v.id } : { value: '', id: 0 }
}
))
}
useEffect(() => {
// 过滤 会员折扣不存在的列表
const hasPriceList = orderProductRequests.filter(v => !v.memberPrice)
if (hasPriceList.length > 0) {
asyncGetMemberPrice(hasPriceList).then((asyncData) => {
const newData = orderProductRequests.map((v, i) => {
if (!v.memberPrice) {
v.memberPrice = asyncData.find(j => j.id === v.id)?.value || ''
}
return v
})
ctl.setData({
...data,
orderProductRequests: newData
})
})
}
}, [orderProductRequests])
const handleSave = row => {
const newData = [...orderProductRequests];
const index = newData.findIndex(item => row.key === item.key);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
ctl.setData({
...data,
orderProductRequests: newData
})
};
const productInfoColumns: any[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
key: 'id',
},
{
title: '商品名称',
dataIndex: 'name',
align: 'center',
key: 'name',
},
{
title: '品类',
dataIndex: 'customerCategoryName',
align: 'center',
key: 'customerCategoryName',
},
{
title: '品牌',
dataIndex: 'brandName',
align: 'center',
key: 'brandName',
},
{
title: '单位',
dataIndex: 'unit',
align: 'center',
key: 'unit',
},
{
title: '单价(元)',
dataIndex: 'price',
align: 'left',
key: 'price',
editable: true
},
{
title: '会员折扣',
dataIndex: 'memberPrice',
align: 'center',
key: 'memberPrice',
render: (text, record) => record.isMemberPrice ? (text + '%') : null
},
{
title: '采购数量',
dataIndex: 'purchaseCount',
align: 'center',
key: 'purchaseCount'
},
{
title: '含税',
dataIndex: 'none',
align: 'center',
key: 'none',
},
{
title: '金额',
dataIndex: 'price',
align: 'center',
key: 'price',
},
// 接口调用
{
title: '配送方式',
dataIndex: 'logistics',
align: 'center',
key: 'logistics',
render: text => (text && text.render) || ''
},
{
title: '仓位库存扣减记录',
dataIndex: 'record',
align: 'center',
key: 'record',
// @todo 尚未实现, 需UI设计
render: text => <Button type='link'>查看(未实现)</Button>
},
]
const columns = productInfoColumns.map(col => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave: handleSave,
}),
};
});
return (
<MellowCard title='订单商品' style={{marginTop: 24}} bordered={false}>
<Table
columns={columns}
dataSource={orderProductRequests}
components={productComponents}
rowKey='id'
pagination={false}
/>
<MoneyTotalBox dataSource={data}/>
</MellowCard>
)
}
OrderProductTable.defaultProps = {}
export default OrderProductTable
\ No newline at end of file
import React, { useContext } from 'react'
import { Tabs, Table } from 'antd'
import StatusColors from '../../../components/StatusColors'
import { formatTimeString } from '@/utils'
import { OrderDetailContext } from '../../context'
import MellowCard from '@/components/MellowCard'
export interface OrderTransformRecordProps {}
const outOrderCols: any[] = [
{
title: '流转顺序号',
dataIndex: 'no',
align: 'center',
key: 'no',
render: (_, __, index: number) => index + 1
},
{
title: '操作角色',
dataIndex: 'roleName',
align: 'center',
key: 'roleName',
},
{
title: '状态',
dataIndex: 'state',
align: 'center',
key: 'state',
render: text => <StatusColors status={text} type='out'/>
// @todo 需传递工作流状态重新render
},
{
title: '操作',
dataIndex: 'operation',
align: 'center',
key: 'operation',
},
{
title: '操作时间',
dataIndex: 'operationTime',
align: 'center',
key: 'operationTime',
render: time => formatTimeString(time)
},
{
title: '审核意见',
dataIndex: 'auditOpinion',
align: 'center',
key: 'auditOpinion',
},
]
const sideOrderCols: any[] = [
{
title: '流转记录',
dataIndex: 'no',
align: 'center',
key: 'no',
render: (_, __, index: number) => index + 1
},
{
title: '操作人',
dataIndex: 'roleName',
align: 'center',
key: 'roleName',
},
{
title: '部门',
dataIndex: 'department',
align: 'center',
key: 'department',
},
{
title: '职位',
dataIndex: 'position',
align: 'center',
key: 'position',
},
{
title: '状态',
dataIndex: 'state',
align: 'center',
key: 'state',
render: text => <StatusColors status={text} type='inside'/>
},
{
title: '操作',
dataIndex: 'operation',
align: 'center',
key: 'operation',
},
{
title: '操作时间',
dataIndex: 'operationTime',
align: 'center',
key: 'operationTime',
},
{
title: '审核意见',
dataIndex: 'auditOpinion',
align: 'center',
key: 'auditOpinion',
},
]
// 订单流转记录
const OrderTransformRecord:React.FC<OrderTransformRecordProps> = (props) => {
const { data } = useContext(OrderDetailContext)
const { externalProcurementOrderLogResponses, interiorProcurementOrderLogResponses } = data
return (
<MellowCard style={{marginTop: 24}} bordered={false}>
<Tabs defaultActiveKey="1" animated={false}>
<Tabs.TabPane tab='外部订单流转记录' key="1">
<Table
columns={outOrderCols}
dataSource={externalProcurementOrderLogResponses}
pagination={false}
rowKey="id"
/>
</Tabs.TabPane>
<Tabs.TabPane tab='内部订单流转记录' key="2">
<Table
columns={outOrderCols}
dataSource={interiorProcurementOrderLogResponses}
pagination={false}
rowKey="id"
/>
</Tabs.TabPane>
</Tabs>
</MellowCard>
)
}
OrderTransformRecord.defaultProps = {}
export default OrderTransformRecord
\ No newline at end of file
import { createContext } from 'react';
export const OrderDetailContext = createContext<any>({})
\ No newline at end of file
import React, { useState, useEffect } from 'react'
import React, { useState, useEffect, useContext } from 'react'
import OrderDetailHeader from '../../components/OrderDetailHeader'
import { Button, Row, Col } from 'antd'
import { Link } from 'umi'
import { OrderModalType } from '@/constants'
import { orderTypeLabel } from './constant'
import { formatTimeString } from '@/utils'
import { usePageStatus } from '@/hooks/usePageStatus'
import { usePageStatus, PageStatus } from '@/hooks/usePageStatus'
import { PublicApi } from '@/services/api'
import AuditProcess from '@/components/AuditProcess'
import { findLastIndexFlowState } from '../utils'
import OrderDetailWrapper from '../../components/OrderDetailWrapper'
import { GlobalConfig } from '@/global/config'
import OrderProductTable from './components/orderProductTable'
import { OrderDetailContext } from './context'
import MellowCard from '@/components/MellowCard'
import OrderMergeInfo from './components/orderMergeInfo'
import OrderTransformRecord from './components/orderTransformRecord'
import OrderPayTabs from './components/orderPayTabs'
export interface CommonOrderDetailProps {}
const mockData = {
const mockList = {
headerTitle: {
picName: '单',
titleLabel: '订单号: ',
......@@ -34,9 +44,27 @@ const mockData = {
},
extraRight: <Button type='primary'>提交审核</Button>
}
const mockData = {
orderNo: '123',
quotationNo: 432,
orderModel: 5,
externalWorkflowFlowRecordLogResponses: [
{state: 1, roleName: "待定", isExecute: 1, operationalProcess: "新增订单"},
{state: 2, roleName: "待定", isExecute: 0, operationalProcess: "审核订单"},
{state: 3, roleName: "待定", isExecute: 0, operationalProcess: "审核订单"},
{state: 4, roleName: "待定", isExecute: 0, operationalProcess: "提交订单"}
],
interiorWorkflowFlowRecordLogResponses: [
{state: 1, roleName: "待定", isExecute: 1, operationalProcess: "新增订单"},
{state: 2, roleName: "待定", isExecute: 0, operationalProcess: "审核订单"},
{state: 3, roleName: "待定", isExecute: 0, operationalProcess: "审核订单"},
{state: 4, roleName: "待定", isExecute: 0, operationalProcess: "提交订单"}
]
}
const CommonOrderDetail:React.FC<CommonOrderDetailProps> = (props) => {
const [formData, setFormData] = useState<any>(null)
const { id } = usePageStatus()
const [formData, setFormData] = useState<any>(mockData)
const { id, pageStatus } = usePageStatus()
useEffect(() => {
if (id) {
PublicApi.getOrderPurchaseOrderDetails({id}).then(({data, code}) => {
......@@ -46,11 +74,20 @@ const CommonOrderDetail:React.FC<CommonOrderDetailProps> = (props) => {
})
}
}, [])
const formContext = {
data: formData,
ctl: {
setData: setFormData
}
}
const extraRight = <Button type='primary'>提交审核</Button>
const detailList = [
{ label: '对应报价单号', name: 'quotationNo', span: 8, render: text => <Link to={'/'}>{text}</Link> },
{ label: '订单摘要', name: 'orderThe', span: 8 },
{ label: '供应会员', name: 'supplyMembersName', span: 8, render: text => <Link to={'/'}>{text}</Link> },
{ label: '下单模式', name: 'orderModel', span: 8, render: text => OrderModalType[text] },
{ label: '下单模式', name: 'orderModel', span: 8, render: text => GlobalConfig.web.orderMode[text].label },
{ label: '订单类型', name: 'type', span: 8, render: text => orderTypeLabel[text] },
{ label: '下单时间', name: 'createTime', span: 8, render: text => formatTimeString(text) },
{ label: '外部状态', name: 'externalState', span: 8 },
......@@ -63,7 +100,34 @@ const CommonOrderDetail:React.FC<CommonOrderDetailProps> = (props) => {
} : null
return formData ? (
<div>
<OrderDetailHeader headerTitle={headerTiTle} detailList={detailList} detailData={formData}/>
<OrderDetailContext.Provider value={formContext}>
<OrderDetailHeader headerTitle={headerTiTle} detailList={detailList} detailData={formData} extraRight={extraRight}/>
<OrderDetailWrapper>
<div className='gray-wrap'>
{/* 工作流进度 */}
{ pageStatus !== PageStatus.ADD && formData && <AuditProcess
customTitleKey='operationalProcess'
customKey='state'
outerVerifyCurrent={findLastIndexFlowState(formData.externalWorkflowFlowRecordLogResponses)}
innerVerifyCurrent={findLastIndexFlowState(formData.interiorWorkflowFlowRecordLogResponses)}
outerVerifySteps={formData.externalWorkflowFlowRecordLogResponses}
innerVerifySteps={formData.interiorWorkflowFlowRecordLogResponses}
></AuditProcess> }
{/* 商品列表 */}
<OrderProductTable/>
{/* 支付信息 todo */}
<OrderPayTabs/>
{/* 杂项 */}
<OrderMergeInfo/>
{/* 订单流转记录 */}
<OrderTransformRecord/>
</div>
</OrderDetailWrapper>
</OrderDetailContext.Provider>
</div>
) : null
}
......
......@@ -25,12 +25,14 @@ const AddRule:React.FC<{}> = (props) => {
// 整体表单提交
const formSubmit = async (values) => {
// const params = omit(values, ['NO_SUBMIT3'])
console.log(values, 'values')
// await PublicApi.postOrderTradingRulesAdd(params)
// setTimeout(() => {
// history.goBack(-1)
// }, 1000)
values.products = values.products.map(item => ({ productId: item.id, productName: item.name, category: item.customerCategoryName, productPrice: item.priceType, brand: item.brandName }))
values.isElectronicContract = values.isElectronicContract ? 1 : 0
const params = omit(values, ['state']) // 移除不需要的字段
console.log(values, params, 'values')
await PublicApi.postOrderTradingRulesAdd(params)
setTimeout(() => {
history.goBack(-1)
}, 1000)
}
return (
......
......@@ -20,6 +20,7 @@ import SearchSelect from '@/components/NiceForm/components/SearchSelect'
import Search from '@/components/NiceForm/components/Search'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import Submit from '@/components/NiceForm/components/Submit'
import SelectProcesss from './selectProcesss'
export interface RuleSettingProps {
addSchemaAction: ISchemaFormActions,
......@@ -31,7 +32,7 @@ export interface RuleSettingProps {
const RuleSetting:React.FC<RuleSettingProps> = (props) => {
const { addSchemaAction, schema, formSubmit, onFieldChange = () => {} } = props
const [visibleChannelRroduct, setVisibleChannelRroduct] = useState(false)
const [productRowSelection, productRowCtl] = useRowSelectionTable({customKey: 'productId'})
const [productRowSelection, productRowCtl] = useRowSelectionTable({customKey: 'id'})
const {
id,
......@@ -43,12 +44,20 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
// useUnitPreview(initValue, addSchemaAction)
const fetchProductList = async (params) => {
const tradingRulesId = addSchemaAction.getFieldValue('transactionProcesssId')
const res = await PublicApi.getOrderTradingRulesProductList({
...params,
tradingRulesId,
})
return res.data
const shopIds = addSchemaAction.getFieldValue('shopIds')
if(shopIds.length){
let shopInfo: any = GlobalConfig.web.shopInfo.filter(item => item.id === shopIds[0])
const res = await PublicApi.getProductCommodityCommonGetCommodityDetailList({
...params,
shopType: shopInfo[0].type,
environment: shopInfo[0].environment,
})
return res.data
}else{
message.error('请先选择适用商城!')
return []
}
}
// table删除商品
......@@ -74,35 +83,43 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
const tableColumns = [
{
dataIndex: 'productId',
dataIndex: 'id',
title: 'ID',
key: 'productId'
key: 'id'
},
{
dataIndex: 'productName',
dataIndex: 'name',
title: '商品名称',
key: 'productName',
render: (_, record) => <EyePreview url={`/memberCenter/commodityAbility/commodity/products/viewProducts?id=${record.productId}`}>{_}</EyePreview>
key: 'name',
render: (_, record) => <EyePreview url={`/memberCenter/commodityAbility/commodity/products/viewProducts?id=${record.id}`}>{_}</EyePreview>
},
{
dataIndex: 'category',
dataIndex: 'customerCategoryName',
title: '品类',
key: 'category'
key: 'customerCategoryName'
},
{
dataIndex: 'brand',
dataIndex: 'brandName',
title: '品牌',
key: 'brand'
key: 'brandName'
},
{
dataIndex: 'productPrice',
title: '商品定价',
key: 'productPrice'
dataIndex: 'priceType',
title: '商品定价',
key: 'priceType',
render: (text:any, reocrd:any)=>{
if(text===1)
return '现货价格'
else if(text===2)
return '价格需要询价'
else if(text===3)
return '积分兑换商品'
},
},
{
dataIndex: 'ctl',
title: '操作',
render: (_, record) => <Button type='link' onClick={() => handleDeleteTable(record.productId)}>删除</Button>
render: (_, record) => <Button type='link' onClick={() => handleDeleteTable(record.id)}>删除</Button>
}
]
......@@ -123,29 +140,37 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
const columnsSetProduct: any[] = [
{
dataIndex: 'productId',
dataIndex: 'id',
title: 'ID',
key: 'productId'
key: 'id'
},
{
dataIndex: 'productName',
dataIndex: 'name',
title: '商品名称',
key: 'productName'
key: 'name'
},
{
dataIndex: 'category',
dataIndex: 'customerCategoryName',
title: '品类',
key: 'category'
key: 'customerCategoryName'
},
{
dataIndex: 'brand',
dataIndex: 'brandName',
title: '品牌',
key: 'brand'
key: 'brandName'
},
{
dataIndex: 'productPrice',
dataIndex: 'priceType',
title: '商品定价',
key: 'productPrice'
key: 'priceType',
render: (text:any, reocrd:any)=>{
if(text===1)
return '现货价格'
else if(text===2)
return '价格需要询价'
else if(text===3)
return '积分兑换商品'
},
},
]
......@@ -153,7 +178,7 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
const formProduct: ISchema = {
type: 'object',
properties: {
productName: {
name: {
type: 'string',
'x-component': 'ModalSearch',
'x-component-props': {
......@@ -176,7 +201,7 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
},
},
properties: {
categoryId: {
customerCategoryId: {
type: 'string',
"x-component": 'SearchSelect',
"x-component-props": {
......@@ -223,6 +248,9 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
tableColumns,
tableAddButton,
}}
components={{
SelectProcesss,
}}
effects={($, { setFieldState }) => {
FormEffectHooks.onFormInputChange$().subscribe(() => {
onFieldChange()
......@@ -252,12 +280,15 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
{
ctx: {
schema: formProduct,
components: { ModalSearch: Search, SearchSelect, Submit } ,
components: {
ModalSearch: Search,
SearchSelect, Submit,
} ,
effects: ($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'productName',
'name',
FORM_FILTER_PATH,
);
}
......@@ -265,7 +296,7 @@ const RuleSetting:React.FC<RuleSettingProps> = (props) => {
}
}
tableProps={{
rowKey: 'productId'
rowKey: 'id'
}}
/>
......
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 } from 'antd'
import { PlusOutlined, DeleteColumnOutlined, EditOutlined, DeleteOutlined, CaretUpOutlined, CaretDownOutlined, EyeOutlined } from '@ant-design/icons'
import cx from 'classnames'
import { PublicApi } from '@/services/api'
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;
}
`
enum ProcessTagColor {
'red',
'orange',
'purple',
'blue'
}
enum ProcessTagType {
'订单交易流程',
'售后换货流程',
'售后退货流程',
'售后维修流程'
}
const SelectProcesss = (props: ISchemaFieldComponentProps) => {
const [formInitValue, setFormInitValue] = useState<any>(null)
const [state, setFieldState] = useFieldState({
dataSource: [],
showMore: false
})
const { dataSource, showMore } = state
const { value, mutators, editable } = props
useEffect(() => {
PublicApi.getOrderTradingRulesTransactionProcessList().then(res => {
setFieldState({
dataSource: res.data,
showMore
})
})
}, [])
const showDataSource = showMore ? dataSource : [...dataSource].splice(0, 3)
const handleCheck = (id) => {
if (editable) {
mutators.change(id)
}
}
const toogleMore = () => {
setFieldState({
dataSource,
showMore: !showMore
})
}
const renderProcessType = (v: any) => {
return <Tag color={ProcessTagColor[v.type-1]}>
{ProcessTagType[v.type-1]}
</Tag>
}
return (
<div style={{width: '100%'}}>
<SelectStyles>
{
showDataSource.map(v => <div key={v.id} onClick={() => handleCheck(v.id)} className={cx('select_style_border', value === v.id ? 'active' : '')}>
<div>
<Row style={{color: '#172B4D'}}>
<Col>{v.name}</Col>
<Col style={{marginLeft: 6}}>
{
renderProcessType(v)
}
</Col>
</Row>
<div style={{color: '#6B778C'}}>{v.explain}</div>
</div>
</div>)
}
</SelectStyles>
{ dataSource.length > 3 &&
<div onClick={toogleMore} style={{textAlign: 'center', cursor: 'pointer'}}>
显示更多{showMore ? <CaretDownOutlined /> : <CaretUpOutlined/>}
</div>
}
</div>
)
}
SelectProcesss.defaultProps = {}
SelectProcesss.isFieldComponent = true;
export default SelectProcesss
\ No newline at end of file
......@@ -52,13 +52,30 @@ export const ruleDetailSchema: ISchema = padRequiredMessage({
"transactionProcesssId": {
type: 'string',
title: '流程选择',
required: true,
"x-component": 'SearchSelect',
"x-component": 'SelectProcesss',
"x-mega-props": {
style: {
full: true
}
},
"x-component-props": {
placeholder: '请选择交易流程',
className: 'fixed-ant-selected-down',
fetchSearch: PublicApi.getOrderTradingRulesTransactionProcessList,
dataSource: []
},
"x-rules": [
{
required: true,
message: '请选择收货方式'
}
],
// required: true,
// "x-component": 'SearchSelect',
// "x-component-props": {
// placeholder: '请选择交易流程',
// className: 'fixed-ant-selected-down',
// fetchSearch: PublicApi.getOrderTradingRulesTransactionProcessList,
// },
},
MEGA_LAYOUT1_1: {
type: 'object',
......@@ -110,7 +127,8 @@ export const ruleDetailSchema: ISchema = padRequiredMessage({
"type": "array:number",
"x-component": 'CardCheckBox',
"x-component-props": {
dataSource: GlobalConfig.web.shopInfo
dataSource: GlobalConfig.web.shopInfo,
type: 'radio' // CardCheckBox 单选模式
},
"title": "适用商城",
required: true,
......
......@@ -13,7 +13,7 @@ export function isObject(obj: any) {
return Object.prototype.toString.call(obj) === '[object Object]'
}
export function formatTimeString(date, format: string = 'YYYY-MM-DD HH:MM:SS') {
export function formatTimeString(date, format: string = 'YYYY-MM-DD HH:mm:ss') {
return date ? moment(date).format(format) : ''
}
......
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