Commit 914bece6 authored by 前端-钟卫鹏's avatar 前端-钟卫鹏

Merge branch 'dev' into test

parents 47220d90 47051a02
......@@ -9,22 +9,24 @@ import moment from 'moment';
const { RangePicker } = DatePicker;
const DateRangePickerUnix = (props) => {
const { value, mutators } = props
const { value, mutators } = props
const { placeholder, dataSource, ...rest } = props.props["x-component-props"] || {}
const handleChange = (dates, dateString) => {
if(dateString.length === 2) {
mutators.change([moment(dateString[0]).format('x'), moment(dateString[1]).format('x')]);
mutators.change([dateString[0] ? moment(dateString[0]).format('x') : null, dateString[1] ? moment(dateString[1]).format('x') : null]);
}
}
return (
<RangePicker
showTime={true}
style={{minWidth: 160}}
placeholder={placeholder}
onChange={handleChange}
format="YYYY-MM-DD HH:mm:ss"
{...rest}
/>
)
......@@ -34,4 +36,4 @@ DateRangePickerUnix.defaultProps = {}
DateRangePickerUnix.isFieldComponent = true;
export default DateRangePickerUnix
\ No newline at end of file
export default DateRangePickerUnix
......@@ -38,9 +38,9 @@ const NumberRange = (props) => {
const [rangeValue, setrangeValue] = useState([])
useEffect(() => {
if(rangeValue.length) {
// if(rangeValue.length) {
mutators.change(rangeValue);
}
// }
}, [rangeValue])
const loseBlur = (e, index) => {
......@@ -60,7 +60,8 @@ const NumberRange = (props) => {
textAlign: 'center'
}}
placeholder={placeholder[0] || '最小值'}
onBlur={(e) => loseBlur(e, 0)}
onChange={(e) => loseBlur(e, 0)}
value={value[0] || null}
/>
<Input
className="site-input-split"
......@@ -81,7 +82,8 @@ const NumberRange = (props) => {
textAlign: 'center',
}}
placeholder={placeholder[1] || '最大值'}
onBlur={(e) => loseBlur(e, 1)}
onChange={(e) => loseBlur(e, 1)}
value={value[1] || null}
/>
</Input.Group>
</RowStyleLayout>
......
......@@ -919,7 +919,7 @@ export enum SaleOrderInsideWorkState {
READY_DELEVED_APPROVED,
/**
* 待审核物流单(新增物流单成功)
* 待确认物流单(新增物流单成功)
*/
DELIVERY_APPROVED_SUCCESS,
......@@ -1038,7 +1038,7 @@ export const SaleOrderInsideWorkStateTexts = {
23: '待确认回单',
24: '订单归档',
25: '待审核发货单',
26: '待审核物流单',
26: '待确认物流单',
27: '待手工发货'
}
......@@ -1772,7 +1772,7 @@ export const RETURN_OUTER_STATUS = {
/**
* 线上支付
*/
export const PAY_WAY_ONLINE = 1;
export const PAY_WAY_ONLINE = 1;
/**
* 线下支付
*/
......@@ -1780,19 +1780,19 @@ export const PAY_WAY_OFFLINE = 2;
/**
* 授信支付
*/
export const PAY_WAY_CREDIT = 3;
export const PAY_WAY_CREDIT = 3;
/**
* 货到付款
*/
export const PAY_WAY_COD = 4;
export const PAY_WAY_COD = 4;
/**
* 支付方式对应中文
*/
export const PAYWAY = {
[PAY_WAY_ONLINE]: '线上支付',
[PAY_WAY_OFFLINE]: '线下支付',
[PAY_WAY_CREDIT]: '授信支付',
[PAY_WAY_COD]: '货到付款',
[PAY_WAY_ONLINE]: '线上支付',
[PAY_WAY_OFFLINE]: '线下支付',
[PAY_WAY_CREDIT]: '授信支付',
[PAY_WAY_COD]: '货到付款',
};
......@@ -1833,12 +1833,12 @@ export const PAY_CHANNEL_COD = 7;
* 支付渠道对应中文
*/
export const PAY_CHANNEL = {
[PAY_CHANNEL_INTEGRAL]: '积分支付',
[PAY_CHANNEL_ALI]: '支付宝',
[PAY_CHANNEL_WECHAT]: '微信',
[PAY_CHANNEL_UNION]: '银联',
[PAY_CHANNEL_BALANCE]: '余额',
[PAY_CHANNEL_OFFLINE]: '线下支付',
[PAY_CHANNEL_CREDIT]: '授信',
[PAY_CHANNEL_COD]: '货到付款',
};
\ No newline at end of file
[PAY_CHANNEL_INTEGRAL]: '积分支付',
[PAY_CHANNEL_ALI]: '支付宝',
[PAY_CHANNEL_WECHAT]: '微信',
[PAY_CHANNEL_UNION]: '银联',
[PAY_CHANNEL_BALANCE]: '余额',
[PAY_CHANNEL_OFFLINE]: '线下支付',
[PAY_CHANNEL_CREDIT]: '授信',
[PAY_CHANNEL_COD]: '货到付款',
};
......@@ -120,7 +120,7 @@ const SelectProduct:React.FC<IProps> = (props) => {
useEffect(() => {
onRef(formProduct)
formProduct.setFieldsValue({source: source})
formProduct.setFieldsValue({source: source})
// 获取会员角色列表
PublicApi.getMemberManageChannelLowerRoleList().then(res => {
const { data } = res
......@@ -148,7 +148,7 @@ const SelectProduct:React.FC<IProps> = (props) => {
state.visible = source===1 ? true : false
})
}, [visibleAddTabs])
// 获取渠道商品
const fetchProductData = (params: any) => {
return new Promise((resolve, reject) => {
......@@ -192,7 +192,7 @@ const SelectProduct:React.FC<IProps> = (props) => {
{...layout}
form={formProduct}
ref={productFormRef}
name="add-channel-origin"
name="add-channel-origin"
labelAlign="left"
colon={false}
>
......@@ -220,12 +220,12 @@ const SelectProduct:React.FC<IProps> = (props) => {
confirm={handleOkAddTabs}
cancel={handleCancelAddTabs}
visible={visibleAddTabs}
resetModal={{destroyOnClose: true, forceRender: true}}
resetModal={{destroyOnClose: true}}
columns={productColumns}
rowSelection={productRowSelection}
fetchTableData={(params:any) => fetchProductData(params)}
currentRef={productRef}
forceRender={true}
forceRender={false}
tableProps={{
rowKey: 'id',
onRow: (record) => ({
......@@ -237,7 +237,7 @@ const SelectProduct:React.FC<IProps> = (props) => {
}}
formilyProps={
{
ctx: {
ctx: {
schema: addChannelSchema,
actions: productFormActions,
components: { ModalSearch: Search, SearchSelect, Submit } ,
......@@ -260,4 +260,4 @@ const SelectProduct:React.FC<IProps> = (props) => {
</>)
}
export default observer(SelectProduct)
\ No newline at end of file
export default observer(SelectProduct)
import React, { useState, useEffect, useRef, ReactNode } from 'react'
import { history } from 'umi'
import { Button, Form, Card, Modal, Result, Progress, Select, Tooltip, Checkbox, Row, Col, Dropdown, Input, Menu, Space, message, InputNumber } from 'antd'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import {
PlusOutlined,
FileExcelOutlined,
EyeOutlined,
QuestionCircleOutlined,
DownOutlined,
DeleteOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons'
import { StandardTable } from 'god'
import { ColumnType } from 'antd/lib/table/interface'
import moment from 'moment'
import styles from "./index.less"
import { PublicApi } from '@/services/api'
import { GetProductCommodityGetShopResponse } from '@/services/ProductApi'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import TableOperation from '@/components/TableOperation'
import { productSchema } from './schema/productSchema'
import NiceForm from '@/components/NiceForm'
import { createFormActions, FormEffectHooks } from '@formily/antd'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { searchBrandOptionEffect, searchCustomerCategoryOptionEffect } from './effect'
const { Option } = Select;
const { confirm } = Modal;
// 定义选择的行数据的类型
interface Item {
key: string;
productName: string;
type: string;
brand: string;
unit: string;
price: string;
time: string;
status: string;
}
let timeChange: any;
const formActions = createFormActions();
const Products: React.FC<{}> = () => {
const ref = useRef<any>({})
const judgeShopRef = useRef<boolean>(true)
const [upForm] = Form.useForm()
const [selectRow, setSelectRow] = useState<Item[]>([]) // 模态框选择的行数据
const [selectedRowKeys, setSelectedRowKeys] = useState<Array<string>>([])
const [importModal, setImportModal] = useState(false)
const [deleteBatchModal, setDeleteBatchModal] = useState(false)
const [modalTitle, setModalTitle] = useState('导入')
const [modalStep, setModalStep] = useState(0)
const [isUp, setIsUp] = useState(1) // 1上0下架状态
const [upDownModal, setUpDownModal] = useState(false)
const [shopsOption, setShopsOption] = useState<GetProductCommodityGetShopResponse>([])
const [checkedValues, setCheckedValues] = useState<any>([])
const [currentOptionId, setCurrentOptionId] = useState()
const [isDisabledOKbtn, setIsDisabledOKbtn] = useState<boolean>(false)
const [shopId, setShopId] = useState<any>()
const columns: ColumnType<any>[] = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 60
},
{
title: '商品名称',
dataIndex: 'name',
key: 'name',
className: 'commonPickColor',
width: 240,
ellipsis: true,
render: (text: any, record: any) => <a title={text} onClick={() => handleSee(record)}>{text}&nbsp;<EyeOutlined /></a>
},
{
title: '商品品类',
dataIndex: ['customerCategory', 'name'],
key: 'customerCategory.name',
},
{
title: '商品品牌',
dataIndex: ['brand', 'name'],
key: 'brand.name',
},
{
title: '单位',
dataIndex: 'unitName',
key: 'unitName',
},
{
title: '产品定价',
dataIndex: 'priceType',
key: 'priceType',
render: (text:any, reocrd:any)=>{
if(text===1)
return '现货价格'
else if(text===2)
return '价格需要询价'
else if(text===3)
return '积分兑换商品'
},
filters: [
{
text: '现货价格',
value: 1,
},
{
text: '价格需要询价',
value: 2,
},
{
text: '积分兑换商品',
value: 3,
},
],
onFilter: (value, record) => record.priceType === value,
},
{
title: '价格',
dataIndex: 'min',
key: 'min',
render: (text:any, reocrd:any) => {
if(reocrd.priceType === 1){
if(reocrd.max === reocrd.min)
return <>{reocrd.min}</>
else
return <>{reocrd.min} ~ ¥{reocrd.max}</>
}
if(reocrd.priceType === 3){
if(reocrd.max === reocrd.min)
return <>{reocrd.min}</>
else
return <>{reocrd.min} ~ {reocrd.max}</>
}
if(reocrd.priceType === 2)
return null
}
},
{
title: '申请审核时间',
dataIndex: 'applyTime',
key: 'applyTime',
render: (text:any, record:any)=>text && moment(text).format('YYYY-MM-DD HH:mm:ss')
},
{
title: '商品状态',
dataIndex: 'status',
key: 'status',
render: (text: any, record: any) => {
let component: ReactNode = null
if (record.status === 1)
component = (<><span className="commonStatusStop"></span>待提交审核</>)
else if (record.status === 2)
component = (<><span className="commonStatusModify"></span>待审核</>)
else if (record.status === 3)
component = (<><span className="commonStatusInvalid"></span>审核不通过</>)
else if (record.status === 4)
component = (<><span className="commonStatusValid"></span>审核通过</>)
else if (record.status === 5)
component = (<span style={{ color: '#00B37A', padding: '2px 5px', background: 'rgba(235,247,242,1)', borderRadius: '4px' }}>已上架</span>)
else if (record.status === 6)
component = (<span style={{ padding: '2px 5px', background: 'rgba(244,245,247,1)', borderRadius: '4px' }}>已下架</span>)
return component
},
filters: [
{
text: '待提交审核',
value: 1,
},
{
text: '待审核',
value: 2,
},
{
text: '审核不通过',
value: 3,
},
{
text: '审核通过',
value: 4,
},
{
text: '已上架',
value: 5,
},
{
text: '已下架',
value: 6,
}
],
onFilter: (value, record) => record.status === value,
},
{
title: '操作',
dataIndex: 'option',
width: 160,
render: (text: any, record: any) => renderOptionButton(record)
}
];
const renderOptionButton = (record: any) => {
// 操作常量
const statusAndOperationList = {
'1': ['复制', '提交审核', '修改', '删除'],
'2': ['复制'],
'3': ['复制', '修改'],
'4': ['复制', '上架', '修改'],
'5': ['复制', '下架'],
'6': ['复制', '上架', '修改'],
}
const operationHandler = {
'复制': () => clickCopy(record),
'提交审核': () => clickSubmitCheck(record),
'修改': () => clickModify(record.id),
'删除': () => confirmDelete(record.id),
'上架': () => clickUp(1, record.id),
'下架': () => clickUp(0, record.id),
}
return (
<TableOperation
record={record}
statusOperationMap={statusAndOperationList}
operationHandler={operationHandler}
priorityOperationName="提交审核"
/>
)
}
const fetchData = (params: any) => {
return new Promise((resolve, reject) => {
PublicApi.getProductCommodityGetCommodityList(params).then(res => {
const { data } = res
resolve(data)
})
})
}
const handleSee = (record: any) => {
history.push(`/memberCenter/commodityAbility/commodity/products/detail?id=${record.id}`)
}
const clickModify = (id: number) => {
history.push(`/memberCenter/commodityAbility/commodity/products/edit?id=${id}`)
}
const handleCancel = () => {
console.log('cancel')
setImportModal(false)
}
const rowSelection = {
selectedRowKeys: selectedRowKeys,
onChange: (selectedRowKeys: any, selectedRows: any) => {
setSelectRow(selectedRows);
setSelectedRowKeys(selectedRowKeys);
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
}
}
const modalLoadTemplate = () => {
console.log('模板下载!')
}
const modalUpload = () => {
console.log('上传')
setModalStep(1)
setModalTitle('导入检查')
}
const exportErrorLog = () => {
console.log('导出错误')
}
const modalImportData = () => {
setModalStep(2)
setModalTitle('数据导入')
console.log('下一步,导入数据')
}
const step0Description = <>
<ul className={styles.step0Description}>
<li>点击下载 EXCEL文件模板 <a onClick={modalLoadTemplate}>下载</a></li>
<li>按照模板整理货品资料</li>
<li>点击导入按钮,导入整理好的货品资料</li>
</ul>
</>
const step1Description = <div className={styles.step1Description}>
<h4>正在进行数据导入检查</h4>
<p>请稍后…</p>
</div>
const step1DescripSuccess = <div className={styles.step1Description}>
<h4>无错误格式数据</h4>
<p>继续导入请按下一步</p>
<Button type="primary" onClick={modalImportData}>下一步</Button>
</div>
const step1Exception = <div className={styles.step1Description}>
<h4>存在错误格式数据,已生成错误日志</h4>
<p>请导出错误日志修正数据后再次导入</p>
</div>
const step2Description = <div className={styles.step1Description}>
<h4>正在进行数据导入</h4>
<p>请稍后…</p>
</div>
const step2DescripSuccess = <div className={styles.step1Description}>
<h4>数据全部导入成功</h4>
<p>继续导入请点击继续导入,导入完成请点击导入完成</p>
<Button type="primary">继续导入</Button>&nbsp;&nbsp;&nbsp;&nbsp;<Button>完成导入</Button>
</div>
const step2Exception = <div className={styles.step1Description}>
<h4>导入完成请点击导入完成</h4>
<p>已生成错误日志,请导出错误日志修正数据后再次导入</p>
</div>
const [step1DescriptState, setStep1DescriptState] = useState(step1Description)
const [step2DescriptState, setStep2DescriptState] = useState(step2Description)
// timer
const [exceptionCheck, setExceptionCheck] = useState(false); // 默认无异常
const [exceptionData, setExceptionData] = useState(false); // 默认无异常
const [time, setTime] = useState(0); // timer
useEffect(() => {
clearInterval(timeChange)
}, [])
useEffect(() => {
console.log(modalStep)
if (modalStep === 1) runTimer()
if (modalStep === 2) runTimer()
}, [modalStep])
useEffect(() => {
if (time >= 100) {
clearInterval(timeChange)
setTime(100)
if (modalStep === 1) setStep1DescriptState(step1DescripSuccess)
if (modalStep === 2) setStep2DescriptState(step2DescripSuccess)
console.log('倒计时完毕!', modalStep)
}
}, [time])
const runTimer = () => {
setTime(0)
timeChange = setInterval(() => setTime(t => t + Math.floor(Math.random() * 10)), 200)
}
//timer end
const step1Icon = <>
<Progress
type="circle"
strokeColor={{
'0%': '#669EDE',
'100%': '#41CC9E',
}}
percent={time}
/>
</>
const step2Icon = <>
<Progress
type="circle"
strokeColor={{
'0%': '#669EDE',
'100%': '#41CC9E',
}}
percent={time}
/>
</>
const handleOkDeleteBatch = () => {
setDeleteBatchModal(false)
console.log('删除批次')
}
const handleCancelDelete = () => {
setDeleteBatchModal(false)
console.log('取消删除')
}
const onChangeUpShop = (values) => {
// 判断上架之前是否有店铺 有即可以上下架
if(judgeShopRef.current){
PublicApi.getTemplateShopFindShop({
memberId: JSON.parse(window.localStorage.getItem('auth')).memberId,
memberRoleId: JSON.parse(window.localStorage.getItem('auth')).memberRoleId
}).then(res => {
if(res.data.id){
setShopId(res.data.id)
setCheckedValues(values)
}else{
message.error('您还还未创建店铺,请先创建店铺!')
setTimeout(() => {
history.push('/memberCenter/shopAbility/infoManage')
}, 1000)
}
})
judgeShopRef.current = false
} else {
setCheckedValues(values)
}
}
const clickUp = (param: any, id: any) => { // param: 0 下架 1上架
setCurrentOptionId(id)
PublicApi.getProductCommodityGetShop({id: id}).then(res => {
setShopsOption(res.data)
setCheckedValues(res.data.filter(_=>_.isCheck))
})
setIsUp(param)
setUpDownModal(true)
}
const handleUp = () => {
setIsDisabledOKbtn(true)
let params = {
id: currentOptionId,
shopList: checkedValues
}
if(isUp)
if(checkedValues.length > 0){
PublicApi.postProductCommodityPublishCommodity({storeId: shopId, ...params}).then(res => {
setUpDownModal(false)
ref.current.reload()
setIsDisabledOKbtn(false)
})
}else{
setIsDisabledOKbtn(false)
message.error('请选择需要上架的商城!')
}
else
PublicApi.postProductCommodityOffPublishCommodity(params).then(res => {
setUpDownModal(false)
ref.current.reload()
setIsDisabledOKbtn(false)
})
}
const handleCancelUp = () => {
upForm.resetFields()
setUpDownModal(false)
}
const clickCopy = (record: any) => {
const { id } = record;
if(id){
confirm({
title: '确定要执行复制操作?',
icon: <ExclamationCircleOutlined />,
onOk() {
PublicApi.postProductCommodityCopyCommodity({id: id}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
},
onCancel() {
console.log('Cancel');
},
okText: '确定',
cancelText: '取消'
})
}
}
const clickSubmitCheck = (record:any) => {
console.log('提交审核')
const { id } = record;
if(id)
PublicApi.postProductCommodityApplyCheckCommodity({id: id}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
}
const handleMenuClick = (e: any) => {
console.log('menu', e, selectedRowKeys); // 1 批量删除;2 删除导入批次
if(e.key === '1'){
console.log('批量删除')
handleBatchDelete(selectedRowKeys, true)
}else if(e.key === '2'){
console.log('删除导入批次')
setDeleteBatchModal(true)
}
}
const handleBatchDelete = (ids: string[], param?: boolean) => {
if(ids.length)
if(param){
confirm({
title: '确定要执行批量删除操作?',
icon: <ExclamationCircleOutlined />,
onOk() {
//@ts-ignore
PublicApi.postProductCommodityDeleteBatchCommodity({idList: ids}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
},
okType: 'danger',
onCancel() {
console.log('Cancel');
},
okText: '确定',
cancelText: '取消'
})
}else{
//@ts-ignore
PublicApi.postProductCommodityDeleteBatchCommodity({idList: ids}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
}
else
message.error('请选择需要操作的商品!')
}
const confirmDelete = (paramId: any) => {
confirm({
title: '确定要执行删除操作?',
icon: <ExclamationCircleOutlined />,
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk() {
handleBatchDelete([paramId])
},
onCancel() {
console.log('Cancel');
},
});
}
const menuMore = (
<Menu onClick={(e) => handleMenuClick(e)}>
<Menu.Item key="1" icon={<DeleteOutlined />}>
批量删除
</Menu.Item>
<Menu.Item key="2" icon={<DeleteOutlined />}>
删除导入批次
</Menu.Item>
</Menu>
)
const controllerBtns = (
<Space>
<Button
type='primary'
onClick={()=>history.push('/memberCenter/commodityAbility/commodity/products/add')}
>
<PlusOutlined />新建
</Button>
<Button style={{margin:'0 16px'}} onClick={()=>setImportModal(true)}>导入数据</Button>
<Dropdown overlay={menuMore} trigger={['click']}>
<Button>
更多 <DownOutlined />
</Button>
</Dropdown>
</Space>
);
return (
<PageHeaderWrapper>
<Card>
<StandardTable
columns={columns}
currentRef={ref}
rowSelection={rowSelection}
tableProps={{
rowKey: 'id',
}}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values =>ref.current.reload(values)}
expressionScope={{
controllerBtns,
}}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'name',
FORM_FILTER_PATH,
)
FormEffectHooks.onFieldChange$('brandId').subscribe(state => {
searchBrandOptionEffect(actions, 'brandId')
})
FormEffectHooks.onFieldChange$('customerCategoryId').subscribe(state => {
searchCustomerCategoryOptionEffect(actions, 'customerCategoryId')
})
}}
schema={productSchema}
/>
}
/>
</Card>
<Modal
title={modalTitle}
visible={importModal}
onCancel={handleCancel}
maskClosable={false}
footer={null}
>
{
modalStep === 0 && <>
<Result
icon={<FileExcelOutlined />}
title={step0Description}
extra={<Button style={{ width: '100%' }} type="primary" onClick={modalUpload}>上传</Button>}
/>
</>
}
{
modalStep === 1 && !exceptionCheck && <>
<Result
icon={step1Icon}
title={step1DescriptState}
/>
</>
}
{
modalStep === 1 && exceptionCheck && <>
<Result
icon={<Progress type="circle" percent={100} status="exception" />}
title={step1Exception}
extra={<Button onClick={exportErrorLog}>导出错误日志</Button>}
/>
</>
}
{
modalStep === 2 && !exceptionData && <>
<Result
icon={step2Icon}
title={step2DescriptState}
/>
</>
}
{
modalStep === 2 && exceptionData && <>
<Result
icon={<Progress type="circle" percent={100} status="exception" />}
title={step2Exception}
extra={<Button onClick={exportErrorLog}>导出错误日志</Button>}
/>
</>
}
</Modal>
<Modal
title="删除导入批次"
visible={deleteBatchModal}
onOk={handleOkDeleteBatch}
onCancel={handleCancelDelete}
okButtonProps={{ danger: true }}
>
<Form
layout="vertical"
>
<Form.Item label="选择要删除的批次">
<Select placeholder="请选择批次号">
<Select.Option value="542424">4245242452</Select.Option>
</Select>
</Form.Item>
</Form>
</Modal>
<Modal
title={isUp ? '商品上架' : '商品下架'}
visible={upDownModal}
onOk={handleUp}
onCancel={handleCancelUp}
forceRender={true}
okButtonProps={{ disabled: isDisabledOKbtn }}
>
<Form
layout="vertical"
>
<Form.Item
label={
<span>
{isUp ? '选择' : '反选'}需要{isUp ? '上架' : '下架'}的商城&nbsp;
<Tooltip title="已上架的商城为已勾选的商城,不可选择,只可以选择未勾选的商城。">
<QuestionCircleOutlined />
</Tooltip>
</span>
}
>
<Checkbox.Group style={{ width: '100%' }} onChange={onChangeUpShop} value={checkedValues}>
<Row>
{
Array.isArray(shopsOption) && shopsOption.map((item, index) => <Col key={index} span={8}>
<Checkbox value={item}>{item.name}</Checkbox>
</Col>)
}
</Row>
</Checkbox.Group>
</Form.Item>
</Form>
</Modal>
</PageHeaderWrapper>
)
}
export default Products
\ No newline at end of file
import React, { useState, useEffect, useRef, ReactNode } from 'react'
import { history } from 'umi'
import { Button, Form, Card, Modal, Result, Progress, Select, Tooltip, Checkbox, Row, Col, Dropdown, Input, Menu, Space, message, InputNumber } from 'antd'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import {
PlusOutlined,
FileExcelOutlined,
EyeOutlined,
QuestionCircleOutlined,
DownOutlined,
DeleteOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons'
import { StandardTable } from 'god'
import { ColumnType } from 'antd/lib/table/interface'
import moment from 'moment'
import styles from "./index.less"
import { PublicApi } from '@/services/api'
import { GetProductCommodityGetShopResponse } from '@/services/ProductApi'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import TableOperation from '@/components/TableOperation'
import { productSchema } from './schema/productSchema'
import NiceForm from '@/components/NiceForm'
import { createFormActions, FormEffectHooks } from '@formily/antd'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { searchBrandOptionEffect, searchCustomerCategoryOptionEffect } from './effect'
const { Option } = Select;
const { confirm } = Modal;
// 定义选择的行数据的类型
interface Item {
key: string;
productName: string;
type: string;
brand: string;
unit: string;
price: string;
time: string;
status: string;
}
let timeChange: any;
const formActions = createFormActions();
const Products: React.FC<{}> = () => {
const ref = useRef<any>({})
const judgeShopRef = useRef<boolean>(true)
const [upForm] = Form.useForm()
const [selectRow, setSelectRow] = useState<Item[]>([]) // 模态框选择的行数据
const [selectedRowKeys, setSelectedRowKeys] = useState<Array<string>>([])
const [importModal, setImportModal] = useState(false)
const [deleteBatchModal, setDeleteBatchModal] = useState(false)
const [modalTitle, setModalTitle] = useState('导入')
const [modalStep, setModalStep] = useState(0)
const [isUp, setIsUp] = useState(1) // 1上0下架状态
const [upDownModal, setUpDownModal] = useState(false)
const [shopsOption, setShopsOption] = useState<GetProductCommodityGetShopResponse>([])
const [checkedValues, setCheckedValues] = useState<any>([])
const [currentOptionId, setCurrentOptionId] = useState()
const [isDisabledOKbtn, setIsDisabledOKbtn] = useState<boolean>(false)
const [shopId, setShopId] = useState<any>()
const columns: ColumnType<any>[] = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 60
},
{
title: '商品名称',
dataIndex: 'name',
key: 'name',
className: 'commonPickColor',
width: 240,
ellipsis: true,
render: (text: any, record: any) => <a title={text} onClick={() => handleSee(record)}>{text}&nbsp;<EyeOutlined /></a>
},
{
title: '商品品类',
dataIndex: ['customerCategory', 'name'],
key: 'customerCategory.name',
},
{
title: '商品品牌',
dataIndex: ['brand', 'name'],
key: 'brand.name',
},
{
title: '单位',
dataIndex: 'unitName',
key: 'unitName',
},
{
title: '产品定价',
dataIndex: 'priceType',
key: 'priceType',
render: (text:any, reocrd:any)=>{
if(text===1)
return '现货价格'
else if(text===2)
return '价格需要询价'
else if(text===3)
return '积分兑换商品'
},
filters: [
{
text: '现货价格',
value: 1,
},
{
text: '价格需要询价',
value: 2,
},
{
text: '积分兑换商品',
value: 3,
},
],
onFilter: (value, record) => record.priceType === value,
},
{
title: '价格',
dataIndex: 'min',
key: 'min',
render: (text:any, reocrd:any) => {
if(reocrd.priceType === 1){
if(reocrd.max === reocrd.min)
return <>{reocrd.min}</>
else
return <>{reocrd.min} ~ ¥{reocrd.max}</>
}
if(reocrd.priceType === 3){
if(reocrd.max === reocrd.min)
return <>{reocrd.min}</>
else
return <>{reocrd.min} ~ {reocrd.max}</>
}
if(reocrd.priceType === 2)
return null
}
},
{
title: '申请审核时间',
dataIndex: 'applyTime',
key: 'applyTime',
render: (text:any, record:any)=>text && moment(text).format('YYYY-MM-DD HH:mm:ss')
},
{
title: '商品状态',
dataIndex: 'status',
key: 'status',
render: (text: any, record: any) => {
let component: ReactNode = null
if (record.status === 1)
component = (<><span className="commonStatusStop"></span>待提交审核</>)
else if (record.status === 2)
component = (<><span className="commonStatusModify"></span>待审核</>)
else if (record.status === 3)
component = (<><span className="commonStatusInvalid"></span>审核不通过</>)
else if (record.status === 4)
component = (<><span className="commonStatusValid"></span>审核通过</>)
else if (record.status === 5)
component = (<span style={{ color: '#00B37A', padding: '2px 5px', background: 'rgba(235,247,242,1)', borderRadius: '4px' }}>已上架</span>)
else if (record.status === 6)
component = (<span style={{ padding: '2px 5px', background: 'rgba(244,245,247,1)', borderRadius: '4px' }}>已下架</span>)
return component
},
filters: [
{
text: '待提交审核',
value: 1,
},
{
text: '待审核',
value: 2,
},
{
text: '审核不通过',
value: 3,
},
{
text: '审核通过',
value: 4,
},
{
text: '已上架',
value: 5,
},
{
text: '已下架',
value: 6,
}
],
onFilter: (value, record) => record.status === value,
},
{
title: '操作',
dataIndex: 'option',
width: 160,
render: (text: any, record: any) => renderOptionButton(record)
}
];
const renderOptionButton = (record: any) => {
// 操作常量
const statusAndOperationList = {
'1': ['复制', '提交审核', '修改', '删除'],
'2': ['复制'],
'3': ['复制', '修改'],
'4': ['复制', '上架', '修改'],
'5': ['复制', '下架'],
'6': ['复制', '上架', '修改'],
}
const operationHandler = {
'复制': () => clickCopy(record),
'提交审核': () => clickSubmitCheck(record),
'修改': () => clickModify(record.id),
'删除': () => confirmDelete(record.id),
'上架': () => clickUp(1, record.id),
'下架': () => clickUp(0, record.id),
}
return (
<TableOperation
record={record}
statusOperationMap={statusAndOperationList}
operationHandler={operationHandler}
priorityOperationName="提交审核"
/>
)
}
const fetchData = (params: any) => {
return new Promise((resolve, reject) => {
PublicApi.getProductCommodityGetCommodityList(params).then(res => {
const { data } = res
resolve(data)
})
})
}
const handleSee = (record: any) => {
history.push(`/memberCenter/commodityAbility/commodity/products/detail?id=${record.id}`)
}
const clickModify = (id: number) => {
history.push(`/memberCenter/commodityAbility/commodity/products/edit?id=${id}`)
}
const handleCancel = () => {
console.log('cancel')
setImportModal(false)
}
const rowSelection = {
selectedRowKeys: selectedRowKeys,
onChange: (selectedRowKeys: any, selectedRows: any) => {
setSelectRow(selectedRows);
setSelectedRowKeys(selectedRowKeys);
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
}
}
const modalLoadTemplate = () => {
console.log('模板下载!')
}
const modalUpload = () => {
console.log('上传')
setModalStep(1)
setModalTitle('导入检查')
}
const exportErrorLog = () => {
console.log('导出错误')
}
const modalImportData = () => {
setModalStep(2)
setModalTitle('数据导入')
console.log('下一步,导入数据')
}
const step0Description = <>
<ul className={styles.step0Description}>
<li>点击下载 EXCEL文件模板 <a onClick={modalLoadTemplate}>下载</a></li>
<li>按照模板整理货品资料</li>
<li>点击导入按钮,导入整理好的货品资料</li>
</ul>
</>
const step1Description = <div className={styles.step1Description}>
<h4>正在进行数据导入检查</h4>
<p>请稍后…</p>
</div>
const step1DescripSuccess = <div className={styles.step1Description}>
<h4>无错误格式数据</h4>
<p>继续导入请按下一步</p>
<Button type="primary" onClick={modalImportData}>下一步</Button>
</div>
const step1Exception = <div className={styles.step1Description}>
<h4>存在错误格式数据,已生成错误日志</h4>
<p>请导出错误日志修正数据后再次导入</p>
</div>
const step2Description = <div className={styles.step1Description}>
<h4>正在进行数据导入</h4>
<p>请稍后…</p>
</div>
const step2DescripSuccess = <div className={styles.step1Description}>
<h4>数据全部导入成功</h4>
<p>继续导入请点击继续导入,导入完成请点击导入完成</p>
<Button type="primary">继续导入</Button>&nbsp;&nbsp;&nbsp;&nbsp;<Button>完成导入</Button>
</div>
const step2Exception = <div className={styles.step1Description}>
<h4>导入完成请点击导入完成</h4>
<p>已生成错误日志,请导出错误日志修正数据后再次导入</p>
</div>
const [step1DescriptState, setStep1DescriptState] = useState(step1Description)
const [step2DescriptState, setStep2DescriptState] = useState(step2Description)
// timer
const [exceptionCheck, setExceptionCheck] = useState(false); // 默认无异常
const [exceptionData, setExceptionData] = useState(false); // 默认无异常
const [time, setTime] = useState(0); // timer
useEffect(() => {
clearInterval(timeChange)
}, [])
useEffect(() => {
console.log(modalStep)
if (modalStep === 1) runTimer()
if (modalStep === 2) runTimer()
}, [modalStep])
useEffect(() => {
if (time >= 100) {
clearInterval(timeChange)
setTime(100)
if (modalStep === 1) setStep1DescriptState(step1DescripSuccess)
if (modalStep === 2) setStep2DescriptState(step2DescripSuccess)
console.log('倒计时完毕!', modalStep)
}
}, [time])
const runTimer = () => {
setTime(0)
timeChange = setInterval(() => setTime(t => t + Math.floor(Math.random() * 10)), 200)
}
//timer end
const step1Icon = <>
<Progress
type="circle"
strokeColor={{
'0%': '#669EDE',
'100%': '#41CC9E',
}}
percent={time}
/>
</>
const step2Icon = <>
<Progress
type="circle"
strokeColor={{
'0%': '#669EDE',
'100%': '#41CC9E',
}}
percent={time}
/>
</>
const handleOkDeleteBatch = () => {
setDeleteBatchModal(false)
console.log('删除批次')
}
const handleCancelDelete = () => {
setDeleteBatchModal(false)
console.log('取消删除')
}
const onChangeUpShop = (values) => {
// 判断上架之前是否有店铺 有即可以上下架
if(judgeShopRef.current){
PublicApi.getTemplateShopFindShop({
memberId: JSON.parse(window.localStorage.getItem('auth')).memberId,
memberRoleId: JSON.parse(window.localStorage.getItem('auth')).memberRoleId
}).then(res => {
if(res.data.id){
setShopId(res.data.id)
setCheckedValues(values)
}else{
message.error('您还还未创建店铺,请先创建店铺!')
setTimeout(() => {
history.push('/memberCenter/shopAbility/infoManage')
}, 1000)
}
})
judgeShopRef.current = false
} else {
setCheckedValues(values)
}
}
const clickUp = (param: any, id: any) => { // param: 0 下架 1上架
setCurrentOptionId(id)
PublicApi.getProductCommodityGetShop({id: id}).then(res => {
setShopsOption(res.data)
setCheckedValues(res.data.filter(_=>_.isCheck))
})
setIsUp(param)
setUpDownModal(true)
}
const handleUp = () => {
setIsDisabledOKbtn(true)
let params = {
id: currentOptionId,
shopList: checkedValues
}
if(isUp)
if(checkedValues.length > 0){
PublicApi.postProductCommodityPublishCommodity({storeId: shopId, ...params}).then(res => {
setUpDownModal(false)
ref.current.reload()
setIsDisabledOKbtn(false)
})
}else{
setIsDisabledOKbtn(false)
message.error('请选择需要上架的商城!')
}
else
PublicApi.postProductCommodityOffPublishCommodity(params).then(res => {
setUpDownModal(false)
ref.current.reload()
setIsDisabledOKbtn(false)
})
}
const handleCancelUp = () => {
upForm.resetFields()
setUpDownModal(false)
}
const clickCopy = (record: any) => {
const { id } = record;
if(id){
confirm({
title: '确定要执行复制操作?',
icon: <ExclamationCircleOutlined />,
onOk() {
PublicApi.postProductCommodityCopyCommodity({id: id}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
},
onCancel() {
console.log('Cancel');
},
okText: '确定',
cancelText: '取消'
})
}
}
const clickSubmitCheck = (record:any) => {
console.log('提交审核')
const { id } = record;
if(id)
PublicApi.postProductCommodityApplyCheckCommodity({id: id}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
}
const handleMenuClick = (e: any) => {
console.log('menu', e, selectedRowKeys); // 1 批量删除;2 删除导入批次
if(e.key === '1'){
console.log('批量删除')
handleBatchDelete(selectedRowKeys, true)
}else if(e.key === '2'){
console.log('删除导入批次')
setDeleteBatchModal(true)
}
}
const handleBatchDelete = (ids: string[], param?: boolean) => {
if(ids.length)
if(param){
confirm({
title: '确定要执行批量删除操作?',
icon: <ExclamationCircleOutlined />,
onOk() {
//@ts-ignore
PublicApi.postProductCommodityDeleteBatchCommodity({idList: ids}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
},
okType: 'danger',
onCancel() {
console.log('Cancel');
},
okText: '确定',
cancelText: '取消'
})
}else{
//@ts-ignore
PublicApi.postProductCommodityDeleteBatchCommodity({idList: ids}).then(res => {
if(res.code === 1000)
ref.current.reload()
})
}
else
message.error('请选择需要操作的商品!')
}
const confirmDelete = (paramId: any) => {
confirm({
title: '确定要执行删除操作?',
icon: <ExclamationCircleOutlined />,
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk() {
handleBatchDelete([paramId])
},
onCancel() {
console.log('Cancel');
},
});
}
const menuMore = (
<Menu onClick={(e) => handleMenuClick(e)}>
<Menu.Item key="1" icon={<DeleteOutlined />}>
批量删除
</Menu.Item>
<Menu.Item key="2" icon={<DeleteOutlined />}>
删除导入批次
</Menu.Item>
</Menu>
)
const controllerBtns = (
<Space>
<Button
type='primary'
onClick={()=>history.push('/memberCenter/commodityAbility/commodity/products/add')}
>
<PlusOutlined />新建
</Button>
<Button style={{margin:'0 16px'}} onClick={()=>setImportModal(true)}>导入数据</Button>
<Dropdown overlay={menuMore} trigger={['click']}>
<Button>
更多 <DownOutlined />
</Button>
</Dropdown>
</Space>
);
return (
<PageHeaderWrapper>
<Card>
<StandardTable
columns={columns}
currentRef={ref}
rowSelection={rowSelection}
tableProps={{
rowKey: 'id',
}}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values =>ref.current.reload(values)}
expressionScope={{
controllerBtns,
}}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'name',
FORM_FILTER_PATH,
)
FormEffectHooks.onFieldChange$('brandId').subscribe(state => {
searchBrandOptionEffect(actions, 'brandId')
})
FormEffectHooks.onFieldChange$('customerCategoryId').subscribe(state => {
searchCustomerCategoryOptionEffect(actions, 'customerCategoryId')
})
}}
schema={productSchema}
/>
}
/>
</Card>
<Modal
title={modalTitle}
visible={importModal}
onCancel={handleCancel}
maskClosable={false}
footer={null}
>
{
modalStep === 0 && <>
<Result
icon={<FileExcelOutlined />}
title={step0Description}
extra={<Button style={{ width: '100%' }} type="primary" onClick={modalUpload}>上传</Button>}
/>
</>
}
{
modalStep === 1 && !exceptionCheck && <>
<Result
icon={step1Icon}
title={step1DescriptState}
/>
</>
}
{
modalStep === 1 && exceptionCheck && <>
<Result
icon={<Progress type="circle" percent={100} status="exception" />}
title={step1Exception}
extra={<Button onClick={exportErrorLog}>导出错误日志</Button>}
/>
</>
}
{
modalStep === 2 && !exceptionData && <>
<Result
icon={step2Icon}
title={step2DescriptState}
/>
</>
}
{
modalStep === 2 && exceptionData && <>
<Result
icon={<Progress type="circle" percent={100} status="exception" />}
title={step2Exception}
extra={<Button onClick={exportErrorLog}>导出错误日志</Button>}
/>
</>
}
</Modal>
<Modal
title="删除导入批次"
visible={deleteBatchModal}
onOk={handleOkDeleteBatch}
onCancel={handleCancelDelete}
okButtonProps={{ danger: true }}
>
<Form
layout="vertical"
>
<Form.Item label="选择要删除的批次">
<Select placeholder="请选择批次号">
<Select.Option value="542424">4245242452</Select.Option>
</Select>
</Form.Item>
</Form>
</Modal>
<Modal
title={isUp ? '商品上架' : '商品下架'}
visible={upDownModal}
onOk={handleUp}
onCancel={handleCancelUp}
forceRender={true}
okButtonProps={{ disabled: isDisabledOKbtn }}
>
<Form
layout="vertical"
>
<Form.Item
label={
<span>
{isUp ? '选择' : '反选'}需要{isUp ? '上架' : '下架'}的商城&nbsp;
<Tooltip title="已上架的商城为已勾选的商城,不可选择,只可以选择未勾选的商城。">
<QuestionCircleOutlined />
</Tooltip>
</span>
}
>
<Checkbox.Group style={{ width: '100%' }} onChange={onChangeUpShop} value={checkedValues}>
<Row>
{
Array.isArray(shopsOption) && shopsOption.map((item, index) => <Col key={index} span={8}>
<Checkbox value={item}>{item.name}</Checkbox>
</Col>)
}
</Row>
</Checkbox.Group>
</Form.Item>
</Form>
</Modal>
</PageHeaderWrapper>
)
}
export default Products
......@@ -3,45 +3,45 @@
* @Date: 2020-10-15 15:41:51
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-10-28 14:49:44
* @Description:
* @Description:
*/
import {
MEMBER_STATUS_NORMAL,
MEMBER_STATUS_FROZEN,
CREDIT_REPAYMENT_STATUS_OUTSTANDING,
CREDIT_REPAYMENT_STATUS_UNCONFIRMED,
CREDIT_REPAYMENT_STATUS_PAID,
CREDIT_REPAYMENT_STATUS_OVERDUE,
CREDIT_OUTER_STATUS_UNCOMMITTED,
CREDIT_OUTER_STATUS_UNCONFIRMED,
CREDIT_OUTER_STATUS_SUCCESS,
CREDIT_OUTER_STATUS_FAILED,
CREDIT_INNER_STATUS_UNCOMMITTED,
CREDIT_INNER_STATUS_COMMITTED,
CREDIT_INNER_STATUS_SUCCESS_1,
CREDIT_INNER_STATUS_SUCCESS_2,
CREDIT_INNER_STATUS_SUCCESS_3,
CREDIT_INNER_STATUS_FAILED,
CREDIT_INNER_STATUS_CONFIRM_SUCCESS,
CREDIT_INNER_STATUS_CONFIRM_FAILED,
CREDIT_STATUS_NOT_APPLIED,
CREDIT_STATUS_APPLYING,
CREDIT_STATUS_NORMAL,
CREDIT_STATUS_FROZEN,
MEMBER_STATUS_NORMAL,
MEMBER_STATUS_FROZEN,
CREDIT_REPAYMENT_STATUS_OUTSTANDING,
CREDIT_REPAYMENT_STATUS_UNCONFIRMED,
CREDIT_REPAYMENT_STATUS_PAID,
CREDIT_REPAYMENT_STATUS_OVERDUE,
CREDIT_OUTER_STATUS_UNCOMMITTED,
CREDIT_OUTER_STATUS_UNCONFIRMED,
CREDIT_OUTER_STATUS_SUCCESS,
CREDIT_OUTER_STATUS_FAILED,
CREDIT_INNER_STATUS_UNCOMMITTED,
CREDIT_INNER_STATUS_COMMITTED,
CREDIT_INNER_STATUS_SUCCESS_1,
CREDIT_INNER_STATUS_SUCCESS_2,
CREDIT_INNER_STATUS_SUCCESS_3,
CREDIT_INNER_STATUS_FAILED,
CREDIT_INNER_STATUS_CONFIRM_SUCCESS,
CREDIT_INNER_STATUS_CONFIRM_FAILED,
CREDIT_STATUS_NOT_APPLIED,
CREDIT_STATUS_APPLYING,
CREDIT_STATUS_NORMAL,
CREDIT_STATUS_FROZEN,
} from '@/constants';
// 授信状态 Badge map
// 账单交易状态
export const BILL_TRADE_STATUS_UNCONFIRMED = 1; // 待确认还款结果
export const BILL_TRADE_STATUS_OUTSTANDIND = 2; // 确认未到账
export const BILL_TRADE_STATUS_RECEIVED = 3; // 确认到账
export const BILL_TRADE_STATUS_UNCONFIRMED = 1; // 待确认还款结果
export const BILL_TRADE_STATUS_OUTSTANDIND = 2; // 确认未到账
export const BILL_TRADE_STATUS_RECEIVED = 3; // 确认到账
// 账单状态 StatusTag map
export const BILL_TRADE_STATUS_TAB_MAP = {
[BILL_TRADE_STATUS_UNCONFIRMED]: 'primary',
[BILL_TRADE_STATUS_OUTSTANDIND]: 'danger',
[BILL_TRADE_STATUS_RECEIVED]: 'success',
[BILL_TRADE_STATUS_UNCONFIRMED]: 'primary',
[BILL_TRADE_STATUS_OUTSTANDIND]: 'danger',
[BILL_TRADE_STATUS_RECEIVED]: 'success',
};
// 还款状态 StatusTag map
......@@ -49,43 +49,43 @@ export const CREDIT_REPAYMENT_STATUS_TAG_MAP = {
[CREDIT_REPAYMENT_STATUS_OUTSTANDING]: 'default',
[CREDIT_REPAYMENT_STATUS_UNCONFIRMED]: 'primary',
[CREDIT_REPAYMENT_STATUS_PAID]: 'success',
[CREDIT_REPAYMENT_STATUS_OVERDUE]: 'danger',
[CREDIT_REPAYMENT_STATUS_OVERDUE]: 'danger',
};
// 授信状态 Badge map
export const CREDIT_STATUS_BADGE_MAP = {
[CREDIT_STATUS_NOT_APPLIED]: '#FF991F',
[CREDIT_STATUS_APPLYING]: '#00B37A',
[CREDIT_STATUS_NOT_APPLIED]: '#FF991F',
[CREDIT_STATUS_APPLYING]: '#00B37A',
[CREDIT_STATUS_NORMAL]: '#00B37A',
[CREDIT_STATUS_FROZEN]: '#E63F3B',
};
// 授信状态 StatusTag map
export const CREDIT_STATUS_TAG_MAP = {
[CREDIT_STATUS_NOT_APPLIED]: 'warning',
[CREDIT_STATUS_APPLYING]: 'success',
[CREDIT_STATUS_NOT_APPLIED]: 'warning',
[CREDIT_STATUS_APPLYING]: 'success',
[CREDIT_STATUS_NORMAL]: 'success',
[CREDIT_STATUS_FROZEN]: 'danger',
};
// 授信外部状态
export const CREDIT_OUTER_STATUS_TAG_MAP = {
[CREDIT_OUTER_STATUS_UNCOMMITTED]: 'default',
[CREDIT_OUTER_STATUS_UNCONFIRMED]: 'primary',
[CREDIT_OUTER_STATUS_SUCCESS]: 'success',
[CREDIT_OUTER_STATUS_FAILED]: 'danger',
[CREDIT_OUTER_STATUS_UNCOMMITTED]: 'default',
[CREDIT_OUTER_STATUS_UNCONFIRMED]: 'primary',
[CREDIT_OUTER_STATUS_SUCCESS]: 'success',
[CREDIT_OUTER_STATUS_FAILED]: 'danger',
};
// 授信内部部状态 Badge map
export const CREDIT_INNER_STATUS_BADGE_MAP = {
[CREDIT_INNER_STATUS_UNCOMMITTED]: '#669EDE',
[CREDIT_INNER_STATUS_COMMITTED]: '#41CC9E',
[CREDIT_INNER_STATUS_SUCCESS_1]: '#41CC9E',
[CREDIT_INNER_STATUS_SUCCESS_2]: '#41CC9E',
[CREDIT_INNER_STATUS_SUCCESS_3]: '#41CC9E',
[CREDIT_INNER_STATUS_FAILED]: '#EF6260',
[CREDIT_INNER_STATUS_CONFIRM_SUCCESS]: '#41CC9E',
[CREDIT_INNER_STATUS_CONFIRM_FAILED]: '#EF6260',
[CREDIT_INNER_STATUS_UNCOMMITTED]: '#669EDE',
[CREDIT_INNER_STATUS_COMMITTED]: '#41CC9E',
[CREDIT_INNER_STATUS_SUCCESS_1]: '#41CC9E',
[CREDIT_INNER_STATUS_SUCCESS_2]: '#41CC9E',
[CREDIT_INNER_STATUS_SUCCESS_3]: '#41CC9E',
[CREDIT_INNER_STATUS_FAILED]: '#EF6260',
[CREDIT_INNER_STATUS_CONFIRM_SUCCESS]: '#41CC9E',
[CREDIT_INNER_STATUS_CONFIRM_FAILED]: '#EF6260',
};
......@@ -108,8 +108,8 @@ export const CREDIT_INNER_STATUS_BADGE_MAP = {
// 流转状态
export const moveStatusMap = {
'1': { title: '冻结', type: 'danger' },
'2': { title: '解冻', type: 'success' },
'2': { title: '冻结', type: 'danger' },
'1': { title: '解冻', type: 'success' },
}
// 会员状态
......@@ -146,4 +146,4 @@ export const accountMemberType = {
'2': '企业个人会员',
'3': '渠道会员',
'4': '渠道个人会员',
}
\ No newline at end of file
}
......@@ -11,6 +11,7 @@ import { history } from 'umi'
import { useHttpRequest } from '@/hooks/useHttpRequest'
import { encryptedByAES } from '@/utils/cryptoAes'
import QRCode from 'qrcode'
import { cond } from 'lodash'
export interface OrderPayModalProps {
currentRef: any,
......@@ -68,19 +69,20 @@ const payTextList = ["",
'货到付款'
]
let timeChange; // Tiemr
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 [current, setCurrent] = useState(0) // 0选择方式 1线下支付方式 2授信支付 3余额支付 4微信支付 5货到付款 6支付宝 1000清除
const [payStep, setPayStep] = useState(0) // 支付模态框的步骤 0选方式 1下一步的具体操作 2输入支付密码
const mobilePayFlag = useRef(0) // 用于判断移动支付类型 4微信
const mobilePayFlag = useRef(0) // 用于判断移动支付类型 4微信6支付宝
const [qrLoading, setQrLoading] = useState(false)
const [code, setCode] = useState('')
const [qrCodeInfo, setQrCodeInfo] = useState({ generateCharacter: '', qrUrl: '' })
const [number, setNumber] = useState([0,1,2,3,4,5])
......@@ -89,6 +91,7 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
const [creditInfo, setCreditInfo] = useState<any>()
const [balanceInfo, setBalanceInfo] = useState<any>()
const [payOnReceived, setPayOnReceived] = useState<boolean>(false) // 是否要禁用到付方式
const [blankAccountInfo, setBlankAccountInfo] = useState<any>()
useEffect(() => {
if (currentRef) {
......@@ -99,6 +102,17 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
}
}, [])
//timer start
const [openTimer, setOpenTimer] = useState(0); // timer
useEffect(() => {
if(openTimer === 1) runTimerJump()
else clearInterval(timeChange)
}, [openTimer])
const runTimerJump = () => {
timeChange = setInterval(() => pollPayResult(), 3000)
}
//timer ending
useEffect(() => {
if (!visible) {
setCurrent(0)
......@@ -128,13 +142,33 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
QRCode.toDataURL(qrCodeInfo.generateCharacter).then((url:any) => {
setQrCodeInfo({...qrCodeInfo, qrUrl: url})
// 轮询支付结果
// setOpenTimer(1)
setOpenTimer(1)
})
.catch((err:any) => {
console.error(err)
})
}
const pollPayResult = () => {
if(qrCodeInfo.qrUrl) {
// @ts-ignore
PublicApi.getOrderPayResultsl({id, paymentInformationId: currentPayInfoId}).then(res => {
console.log(res)
if(res.code === 1000) {
if(res.data) {
setOpenTimer(0)
message.success('支付成功')
setTimeout(() => {
history.goBack()
}, 1000)
}
} else {
message.error(res.message)
}
})
}
}
const handleConfirm = () => {
console.log(data,'data')
if (current === 0) {
......@@ -142,6 +176,12 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
if (checked.id === 5) { // 线下支付
setCurrent(1)
setPayStep(1)
// 获取账户信息
PublicApi.getSettleAccountsCorporateAccountConfig({memberId: data.supplyMembersId}).then(res => {
if(res.code === 1000) {
setBlankAccountInfo(res.data)
}
})
} else if (checked.id === 6) { // 授信额度支付
console.log('选择了授信支付')
setIsSpin(true)
......@@ -181,15 +221,24 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
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()
// 生成微信扫码支付
mobilePayFlag.current = 4
setCurrent(4)
setPayStep(1)
setQrLoading(true)
handleSubmitPay()
}
// else if(checked.id === 1) {
// console.log('选择了支付宝支付')
// // 生成支付宝扫码支付
// mobilePayFlag.current = 6
// setCurrent(6)
// setPayStep(1)
// setQrLoading(true)
// handleSubmitPay()
// }
else {
message.error('暂只支持线下支付、授信额度支付、余额支付方式、货到付款')
message.error('暂只支持线下支付、授信额度支付、余额支付、货到付款、微信支付方式')
}
} else {
message.error('请先选择支付方式')
......@@ -243,6 +292,7 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
} else {
setCurrent(0)
setPayStep(0)
setOpenTimer(0)
}
}
......@@ -269,11 +319,11 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
const res = await run(params)
if (res.code === 1000) {
if(mobilePayFlag.current !== 4) {
if(mobilePayFlag.current !== 4) { // 非微信
history.goBack()
} else {
console.log(res, '二维码信息')
setQrCodeInfo({ ...qrCodeInfo, generateCharacter: res.data })
setQrLoading(false)
}
}
}
......@@ -287,6 +337,7 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
const handleBack = () => {
setCurrent(0)
setPayStep(0)
setOpenTimer(0)
}
const handleOk = () => {
......@@ -341,9 +392,6 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
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 }}>
......@@ -352,7 +400,7 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
<div className={style.radioBox}>
{
(value as any[]).map(v => {
if(payOnReceived && v.value === 7) { // 到付
if(payOnReceived && v.value === 7) { // 过滤到付
return null
} else {
return <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>
......@@ -367,6 +415,9 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
{
current === 1 &&
<div>
<p>账号名称:{blankAccountInfo?.name}</p>
<p>银行账号:{blankAccountInfo?.bankAccount}</p>
<p>开 户 行:{blankAccountInfo?.bankDeposit}</p>
<p style={{fontWeight: "bold"}}>上传支付凭证</p>
<Upload
name='file'
......@@ -471,15 +522,21 @@ const OrderPayModal: React.FC<OrderPayModalProps> = (props) => {
}
{/* 微信扫码支付 */}
{
current === 4 &&
(current === 4 || current === 6) &&
<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>
<Spin spinning={qrLoading}>
<div className={style.qrCodeImage}>
{
qrCodeInfo.qrUrl && <>
<img src={qrCodeInfo.qrUrl} alt="扫码支付"/>
<div className={style.scanTips}>
<ScanOutlined className={style.scanIcon} />
<span>打开 {mobilePayFlag.current === 4 ? '微信' : '支付宝'}App<br />扫码完成支付</span>
</div>
</>
}
</div>
</div>
</Spin>
</div>
}
{/* 输入支付密码 payStep===2 */}
......
import React, { useState } from 'react'
import { Card, Button, Modal } from 'antd'
import { StandardTable } from 'god'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { PublicApi } from '@/services/api'
import { baseOrderListColumns } from './constant'
import { PurchaseOrderOutWorkState } from '@/constants'
import { history } from 'umi'
import { tableListSchema } from '../_public/order/constant'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import { DatePicker } from '@formily/antd-components'
import Submit from '@/components/NiceForm/components/Submit'
import DateRangePickerUnix from '@/components/NiceForm/components/DateRangePickerUnix'
// 订单查询
export interface PurchaseOrderProps { }
const fetchTableData = async (params) => {
console.log(params,'params')
const { data } = await PublicApi.getOrderProcurementOrderList(params)
return data
}
// 最后一步开始调试 TODO
const PurchaseOrder: React.FC<PurchaseOrderProps> = (props) => {
const [saleVisible, setSaleVisible] = useState<any>(false)
// 售后唤起弹窗 @todo
const handleSaleAfter = (id) => {
}
const handleEvaluate = (id) => {
history.push(`/memberCenter/tranactionAbility/purchaserEvaluation/unevaluated`)
}
const secondColumns: any[] = baseOrderListColumns.concat([
{
title: '操作',
align: 'center',
dataIndex: 'ctl',
key: 'ctl',
render: (text, record) => <>
{ record.externalState === PurchaseOrderOutWorkState.FINISH_ORDER && <Button type='link' onClick={() => handleEvaluate(record.id)}>评价</Button> }
{/* todo */}
{/* <Button type='link' onClick={() => handleSaleAfter(record.id)}>售后</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) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'orderNo',
FORM_FILTER_PATH,
);
},
components: {
DateRangePickerUnix,
Submit
}
}
}}
/>
</Card>
</PageHeaderWrapper>
}
PurchaseOrder.defaultProps = {}
export default PurchaseOrder
\ No newline at end of file
import React, { useState, useRef } from 'react'
import { Card, Button, Modal } from 'antd'
import { StandardTable } from 'god'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { PublicApi } from '@/services/api'
import { baseOrderListColumns } from './constant'
import { PurchaseOrderOutWorkState } from '@/constants'
import { history } from 'umi'
import { tableListSchema } from '../_public/order/constant'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import { DatePicker } from '@formily/antd-components'
import Submit from '@/components/NiceForm/components/Submit'
import DateRangePickerUnix from '@/components/NiceForm/components/DateRangePickerUnix'
import NiceForm from '@/components/NiceForm'
import { createFormActions } from '@formily/antd'
// 订单查询
export interface PurchaseOrderProps { }
const fetchTableData = async (params) => {
console.log(params,'params')
const { data } = await PublicApi.getOrderProcurementOrderList(params)
return data
}
const formActions = createFormActions();
// 最后一步开始调试 TODO
const PurchaseOrder: React.FC<PurchaseOrderProps> = (props) => {
const [saleVisible, setSaleVisible] = useState<any>(false)
const ref = useRef<any>({})
// 售后唤起弹窗 @todo
const handleSaleAfter = (id) => {
}
const handleEvaluate = (id) => {
history.push(`/memberCenter/tranactionAbility/purchaserEvaluation/unevaluated`)
}
const secondColumns: any[] = baseOrderListColumns.concat([
{
title: '操作',
align: 'center',
dataIndex: 'ctl',
key: 'ctl',
render: (text, record) => <>
{ record.externalState === PurchaseOrderOutWorkState.FINISH_ORDER && <Button type='link' onClick={() => handleEvaluate(record.id)}>评价</Button> }
{/* todo */}
{/* <Button type='link' onClick={() => handleSaleAfter(record.id)}>售后</Button> */}
</>
}
])
const controllerBtns = <Button style={{width: 140}} onClick={() => {}} type='default'>导出</Button>
return <PageHeaderWrapper>
<Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
columns={secondColumns}
currentRef={ref}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => ref.current.reload(values)}
expressionScope={{
controllerBtns,
}}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'orderNo',
FORM_FILTER_PATH,
)
}}
schema={tableListSchema}
components={{
DateRangePickerUnix,
Submit
}}
/>
}
tableProps={{
rowKey: 'orderNo',
}}
// 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) => {
// useStateFilterSearchLinkageEffect(
// $,
// actions,
// 'orderNo',
// FORM_FILTER_PATH,
// );
// },
// components: {
// DateRangePickerUnix,
// Submit
// }
// }
// }}
/>
</Card>
</PageHeaderWrapper>
}
PurchaseOrder.defaultProps = {}
export default PurchaseOrder
import React, { useState, useCallback, useRef, useContext, useEffect } from 'react';
import { OrderDetailContext } from '../../../_public/order/context';
import { PublicApi } from '@/services/api';
import { history } from 'umi'
import { Button } from 'antd';
import OrderDetailHeader from '@/pages/transaction/components/OrderDetailHeader';
import OrderDetailWrapper from '@/pages/transaction/components/OrderDetailWrapper';
......@@ -11,14 +11,24 @@ import OrderPayModal from '@/pages/transaction/components/orderPayModal';
const ReadyConfirmContract: React.FC = () => {
const { formContext, id, detailList } = useOrderDetail({type: 'purchaseOrder'})
const {data, currentPayInfoId} = formContext
const payRef = useRef<any>({})
const handleClick = useCallback(() => {
payRef.current.setVisible(true)
}, [])
// 处理积分支付跳转
if(data && currentPayInfoId){
if(data.paymentInformationResponses.length > 0){
let obj = data.paymentInformationResponses.filter(item => item.id === Number(currentPayInfoId))[0]
if(obj.channel === 0) {
history.push(`/pay?orderId=${btoa(JSON.stringify({ orderId: id, memberId: data.supplyMembersId, memberRoleId: data.supplyMembersRoleId }))}`)
} else {
payRef.current.setVisible(true)
}
}
}
}, [data, currentPayInfoId])
const renderPayPrice = () => {
const {data, currentPayInfoId} = formContext
if(data){
if(data.paymentInformationResponses.length > 0){
let obj = data.paymentInformationResponses.filter(item => item.id === Number(currentPayInfoId))[0]
......
import React, { useRef } from 'react'
import { history, Link } from 'umi'
import { Button, Row, Col, Progress, Popconfirm } from 'antd'
import { PublicApi } from '@/services/api'
import EyePreview from '@/components/EyePreview'
import { formatTimeString } from '@/utils'
import { ORDER_TYPE, PurchaseOrderInsideWorkState, PurchaseOrderOutWorkState } from '@/constants'
import StatusColors from '../../components/StatusColors'
import { FieldTimeOutlined } from '@ant-design/icons'
import {
Chart,
Coordinate,
Legend,
View,
} from 'bizcharts';
import Interval from 'bizcharts/lib/geometry/Interval'
import DataSet from "@antv/data-set";
// 圆形环状金额显示
const CircleChart = props => {
const { sumPrice = 100, alreadyPay = 10 } = props
const { DataView } = DataSet;
const userData = [
{ type: '总金额', value: (sumPrice - alreadyPay) || 100 },
{ type: '已支付', value: alreadyPay }
];
const userDv = new DataView();
userDv.source(userData).transform({
type: 'percent',
field: 'value',
dimension: 'type',
as: 'percent',
});
return <Chart placeholder={false} height={40} autoFit>
<Legend visible={false} />
{/* 绘制图形 */}
<View data={userDv.rows}>
<Coordinate type="theta" innerRadius={0.75} />
<Interval
position="percent"
adjust="stack"
color={['type', ['#EEF0F3', '#41CC9E']]}
tooltip={false}
/>
</View>
</Chart>
}
// 业务hooks, 待支付订单
export const useSelfTable = (props) => {
const { refTable } = props
const ref = useRef<any>({})
const handleCancel = (param) => {
PublicApi.postOrderPurchaseOrderCancel({id: param}).then(res => {
if(res.code === 1000) {
refTable.current.reload()
}
})
}
const payOrderColumns: any[] = [
{
title: '订单号',
align: 'center',
dataIndex: 'orderNo',
key: 'orderNo',
render: (text, record) => {
// 查看订单, 需根据状态显示不同schema
return (
<EyePreview url={`/memberCenter/tranactionAbility/purchaseOrder/readyPayOrder/preview?id=${record.id}`}>
{text}
</EyePreview>
)
}
},
{
title: '订单摘要/下单时间',
align: 'center',
dataIndex: 'orderThe',
key: 'orderThe',
render: (text, record) => <>
<div>{text}</div>
<div><FieldTimeOutlined />{formatTimeString(record.createTime)}</div>
</>,
width: 200
},
{
title: '供应会员',
align: 'left',
dataIndex: 'supplyMembersName',
key: 'supplyMembersName',
},
{
title: '总金额/已支付(元)',
align: 'left',
dataIndex: 'sumPrice',
key: 'sumPrice',
render: (text, record) => <Row justify='space-between'>
<Col>
<div><span>总金额:</span><span>{record.sumPrice}</span></div>
<div><span>已支付:</span><span>{record.alreadyPay || 0}</span></div>
</Col>
<Col style={{ width: 40 }}>
<CircleChart sumPrice={record.sumPrice} alreadyPay={record.alreadyPay} />
</Col>
</Row>,
width: 200
},
{
title: '订单类型',
align: 'center',
dataIndex: 'type',
key: 'type',
render: (text) => ORDER_TYPE[text]
},
{
title: '外部状态',
align: 'center',
dataIndex: 'externalState',
key: 'externalState',
render: text => <StatusColors status={text} type='out' />
},
{
title: '内部状态',
align: 'center',
dataIndex: 'interiorState',
key: 'interiorState',
render: (text) => <StatusColors status={text} type='inside' />
},
{
title: '当前支付', align: 'center', dataIndex: 'currentPayments', width: 140, render: (text, record) => <>
<Row justify='space-between'>
<Col>{record.currentPayments} / {record.sum}</Col>
{/* <Col>
{
record.currentPayments !== record.sum &&
(record.externalState === PurchaseOrderOutWorkState.PAY_ORDER || record.externalState === PurchaseOrderOutWorkState.CONFIRM_NOT_ARRIVED_ACCOUNT) &&
<Link to={`/memberCenter/tranactionAbility/purchaseOrder/readyPayOrder/detail?id=${record.id}`}>去支付</Link>
}
</Col> */}
</Row>
<Progress percent={Math.ceil(record.currentPayments / record.sum)} showInfo={false} />
</>
},
{
title: '操作',
align: 'center',
dataIndex: 'ctl',
key: 'ctl',
render: (text, record) => <>
{
record.currentPayments !== record.sum &&
(
record.externalState === PurchaseOrderOutWorkState.PAY_ORDER ||
record.externalState === PurchaseOrderOutWorkState.CONFIRM_NOT_ARRIVED_ACCOUNT ||
record.externalState === PurchaseOrderOutWorkState.NOT_PAYMENT_FINAL ||
record.externalState === PurchaseOrderOutWorkState.CONFIRM_WITHOUT_ARRIVED_ACCOUNT
) &&
<Link to={`/memberCenter/tranactionAbility/purchaseOrder/readyPayOrder/detail?id=${record.id}`}>去支付</Link>
}
{
(
record.externalState === PurchaseOrderOutWorkState.PAY_ORDER &&
!record.signatureLogId ||
record.externalState === PurchaseOrderOutWorkState.CONFIRM_NOT_ARRIVED_ACCOUNT &&
record.interiorState !== PurchaseOrderInsideWorkState.PAY_SUCCESS
) &&
<Popconfirm
title="是否要取消该订单?"
onConfirm={() => handleCancel(record.id)}
okText="是"
cancelText="否"
>
<Button type='link'>取消订单</Button>
</Popconfirm>
}
</>
}
]
return {
columns: payOrderColumns
}
}
import React, { useRef } from 'react'
import { history, Link } from 'umi'
import { Button, Row, Col, Progress, Popconfirm } from 'antd'
import { PublicApi } from '@/services/api'
import EyePreview from '@/components/EyePreview'
import { formatTimeString } from '@/utils'
import { ORDER_TYPE, PurchaseOrderInsideWorkState, PurchaseOrderOutWorkState } from '@/constants'
import StatusColors from '../../components/StatusColors'
import { FieldTimeOutlined } from '@ant-design/icons'
import {
Chart,
Coordinate,
Legend,
View,
} from 'bizcharts';
import Interval from 'bizcharts/lib/geometry/Interval'
import DataSet from "@antv/data-set";
// 圆形环状金额显示
const CircleChart = props => {
const { sumPrice = 100, alreadyPay = 10 } = props
const { DataView } = DataSet;
const userData = [
{ type: '总金额', value: (sumPrice - alreadyPay) || 100 },
{ type: '已支付', value: alreadyPay }
];
const userDv = new DataView();
userDv.source(userData).transform({
type: 'percent',
field: 'value',
dimension: 'type',
as: 'percent',
});
return <Chart placeholder={false} height={40} autoFit>
<Legend visible={false} />
{/* 绘制图形 */}
<View data={userDv.rows}>
<Coordinate type="theta" innerRadius={0.75} />
<Interval
position="percent"
adjust="stack"
color={['type', ['#EEF0F3', '#41CC9E']]}
tooltip={false}
/>
</View>
</Chart>
}
// 业务hooks, 待支付订单
export const useSelfTable = (props) => {
const { refTable } = props
const ref = useRef<any>({})
const handleCancel = (param) => {
PublicApi.postOrderPurchaseOrderCancel({id: param}).then(res => {
if(res.code === 1000) {
refTable.current.reload()
}
})
}
const payOrderColumns: any[] = [
{
title: '订单号',
align: 'center',
dataIndex: 'orderNo',
key: 'orderNo',
render: (text, record) => {
// 查看订单, 需根据状态显示不同schema
return (
<EyePreview url={`/memberCenter/tranactionAbility/purchaseOrder/readyPayOrder/preview?id=${record.id}`}>
{text}
</EyePreview>
)
}
},
{
title: '订单摘要/下单时间',
align: 'center',
dataIndex: 'orderThe',
key: 'orderThe',
render: (text, record) => <>
<div>{text}</div>
<div><FieldTimeOutlined />{formatTimeString(record.createTime)}</div>
</>,
width: 200
},
{
title: '供应会员',
align: 'left',
dataIndex: 'supplyMembersName',
key: 'supplyMembersName',
},
{
title: '总金额/已支付(元)',
align: 'left',
dataIndex: 'sumPrice',
key: 'sumPrice',
render: (text, record) => <Row justify='space-between'>
<Col>
<div><span>总金额:</span><span>{record.sumPrice}</span></div>
<div><span>已支付:</span><span>{record.alreadyPay || 0}</span></div>
</Col>
<Col style={{ width: 40 }}>
<CircleChart sumPrice={record.sumPrice} alreadyPay={record.alreadyPay} />
</Col>
</Row>,
width: 200
},
{
title: '订单类型',
align: 'center',
dataIndex: 'type',
key: 'type',
render: (text) => ORDER_TYPE[text]
},
{
title: '外部状态',
align: 'center',
dataIndex: 'externalState',
key: 'externalState',
render: text => <StatusColors status={text} type='out' />
},
{
title: '内部状态',
align: 'center',
dataIndex: 'interiorState',
key: 'interiorState',
render: (text) => <StatusColors status={text} type='inside' />
},
{
title: '当前支付', align: 'center', dataIndex: 'currentPayments', width: 140, render: (text, record) => <>
<Row justify='space-between'>
<Col>{record.currentPayments} / {record.sum}</Col>
{/* <Col>
{
record.currentPayments !== record.sum &&
(record.externalState === PurchaseOrderOutWorkState.PAY_ORDER || record.externalState === PurchaseOrderOutWorkState.CONFIRM_NOT_ARRIVED_ACCOUNT) &&
<Link to={`/memberCenter/tranactionAbility/purchaseOrder/readyPayOrder/detail?id=${record.id}`}>去支付</Link>
}
</Col> */}
</Row>
<Progress percent={Math.ceil(record.currentPayments / record.sum)} showInfo={false} />
</>
},
{
title: '操作',
align: 'center',
dataIndex: 'ctl',
key: 'ctl',
render: (text, record) => <>
{
record.currentPayments !== record.sum &&
(
record.externalState === PurchaseOrderOutWorkState.PAY_ORDER ||
record.externalState === PurchaseOrderOutWorkState.CONFIRM_NOT_ARRIVED_ACCOUNT ||
record.externalState === PurchaseOrderOutWorkState.NOT_PAYMENT_FINAL ||
record.externalState === PurchaseOrderOutWorkState.CONFIRM_WITHOUT_ARRIVED_ACCOUNT
) &&
<Link to={`/memberCenter/tranactionAbility/purchaseOrder/readyPayOrder/detail?id=${record.id}`}>去支付</Link>
}
{
(
record.externalState === PurchaseOrderOutWorkState.PAY_ORDER &&
!record.signatureLogId ||
record.externalState === PurchaseOrderOutWorkState.CONFIRM_NOT_ARRIVED_ACCOUNT &&
record.interiorState !== PurchaseOrderInsideWorkState.PAY_SUCCESS
) &&
<Popconfirm
title="是否要取消该订单?"
onConfirm={() => handleCancel(record.id)}
okText="是"
cancelText="否"
>
<Button type='link'>取消订单</Button>
</Popconfirm>
}
</>
}
]
return {
columns: payOrderColumns
}
}
import React from 'react'
import { history } from 'umi'
import { Card, Button, Space, Dropdown, Menu } from 'antd'
import { StandardTable } from 'god'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { PublicApi } from '@/services/api'
import { useSelfTable } from './model/useSelfTable'
import { PlusCircleOutlined, DownOutlined, DeleteOutlined } from '@ant-design/icons'
import DropDeleteDown from '@/components/DropDeleteDown'
import { tableListSchema } from './schema'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import Submit from '@/components/NiceForm/components/Submit'
import DateRangePickerUnix from '@/components/NiceForm/components/DateRangePickerUnix'
// 待确认收货单
export interface FirstApprovedOrderProps {}
const fetchTableData = async (params) => {
const { data } = await PublicApi.getOrderReceivingGoodsPendingOrderList(params)
return data
}
// TODO
const FirstApprovedOrder:React.FC<FirstApprovedOrderProps> = (props) => {
const {
columns
} = useSelfTable()
return <PageHeaderWrapper>
<Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
columns={columns}
rowKey={'orderNo'}
formilyLayouts={{
justify: 'space-between'
}}
formilyProps={{
ctx: {
inline: false,
schema: tableListSchema,
effects: ($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'orderNo',
FORM_FILTER_PATH,
);
},
components: {
DateRangePickerUnix,
Submit
}
}
}}
/>
</Card>
</PageHeaderWrapper>
}
FirstApprovedOrder.defaultProps = {}
export default FirstApprovedOrder
\ No newline at end of file
import React from 'react'
import { history } from 'umi'
import { Card, Button, Space, Dropdown, Menu } from 'antd'
import { StandardTable } from 'god'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { PublicApi } from '@/services/api'
import { useSelfTable } from './model/useSelfTable'
import { PlusCircleOutlined, DownOutlined, DeleteOutlined } from '@ant-design/icons'
import DropDeleteDown from '@/components/DropDeleteDown'
import { tableListSchema } from './schema'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import Submit from '@/components/NiceForm/components/Submit'
import DateRangePickerUnix from '@/components/NiceForm/components/DateRangePickerUnix'
// 待确认收货单
export interface FirstApprovedOrderProps {}
const fetchTableData = async (params) => {
const { data } = await PublicApi.getOrderReceivingGoodsPendingOrderList(params)
return data
}
// TODO
const FirstApprovedOrder:React.FC<FirstApprovedOrderProps> = (props) => {
const {
columns
} = useSelfTable()
return <PageHeaderWrapper>
<Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
columns={columns}
rowKey={'orderNo'}
formilyLayouts={{
justify: 'space-between'
}}
formilyProps={{
ctx: {
inline: false,
schema: tableListSchema,
effects: ($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'orderNo',
FORM_FILTER_PATH,
);
},
components: {
DateRangePickerUnix,
Submit
}
}
}}
/>
</Card>
</PageHeaderWrapper>
}
FirstApprovedOrder.defaultProps = {}
export default FirstApprovedOrder
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