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

feat: 新增e账户管理通联页面

parent 9e2bd3b9
......@@ -5,17 +5,17 @@
* @LastEditTime: 2021-08-26 16:31:22
*/
// import CommodityRoute from './commodityRoute' // 商品能力路由
import MemberRoute from './memberRoute' // 会员能力路由
// import MemberRoute from './memberRoute' // 会员能力路由
// import ShopRoute from './shopRoute' // 店铺能力路由
// import ChannelRoute from './channelRoute' // 渠道能力路由
import TranactionRoute from './tranactionRoute' // 交易能力路由
// import TranactionRoute from './tranactionRoute' // 交易能力路由
// import LogisticsRoute from './logisticsRoutes' // 物流能力路由
// import PayandSettleRoute from './payandSettle' //支付与结算
import AuthConfigRoute from './authConfigRoute'
import PayandSettleRoute from './payandSettle' //支付与结算
// import AuthConfigRoute from './authConfigRoute'
// import AfterService from './afterServiceRoute' // 售后
// import HandlingRoute from './handlingRoute'; // 加工能力
import DealAbilityRoute from './dealAbilityRoute'; //
import marketingRoute from './marketingRoute';
// import DealAbilityRoute from './dealAbilityRoute'; //
// import marketingRoute from './marketingRoute';
import asyncRoutes from '../router.config.json';
// import ProcurementRoute from './procurementRoute';
// import { callForBidsRoute } from './procurementRoute/callForBids';
......@@ -33,7 +33,7 @@ const homeRoute = {
component: '@/pages/home',
};
// const routes = isDev ? [ homeRoute, marketingRoute, MemberRoute ] : asyncRoutes;
const routes = isDev ? [ homeRoute, MemberRoute, marketingRoute ] : asyncRoutes;
const routes = isDev ? [ PayandSettleRoute ] : asyncRoutes;
const memberCenterRoute = {
path: '/memberCenter',
......
......@@ -317,6 +317,12 @@ const payandSettleRoute: RouterChild = {
component: '@/pages/payandSettle/capitalAccounts/accountLists/applyWithdraw',
hideInMenu: true,
},
// e账户管理-通联
{
path: '/memberCenter/payandSettle/capitalAccounts/eAccount',
name: 'eAccount',
component: '@/pages/payandSettle/capitalAccounts/eAccount',
},
],
},
// 资金账户管理
......@@ -367,4 +373,5 @@ const payandSettleRoute: RouterChild = {
},
]
}
export default payandSettleRoute
.repayment {
padding: 56px 24px 33px;
display: flex;
align-items: center;
background: #8777D9;
border-radius: 4px;
border: 1px solid #8777D9;
color: #fff;
&-left {
flex: 1;
}
&-right {
flex-shrink: 0;
}
&-end {
margin-top: 32px;
}
&-action {
margin-left: 24px;
}
&-time {
line-height: 22px;
margin-right: 8px;
font-weight: 400;
}
}
.statistic {
&-title {
margin-bottom: 28px;
line-height: 22px;
font-weight: 400;
}
&-amount {
line-height: 40px;
font-size: 32px;
font-weight: 500;
}
&-input {
display: block !important;
width: 180px !important;
line-height: 40px !important;
padding: 8px 0 !important;
font-size: 32px !important;
font-weight: 500 !important;
color: #fff !important;
background: none !important;
border-top: none !important;
border-right: none !important;
border-left: none !important;
border-image: initial !important;
outline: none !important;
border-bottom: 1px solid #fff !important;
}
}
.infoRight {
margin: 35px 0;
.rightTitle {
height: 36px;
font-weight: 400;
color: #6B778C;
line-height: 36px;
}
.rightInfo {
height: 36px;
font-weight: 500;
color: #303133;
line-height: 36px;
}
}
.repayinfo {
background-color: #4279DF;
}
// 账户详情右侧操作按钮
.rightActions {
display: flex;
margin-top: 70px;
.rightAction {
width: 88px;
height: 40px;
&:last-child{
background-color: #6B778C;
color: #fff;
margin-left: 24px;
}
}
}
// 扫码充值
.qrCodeImage {
text-align: center;
width: 224px;
height: 224px;
margin: 20px auto 42px;
&>img {
display: block;
width: 100%;
height: 100%;
}
}
.scanTips {
display: flex;
justify-content: center;
align-items: center;
color: #6b778c;
margin-bottom: 18px;
.scanIcon {
font-size: 30px;
margin-right: @margin-sm;
}
}
\ No newline at end of file
import React, { useState, useEffect, useRef } from 'react'
import { history } from 'umi'
import { Card, Space, Row, Col, Button, Table, Modal, message } from 'antd'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import ReutrnEle from '@/components/ReturnEle'
import styles from './index.less'
import StatusTag from '@/components/StatusTag'
import cx from 'classnames'
import moment from 'moment'
import { ColumnType } from 'antd/lib/table/interface'
import ModalForm from '@/components/ModalForm'
import { createFormActions } from '@formily/antd'
import { rechargeSchema } from './schema'
import { memberStatusMap, moveStatusMap, operationMap, statusMap } from '../../constant'
import { StandardTable } from 'god'
import QRCode from 'qrcode';
import { ScanOutlined } from '@ant-design/icons'
import { getPayAssetAccountGetAccountStatusRecord, getPayAssetAccountGetAccountTradeRecord, getPayAssetAccountGetAssetAccount, getPayAssetAccountGetRechargeResult, postPayAssetAccountRecharge } from '@/services/PayV2Api'
interface rechargeItem {
codeUrl: string;
tradeRecordId: number;
}
const schemaActions = createFormActions()
let timeChange; // Tiemr
const EAccountDetail: React.FC<{}> = () => {
const modalRef = useRef<any>()
const refTrade = useRef<any>({})
const [moveData, setMoveData] = useState<any>()
const [details, setDetails] = useState<any>({ accountBalance: 0, lockBalance: 0})
const [pageId, setPageId] = useState<any>()
const [isBtnLoading, setIsBtnLoading] = useState<boolean>(false)
const [scanVisible, setScanVisible] = useState<boolean>(false)
const [qrCode, setQrCode] = useState('')
const [renderCodeCharacter, setRenderCodeCharacter] = useState<rechargeItem>()
const [rechargeType, setRechargeType] = useState<number>()
useEffect(() => {
getAccountInfo()
clearInterval(timeChange)
} ,[])
//timer
const [openTimer, setOpenTimer] = useState(0); // timer
useEffect(() => {
console.log(openTimer)
if(openTimer === 1) runTimerJump()
}, [openTimer])
const runTimerJump = () => {
timeChange = setInterval(() => pollPayResult(), 3000)
}
useEffect(() => {
if(renderCodeCharacter?.codeUrl){
generateQrCode()
}
}, [renderCodeCharacter])
const getAccountInfo = async () => {
const { id = 161 } = history.location.query
setPageId(id)
let res = await getPayAssetAccountGetAssetAccount({id: id+''})
const { code, data } = res
setDetails(data)
getPayAssetAccountGetAccountStatusRecord({memberAssetAccountId: id + ''}).then(res => {
const { data } = res
setMoveData(data)
})
refTrade.current.reload()
}
// 获取交易记录
const fetchTradeData = (params) => {
return new Promise((resolve, reject) => {
getPayAssetAccountGetAccountTradeRecord({memberAssetAccountId: history.location.query.id + '', ...params}).then(res => {
const { data } = res
resolve(data)
})
})
}
const generateQrCode = () => {
// 生成二维码
QRCode.toDataURL(renderCodeCharacter.codeUrl).then((url:any) => {
setQrCode(url)
// 轮询支付结果
setOpenTimer(1)
})
.catch((err:any) => {
console.error(err)
})
}
const pollPayResult = () => {
if(renderCodeCharacter?.tradeRecordId) {
getPayAssetAccountGetRechargeResult({tradeRecordId: renderCodeCharacter.tradeRecordId + ''}).then(res => {
console.log(res)
if(res.code === 1000) {
if(res.data) {
clearInterval(timeChange)
setScanVisible(false)
Modal.success({
content: '充值成功',
});
getAccountInfo()
}
} else {
message.error(res.message)
}
})
}
}
const columns: ColumnType<any>[] = [
{
title: '交易流水号',
dataIndex: 'tradeCode',
key: 'tradeCode',
},
{
title: '交易时间',
dataIndex: 'tradeTime',
key: 'tradeTime',
render: (text: any) => moment(text).format("YYYY-MM-DD HH:mm:ss")
},
{
title: '交易金额(元)',
dataIndex: 'tradeMoney',
key: 'tradeMoney',
render: (t, r) => `${operationMap[r.operation]['operator']} ${t.toFixed(2)}`
},
{
title: '交易项目',
dataIndex: 'operation',
key: 'operation',
render: (t, r) => operationMap[t]['title']
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (text:any, record:any) => (<StatusTag title={statusMap[text]['title']} type={statusMap[text]['type']} />)
},
{
title: '意见',
dataIndex: 'remark',
key: 'remark',
},
];
const moveColumns: ColumnType<any>[] = [
{
title: '序号',
dataIndex: 'id',
key: 'id',
render: (t, c, i) => i + 1
},
{
title: '操作角色',
dataIndex: ['memberAssetAccount','parentMemberRoleName'],
key: 'id',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (text:any, record:any) => (<StatusTag title={moveStatusMap[text]['title']} type={moveStatusMap[text]['type']} />)
},
{
title: '操作',
dataIndex: 'operation',
key: 'operation',
render: (t, r)=> {
return t === 1 ? '解冻资金账户' : '冻结资金账户'
}
},
{
title: '操作时间',
dataIndex: 'createTime',
key: 'createTime',
render: (text: any) => moment(text).format("YYYY-MM-DD HH:mm:ss")
},
{
title: '意见',
dataIndex: 'remark',
key: 'remark',
},
];
const handleConfirm = () => {
schemaActions.submit()
}
const handleCannel = () => {
}
const handleSubmit = (value) => {
// 提交重置
setIsBtnLoading(true)
setRechargeType(value['type'][0])
let parasm = {
memberAssetAccountId: pageId,
money: Number(value.money),
type: value['type'][0]
}
postPayAssetAccountRecharge(parasm).then(res => {
const { code, data } = res
if(code === 1000){
modalRef.current.setVisible(false)
setScanVisible(true)
setRenderCodeCharacter(data)
}
// else{
// message.error(res.message)
// }
setIsBtnLoading(false)
})
}
const handleRecharge = () => {
modalRef.current.setVisible(true)
}
const handleScan = () => {
setScanVisible(false)
getAccountInfo()
refTrade.current.reload()
clearInterval(timeChange)
}
return (
<PageHeaderWrapper
title="账户详情"
onBack={() => history.goBack()}
backIcon={<ReutrnEle />}
>
<Space direction="vertical" style={{width:'100%'}}>
<Card headStyle={{borderBottom:'none'}} title="账户信息">
<Row gutter={100}>
<Col
// span={8}
xxl={8}
xl={9}
lg={9}
>
<div className={cx(styles.repayment, styles.repayinfo)}>
<div className={styles['repayment-left']}>
<div className={styles.statistic}>
<div className={styles['statistic-title']}>可用余额(元):</div>
<div className={styles['statistic-amount']}>
{`${((details.accountBalance*100 - details.lockBalance*100)/100).toFixed(2)}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
</div>
</div>
<div className={styles['repayment-end']}>
<span className={styles['repayment-time']}>
{details?.parentMemberName}
</span>
</div>
</div>
</div>
</Col>
<Col
// span={10}
xxl={10}
xl={8}
lg={8}
>
<div className={styles.infoRight}>
<Row>
<Col
// span={4}
xxl={4}
xl={10}
lg={10}
>
<p className={styles.rightTitle}>账户归属:</p>
</Col>
<Col
// span={20}
xxl={20}
xl={14}
lg={14}
>
<p className={styles.rightInfo}>{details?.parentMemberName}</p>
</Col>
</Row>
<Row>
<Col
xxl={4}
xl={10}
lg={10}
>
<p className={styles.rightTitle}>账户余额(元):</p>
</Col>
<Col
// span={20}
xxl={20}
xl={14}
lg={14}
>
<p className={styles.rightInfo}>{details?.accountBalance?.toFixed(2)}</p>
</Col>
</Row>
<Row>
<Col
xxl={4}
xl={10}
lg={10}
>
<p className={styles.rightTitle}>锁定金额(元):</p>
</Col>
<Col
// span={20}
xxl={20}
xl={14}
lg={14}
>
<p className={styles.rightInfo}>{details?.lockBalance?.toFixed(2)}</p>
</Col>
</Row>
<Row>
<Col
xxl={4}
xl={10}
lg={10}
>
<p className={styles.rightTitle}>账户状态:</p>
</Col>
<Col
// span={20}
xxl={20}
xl={14}
lg={14}
>
<p className={styles.rightInfo}>
{
details?.accountStatus &&
<StatusTag title={memberStatusMap[details.accountStatus]['title']} type={memberStatusMap[details.accountStatus]['type']} />
}
</p>
</Col>
</Row>
</div>
</Col>
<Col
// span={20}
xxl={6}
xl={7}
lg={7}
>
<div className={styles.rightActions}>
<Button className={styles.rightAction} type="primary" onClick={handleRecharge}>充值</Button>
<Button className={styles.rightAction} onClick={() => history.push(`/memberCenter/payandSettle/capitalAccounts/accountLists/applyWithdraw?id=${details?.id}`)}>申请提现</Button>
</div>
</Col>
</Row>
</Card>
</Space>
<Space direction="vertical" style={{width:'100%'}}>
<Card headStyle={{borderBottom:'none'}} title="交易记录">
<StandardTable
columns={columns}
currentRef={refTrade}
fetchTableData={(params: any) => fetchTradeData(params)}
/>
</Card>
</Space>
<Space direction="vertical" style={{width:'100%'}}>
<Card headStyle={{borderBottom:'none'}} title="流转记录">
<Table columns={moveColumns} dataSource={moveData} pagination={false} />
</Card>
</Space>
<ModalForm
modalTitle='账户充值'
currentRef={modalRef}
schema={rechargeSchema}
actions={schemaActions}
confirm={handleConfirm}
onSubmit={handleSubmit}
cancel={handleCannel}
modalProps={{
okText: "确定充值",
confirmLoading: isBtnLoading,
destroyOnClose: true
}}
// effects={($, {setFieldState}) => {
// $('onFieldInit', 'type').subscribe(parentState => {
// getPayMemberPayList({memberId: details.memberId, memberType: details.memberLevelType}).then(res => {
// console.log(res, 'res')
// })
// setFieldState('type', state => {
// state.props["x-component-props"].dataSource = []
// });
// })
// }}
/>
{/* 扫码充值 */}
<Modal
title='账户充值'
visible={scanVisible}
onOk={handleScan}
onCancel={handleScan}
>
<div className={styles.qrCodeImage}>
<img src={qrCode} alt=""/>
<div className={styles.scanTips}>
<ScanOutlined className={styles.scanIcon} />
<span>打开 {rechargeType === 2 ? '微信' : '支付宝'}App<br />扫码完成充值</span>
</div>
</div>
</Modal>
</PageHeaderWrapper>
)
}
export default EAccountDetail
import { ISchema } from '@formily/antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import alipay from '@/assets/imgs/alipay_icon.png';
import wxpay from '@/assets/imgs/wechat_icon.png';
export const searchSchema: ISchema = {
type: 'object',
properties: {
mageLayout: {
type: 'object',
'x-component': 'mega-layout',
properties: {
topLayout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
grid: true,
},
properties: {
parentMemberName: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
placeholder: '账户归属',
align: 'flex-left',
},
},
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
justifyContent: 'end',
},
colStyle: {
marginRight: 20,
},
},
properties: {
memberStatus: {
type: 'string',
'x-component-props': {
placeholder: '会员状态',
style: { width: '174px' },
},
enum: [
{
label: '正常',
value: 1,
},
{
label: '已冻结',
value: 2,
}
],
},
accountStatus: {
type: 'string',
'x-component-props': {
placeholder: '账户状态',
style: { width: '174px' },
},
enum: [
{
label: '正常',
value: 1,
},
{
label: '已冻结',
value: 2,
}
],
},
"[startTime,endTime]": {
type: 'array',
"x-component": 'DateRangePickerUnix',
'x-component-props': {
placeholder: ['开始时间','结束时间'],
},
},
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: '查询',
},
},
},
},
},
},
},
};
export const rechargeSchema: ISchema = {
type: 'object',
properties: {
NO_SUBMIT: {
type: 'object',
"x-component": "mega-layout",
"x-component-props": {
labelAlign: 'left',
labelCol: 24,
wrapperCol: 24
},
properties: {
money: {
type: "string",
title: '充值金额',
'x-component-props': {
addonBefore: "¥",
// suffix: "RMB"
},
"x-rules": [
{
required: true,
message: '请输入充值金额'
},
{
validator: value => {
return isNaN(value)
},
message:'请正确输入数字金额'
},
{
pattern: /^\d+(\.\d{1,2})?$/,
message: '充值金额仅限两位小数',
},
]
},
type: {
type: "array:number",
"x-component": 'CardCheckBox',
"x-component-props": {
dataSource: [
// {id: 1, name: '支付宝', logoUrl: alipay},
{id: 2, name: '微信', logoUrl: wxpay}
],
type: 'radio' // CardCheckBox 单选模式
},
"title": "充值方式",
"x-rules": [
{
required: true,
message: '请选择充值方式'
}
],
}
}
}
}
}
\ No newline at end of file
// import { ISchema } from '@formily/antd';
import { useIntl } from '@/.umi/plugin-locale/localeExports';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { useIntl } from 'umi';
// import { getPurchaseOrderReadyAddPageSelectOption } from '@/pages/transaction/effect';
export const tableListSchema: any = () => {
......
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