Commit e4b3e975 authored by XieZhiXiong's avatar XieZhiXiong

Merge branch 'dev' into test

parents a8216b1b 5f4fb4e9
export default {
'/api': {
'target': 'http://10.0.0.10:8100/',
'target': 'http://10.0.0.25:8100/',
'changeOrigin': true,
'pathRewrite': { '^/api': '' },
}
......
......@@ -46,7 +46,7 @@
"copy-to-clipboard": "^3.3.1",
"god": "0.1.28",
"lingxi-design": "^1.0.8",
"lingxi-design-ui": "^1.1.9",
"lingxi-design-ui": "^1.1.10",
"lingxi-editor-core": "^1.0.6",
"lingxi-web": "^1.0.6",
"lint-staged": "^10.0.7",
......
......@@ -2,7 +2,7 @@
* @Author: XieZhiXiong
* @Date: 2020-08-31 17:52:14
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-08-31 18:59:18
* @LastEditTime: 2020-10-22 13:56:48
* @Description: 状态 tag
*/
import React from 'react';
......@@ -11,7 +11,7 @@ import styles from './index.less';
interface StatusTagProps {
type: 'success' | 'warnning' | 'default' | 'danger' | 'primary';
title: string;
title: React.ReactNode;
};
const StatusTag: React.FC<StatusTagProps> = ({ type, title }) => {
......
......@@ -4,12 +4,16 @@ import PolymericTable from '@/components/PolymericTable';
import { EditableColumns } from '@/components/PolymericTable/interface';
import EyePreview from '@/components/EyePreview';
interface HistoryListHistoryListProps {
};
const HistoryList: React.FC = () => {
const columns: EditableColumns[] = [
{
title: '申请单号',
dataIndex: 'order',
dataIndex: 'applyNo',
render: text => (
<EyePreview
url={``}
......@@ -20,12 +24,12 @@ const HistoryList: React.FC = () => {
},
{
title: '调整前额度(元)',
dataIndex: 'content',
dataIndex: 'originalQuota',
align: 'center',
},
{
title: '申请调整额度(元)',
dataIndex: 'byMemberName',
dataIndex: 'applyQuota',
align: 'center',
},
{
......@@ -35,7 +39,7 @@ const HistoryList: React.FC = () => {
},
{
title: '申请时间',
dataIndex: 'createTime',
dataIndex: 'applyTime',
align: 'center',
},
];
......
......@@ -35,4 +35,8 @@
&-right {
flex: 1;
}
}
.noData {
padding-top: 24px;
}
\ No newline at end of file
......@@ -4,7 +4,11 @@ import {
Descriptions,
Row,
Col,
Empty,
} from 'antd';
import { GetPayCreditApplyPageCreditOverdueResponseDetail } from '@/services/PayApi';
import { BILL_TRADE_OPERATION } from '@/constants';
import { normalizeFiledata, FileData } from '@/utils';
import MellowCard from '@/components/MellowCard';
import StatusTag from '@/components/StatusTag';
import TradeWrap from '../TradeWrap';
......@@ -13,9 +17,28 @@ import styles from './index.less';
const { TabPane } = Tabs;
const BillInfo: React.FC = () => {
export interface BillInfoProps {
overdueList: GetPayCreditApplyPageCreditOverdueResponseDetail[];
loading?: boolean;
};
const BillInfo: React.FC<BillInfoProps> = ({
overdueList = [],
loading = false,
}) => {
const [currentVoucher, setCurrentVoucher] = useState<FileData[]>([]);
const [voucherVisible, setVoucherVisible] = useState(false);
const handleCheckVoucher = record => {
if (!Array.isArray(record)) {
setCurrentVoucher([]);
} else {
const voucher = record.map(item => normalizeFiledata(item.proveUrl));
setCurrentVoucher(voucher);
}
setVoucherVisible(true);
};
return (
<MellowCard
style={{
......@@ -26,91 +49,85 @@ const BillInfo: React.FC = () => {
}}
>
<div className={styles.billInfo}>
<Tabs defaultActiveKey="1" onChange={() => {}}>
<TabPane
tab={(
<div className={styles.dateWrap}>
<StatusTag type="danger" title="逾期 9 天" />
<div className={styles.time}>2020/06/11 ~ 2020/07/11</div>
</div>
)}
key="1"
>
<div className={styles.content}>
<div className={styles['content-left']}>
<Descriptions column={1}>
<Descriptions.Item label="账单金额(元)">30,000.00</Descriptions.Item>
<Descriptions.Item label="账单最后还款日期">2020-08-20</Descriptions.Item>
<Descriptions.Item label="账单最后还款金额(元)">20,000.00</Descriptions.Item>
<Descriptions.Item label="还清日期">2020-08-21</Descriptions.Item>
</Descriptions>
</div>
<div className={styles['content-right']}>
<TradeWrap>
<TradeWrap.TradeItem width="33.33%">
{(!loading && overdueList && overdueList.length > 0 ) ? (
<Tabs onChange={() => {}}>
{overdueList.map((item, index) => (
<TabPane
tab={(
<div className={styles.dateWrap}>
<StatusTag type="danger" title={item.OverdueDay} />
<div className={styles.time}>{item.billName}</div>
</div>
)}
key={index}
>
<div className={styles.content}>
<div className={styles['content-left']}>
<Descriptions column={1}>
<Descriptions.Item label="交易流水号">
<Row justify="space-between">
<Col span={12}>
<a onClick={() => setVoucherVisible(true)}>20200820000010</a>
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<StatusTag type="danger" title="待确认还款结果" />
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易项目">
<Row justify="space-between">
<Col span={12}>
还款
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<strong>+30,000.00元</strong>
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易时间">2020-08-25 08:58</Descriptions.Item>
<Descriptions.Item label="账单金额(元)">{item.billQuota}</Descriptions.Item>
<Descriptions.Item label="账单最后还款日期">{item.lastRepayDate}</Descriptions.Item>
<Descriptions.Item label="账单最后还款金额(元)">{item.lastRepayQuota}</Descriptions.Item>
<Descriptions.Item label="还清日期">{item.payOffDate}</Descriptions.Item>
</Descriptions>
</TradeWrap.TradeItem>
</TradeWrap>
</div>
</div>
</TabPane>
</Tabs>
</div>
<div className={styles['content-right']}>
<TradeWrap>
{item.tradeList && item.tradeList.map(trade => (
<TradeWrap.TradeItem
width="33.33%"
key={trade.tradeCode}
>
<Descriptions column={1}>
<Descriptions.Item label="交易流水号">
<Row justify="space-between">
<Col span={12}>
<a onClick={() => handleCheckVoucher(trade.payProveList)}>{trade.tradeCode}</a>
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<StatusTag type="danger" title={trade.OverdueDay} />
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易项目">
<Row justify="space-between">
<Col span={12}>
{BILL_TRADE_OPERATION[trade.operation]}
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<strong>{trade.tradeMoney}</strong>
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易时间">{trade.tradeTime}</Descriptions.Item>
</Descriptions>
</TradeWrap.TradeItem>
))}
</TradeWrap>
</div>
</div>
</TabPane>
))}
</Tabs>
) : (
<div className={styles.noData}>
<Empty />
</div>
)}
</div>
<CheckVoucherModal
visible={voucherVisible}
fileList={[
{
uid: '1',
name: 'xxx.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png',
},
{
uid: '2',
name: 'yyy.png',
status: 'done',
url: 'http://www.baidu.com/yyy.png',
},
{
uid: '3',
name: 'zzz.png',
status: 'done',
url: 'http://www.baidu.com/zzz.png',
},
]}
fileList={currentVoucher}
onCancel={() => setVoucherVisible(false)}
/>
</MellowCard>
......
import { useBusinessEffects } from './useBusinessEffects';
export const createEffects = (context, actions) => {
useBusinessEffects(context, actions);
};
\ No newline at end of file
/*
* @Author: XieZhiXiong
* @Date: 2020-10-22 17:31:08
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-10-22 17:33:08
* @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);
});
}
\ No newline at end of file
......@@ -12,7 +12,7 @@ export const repaymentModalSchema: ISchema = {
full: true,
},
properties: {
amount: {
repayQuota: {
type: 'string',
title: '还款金额',
'x-component-props': {
......@@ -33,10 +33,10 @@ export const repaymentModalSchema: ISchema = {
'x-component-props': {
min: 0,
max: 20000,
marks: [0, 5000, 10000, 15000, 20000],
},
},
editable: false,
},
payType: {
tradeType: {
type: 'number',
enum: [
{
......@@ -60,7 +60,7 @@ export const repaymentModalSchema: ISchema = {
},
],
},
payChannels: {
tradeChannel: {
type: 'string',
title: '选择支付渠道',
enum: [
......@@ -111,29 +111,20 @@ export const uploadVoucherModalSchema: ISchema = {
title: '还款账户名称',
default: '温州市隆昌皮具有限公司',
'x-component': 'Text',
'x-component-props': {
},
},
bankAccount: {
type: 'string',
title: '银行账号',
default: '6214 7812 3456 7891 1234',
'x-component': 'Text',
'x-component-props': {
},
},
bod: {
type: 'string',
title: '开户行',
default: '中国建设银行广州市分行营业部',
'x-component': 'Text',
'x-component-props': {
},
},
voucher: {
payProveList: {
type: 'string',
title: '上传支付凭证',
'x-component': 'Upload',
......
......@@ -12,4 +12,8 @@
margin-top: 10px;
text-align: right;
}
.noData {
padding-top: 62px;
}
}
\ No newline at end of file
......@@ -4,7 +4,10 @@ import {
Col,
Descriptions,
Pagination,
Empty,
Spin,
} from 'antd';
import { normalizeFiledata, FileData } from '@/utils';
import StatusTag from '@/components/StatusTag';
import {
BILL_TRADE_STATUS_TAB_MAP,
......@@ -12,14 +15,13 @@ import {
import TradeWrap from '../TradeWrap';
import CheckVoucherModal from '../CheckVoucherModal';
import styles from './index.less';
import { render } from '@/app';
const PAGE_SIZE = 4;
export interface RecordParams {
// creditId: string; // 授信id
// billId: string; // 账单id
current: number;
pageSize: number;
current: string;
pageSize: string;
};
export interface RecordItem {
......@@ -75,122 +77,170 @@ export interface RecordRes {
totalCount: number;
};
export interface TradeRecordProps {
interface TradeRecordProps {
// 获取账单账单记录详情
fetchRecordList: (params: RecordParams) => Promise<RecordRes>;
};
const TradeRecord: React.FC<TradeRecordProps> = ({
fetchRecordList,
}) => {
const [voucherVisible, setVoucherVisible] = useState(false);
const [record, setRecord] = useState<{ data: RecordItem[], totalCount: number }>({ data: [], totalCount: 0 });
const [page, setPage] = useState(1);
const [size, setSize] = useState(PAGE_SIZE);
useEffect(() => {
interface TradeRecordState {
voucherVisible: boolean;
record: {
data: RecordItem[],
totalCount: number,
},
page: number;
size: number;
currentVoucher: FileData[];
loading: boolean;
};
class TradeRecord extends React.Component<TradeRecordProps, TradeRecordState> {
constructor(props) {
super(props);
this.state = {
record: {
data: [],
totalCount: 0,
},
page: 1,
size: PAGE_SIZE,
currentVoucher: [],
voucherVisible: false,
loading: false,
};
}
getRecordList = () => {
const { fetchRecordList } = this.props;
const { page, size } = this.state;
if (fetchRecordList) {
fetchRecordList
this.setState({ loading: true });
fetchRecordList({
current: `${page}`,
pageSize: `${size}`,
}).then(res => {
this.setState({ record: res });
}).finally(() => {
this.setState({ loading: false });
});
}
}, []);
};
const handleCheckInfo = record => {
// setData
setVoucherVisible(true);
componentDidMount() {
this.getRecordList();
};
handleCheckVoucher = record => {
if (!Array.isArray(record)) {
this.setState({ currentVoucher: [] });
} else {
const voucher = record.map(item => normalizeFiledata(item.proveUrl));
this.setState({ currentVoucher: voucher });
}
this.setState({ voucherVisible: true });
};
const handlePaginationChange = (page, size) => {
setPage(page);
setSize(size);
fetchRecordList({
current: page,
pageSize: size,
}).then(res => {
setRecord(res);
handlePaginationChange = (page, size) => {
this.setState({
page,
size
}, () => {
this.getRecordList();
});
};
return (
<div className={styles.record}>
<div className={styles.list}>
<TradeWrap>
{record.data.map(item => (
<TradeWrap.TradeItem key={item.tradeCode}>
<Descriptions column={1}>
<Descriptions.Item label="交易流水号">
<Row justify="space-between">
<Col span={12}>
<a onClick={() => handleCheckInfo({})}>{item.tradeCode}</a>
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<StatusTag type={BILL_TRADE_STATUS_TAB_MAP[item.status]} title={item.statusName} />
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易项目">
<Row justify="space-between">
<Col span={12}>
{item.operationName}
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<strong>{item.tradeMoney}</strong>
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易时间">{item.tradeTime}</Descriptions.Item>
<Descriptions.Item label="备注">{item.remark}</Descriptions.Item>
</Descriptions>
</TradeWrap.TradeItem>
))}
</TradeWrap>
</div>
<div className={styles.pagination}>
<Pagination
size="small"
current={page}
pageSize={size}
total={50}
onChange={handlePaginationChange}
/>
</div>
reloadRecordList() {
this.setState({
page: 1,
size: PAGE_SIZE,
}, () => {
this.getRecordList();
});
};
<CheckVoucherModal
visible={voucherVisible}
fileList={[
{
uid: '1',
name: 'xxx.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png',
},
{
uid: '2',
name: 'yyy.png',
status: 'done',
url: 'http://www.baidu.com/yyy.png',
},
{
uid: '3',
name: 'zzz.png',
status: 'done',
url: 'http://www.baidu.com/zzz.png',
},
]}
onCancel={() => setVoucherVisible(false)}
/>
</div>
);
render() {
const {
record,
page,
size,
voucherVisible,
currentVoucher,
loading,
} = this.state;
return (
<div className={styles.record}>
<Spin spinning={loading}>
<div className={styles.list}>
{(!loading && record.data.length > 0) ? (
<TradeWrap>
{record.data.map(item => (
<TradeWrap.TradeItem key={item.tradeCode}>
<Descriptions column={1}>
<Descriptions.Item label="交易流水号">
<Row justify="space-between">
<Col span={12}>
<a onClick={() => this.handleCheckVoucher(item.payProveList)}>{item.tradeCode}</a>
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<StatusTag type={BILL_TRADE_STATUS_TAB_MAP[item.status]} title={item.statusName} />
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易项目">
<Row justify="space-between">
<Col span={12}>
{item.operationName}
</Col>
<Col
span={10}
style={{
textAlign: 'right',
}}
>
<strong>{item.tradeMoney}</strong>
</Col>
</Row>
</Descriptions.Item>
<Descriptions.Item label="交易时间">{item.tradeTime}</Descriptions.Item>
<Descriptions.Item label="备注">{item.remark}</Descriptions.Item>
</Descriptions>
</TradeWrap.TradeItem>
))}
</TradeWrap>
) : (
<div className={styles.noData}>
<Empty />
</div>
)}
</div>
</Spin>
{(!loading && record.data.length > 0) && (
<div className={styles.pagination}>
<Pagination
size="small"
current={page}
pageSize={size}
total={record.totalCount}
onChange={this.handlePaginationChange}
/>
</div>
)}
<CheckVoucherModal
visible={voucherVisible}
fileList={currentVoucher}
onCancel={() => this.setState({ voucherVisible: false })}
/>
</div>
);
}
};
export default TradeRecord;
\ No newline at end of file
......@@ -31,7 +31,9 @@ const HistoryList = React.lazy(() => import('../../components/HistoryList'));
const QuotaMenageDetail: React.FC = () => {
const { id, validateId, pageStatus } = usePageStatus();
const [creditInfo, setCreditInfo] = useState<GetPayCreditApplyGetCreditDetailResponse>(null);
const [creditOverdueList, setCreditOverdueList] = useState([]);
const [infoLoading, setInfoLoading] = useState(false);
const [creditOverdueListLoading, setCreditOverdueListLoading] = useState(false);
const getCreditDetail = () => {
setInfoLoading(true);
......@@ -48,6 +50,7 @@ const QuotaMenageDetail: React.FC = () => {
useEffect(() => {
getCreditDetail();
getCreditOverdueList();
}, []);
const quotaData = [
......@@ -92,6 +95,21 @@ const QuotaMenageDetail: React.FC = () => {
});
};
const getCreditOverdueList = () => {
setCreditOverdueListLoading(true);
PublicApi.getPayCreditApplyPageCreditOverdue({
creditId: id,
current: '1',
pageSize: '9999', // 暂时写死
}).then(res => {
if (res.code === 1000) {
setCreditOverdueList(res.data.data);
}
}).finally(() => {
setCreditOverdueListLoading(false);
});
};
const normalizeOptions = arr => {
if (!arr || !Array.isArray(arr)) {
return [];
......@@ -165,7 +183,7 @@ const QuotaMenageDetail: React.FC = () => {
</Suspense>
<Suspense fallback={null}>
<BillInfo />
<BillInfo overdueList={creditOverdueList} loading={creditOverdueListLoading} />
</Suspense>
<Suspense fallback={null}>
......
......@@ -2,7 +2,7 @@
* @Author: XieZhiXiong
* @Date: 2020-09-16 15:16:47
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-10-22 09:25:26
* @LastEditTime: 2020-10-22 18:49:22
* @Description: 联动逻辑相关
*/
import { Modal } from 'antd';
......@@ -463,7 +463,7 @@ export const useBusinessEffects = (context, actions) => {
return `invoicesDetailsRequests.${$1}.price`
}),
state => {
state.value = (current.price / current.purchaseCount).toFixed(2);
state.value = current.price.toFixed(2);
}
);
setFieldState(
......@@ -479,7 +479,7 @@ export const useBusinessEffects = (context, actions) => {
return `invoicesDetailsRequests.${$1}.amount`
}),
state => {
state.value = `¥${(1 * (current.price / current.purchaseCount)).toFixed(2)}`;
state.value = `¥${(1 * current.price).toFixed(2)}`;
}
);
});
......@@ -519,7 +519,7 @@ export const useBusinessEffects = (context, actions) => {
return `invoicesDetailsRequests.${$1}.amount`
}),
state => {
state.value = `¥${(+value * (current.price / current.purchaseCount)).toFixed(2)}`;
state.value = `¥${(+value * current.price).toFixed(2)}`;
}
);
});
......
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