Commit 42224544 authored by XieZhiXiong's avatar XieZhiXiong

Merge branch 'dev' into test

parents b1224a8b f79db54e
......@@ -53,6 +53,17 @@ const config: any = {
inlineLimit: 10000,
chunks: isProduction && ['vendors', 'umi'],
chainWebpack: function (config, { webpack }) {
config.module
.rule('svg')
.exclude.add(/pages/).end(); // 给内置的添加 exclude,这里根据自己的情况处理
config.module
.rule('svgr')
.test(/.svg$/)
.include.add(/pages/).end() // include 指定需要直接 svgr 的情况
.use('@svgr/webpack')
.loader(require.resolve('@svgr/webpack'));
isProduction && config.merge({
optimization: {
minimize: true,
......
<?xml version="1.0" encoding="UTF-8"?>
<svg width="56px" height="56px" viewBox="0 0 56 56" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title></title>
<defs>
<circle id="path-1" cx="28" cy="28" r="28"></circle>
</defs>
<g id="我" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Mask" fill="#E6E7EB" xlink:href="#path-1"></use>
<path d="M33.6555679,41.9707886 C33.6555679,39.4830014 35.5358268,40.29543 36.3612399,35.7393901 C36.7035576,33.8493771 38.3642448,35.7089168 38.6821448,31.3941714 C38.6821448,29.6745403 37.7757776,29.2472439 37.7757776,29.2472439 C37.7757776,29.2472439 38.2364274,26.702535 38.4170246,24.7441009 C38.640259,22.3042277 37.0383622,16 28.4925336,16 C19.9463292,16 18.3434933,22.3042277 18.5680425,24.7441009 C18.7482641,26.702535 19.2089139,29.2472439 19.2089139,29.2472439 C19.2089139,29.2472439 18.3025467,29.6745403 18.3025467,31.3941714 C18.6196954,35.7089168 20.2801947,33.8493771 20.6227003,35.7393901 C21.4491464,40.2953342 23.3279966,39.4830014 23.3279966,41.9707886 C23.3279966,46.1150562 21.3612426,48.0505874 15.2037493,50.3452814 C9.02681572,52.6468751 4,55.4864395 4,57.0869565 L4,61 L52.9999992,61 C52.9999992,61 53,58.6864194 53,57.0869565 C53,55.4864395 47.9580635,52.6468751 41.78113,50.3452814 C35.6234488,48.0505874 33.6555679,46.1150562 33.6555679,41.9707886 Z" fill="#FAFAFA" mask="url(#mask-2)"></path>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -35,17 +35,50 @@ const InputNumber: React.FC<InputNumberPropsType> = (props) => {
const handleReduce = (e) => {
e.stopPropagation()
if (value > minCount) {
onChange(Number(value) - 1, 'click')
onChange(accSub(value, 1), 'click')
}
}
const handleAdd = (e) => {
e.stopPropagation()
if (value < maxCount) {
onChange(Number(value) + 1, 'click')
onChange(accAdd(value, 1), 'click')
}
}
const accAdd = (num1,num2) => {
let r1, r2
try{
r1 = num1.toString().split('.')[1].length;
}catch(e){
r1 = 0;
}
try{
r2 = num2.toString().split(".")[1].length;
}catch(e){
r2 = 0;
}
const m = Math.pow(10, Math.max(r1,r2));
return Math.round(num1 * m + num2 * m)/m;
}
const accSub = (num1, num2) => {
let r1, r2;
try{
r1 = num1.toString().split('.')[1].length;
}catch(e){
r1 = 0;
}
try{
r2 = num2.toString().split(".")[1].length;
}catch(e){
r2 = 0;
}
const m = Math.pow(10,Math.max(r1,r2));
const n = (r1 >= r2) ? r1 : r2;
return (Math.round(num1 * m-num2 * m) / m).toFixed(n);
}
const handleChange = (e) => {
const { value } = e.target;
const reg = /^\d*([.]?\d{0,3})$/
......
......@@ -6,6 +6,8 @@ import PersonDropdown from './PersonDropdown'
import styles from '../styles/RightContent.less';
import { removeAuth, removeRouters, getAuth } from '@/utils/auth';
import { inject, observer } from 'mobx-react'
import Icon from '@ant-design/icons';
import { ReactComponent as DefaultAvatar } from '@/assets/imgs/default_avatar.svg';
const AvatarDropdown = (props) => {
......@@ -44,7 +46,12 @@ const AvatarDropdown = (props) => {
return (
<PersonDropdown overlay={menuHeaderDropdown}>
<span className={`${styles.action} ${styles.account}`}>
<Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
{
currentUser.avatar
? <Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
: <Icon component={() => <DefaultAvatar className={styles.logo} />} />
}
<span className={styles.name}>{currentUser.name}</span>
</span>
</PersonDropdown>
......
import React from 'react'
import { Layout, Menu, Avatar, Image } from 'antd'
import { AppstoreOutlined } from '@ant-design/icons'
import { Link } from 'umi'
import styles from '../styles/MenuSlider.less'
import { getRouters } from '@/utils/auth'
import { isDev } from '@/constants'
import {observer, inject} from 'mobx-react';
import CustomIcon from './CustomIcon'
import CustomIcon from './CustomIcon';
import Icon from '@ant-design/icons';
import { ReactComponent as DefaultAvatar } from '@/assets/imgs/default_avatar.svg';
const { Sider } = Layout
export interface OuterSiderProps {
......@@ -46,13 +47,13 @@ const OuterSider: React.FC<OuterSiderProps> = observer((props) => {
const siderMenu = getSubMenu()
return <>
<Sider collapsed={true} collapsedWidth={64} className={styles.wrapperSilder}>
{
props.UserStore.avatar
? <div className={styles.userPic}>
<img src={props.UserStore.avatar} className={styles.avatar} />
</div>
: <div className={styles.userPic} />
}
<div className={styles.userPic}>
{
props.UserStore.avatar
? <img src={props.UserStore.avatar} className={styles.avatar} />
: <Icon component={() => <DefaultAvatar className={styles.logo} />} />
}
</div>
<ul className={styles.menuBox}>
{
siderMenu.map(item => (
......
......@@ -53,6 +53,11 @@
width: 32px;
height: 32px;
}
.logo {
width: 32px;
height: 32px;
}
}
.wrapperSilder {
......
......@@ -58,6 +58,11 @@
vertical-align: top;
background: rgba(255, 255, 255, 0.85);
}
.logo {
width: 24px;
height: 24px;
margin-right: 8px;
}
}
}
......@@ -120,4 +125,4 @@
display: none;
}
}
}
\ No newline at end of file
}
......@@ -133,7 +133,13 @@ export const addSchema = {
prefix: "{{tableAddButton}}",
columns: "{{tableColumns}}"
// columns: "{{tableColumns}}",
}
},
'x-rules': [
{
required: true,
message: '请选择使用会员'
}
]
}
}
}
......
......@@ -13,6 +13,10 @@ import home_user from '@/assets/imgs/home_user.png';
import { UPLOAD_TYPE } from '@/constants'
import { PublicApi } from '@/services/api';
import {observer, inject} from 'mobx-react';
// import Icon from '@ant-design/icons';
import Icon from '@ant-design/icons';
import { ReactComponent as DefaultAvatar } from '@/assets/imgs/default_avatar.svg';
interface Iprops {}
const WEEKDAYS = ["天", "一","二", "三", "四", "五","六"];
......@@ -102,7 +106,7 @@ const UserCenter: React.FC<Iprops> = (props) => {
{
state.logo
? <img src={state.logo || ''} className={styles.logo}/>
: <span className={styles.text}>H</span>
: <Icon component={() => <DefaultAvatar className={styles.logo} />} />
}
<span className={styles.upload}>修改</span>
</Upload>
......
......@@ -24,11 +24,11 @@ const Address: React.FC<AddressPropsType> = (props) => {
}, [])
const fetchAddressList = (init = false) => {
let param = {
const param: any = {
current: 1,
pageSize: 50
}
//@ts-ignore
PublicApi.getLogisticsReceiverAddressPage(param).then(res => {
if (res.code === 1000) {
setAddressList(res.data?.data)
......@@ -41,14 +41,14 @@ const Address: React.FC<AddressPropsType> = (props) => {
const initDefaultAddress = async (addressList: GetLogisticsReceiverAddressPageResponseDetail[]) => {
let selectItem
for (let item of addressList) {
for (const item of addressList) {
if (item.isDefault === 1) {
selectItem = item
}
}
if (selectItem) {
setSelectKey(selectItem.id)
let res = await PublicApi.getLogisticsReceiverAddressGet({ id: selectItem.id })
const res = await PublicApi.getLogisticsReceiverAddressGet({ id: selectItem.id })
onChange(Object.assign(selectItem, res.data))
}
}
......@@ -56,13 +56,13 @@ const Address: React.FC<AddressPropsType> = (props) => {
const handleSelect = async (e: any) => {
setSelectKey(e.target.value)
let selectItem
for (let item of addressList) {
for (const item of addressList) {
if (item.id === e.target.value) {
selectItem = item
}
}
if (selectItem) {
let res = await PublicApi.getLogisticsReceiverAddressGet({ id: selectItem.id })
const res = await PublicApi.getLogisticsReceiverAddressGet({ id: selectItem.id })
onChange(Object.assign(selectItem, res.data))
}
}
......@@ -91,11 +91,11 @@ const Address: React.FC<AddressPropsType> = (props) => {
}
const handleSetDefaultAddress = async (addressItem: GetLogisticsReceiverAddressPageResponseDetail) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
let addressDetailRes = await PublicApi.getLogisticsReceiverAddressGet({ id: addressItem.id })
let param: GetLogisticsReceiverAddressGetResponse = addressDetailRes.data
const addressDetailRes = await PublicApi.getLogisticsReceiverAddressGet({ id: addressItem.id })
const param: GetLogisticsReceiverAddressGetResponse = addressDetailRes.data
param.isDefault = 1
//@ts-ignore
PublicApi.postLogisticsReceiverAddressUpdate(param).then(res => {
if (res.code === 1000) {
fetchAddressList()
......
......@@ -26,7 +26,7 @@ const Contract: React.FC<ContractPropsType> = (props) => {
<span>我同意签订:</span>
</Checkbox>
{
contractInfo && <a href={contractInfo?.contractUrl} download target="_blank" className={styles.checkbox_contract_text}>{contractInfo?.contractName}</a>
contractInfo && <a href={contractInfo?.contractUrl} download rel="noreferrer" target="_blank" className={styles.checkbox_contract_text}>{contractInfo?.contractName}</a>
}
</div>
</div>
......
......@@ -85,13 +85,15 @@ const Order: React.FC<OrderPropsType> = (props) => {
message.error("订单不存在")
history.goBack()
}
initOrderInfo()
if(storeId) {
initOrderInfo()
}
return () => {
if (sessionStorage.getItem("contractInfo")) {
sessionStorage.removeItem("contractInfo")
}
}
}, [])
}, [storeId])
const initOrderInfo = async () => {
const result = []
......@@ -120,9 +122,9 @@ const Order: React.FC<OrderPropsType> = (props) => {
try {
const param: any = {
productId,
shopId, storeId,
memberId: orderInfo.supplyMembersId,
memberRoleId: orderInfo.supplyMembersRoleId,
shopId: storeId,
memberId: sessionOrderInfo.supplyMembersId,
memberRoleId: sessionOrderInfo.supplyMembersRoleId,
}
const rulesRes = await PublicApi.getOrderTradingRulesByProductId(param)
const { data } = rulesRes
......
......@@ -33,8 +33,10 @@ const PayWay: React.FC<PayWayProps> = (props) => {
}
useEffect(() => {
fetchCreditInfo()
}, [])
if(expand) {
fetchCreditInfo()
}
}, [expand])
useEffect(() => {
if (payWayList && payWayList.length === 1) {
......@@ -49,9 +51,10 @@ const PayWay: React.FC<PayWayProps> = (props) => {
}
PublicApi.getPayCreditGetCredit(param).then(res => {
message.destroy()
if(res.code === 1000) {
setCreditInfo(res.data)
} else {
message.destroy()
}
})
}
......
/*
* @Author: XieZhiXiong
* @Date: 2020-09-29 15:51:31
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-11-04 10:02:55
* @Description:
*/
import { ISchema } from '@formily/antd';
import { UPLOAD_TYPE } from '@/constants';
import { PATTERN_MAPS } from '@/constants/regExp';
export const editModalSchema: ISchema = {
type: 'object',
properties: {
MEGA_LAYOUT: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelAlign: 'top',
full: true,
},
properties: {
applyQuota: {
type: 'string',
title: '申请调整额度',
'x-component-props': {
placeholder: '',
addonBefore: '¥',
},
'x-rules': [
{
required: true,
message: '请填写申请调整额度',
},
{
pattern: PATTERN_MAPS.money,
message: '请填写正数',
},
],
},
quotaSlide: {
type: 'number',
title: '',
'x-component': 'range',
'x-component-props': {
min: 0,
// max: 1024,
// marks: {
// 0: {
// label: '{{MinMarks}}',
// },
// 1024: {
// label: '{{MaxMarks}}',
// },
// },
style: {
margin: '0 20px 28px'
},
},
},
billDay: {
type: 'string',
title: '申请调整账单日期',
'x-component-props': {
placeholder: '',
addonAfter: '日',
},
'x-rules': [
{
required: true,
message: '请填写申请调整账单日期',
},
{
pattern: PATTERN_MAPS.quantity,
message: '请填写大于等于1的正整数',
},
{
validator(value) {
const intVal = +value;
return intVal > 28 || intVal < 0 ? '请输入大于0 小于等于 28的数值' : '';
}
},
],
},
repayPeriod: {
type: 'string',
title: '申请还款周期',
'x-component-props': {
placeholder: '',
addonAfter: '天',
},
'x-rules': [
{
required: true,
message: '请填写申请还款周期',
},
{
pattern: PATTERN_MAPS.quantity,
message: '请填写大于等于1的正整数',
},
],
},
fileList: {
type: 'string',
title: '申请附件',
'x-component': 'AntUpload',
'x-component-props': {
action: '/api/file/file/upload/prefix',
data: {
fileType: UPLOAD_TYPE,
prefix: '/creditApplication/applicationAttachment/',
},
beforeUpload: '{{beforeUpload}}',
accept: '.xls, .xlsx, .doc, .docx, .wps, .pdf, .jpg, .png, .jpeg',
},
'x-rules': [
{
required: false,
message: '请上传申请附件',
},
],
description: '一次只能上传一个附件,每个附件大小不能超过20M',
},
},
},
},
/*
* @Author: XieZhiXiong
* @Date: 2020-09-29 15:51:31
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-11-04 10:02:55
* @Description:
*/
import { ISchema } from '@formily/antd';
import { UPLOAD_TYPE } from '@/constants';
import { PATTERN_MAPS } from '@/constants/regExp';
export const editModalSchema: ISchema = {
type: 'object',
properties: {
MEGA_LAYOUT: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelAlign: 'top',
full: true,
},
properties: {
applyQuota: {
type: 'string',
title: '申请调整额度',
'x-component-props': {
placeholder: '',
addonBefore: '¥',
},
'x-rules': [
{
required: true,
message: '请填写申请调整额度',
},
{
pattern: PATTERN_MAPS.money,
message: '请填写正数',
},
],
},
quotaSlide: {
type: 'number',
title: '',
'x-component': 'range',
'x-component-props': {
min: 0,
// max: 1024,
// marks: {
// 0: {
// label: '{{MinMarks}}',
// },
// 1024: {
// label: '{{MaxMarks}}',
// },
// },
style: {
margin: '0 20px 28px'
},
},
},
billDay: {
type: 'string',
title: '申请调整账单日期',
'x-component-props': {
placeholder: '',
addonAfter: '日',
},
'x-rules': [
{
required: true,
message: '请填写申请调整账单日期',
},
{
pattern: PATTERN_MAPS.quantity,
message: '请填写大于等于1的正整数',
},
{
validator(value) {
const intVal = +value;
return intVal > 28 || intVal < 0 ? '请输入大于0 小于等于 28的数值' : '';
}
},
],
},
repayPeriod: {
type: 'string',
title: '申请还款周期',
'x-component-props': {
placeholder: '',
addonAfter: '天',
},
'x-rules': [
{
required: true,
message: '请填写申请还款周期',
},
{
pattern: PATTERN_MAPS.quantity,
message: '请填写大于等于1的正整数',
},
],
},
fileList: {
type: 'string',
title: '申请附件',
'x-component': 'AntUpload',
'x-component-props': {
action: '/api/file/file/upload/prefix',
data: {
fileType: UPLOAD_TYPE,
prefix: '/creditApplication/applicationAttachment/',
},
beforeUpload: '{{beforeUpload}}',
accept: '.xls, .xlsx, .doc, .docx, .wps, .pdf, .jpg, .png, .jpeg',
},
'x-rules': [
{
required: true,
message: '请上传申请附件',
},
],
description: '一次只能上传一个附件,每个附件大小不能超过20M',
},
},
},
},
};
\ No newline at end of file
......@@ -10,7 +10,6 @@ const QuotaFormQueryDetail: React.FC = () => {
id={id}
creditId={creditId}
target="/memberCenter/payandSettle/creditApplication/quotaFormQuery/detail"
isEdit
/>
);
};
......
......@@ -14,21 +14,19 @@ import {
import { createFormActions, FormEffectHooks } from '@formily/antd';
import lodash from 'lodash';
import { PublicApi } from '@/services/api';
import { PAY_CHANNEL_WECHAT } from '@/constants';
import MellowCard from '@/components/MellowCard';
import { Pie } from '@/components/Charts';
import StatusTag from '@/components/StatusTag';
import NiceForm from '@/components/NiceForm';
import { repaymentModalSchema, uploadVoucherModalSchema } from './schema';
import { createEffects } from './effects/repayment';
import { uploadVoucherModalSchema } from './schema';
import TradeRecord, { RecordParams, RecordRes } from '../TradeRecord';
import WxPayModal from '../WxPayModal';
import RefundModal from '../RefundModal';
import styles from './index.less';
const repaymentFormActions = createFormActions();
const uploadVoucherFormActions = createFormActions();
const { onFormInit$ } = FormEffectHooks;
const { Option } = Select;
export interface BillDetailParams {
......@@ -72,6 +70,10 @@ export interface BillDetailData {
* 收款人Id
*/
memberId: number
/**
* 收款人角色Id
*/
memberRoleId: number
};
export interface BillRecordParams extends RecordParams {
......@@ -113,7 +115,6 @@ interface IntroduceRowState {
name: string,
bankAccount: string,
bankDeposit: string,
memberId: number,
},
visibleRecord: boolean;
visibleRepayment: boolean;
......@@ -144,7 +145,6 @@ class IntroduceRow extends React.Component<IntroduceRowProps, IntroduceRowState>
name: '',
bankAccount: '',
bankDeposit: '',
memberId: 0,
},
visibleRecord: false,
visibleRepayment: false,
......@@ -180,7 +180,7 @@ class IntroduceRow extends React.Component<IntroduceRowProps, IntroduceRowState>
id: `${id}`,
}).then(res => {
this.setState({ billInfo: res });
this.getSettleAccountsCorporateAccountConfig(res.memberId, res.memberRoleId);
this.getSettleAccountsGetMemberAccountConfig(res.memberId, res.memberRoleId);
}).finally(() => {
this.setState({ billInfoLoading: false });
});
......@@ -188,13 +188,13 @@ class IntroduceRow extends React.Component<IntroduceRowProps, IntroduceRowState>
};
// 获取对公账户信息
getSettleAccountsCorporateAccountConfig = (memberId: number, memberRoleId: number) => {
getSettleAccountsGetMemberAccountConfig = (memberId: number, memberRoleId: number) => {
if (!memberId || !memberRoleId) {
return;
}
PublicApi.getSettleAccountsCorporateAccountConfig({
PublicApi.getSettleAccountsGetMemberAccountConfig({
memberId: `${memberId}`,
memberRoleId: `${memberRoleId}`,
roleId: `${memberRoleId}`,
}).then(res => {
if (res.code === 1000) {
this.setState({
......@@ -257,7 +257,7 @@ class IntroduceRow extends React.Component<IntroduceRowProps, IntroduceRowState>
switch (tradeChannel) {
// 微信支付
case 1: {
case PAY_CHANNEL_WECHAT: {
this.setState({
wxPayPrice: values.repayQuota,
wxPayUrl: res.data.payQRCode,
......@@ -289,10 +289,10 @@ class IntroduceRow extends React.Component<IntroduceRowProps, IntroduceRowState>
};
handleUploadVoucherSubmit = values => {
const { payProveList } = values;
const { payProveList = [] } = values;
const { repaymentValues, billId, bankAccount } = this.state;
if (!bankAccount || !bankAccount.id || !bankAccount.memberId) {
if (!bankAccount || !bankAccount.id) {
message.error('没有还款账户相关信息,无法还款');
return;
}
......@@ -317,7 +317,6 @@ class IntroduceRow extends React.Component<IntroduceRowProps, IntroduceRowState>
};
beforeUploadVoucher = file => {
console.log(file.size)
if (file.size / 1024 > 200) {
message.warning('图片大小超过200K');
return Promise.reject();
......@@ -563,57 +562,14 @@ class IntroduceRow extends React.Component<IntroduceRowProps, IntroduceRowState>
</MellowCard>
</Col>
</Row>
<Modal
title="还款"
width={576}
<RefundModal
visible={visibleRepayment}
confirmLoading={repaymentSubmitLoading}
onOk={() => repaymentFormActions.submit()}
billInfo={billInfo}
onCancel={() => this.setState({ visibleRepayment: false })}
destroyOnClose
>
<NiceForm
previewPlaceholder=""
effects={($, actions) => {
const { setFieldState, setFieldValue } = actions;
onFormInit$().subscribe(() => {
// 初始化数据
setFieldState('repayQuota', fileState => {
fileState.value = billInfo.residueRepayQuota;
fileState.rules = fileState.rules.concat({
validator(value) {
return +value > billInfo.residueRepayQuota ? '输入值已超出还款金额' : '';
}
});
});
setFieldState('amountSlide', fileState => {
fileState.value = billInfo.residueRepayQuota;
fileState.props['x-component-props'].max = billInfo.residueRepayQuota;
fileState.props['x-component-props'].marks = {
0: {
label: 0,
},
[billInfo.residueRepayQuota]: {
label: billInfo.residueRepayQuota,
},
};
});
});
createEffects($, actions);
}}
expressionScope={{
}}
actions={repaymentFormActions}
schema={repaymentModalSchema}
onSubmit={this.handleRepaymentSubmit}
/>
</Modal>
onSubmit={this.handleRepaymentSubmit}
confirmLoading={repaymentSubmitLoading}
/>
<Modal
title="上传支付凭证"
......
import { ISchema } from '@formily/antd';
import { UPLOAD_TYPE } from '@/constants';
export const repaymentModalSchema: ISchema = {
type: 'object',
properties: {
MEGA_LAYOUT: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelAlign: 'top',
full: true,
},
properties: {
repayQuota: {
type: 'string',
title: '还款金额',
'x-component-props': {
placeholder: '',
addonBefore: '¥',
},
'x-rules': [
{
required: true,
message: '请填写还款金额',
},
],
},
amountSlide: {
type: 'number',
title: '',
'x-component': 'range',
'x-component-props': {
min: 0,
// max: 20000,
},
},
tradeType: {
type: 'number',
enum: [
{
label: '线上支付方式',
value: 1,
},
{
label: '线下支付方式',
value: 2,
},
],
default: 1,
title: '选择支付方式',
'x-component-props': {
placeholder: '请选择',
},
'x-rules': [
{
required: true,
message: '请选择支付方式',
},
],
},
tradeChannel: {
type: 'string',
title: '选择支付渠道',
enum: [
{
label: '微信',
value: 1,
},
{
label: '支付宝',
value: 2,
},
{
label: '银联',
value: 3,
},
],
default: 1,
'x-component-props': {
placeholder: '请选择',
},
'x-rules': [
{
required: true,
message: '请选择支付渠道',
},
],
},
},
},
},
};
export const uploadVoucherModalSchema: ISchema = {
type: 'object',
properties: {
MEGA_LAYOUT: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelCol: 6,
wrapperCol: 18,
labelAlign: 'left',
full: true,
},
properties: {
name: {
type: 'string',
title: '还款账户名称',
'x-component': 'Text',
},
bankAccount: {
type: 'string',
title: '银行账号',
'x-component': 'Text',
},
bankDeposit: {
type: 'string',
title: '开户行',
'x-component': 'Text',
},
payProveList: {
type: 'string',
title: '上传支付凭证',
'x-component': 'AntUpload',
'x-component-props': {
action: '/api/file/file/upload/prefix',
data: {
fileType: UPLOAD_TYPE,
prefix: '/creditApplication/paymentVoucher/',
},
beforeUpload: '{{beforeUpload}}',
accept: '.png, .jpg, .jpeg',
},
'x-mega-props': {
labelAlign: 'top',
full: true,
},
'x-rules': [
{
required: false,
message: '请上传支付凭证',
},
],
description: '单个凭证文件大小不能超过 200K',
},
},
},
},
import { ISchema } from '@formily/antd';
import { UPLOAD_TYPE } from '@/constants';
export const uploadVoucherModalSchema: ISchema = {
type: 'object',
properties: {
MEGA_LAYOUT: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelCol: 6,
wrapperCol: 18,
labelAlign: 'left',
full: true,
},
properties: {
name: {
type: 'string',
title: '还款账户名称',
'x-component': 'Text',
},
bankAccount: {
type: 'string',
title: '银行账号',
'x-component': 'Text',
},
bankDeposit: {
type: 'string',
title: '开户行',
'x-component': 'Text',
},
payProveList: {
type: 'string',
title: '上传支付凭证',
'x-component': 'AntUpload',
'x-component-props': {
action: '/api/file/file/upload/prefix',
data: {
fileType: UPLOAD_TYPE,
prefix: '/creditApplication/paymentVoucher/',
},
beforeUpload: '{{beforeUpload}}',
accept: '.png, .jpg, .jpeg',
},
'x-mega-props': {
labelAlign: 'top',
full: true,
},
'x-rules': [
{
required: true,
message: '请上传支付凭证',
},
],
description: '单个凭证文件大小不能超过 200K',
},
},
},
},
};
\ No newline at end of file
/*
* @Author: XieZhiXiong
* @Date: 2020-10-22 17:31:08
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-11-24 10:40:03
* @Description: 联动逻辑相关
*/
import { FormEffectHooks, FormPath } from '@formily/antd';
import { useLinkageUtils } from '@/utils/formEffectUtils';
const {
onFieldInputChange$,
onFieldValueChange$,
} = FormEffectHooks;
export const useBusinessEffects = (context, actions) => {
const {
getFieldValue,
setFieldValue,
getFieldState,
setFieldState,
} = actions;
const linkage = useLinkageUtils();
// 还款金额 联动 滑块条
onFieldInputChange$('repayQuota').subscribe(fieldState => {
linkage.value('amountSlide', +fieldState.value);
});
// 滑块条 联动 还款金额
onFieldInputChange$('amountSlide').subscribe(fieldState => {
linkage.value('repayQuota', `${fieldState.value}`);
});
// 支付方式 联动 支付渠道
onFieldValueChange$('tradeType').subscribe(fieldState => {
const { value } = fieldState;
if (value === 2) {
linkage.hide('tradeChannel');
} else {
linkage.show('tradeChannel');
}
});
/*
* @Author: XieZhiXiong
* @Date: 2020-10-22 17:31:08
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-11-24 10:40:03
* @Description: 联动逻辑相关
*/
import { FormEffectHooks, FormPath } from '@formily/antd';
import { useLinkageUtils } from '@/utils/formEffectUtils';
const {
onFieldInputChange$,
onFieldValueChange$,
} = FormEffectHooks;
export const useBusinessEffects = (context, actions) => {
const {
getFieldValue,
setFieldValue,
getFieldState,
setFieldState,
} = actions;
const linkage = useLinkageUtils();
// 还款金额 联动 滑块条
onFieldInputChange$('repayQuota').subscribe(fieldState => {
linkage.value('amountSlide', +fieldState.value);
});
// 滑块条 联动 还款金额
onFieldInputChange$('amountSlide').subscribe(fieldState => {
linkage.value('repayQuota', `${fieldState.value}`);
});
// 支付方式 联动 支付渠道
onFieldValueChange$('tradeType').subscribe(fieldState => {
const { value } = fieldState;
if (value === 2) {
linkage.hide('tradeChannel');
} else {
linkage.show('tradeChannel');
}
});
}
\ No newline at end of file
import React from 'react';
import { Modal } from 'antd';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { PublicApi } from '@/services/api';
import NiceForm from '@/components/NiceForm';
import { BillDetailData } from '../IntroduceRow';
import { repaymentModalSchema } from './schema';
import { createEffects } from './effects';
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
const { onFormInit$ } = FormEffectHooks;
const repaymentFormActions = createFormActions();
interface RefundModalProps {
/**
* 是否可见
*/
visible: boolean,
/**
* 隐藏事件
*/
onCancel: () => void,
/**
* 确认按钮 loading
*/
confirmLoading?: boolean,
/**
* 账单信息
*/
billInfo: BillDetailData | null,
/**
* 提交事件
*/
onSubmit: (values: any) => void,
};
const RefundModal: React.FC<RefundModalProps> = (props) => {
const {
visible,
onCancel,
confirmLoading,
billInfo,
onSubmit,
} = props;
// 获取供应商支付渠道
const getPayChannels = (): Promise<any[]> => {
return new Promise((resolve, reject) => {
PublicApi.getPayCreditRepaymentList({
payType: `${1}`, // 支付方式:1 线上支付
memberId: `${billInfo.memberId}`,
memberRoleId: `${billInfo.memberRoleId}`,
}).then(res => {
if (res.code === 1000) {
const options =
res.data ?
res.data.map(item => ({
label: item.way,
value: item.wayId,
})) :
[];
resolve(options);
}
reject();
}).catch(() => {
reject();
});
});
};
const handleRepaymentSubmit = (values) => {
if (onSubmit) {
onSubmit(values);
}
};
return (
<Modal
title="还款"
width={576}
visible={visible}
confirmLoading={confirmLoading}
onOk={() => repaymentFormActions.submit()}
onCancel={onCancel}
destroyOnClose
>
<NiceForm
previewPlaceholder=""
effects={($, actions) => {
const { setFieldState, setFieldValue } = actions;
onFormInit$().subscribe(() => {
// 初始化数据
setFieldState('repayQuota', fileState => {
fileState.value = billInfo.residueRepayQuota;
fileState.rules = fileState.rules.concat({
validator(value) {
return +value > billInfo.residueRepayQuota ? '输入值已超出还款金额' : '';
}
});
});
setFieldState('amountSlide', fileState => {
fileState.value = billInfo.residueRepayQuota;
fileState.props['x-component-props'].max = billInfo.residueRepayQuota;
fileState.props['x-component-props'].marks = {
0: {
label: 0,
},
[billInfo.residueRepayQuota]: {
label: billInfo.residueRepayQuota,
},
};
});
});
createEffects($, actions);
console.log('123')
useAsyncSelect('tradeChannel', getPayChannels, ['label', 'value']);
}}
expressionScope={{
}}
actions={repaymentFormActions}
schema={repaymentModalSchema}
onSubmit={handleRepaymentSubmit}
/>
</Modal>
);
};
export default RefundModal;
\ No newline at end of file
import { ISchema } from '@formily/antd';
import { UPLOAD_TYPE } from '@/constants';
export const repaymentModalSchema: ISchema = {
type: 'object',
properties: {
MEGA_LAYOUT: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelAlign: 'top',
full: true,
},
properties: {
repayQuota: {
type: 'string',
title: '还款金额',
'x-component-props': {
placeholder: '',
addonBefore: '¥',
},
'x-rules': [
{
required: true,
message: '请填写还款金额',
},
],
},
amountSlide: {
type: 'number',
title: '',
'x-component': 'range',
'x-component-props': {
min: 0,
// max: 20000,
},
},
tradeType: {
type: 'number',
enum: [
{
label: '线上支付方式',
value: 1,
},
{
label: '线下支付方式',
value: 2,
},
],
default: 1,
title: '选择支付方式',
'x-component-props': {
placeholder: '请选择',
},
'x-rules': [
{
required: true,
message: '请选择支付方式',
},
],
},
tradeChannel: {
type: 'string',
title: '选择支付渠道',
enum: [
{
label: '微信',
value: 1,
},
{
label: '支付宝',
value: 2,
},
{
label: '银联',
value: 3,
},
],
default: 1,
'x-component-props': {
placeholder: '请选择',
},
'x-rules': [
{
required: true,
message: '请选择支付渠道',
},
],
},
},
},
},
};
\ No newline at end of file
/*
* @Author: XieZhiXiong
* @Date: 2020-12-16 11:07:13
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-12-16 15:09:21
* @Description: 微信支付弹窗
*/
import React, { useState, useEffect, useRef } from 'react';
import { Modal, Upload } from 'antd';
import QRCode from 'qrcode';
import { priceFormat } from '@/utils/numberFomat';
import WechatIcon from '@/assets/imgs/wechat_icon.png';
import styles from './index.less';
interface WxPayModalProps {
/**
* 需要生成 二维码的 地址
*/
url: string;
/**
* 支付金额
*/
price: number;
/**
* 是否可见
*/
visible: boolean;
/**
* 弹窗取消事件
*/
onCancel: () => void;
/**
* 轮训查询支付结果事件
*/
onCheckResult: () => Promise<{ success: Boolean }>;
/**
* 轮训查询支付结果成功
*/
onSuccess?: () => void;
/**
* 轮训查询支付结果失败
*/
onFail?: () => void;
};
const WxPayModal: React.FC<WxPayModalProps> = ({
url,
price,
visible,
onCancel,
onCheckResult,
onSuccess,
onFail,
}) => {
const [qrCode, setQrCode] = useState<string>('');
const getQRCode = async params => {
if (!params) {
return;
}
// 生成二维码
const res = await QRCode.toDataURL(params);
setQrCode(res);
};
let timer = useRef(null);
// 最多请求3600次,2000毫秒一次,二维码过期两小时
let count = 0;
const handleCheckResult = () => {
if (!onCheckResult) {
return;
}
count++;
if (count > 3600) {
return;
}
onCheckResult().then(res => {
if (!res.success) {
timer.current = setTimeout(() => {
handleCheckResult();
}, 2000);
console.log('timer', timer)
} else {
clearTimeout(timer.current);
timer = null;
if (onSuccess) {
onSuccess();
}
}
});
};
useEffect(() => {
getQRCode(url);
if (url) {
handleCheckResult();
}
return () => {
if (timer.current) {
clearTimeout(timer.current);
timer.current = null;
}
};
}, [url]);
useEffect(() => {
if (!visible) {
console.log('隐藏咯')
console.log('timer', timer.current)
if (timer.current) {
clearTimeout(timer.current);
timer.current = null;
}
}
}, [visible]);
const handleCancel = () => {
if (onCancel) {
onCancel();
}
};
return (
<Modal
title={(
<div className={styles.common_title}>
<div className={styles.common_title_icon}><img src={WechatIcon} /></div>
<span>微信支付</span>
</div>
)}
width={576}
visible={visible}
onCancel={handleCancel}
footer={null}
maskClosable={false}
destroyOnClose
>
<div className={styles.wechat_payway}>
<p className={styles.wechat_payway_title}>使用微信扫一扫下方二维码</p>
<div className={styles.wechat_payway_imgbox}>
{qrCode && <img src={qrCode} />}
</div>
<div className={styles.wechat_payway_needpay}>
<label>当前需支付:</label>
<span>{priceFormat(price)}</span>
<label>RMB</label>
</div>
</div>
</Modal>
);
};
/*
* @Author: XieZhiXiong
* @Date: 2020-12-16 11:07:13
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-12-30 13:50:05
* @Description: 微信支付弹窗
*/
import React, { useState, useEffect, useRef } from 'react';
import { Modal, Upload } from 'antd';
import QRCode from 'qrcode';
import { priceFormat } from '@/utils/numberFomat';
import WechatIcon from '@/assets/imgs/wechat_icon.png';
import styles from './index.less';
interface WxPayModalProps {
/**
* 需要生成 二维码的 地址
*/
url: string;
/**
* 支付金额
*/
price: number;
/**
* 是否可见
*/
visible: boolean;
/**
* 弹窗取消事件
*/
onCancel: () => void;
/**
* 轮训查询支付结果事件
*/
onCheckResult: () => Promise<{ success: Boolean }>;
/**
* 轮训查询支付结果成功
*/
onSuccess?: () => void;
/**
* 轮训查询支付结果失败
*/
onFail?: () => void;
};
const WxPayModal: React.FC<WxPayModalProps> = ({
url,
price,
visible,
onCancel,
onCheckResult,
onSuccess,
onFail,
}) => {
const [qrCode, setQrCode] = useState<string>('');
const getQRCode = async params => {
if (!params) {
return;
}
// 生成二维码
const res = await QRCode.toDataURL(params);
setQrCode(res);
};
let timer = useRef(null);
// 最多请求3600次,2000毫秒一次,二维码过期两小时
let count = 0;
const handleCheckResult = () => {
if (!onCheckResult) {
return;
}
count++;
if (count > 3600) {
return;
}
onCheckResult().then(res => {
if (!res.success) {
timer.current = setTimeout(() => {
handleCheckResult();
}, 2000);
} else {
clearTimeout(timer.current);
timer = null;
if (onSuccess) {
onSuccess();
}
}
});
};
useEffect(() => {
getQRCode(url);
if (url) {
handleCheckResult();
}
return () => {
if (timer.current) {
clearTimeout(timer.current);
timer.current = null;
}
};
}, [url]);
useEffect(() => {
if (!visible) {
if (timer.current) {
clearTimeout(timer.current);
timer.current = null;
}
}
}, [visible]);
const handleCancel = () => {
if (onCancel) {
onCancel();
}
};
return (
<Modal
title={(
<div className={styles.common_title}>
<div className={styles.common_title_icon}><img src={WechatIcon} /></div>
<span>微信支付</span>
</div>
)}
width={576}
visible={visible}
onCancel={handleCancel}
footer={null}
maskClosable={false}
destroyOnClose
>
<div className={styles.wechat_payway}>
<p className={styles.wechat_payway_title}>使用微信扫一扫下方二维码</p>
<div className={styles.wechat_payway_imgbox}>
{qrCode && <img src={qrCode} />}
</div>
<div className={styles.wechat_payway_needpay}>
<label>当前需支付:</label>
<span>{priceFormat(price)}</span>
<label>RMB</label>
</div>
</div>
</Modal>
);
};
export default WxPayModal;
\ No newline at end of file
......@@ -79,7 +79,7 @@ const BillInfo: React.FC<BillInfoProps> = ({
>
<Descriptions column={1}>
<Descriptions.Item label="交易流水号">
<Row justify="space-between">
<Row justify="space-between" style={{ width: '100%' }}>
<Col span={12}>
<a onClick={() => handleCheckVoucher(trade.payProveList)}>{trade.tradeCode}</a>
</Col>
......@@ -94,7 +94,7 @@ const BillInfo: React.FC<BillInfoProps> = ({
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易项目">
<Row justify="space-between">
<Row justify="space-between" style={{ width: '100%' }}>
<Col span={12}>
{BILL_TRADE_OPERATION[trade.operation]}
</Col>
......
......@@ -240,7 +240,7 @@ class TradeRecord extends React.Component<TradeRecordProps, TradeRecordState> {
<TradeWrap.TradeItem key={item.tradeCode}>
<Descriptions column={1}>
<Descriptions.Item label="交易流水号">
<Row justify="space-between">
<Row justify="space-between" style={{ width: '100%' }}>
<Col span={10}>
<a onClick={() => this.handleCheckVoucher(item.payProveList)}>{item.tradeCode}</a>
</Col>
......@@ -255,7 +255,7 @@ class TradeRecord extends React.Component<TradeRecordProps, TradeRecordState> {
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易项目">
<Row justify="space-between">
<Row justify="space-between" style={{ width: '100%' }}>
<Col span={12}>
{item.operationName}
</Col>
......
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