Commit 226af49c authored by FE-安焕焕's avatar FE-安焕焕 👣

商户贷款结算开发

parent 18119c04
/lambda/ /lambda/
/scripts /scripts
/config /config
.history .history
\ No newline at end of file /src/util/qiniu.min.js
...@@ -117,6 +117,11 @@ export default { ...@@ -117,6 +117,11 @@ export default {
name: 'reconciliationDetail', name: 'reconciliationDetail',
component: './reconciliation/detail/index', component: './reconciliation/detail/index',
}, },
{
path: '/settleManage',
name: 'settleManage',
component: './settleManage',
},
{ {
component: './404', component: './404',
}, },
......
...@@ -5,11 +5,15 @@ let envAPi = { ...@@ -5,11 +5,15 @@ let envAPi = {
// kdspApi: '//yapi.quantgroups.com/mock/351', // kdspApi: '//yapi.quantgroups.com/mock/351',
// kdspApi: 'http://192.168.28.172:8042', // kdspApi: 'http://192.168.28.172:8042',
kdspApi: 'https://kdsp-operation-vcc3.liangkebang.net', kdspApi: 'https://kdsp-operation-vcc3.liangkebang.net',
qiniuHost: 'https://appsync.lkbang.net',
opapiHost: 'https://opapi-vcc2.liangkebang.net',
}; };
let prodApi = { let prodApi = {
api: '//backstms.q-gp.com', api: '//backstms.q-gp.com',
kdspApi: '//kdsp-operation.q-gp.com', kdspApi: '//kdsp-operation.q-gp.com',
qiniuHost: 'https://appsync.lkbang.net',
opapiHost: 'https://opapi.xyqb.com',
}; };
let exportApi; let exportApi;
......
import { Upload, Icon, Modal } from 'antd';
import React from 'react';
import localStorage from '@/utils/localStorage';
import config from '../../../config/env.config';
const qiniu = require('@/utils/qiniu.min.js');
const { qiniuHost } = config;
const token = localStorage.get('qiniuToken');
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
class PicturesWall extends React.Component {
state = {
previewVisible: false,
previewImage: '',
fileList: [],
};
handleCancel = () => this.setState({ previewVisible: false });
handlePreview = async file => {
const fileC = file;
if (!file.url && !file.preview) {
fileC.preview = await getBase64(file.originFileObj);
}
this.setState({
previewImage: fileC.url || fileC.preview,
previewVisible: true,
});
};
handleChange = ({ fileList }) => {
this.setState({ fileList });
};
customRequest = ({ file, onError, onSuccess }) => {
const observable = qiniu.upload(file, null, token);
const observer = {
next() {
// ...
},
error() {
onError(file);
// ...
},
complete(res) {
const comFile = file;
const url = `${qiniuHost}/${res.hash}`;
comFile.url = url;
onSuccess(comFile);
// ...
},
};
observable.subscribe(observer); // 上传开始
};
getFileList = () => {
const fileList = this.state.fileList.map(item => item.response?.url);
return fileList;
};
render() {
const { previewVisible, previewImage, fileList } = this.state;
const uploadButton = (
<div>
<Icon type="plus" />
<div className="ant-upload-text">上传图片</div>
</div>
);
const { max } = this.props;
return (
<div className="clearfix">
<Upload
customRequest={this.customRequest}
listType="picture-card"
fileList={fileList}
onPreview={this.handlePreview}
onChange={this.handleChange}
{...this.props}
>
{max && fileList.length >= max ? null : uploadButton}
</Upload>
<Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
<img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal>
</div>
);
}
}
export default PicturesWall;
export const settleStatus = {
0: { text: '全部' },
1: { text: '待提交' },
2: { text: '待商家确认' },
3: { text: '商家已确认' },
4: { text: '商家已拒绝' },
5: { text: '财务审核中' },
6: { text: '待付款' },
7: { text: '已付款' },
8: { text: '驳回' },
};
export const actionStatus = {
1: { text: '已确认' },
2: { text: '已拒绝' },
};
import { Modal, Button, Table } from 'antd';
import React, { Component } from 'react';
import styles from '../style.less';
class fileModal extends Component {
state = {
imgModal: false,
selectImg: '',
};
render() {
const { visible, fileData = [] } = this.props;
const imgData = fileData.filter(item => item.docType === 2);
const tableData = fileData.filter(item => item.docType === 1);
const tableColumns = [
{
title: '发票号',
dataIndex: 'invoiceNo',
},
{
title: '物流单号',
dataIndex: 'deliveryNo',
},
];
return (
<Modal
title="附件详情"
visible={visible}
footer={null}
onCancel={this.props.onCancel}
width="700px"
>
<div className={styles.imgWrap}>
{imgData.map(item => (
<img
onClick={() => {
this.setState({ imgModal: true, selectImg: item.downloadUrl });
}}
key={item.id}
width={200}
alt=""
src={item.downloadUrl}
style={{ margin: 5 }}
></img>
))}
</div>
<Table
pagination={{ pageSize: 5 }}
dataSource={tableData}
columns={tableColumns}
rowKey={record => record.id}
/>
<Button type="primary" onClick={this.props.onCancel} className={styles.logBtn}>
关闭
</Button>
<Modal
title="附件详情"
visible={this.state.imgModal}
footer={null}
onCancel={() => this.setState({ imgModal: false })}
width="800px"
>
<img width="700px" src={this.state.selectImg} alt=""></img>
</Modal>
</Modal>
);
}
}
export default fileModal;
import React, { useState, useRef } from 'react';
import ProTable from '@ant-design/pro-table';
import { Input, Button, Popconfirm, Notification } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { actionStatus, settleStatus } from './data';
import style from './style.less';
import { query, updateStatus, download, docQuery, qiniuToken } from './service';
import FileModal from './fileModal';
import UploadModal from './uploadModal';
const { TextArea } = Input;
export default () => {
const protable = useRef();
const [refuse, setRefuse] = useState('');
const [showViewFile, setShowViewFile] = useState(false);
const [viewFileData, setViewFileData] = useState([]);
const [showViewUpload, setShowViewUpload] = useState(false);
const [settlementNoV, setSettlementNo] = useState('');
const reload = () => {
if (protable.reload) {
protable.reload();
}
};
qiniuToken();
const confirmText = '您是否已确认结算金额是否正确?确认后无法撤回';
const confirmAction = async (r, isRefuse) => {
const data = await updateStatus({
id: r.id,
status: isRefuse ? 4 : 3,
remarks: isRefuse && refuse,
});
if (data.businessCode === '0000') {
Notification.success({ message: '操作成功' });
reload();
}
};
const refuseContent = ({ target: { value } }) => {
setRefuse(value);
};
const uploadInvoice = ({ settlementNo }) => {
setSettlementNo(settlementNo);
setShowViewUpload(true);
};
const downDetail = ({ settlementNo }) => {
// type 1非财务 2财务
download({ settlementNo, type: 1 });
};
const clearRefuseContent = () => {
setRefuse('');
};
const viewAccessory = async ({ settlementNo }) => {
const data = await docQuery(settlementNo);
setViewFileData(data);
setShowViewFile(true);
};
const refuseNode = () => <TextArea rows={4} onChange={refuseContent} value={refuse} />;
const tableRenderBtn = r => [
<Popconfirm
placement="topLeft"
title={confirmText}
onConfirm={() => confirmAction(r)}
okText="确认"
cancelText="取消"
>
<Button type="primary">确认</Button>
</Popconfirm>,
<Popconfirm
icon={null}
placement="topLeft"
title={refuseNode()}
onConfirm={() => confirmAction(r, true)}
okText="确认"
cancelText="取消"
>
<Button type="primary" onClick={clearRefuseContent}>
拒绝
</Button>
</Popconfirm>,
<Button type="primary" onClick={() => downDetail(r)}>
下载明细
</Button>,
<Button type="primary" onClick={() => uploadInvoice(r)}>
上传发票
</Button>,
<Button type="primary" onClick={() => viewAccessory(r)}>
查看附件
</Button>,
];
const columns = [
{
title: '排序',
dataIndex: 'index',
valueType: 'index',
width: 80,
},
{
title: '结算订单号',
dataIndex: 'settlementNo',
width: 200,
},
{
title: '结算周期',
dataIndex: 'settlementTime',
valueType: 'dateRange',
width: 200,
},
{
title: '结算周期',
dataIndex: 'settlementDate',
hideInSearch: true,
width: 200,
},
{
title: '待结算金额',
dataIndex: 'settlementAmount',
hideInSearch: true,
width: 200,
},
{
title: '货款结算状态',
dataIndex: 'settlementStatus',
valueEnum: settleStatus,
width: 200,
},
{
title: '操作状态',
dataIndex: 'supplierOperateStatus',
valueEnum: actionStatus,
width: 200,
},
{
title: '原因',
dataIndex: 'remarktrgyurew',
hideInSearch: true,
width: 200,
},
{
title: '操作',
valueType: 'option',
dataIndex: 'id',
width: 200,
fixed: 'right',
render: (_, r) => tableRenderBtn(r),
},
];
return (
<PageHeaderWrapper>
<ProTable
size="small"
columns={columns}
className={style.table}
request={query}
search={{ collapsed: false }}
rowKey="id"
pagination={{
defaultCurrent: 1,
}}
actionRef={protable}
scroll={{ x: '100%' }}
/>
<FileModal
visible={showViewFile}
fileData={viewFileData}
onCancel={() => {
setShowViewFile(false);
}}
/>
<UploadModal
visible={showViewUpload}
settlementNo={settlementNoV}
onCancel={() => {
setShowViewUpload(false);
}}
/>
</PageHeaderWrapper>
);
};
import { stringify } from 'querystring';
import _ from 'lodash';
import request from '@/utils/request';
import { saveAs } from 'file-saver';
import { format } from 'date-fns';
import config from '../../../config/env.config';
import localStorage from '@/utils/localStorage';
// 分页查询
export async function query(data) {
const params = {
...data,
pageNo: data.current,
startDate: data.settlementTime?.[0],
endDate: data.settlementTime?.[1],
};
try {
const {
data: { current, records, total, size },
} = await request.get('/api/kdsp/settlement/wait-confirm/page/query', {
prefix: config.kdspApi,
params: stringify(_.omitBy(params, v => !v)),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
return {
current,
data: records.map(v => ({ ...v, logisticsStatus: `_${v.logisticsStatus}` })),
total,
pageSize: size,
};
} catch (error) {
return {};
}
}
export async function updateStatus(params) {
const data = await request.post('/api/kdsp/settlement/status/update', {
prefix: config.kdspApi,
data: stringify(_.omitBy(params, v => !v)),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
return data;
}
// export async function getGoods(orderId) {
// const { data } = await request.get(`/api/kdsp/op/mch-order/skus?orderId=${orderId}`, {
// prefix: config.kdspApi,
// });
// return data;
// }
// export async function getLogistics(orderId) {
// const { data } = await request.get(`/api/kdsp/op/mch-order/logistics-skus?orderId=${orderId}`, {
// prefix: config.kdspApi,
// });
// return data;
// }
export async function uploadFile(file, settlementNo) {
const params = new FormData();
params.append('file', file);
params.append('settlementNo', settlementNo);
const data = await request.post('/api/kdsp/settlement/doc/upload', {
data: params,
prefix: config.kdspApi,
});
return data;
}
export async function download(params) {
const data = await request.post('/api/kdsp/settlement/detail/download/v1', {
data: stringify(_.omitBy(params, v => !v)),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
prefix: config.kdspApi,
responseType: 'arrayBuffer',
});
const blob = new Blob([data]);
saveAs(blob, `商户贷款结算明细-${format(new Date(), 'yyyyMMddHHmmss')}.xlsx`);
}
// 附件信息
export async function docQuery(settlementNo) {
const data = await request.get(`/api/kdsp/settlement/doc/query?settlementNo=${settlementNo}`, {
prefix: config.kdspApi,
});
if (data.businessCode === '0000') {
return data.data;
}
return [];
}
export async function qiniuToken() {
const data = await request.get('/upload/getToken', {
prefix: config.opapiHost,
});
localStorage.set('qiniuToken', data.uptoken);
}
.table {
:global {
.ant-table-wrapper {
margin: 20px;
}
}
}
.logBtn {
display: block;
margin: auto;
}
.imgWrap {
display: flex;
justify-content: space-around;
}
.tab {
min-height: 400px;
}
import React, { createRef, useState } from 'react';
import { Modal, Button, Tabs, Upload, notification, Icon } from 'antd';
import styles from '../style.less';
import { uploadFile } from '../service';
import UploadC from '../../components/upload';
const { Dragger } = Upload;
const { TabPane } = Tabs;
export default props => {
const { visible, settlementNo } = props;
const [tabValue, setTabValue] = useState('1');
const picUpload = createRef();
const uploadProps = {
name: 'file',
async customRequest(info) {
const result = await uploadFile(info.file, settlementNo);
if (result.businessCode === '0000') {
notification.success({ message: '导入成功' });
}
},
accept: '.xlsx',
showUploadList: false,
};
const uploadFn = () => {
// 上传图片的接口
};
const changeTab = tabV => {
setTabValue(tabV);
};
return (
<Modal title="上传发票" visible={visible} footer={null} onCancel={props.onCancel} width="700px">
<Tabs defaultActiveKey="1" className={styles.tab} onChange={changeTab} activeKey={tabValue}>
<TabPane tab="上传凭证" key="1">
<UploadC ref={picUpload} accept=".png,.jpg" />
</TabPane>
<TabPane tab="上传附件" key="2">
<Dragger {...uploadProps}>
<p>
<Icon type="upload" />
</p>
<p>点击上传附件</p>
</Dragger>
</TabPane>
</Tabs>
{tabValue === '1' && (
<Button type="primary" onClick={uploadFn} className={styles.logBtn}>
确定上传
</Button>
)}
{/* <Button type="primary" onClick={props.onCancel}>
关闭
</Button> */}
</Modal>
);
};
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