Commit b2943b46 authored by 前端-许冠华's avatar 前端-许冠华

Merge branch 'feat-0518' into 'v2-220518'

Feat 0518 See merge request linkseeks-design/pro-platform!590
parents 8fe7b71d f60a10ce
......@@ -558,6 +558,102 @@ const BalancedRoute = {
},
],
},
{
"path": "/memberCenter/balance/invoice",
"name": "发票管理",
"icon": "smile",
"btns": [],
"routes": [
{
"path": "/memberCenter/balance/invoice/list",
"component": "@/pages/balance/invoice/b2b",
"name": "待开票(B2B)",
"relationParentCode": "balance",
"icon": "smile",
"btns": []
},
{
"path": "/memberCenter/balance/invoice/ready",
"component": "@/pages/balance/invoice/srm/readyInvoice",
"relationParentCode": "balance",
"name": "待开票(SRM)",
"icon": "smile",
"btns": []
},
{
"path": "/memberCenter/balance/invoice/manage",
"component": "@/pages/balance/invoice/srm/manage",
"relationParentCode": "balance",
"name": "开票管理",
"icon": "smile",
"btns": []
},
{
"path": "/memberCenter/balance/invoice/add",
"component": "@/pages/balance/invoice/srm/manage/add",
"relationParentCode": "balance",
"hideInMenu": true,
"noMargin": true,
"name": "新增开票",
"icon": "smile",
"btns": []
},
{
"path": "/memberCenter/balance/invoice/inquire",
"component": "@/pages/balance/invoice/srm/inquire",
"relationParentCode": "balance",
"name": "发票查询",
"icon": "smile",
"btns": []
},
{
"path": "/memberCenter/balance/invoice/detail",
"component": "@/pages/balance/invoice/srm/manage/detail",
"relationParentCode": "balance",
"hideInMenu": true,
"noMargin": true,
"name": "发票详情",
"icon": "smile",
"btns": []
},
{
"path": "/memberCenter/balance/invoice/edit",
"component": "@/pages/balance/invoice/srm/manage/edit",
"relationParentCode": "balance",
"hideInMenu": true,
"noMargin": true,
"name": "编辑发票",
"icon": "smile",
"btns": []
}
]
},
{
"path": "/memberCenter/balance/invoiceJoint",
"name": "发票协同",
"icon": "smile",
"btns": [],
"routes": [
{
"path": "/memberCenter/balance/invoiceJoint/list",
"component": "@/pages/balance/invoice/srm/joint",
"relationParentCode": "balance",
"name": "发票查询",
"icon": "smile",
"btns": []
},
{
"path": "/memberCenter/balance/invoiceJoint/detail",
"component": "@/pages/balance/invoice/srm/manage/detail",
"relationParentCode": "balance",
"hideInMenu": true,
"noMargin": true,
"name": "发票详情",
"icon": "smile",
"btns": []
}
]
},
],
};
......
......@@ -16,7 +16,7 @@ import AuthConfigRoute from './authConfigRoute'
// import HandlingRoute from './handlingRoute'; // 加工能力
// import DealAbilityRoute from './dealAbilityRoute'; //
// import marketingRoute from './marketingRoute';
// import BalancedRoute from './balanceRoute';
// import BalancedRoute from './balanceRoute'; // 结算能力
import OrderRoute from './orderRoute'; // 订单能力
import asyncRoutes from '../router.config.json';
import ProcurementRoute from './procurementRoute';
......
......@@ -62,7 +62,7 @@
a {
display: inline-block;
font-size: 14px;
color: #909399;
color: #909399!important;
margin: 0 16px;
height: 48px;
line-height: 48px;
......@@ -71,7 +71,7 @@
.ant-anchor-link-active {
a{
font-weight: 500;
color: #303133;
color: #303133!important;
border-bottom: 2px solid #00B37A;
}
}
......
......@@ -9,6 +9,10 @@ import { FormDetailContext } from '@/formSchema/context'
const { Link } = Anchor;
const intl = getIntl();
export interface FormDetailHeaderProps {
/**
* 是否显示信息完成度
*/
showProcess?: boolean,
title: string,
/**
* 右侧额外操作
......@@ -36,6 +40,7 @@ interface itemProps extends ISchema {
*/
const FormDetailHeader: React.FC<FormDetailHeaderProps> = ({
showProcess,
title,
extraRight,
backLink,
......@@ -97,9 +102,13 @@ const FormDetailHeader: React.FC<FormDetailHeaderProps> = ({
<Col>
<div className={style.titleAvatorText}>{title}</div>
</Col>
<Col>
<div className={style.titleCompleteProcess}>{intl.formatMessage({id: 'components.xinxiwanchengdu'})}{` ${parseInt((Number(ctx.formContext.formProcess) * 100).toFixed(2))}%`}</div>
</Col>
{
showProcess && (
<Col>
<div className={style.titleCompleteProcess}>{intl.formatMessage({id: 'components.xinxiwanchengdu'})}{` ${parseInt((Number(ctx.formContext.formProcess || 0) * 100).toFixed(2))}%`}</div>
</Col>
)
}
</Row>
<Row>
<Col>
......@@ -133,6 +142,8 @@ const FormDetailHeader: React.FC<FormDetailHeaderProps> = ({
)
}
FormDetailHeader.defaultProps = {}
FormDetailHeader.defaultProps = {
showProcess: true,
}
export default FormDetailHeader
.god-standard-table {
position: relative;
height: 100%;
}
.god-table-control {
margin-bottom: 24px;
}
\ No newline at end of file
}
......@@ -7,16 +7,21 @@
background: #EBF7F2;
border-radius: 4px;
&__active {
color: #4787F0;
background: #ECF2FE;
}
&__success {
color: #00B37A;
background: #EBF7F2;
}
&__warning {
color: #FF991F;
background: #FFFAE6;
}
&__default {
color: #606266;
background: #F4F5F7;
......@@ -26,14 +31,14 @@
color: #E63F3B;
background: #FFEBE6;
}
&__primary {
color: #3F7ED2;
background: #F0F8FF;
}
&__nobility {
color: #6554C0;
background: #EAE6FF;
}
}
\ No newline at end of file
}
......@@ -9,10 +9,10 @@ import React from 'react';
import classNames from 'classnames';
import styles from './index.less';
export const STATUS_TYPE = ['success', 'warning', 'default', 'danger', 'primary', 'nobility']
export const STATUS_TYPE = ['success', 'warning', 'default', 'danger', 'primary', 'nobility', 'active']
export type StatusTagProps = {
type: 'success' | 'warning' | 'default' | 'danger' | 'primary' | 'nobility';
type: 'success' | 'warning' | 'default' | 'danger' | 'primary' | 'nobility' | 'active';
title: React.ReactNode;
style?: React.CSSProperties,
};
......
import React, { useEffect, useRef, useState } from 'react';
import { ISchema } from '@formily/antd';
import { useIntl } from 'umi';
import { Modal, Row, Col, Drawer,Button } from 'antd';
import { createFormActions } from '@formily/antd';
import StandardTable from '@/components/StandardTable';
import { ColumnsType } from 'antd/es/table';
import NiceForm from '@/components/NiceForm';
const formActions = createFormActions();
interface Iprops {
modalType?: "Modal" | "Drawer"
/**
* 是否显示
*/
visible: boolean,
/**
* Modal 标题
*/
title: string,
/**
* 搜索schema
*/
schema: ISchema,
/**
* table Ccolumn
*/
columns: ColumnsType,
footer?: React.ReactNode,
tableProps?: {
rowKey: string | ((record) => any),
expandable?: any,
},
width?: number,
mode: 'checkbox' | 'radio',
customizeRadio?: boolean,
/** 回显值 */
value?: {[key: string]: any}[],
/**
* onChange
*/
expressionScope?: {[key: string]: any}
/**
* format话参数
*/
format?: ((value) => any) | null,
components?: { [key: string]: any },
effects?: ($, actions) => void,
fetchData: (params: any) => any,
onClose: () => void,
onOk: (selectRow: number[] | string[], selectedRows: {[key: string]: any}[]) => void,
/**
* 勾选前操作,
*/
beforeChecked?: ((record: any, selected: boolean, selectedRows: any[]) => boolean) | ((record: any, selected: boolean, selectedRows: any[]) => Promise<any>),
/**
* rowSelection
*/
rowSelection?: {
getCheckboxProps?: (record) => any,
},
}
const TableModal: React.FC<Iprops> = (props: Iprops) => {
const {
title,
visible,
schema,
columns,
effects,
tableProps,
mode,
expressionScope,
fetchData,
onClose,
onOk,
value,
format,
customizeRadio,
modalType,
footer,
width,
components,
beforeChecked,
rowSelection
} = props;
const ref = useRef<any>({});
const isFirstLoad = useRef<boolean>(true)
const [selectRow, setSelectRow] = useState<number[] | string[]>(() => {
return value.map( (_row) => typeof tableProps.rowKey === 'string' ? _row[tableProps.rowKey as string] : tableProps.rowKey(_row))
})
const [selectRowRecord, setSelectRowRecord] = useState<{[key: string]: any}[]>([]);
const intl = useIntl();
useEffect(() => {
if (!visible) {
return;
}
let list = value;
const currentMode = customizeRadio || mode === 'radio';
if (currentMode) {
list = list.slice(-1);
}
const keys = list.map(
(_row) => {
// console.log(typeof tableProps.rowKey === 'string' && tableProps.rowKey(_row))
return typeof tableProps.rowKey === 'string' ? _row[tableProps.rowKey as string] : tableProps.rowKey(_row)
});
setSelectRow(keys)
setSelectRowRecord(value);
}, [visible, value, mode, customizeRadio])
const handleEffects = ($: any, actions: any) => {
effects?.($, actions);
}
const handleOnClose = () => {
onClose?.()
}
const handleOk = () => {
onOk?.(selectRow, selectRowRecord)
}
useEffect(() => {
if (!visible) {
return ;
}
if (!isFirstLoad.current) {
ref.current?.reload?.();
}
isFirstLoad.current = false;
}, [visible])
const onSelectChange = async (record, selected: boolean, selectedRows) => {
const recordRows = customizeRadio || mode === 'radio' ? selectedRows.slice(-1) : selectedRows;
const keys = recordRows.map((_item) => typeof tableProps.rowKey === 'string' ? _item[tableProps.rowKey as string] : tableProps.rowKey(_item));
// if (selected) {
const returnValue =await beforeChecked(record, selected, recordRows);
if (returnValue === false) {
return;
}
// }
setSelectRowRecord(recordRows)
setSelectRow(keys)
};
const onSelectAll = async (selected: boolean, selectedRows: any[], changeRows: any[]) => {
const keys = selectedRows.map((_item) => typeof tableProps.rowKey === 'string' ? _item[tableProps.rowKey as string] : tableProps.rowKey(_item));
setSelectRowRecord(selectedRows)
setSelectRow(keys)
}
const handleSearch = (params: any) => {
const res = (format && format(params)) || params;
ref.current?.reload(res)
}
const Component = modalType === 'Modal' ? Modal : Drawer;
const renderFooter = () => {
return (
<div style={{ textAlign: 'right'}}>
<Button onClick={handleOnClose} style={{ marginRight: 8 }}>
{intl.formatMessage({ id: 'member.actions.cancel' })}
</Button>
<Button onClick={handleOk} type="primary">
{intl.formatMessage({ id: 'member.actions.confirm' })}
</Button>
</div>
)
}
const otherProps = modalType === 'Drawer' ? { footer: renderFooter(), maskClosable: true, onClose: handleOnClose } : { onOk: handleOk}
return (
<Component
title={title}
visible={visible}
onCancel={handleOnClose}
// onOk={handleOk}
width={width}
{...otherProps}
>
<StandardTable
columns={columns}
tableProps={{
...tableProps,
pagination: false
}}
keepAlive={false}
fetchTableData={fetchData}
currentRef={ref}
rowSelection={{
type: customizeRadio && mode === 'radio' ? 'checkbox' : mode,
onSelect: onSelectChange,
onSelectAll: onSelectAll,
selectedRowKeys: selectRow,
hideSelectAll: customizeRadio,
...rowSelection
}}
formRender={(child, ps) => (
// <div style={{display: "flex", flexDirection: 'row', justifyContent: 'space-between'}}>
// <div>{child}</div>
// <div>{ps}</div>
// </div>
<>
<div >{child}</div>
<div style={{position: 'absolute', right: 0, bottom: 4}}>{ps}</div>
</>
)}
controlRender={
<NiceForm
schema={schema}
components={components}
actions={formActions}
onSubmit={handleSearch}
expressionScope={expressionScope}
effects={($, actions) => handleEffects($, actions)}
/>
}
>
</StandardTable>
</Component>
)
}
TableModal.defaultProps = {
rowSelection: {},
mode: 'radio',
tableProps: {
rowKey: 'memberId'
},
value: [],
expressionScope: {},
format: null,
customizeRadio: false,
modalType: "Modal",
footer: null,
width: 840,
components: {},
beforeChecked: () => true
}
export default TableModal;
......@@ -48,6 +48,13 @@
.textOverflow();
}
}
.delete_btn {
margin-left: 8px;
font-size: 12px;
cursor: pointer;
color: #909399;
}
}
// &:hover {
// background-color: @secondary-color;
......
......@@ -5,6 +5,8 @@ import { UPLOAD_TYPE } from '@/constants';
import { Upload, Progress, Button, message } from 'antd';
import { CloudUploadOutlined, DeleteOutlined } from '@ant-design/icons';
import pdfIcon from '@/assets/imgs/pdf_icon.png';
import photoIcon from '@/assets/imgs/file_photo.png'
import othersIcon from '@/assets/imgs/file_others.png'
import { getAuth } from '@/utils/auth';
import styles from './UploadFiles.less';
import { getIntl } from 'umi';
......@@ -13,6 +15,7 @@ type PickProps = "headers" | "action" | "accept" | "beforeUpload" | "onChange" |
interface PickUploadProps extends Pick<UploadProps, PickProps> {
containerStyle?: React.CSSProperties,
btnClassName?: string,
/**
* 表示当前上传组件的order值, 越大越后, 即flex-order
*/
......@@ -57,6 +60,7 @@ const UploadFiles: React.FC<PickUploadProps> = (props: PickUploadProps) => {
renderUploadChild,
maxCount,
multiple,
btnClassName,
} = props;
const hasFileListProps = "fileList" in props;
const hasMaxCount = typeof maxCount !== 'undefined' ? { maxCount } : {};
......@@ -128,6 +132,22 @@ const UploadFiles: React.FC<PickUploadProps> = (props: PickUploadProps) => {
setFiles(newFileList);
}
};
const getIconByName = (name: string) => {
if (name && typeof name === 'string') {
const tempList = name.split('.')
const fileType = tempList[tempList.length - 1].toLocaleUpperCase()
if (fileType.indexOf('PDF') > -1) {
return pdfIcon
} else if (['JPG', 'PNG', 'GIF', 'JPEG'].includes(fileType)) {
return photoIcon
} else {
return othersIcon
}
}
return othersIcon
}
const renderFileItem = () => {
return (
<div className={filesContainerCs} style={{ order: 1 }}>
......@@ -144,7 +164,7 @@ const UploadFiles: React.FC<PickUploadProps> = (props: PickUploadProps) => {
}
<div className={styles.renderFileItem} >
<div className={styles['fileItem-left']}>
<img className={styles.img} src={pdfIcon} />
<img className={styles.img} src={getIconByName(_item.name)} />
<a
className={cx({ [styles.error]: _item.status === 'error' || !_item.url })}
href={_item.url}
......@@ -156,7 +176,7 @@ const UploadFiles: React.FC<PickUploadProps> = (props: PickUploadProps) => {
</div>
{
!disable && (
<DeleteOutlined onClick={() => handleRemove(_item)} />
<DeleteOutlined className={styles.delete_btn} onClick={() => handleRemove(_item)} />
)
}
</div>
......@@ -187,7 +207,7 @@ const UploadFiles: React.FC<PickUploadProps> = (props: PickUploadProps) => {
{renderUploadChild?.(files)}
{
typeof children !== 'undefined' ? children : (
<Button type={mode} icon={<CloudUploadOutlined />}>
<Button className={btnClassName} type={mode} icon={<CloudUploadOutlined />}>
{buttonText}
</Button>
)
......
......@@ -20,4 +20,5 @@ export const PATTERN_MAPS = {
weight:/^\d*(?:\.\d{0,3})?$/,
quantity: /^[1-9]+[0-9]*$/, // 数量,大于等于1的正整数
identity: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, // 身份证
decimal: /(^$)|^[0-9]+(.?[0-9]{1,3})?$/,
}
......@@ -121,6 +121,10 @@ a {
}
}
.white_bg_card {
background-color: #FFFFFF;
}
// 公共显示隐藏处理
.commonShowBlock {
display: block;
......
......@@ -29,10 +29,22 @@ export default {
'balance.accountsReceivable.invoice.columns.orderNo':'Order number',
'balance.accountsReceivable.invoice.columns.orderAbstract':'Invoice summary',
'balance.accountsReceivable.invoice.columns.orderTime': 'Invoice time',
'balance.accountsReceivable.invoice.columns.payer': 'Payer',
'balance.accountsReceivable.invoice.columns.code': 'Invoice code',
'balance.accountsReceivable.invoice.columns.number': 'Invoice number',
'balance.accountsReceivable.invoice.columns.invoiceDate': 'Invoice Date',
'balance.accountsReceivable.invoice.columns.invoiceTitle': 'Invoice header',
'balance.accountsReceivable.invoice.columns.invoiceAmount': 'Invoice Amount',
'balance.accountsReceivable.invoice.columns.examineStatus': 'Status',
'balance.accountsReceivable.invoice.columns.examineStatus.0': 'to be submitted',
'balance.accountsReceivable.invoice.columns.examineStatus.1': 'to be confirmed',
'balance.accountsReceivable.invoice.columns.examineStatus.2': 'Confirmed',
'balance.accountsReceivable.invoice.columns.examineStatus.3': 'Returned',
'balance.accountsReceivable.invoice.columns.orderTypeName':'Order Type',
'balance.accountsReceivable.invoice.columns.settlementOrderTypeName': 'Document Type',
'balance.accountsReceivable.invoice.columns.tax':'Tax included/tax rate',
'balance.accountsReceivable.invoice.columns.tax.none':'No',
'balance.accountsReceivable.invoice.columns.tax.yes': 'Yes',
'balance.accountsReceivable.invoice.columns.orderAmount':'Invoice total',
'balance.accountsReceivable.invoice.columns.batch':'Payment batch',
'balance.accountsReceivable.invoice.columns.batch.1':'The {data}th time',
......@@ -42,6 +54,7 @@ export default {
'balance.accountsReceivable.invoice.columns.invoiceStatus':'Invoice status',
'balance.accountsReceivable.invoice.columns.invoiceStatus.0':'Not invoiced',
'balance.accountsReceivable.invoice.columns.invoiceStatus.1':'Invoice has been issued',
'balance.accountsReceivable.invoice.columns.invoiceStatus.2': 'Invoicing',
'balance.accountsReceivable.invoice.columns.status':'Payment Status',
'balance.accountsReceivable.invoice.columns.status.1':'Unpaid',
'balance.accountsReceivable.invoice.columns.status.2':'paid',
......@@ -56,11 +69,18 @@ export default {
'balance.accountsReceivable.invoice.schema.orderNo':'Search Doc number',
'balance.accountsReceivable.invoice.schema.orderAbstract':'Document Summary',
'balance.accountsReceivable.invoice.schema.invoiceNumber': 'Invoice Number',
'balance.accountsReceivable.invoice.schema.invoiceTitlte': 'Invoice header',
'balance.accountsReceivable.invoice.schema.orderStartTime':'Order time (start time)',
'balance.accountsReceivable.invoice.schema.orderEndTime':'Order time (end time)',
'balance.accountsReceivable.invoice.schema.invoiceStartTime': 'Invoice time (start time)',
'balance.accountsReceivable.invoice.schema.invoiceEndTime': 'Invoice time (end time)',
'balance.accountsReceivable.invoice.schema.invoiceStartDate': 'Invoice date (start time)',
'balance.accountsReceivable.invoice.schema.invoiceEndDate': 'Invoice date (end time)',
'balance.accountsReceivable.invoice.schema.payStartTime':'Payment time (start time)',
'balance.accountsReceivable.invoice.schema.payEndTime':'Payment time (end time)',
'balance.accountsReceivable.invoice.schema.invoiceStatus':'Invoice status (all)',
'balance.accountsReceivable.invoice.schema.status': 'Status (all)',
'balance.accountsReceivable.invoice.schema.payStatus':'Payment status (all)',
'balance.accountsReceivable.invoice.schema.submit':'Query',
......
......@@ -29,10 +29,22 @@ export default {
'balance.accountsReceivable.invoice.columns.orderNo': '주문 번호',
'balance.accountsReceivable.invoice.columns.orderAbstract': '영수증 요약',
'balance.accountsReceivable.invoice.columns.orderTime': '영수증 시간',
'balance.accountsReceivable.invoice.columns.payer': '지급인',
'balance.accountsReceivable.invoice.columns.code': '송장 코드',
'balance.accountsReceivable.invoice.columns.number': '송장 번호',
'balance.accountsReceivable.invoice.columns.invoiceDate': '송장 날짜',
'balance.accountsReceivable.invoice.columns.invoiceTitle': '송장 헤더',
'balance.accountsReceivable.invoice.columns.invoiceAmount': '송장 금액',
'balance.accountsReceivable.invoice.columns.examineStatus': '상태',
'balance.accountsReceivable.invoice.columns.examineStatus.0': '제출 예정',
'balance.accountsReceivable.invoice.columns.examineStatus.1': '확인 예정',
'balance.accountsReceivable.invoice.columns.examineStatus.2': '확인됨',
'balance.accountsReceivable.invoice.columns.examineStatus.3': '반환됨',
'balance.accountsReceivable.invoice.columns.orderTypeName': '주문 유형',
'balance.accountsReceivable.invoice.columns.settlementOrderTypeName': '증빙서류 유형',
'balance.accountsReceivable.invoice.columns.tax': '세금 포함/세율',
'balance.accountsReceivable.invoice.columns.tax.none': '아니요',
'balance.accountsReceivable.invoice.columns.tax.yes': '예',
'balance.accountsReceivable.invoice.columns.orderAmount': '증빙서류 총액',
'balance.accountsReceivable.invoice.columns.batch': '일괄 지불',
'balance.accountsReceivable.invoice.columns.batch.1': '{data}회',
......@@ -42,6 +54,7 @@ export default {
'balance.accountsReceivable.invoice.columns.invoiceStatus': '개표 상태',
'balance.accountsReceivable.invoice.columns.invoiceStatus.0': '미개표',
'balance.accountsReceivable.invoice.columns.invoiceStatus.1': '개표됨',
'balance.accountsReceivable.invoice.columns.invoiceStatus.2': '송장 발행',
'balance.accountsReceivable.invoice.columns.status': '지불 상태',
'balance.accountsReceivable.invoice.columns.status.1': '미지급',
'balance.accountsReceivable.invoice.columns.status.2': '지불됨',
......@@ -56,11 +69,18 @@ export default {
'balance.accountsReceivable.invoice.schema.orderNo': '영수증 번호 검색',
'balance.accountsReceivable.invoice.schema.orderAbstract': '증빙서류 요약',
'balance.accountsReceivable.invoice.schema.invoiceNumber': '송장 번호',
'balance.accountsReceivable.invoice.schema.invoiceTilte': '송장 헤더',
'balance.accountsReceivable.invoice.schema.orderStartTime': '주문 시간(시작 시간)',
'balance.accountsReceivable.invoice.schema.orderEndTime': '주문 시간(종료 시간)',
'balance.accountsReceivable.invoice.schema.invoiceStartDate': '송장 날짜(시작 시간)',
'balance.accountsReceivable.invoice.schema.invoiceEndDate': '송장 날짜(종료 시간)',
'balance.accountsReceivable.invoice.schema.invoiceStartTime': '송장 시간(시작 시간)',
'balance.accountsReceivable.invoice.schema.invoiceEndTime': '송장 시간(종료 시간)',
'balance.accountsReceivable.invoice.schema.payStartTime': '지불 시간(시작 시간)',
'balance.accountsReceivable.invoice.schema.payEndTime': '지불 시간(종료 시간)',
'balance.accountsReceivable.invoice.schema.invoiceStatus': '개표 상태(전체)',
'balance.accountsReceivable.invoice.schema.status': '상태(전체)',
'balance.accountsReceivable.invoice.schema.payStatus': '지불 상태(전체)',
'balance.accountsReceivable.invoice.schema.submit': '조회',
......
......@@ -29,10 +29,22 @@ export default {
'balance.accountsReceivable.invoice.columns.orderNo': '订单号',
'balance.accountsReceivable.invoice.columns.orderAbstract': '单据摘要',
'balance.accountsReceivable.invoice.columns.orderTime': '单据时间',
'balance.accountsReceivable.invoice.columns.payer': '付款方',
'balance.accountsReceivable.invoice.columns.code': '发票代码',
'balance.accountsReceivable.invoice.columns.number': '发票号码',
'balance.accountsReceivable.invoice.columns.invoiceDate': '开票日期',
'balance.accountsReceivable.invoice.columns.invoiceTitle': '发票抬头',
'balance.accountsReceivable.invoice.columns.invoiceAmount': '开票金额',
'balance.accountsReceivable.invoice.columns.examineStatus': '状态',
'balance.accountsReceivable.invoice.columns.examineStatus.0': '待提交',
'balance.accountsReceivable.invoice.columns.examineStatus.1': '待确认',
'balance.accountsReceivable.invoice.columns.examineStatus.2': '已确认',
'balance.accountsReceivable.invoice.columns.examineStatus.3': '已退回',
'balance.accountsReceivable.invoice.columns.orderTypeName': '订单类型',
'balance.accountsReceivable.invoice.columns.settlementOrderTypeName': '单据类型',
'balance.accountsReceivable.invoice.columns.tax': '含税/税率',
'balance.accountsReceivable.invoice.columns.tax.none': '否',
'balance.accountsReceivable.invoice.columns.tax.yes': '是',
'balance.accountsReceivable.invoice.columns.orderAmount': '单据总额',
'balance.accountsReceivable.invoice.columns.batch': '支付批次',
'balance.accountsReceivable.invoice.columns.batch.1': '第{data}次',
......@@ -42,6 +54,7 @@ export default {
'balance.accountsReceivable.invoice.columns.invoiceStatus': '开票状态',
'balance.accountsReceivable.invoice.columns.invoiceStatus.0': '未开票',
'balance.accountsReceivable.invoice.columns.invoiceStatus.1': '已开票',
'balance.accountsReceivable.invoice.columns.invoiceStatus.2': '开票中',
'balance.accountsReceivable.invoice.columns.status': '支付状态',
'balance.accountsReceivable.invoice.columns.status.1': '未支付',
'balance.accountsReceivable.invoice.columns.status.2': '已支付',
......@@ -56,11 +69,18 @@ export default {
'balance.accountsReceivable.invoice.schema.orderNo': '搜索单据号',
'balance.accountsReceivable.invoice.schema.orderAbstract': '单据摘要',
'balance.accountsReceivable.invoice.schema.invoiceNumber': '发票号码',
'balance.accountsReceivable.invoice.schema.invoiceTitlte': '发票抬头',
'balance.accountsReceivable.invoice.schema.orderStartTime': '下单时间(开始时间)',
'balance.accountsReceivable.invoice.schema.orderEndTime': '下单时间(结束时间)',
'balance.accountsReceivable.invoice.schema.invoiceStartDate': '开票日期(开始时间)',
'balance.accountsReceivable.invoice.schema.invoiceEndDate': '开票日期(结束时间)',
'balance.accountsReceivable.invoice.schema.invoiceStartTime': '单据时间(开始时间)',
'balance.accountsReceivable.invoice.schema.invoiceEndTime': '单据时间(结束时间)',
'balance.accountsReceivable.invoice.schema.payStartTime': '支付时间(开始时间)',
'balance.accountsReceivable.invoice.schema.payEndTime': '支付时间(结束时间)',
'balance.accountsReceivable.invoice.schema.invoiceStatus': '开票状态(全部)',
'balance.accountsReceivable.invoice.schema.status': '状态(全部)',
'balance.accountsReceivable.invoice.schema.payStatus': '支付状态(全部)',
'balance.accountsReceivable.invoice.schema.submit': '查询',
......@@ -886,6 +906,13 @@ export default {
'balance.platformSettlement.columns.payTime': '实际付款时间',
'balance.platformSettlement.columns.settlementName': '结算方',
'balance.memberSettle.settleMethod.payDay.default': '付款日:付款日未设置,默认为结算日',
'balance.invoice.add.page.title': '新增开票',
'balance.invoice.manage.addSchema.receiptInfo': '单据信息',
'balance.invoice.manage.addSchema.invoiceInfo': '发票信息',
'balance.invoice.manage.addSchema.billInfo': '开票信息',
'balance.invoice.manage.addSchema.invoiceDetails': '发票明细',
'balance.invoice.reconciliationNo.required': '请选择单据号',
'balance.createTimeStart': '单据开始时间',
'balance.createTimeEnd': '单据结束时间',
'balance.expectPayTimeStart': '预计付款开始日期',
......
......@@ -49,3 +49,19 @@ export const fetchOptions = (service) => {
return [];
}
}
/**
* 获取结算状态
*/
export const fetchInvoiceOptions = (service) => {
return async function() {
const res = await service();
if(res.code === 1000) {
const list: any[] = res.data || []
const lastItem = list.pop()
const newList = [lastItem, ...list]
return newList.map((item) => {return { label: item.name, value: item.code.toString() }})
}
return [];
}
}
.itemTitle {
font-size: 12px;
color: #303133;
margin-bottom: 16px;
display: flex;
align-items: center;
&::before {
content: ' ';
width: 2px;
height: 12px;
background-color: #00A98F;
border-radius: 1px;
margin-right: 6px;
}
}
.baseItem {
display: flex;
font-size: 12px;
margin-bottom: 16px;
.label {
width: 104px;
color: #909399;
margin: 0;
p {
margin: 0;
}
}
.content {
flex: 1;
margin: 0;
word-break: break-all;
}
}
.invoiceList {
padding: 14px 32px;
background-color: #FAFBFC;
border-radius: 4px;
font-size: 12px;
margin-bottom: 16px;
.title {
color: #91959B;
height: 16px;
}
.content {
color: #303133;
}
}
.addInvoice {
color: #91959B;
margin-bottom: 8px;
.required {
color: #F25767;
}
}
.addInvoiceTable {
:global {
.ant-form-item {
margin-bottom: 12px;
}
.ant-input,
.ant-picker {
background-color: #F5F6F7;
border-color: #F5F6F7;
&:focus {
border-color: #F5F6F7;
box-shadow: none;
}
}
.ant-input-focused,
.ant-picker-focused {
border-color: #F5F6F7;
box-shadow: none;
}
}
}
.customerButton {
background-color: #F5F6F7;
border: 0;
&:hover{
background-color: #F5F6F7;
}
}
import React, { Fragment, useEffect, useState, useMemo, useRef } from 'react';
import { Row, Col, Button, Form, Input, DatePicker } from 'antd';
import { MinusOutlined, PlusOutlined } from '@ant-design/icons'
import { priceFormat } from '@/utils/numberFomat';
import Card from '@/pages/transaction/purchaseAbility/components/card';
import styles from './index.less';
interface InvoiceCardProps {
id: string,
title: string,
editAble: boolean,
data?: any,
formRef?: any
}
interface InvoiceListItem {
number: number,
invoiceDate: string | number,
invoiceAmount: number,
remark: string
}
interface InvoiceListProps {
data: InvoiceListItem
}
const Col_1 = [
{ label: '开具类型', key: 'typeName' },
{ label: '发票种类', key: 'kindName' },
{ label: '发票抬头', key: 'invoiceTitle' },
{ label: '纳税号', key: 'taxNo' },
]
const Col_2 = [
{ label: '开户行', key: 'bankOfDeposit' },
{ label: '账号', key: 'account' },
{ label: '地址', key: 'address' },
{ label: '电话号码', key: 'tel' },
]
const InvoiceList: React.FC<InvoiceListProps> = (props: InvoiceListProps) => {
const { data } = props;
return (
<Row gutter={[8, 8]} className={styles.invoiceList}>
<Col span={6}>
<div className={styles.title}>发票号码</div>
<div className={styles.content}>{data.number}</div>
</Col>
<Col span={6}>
<div className={styles.title}>开票日期</div>
<div className={styles.content}>{data.invoiceDate}</div>
</Col>
<Col span={6}>
<div className={styles.title}>开票金额(元)</div>
<div className={styles.content}>¥ {priceFormat(data.invoiceAmount)}</div>
</Col>
<Col span={6}>
<div className={styles.title}>备注</div>
<div className={styles.content}>{data.remark}</div>
</Col>
</Row>
)
}
const InvoiceCard: React.FC<InvoiceCardProps> = (props: InvoiceCardProps) => {
const { id, title, data } = props;
const [dataSource, setDataSource] = useState<any>([])
const _handleAdd = () => {
setDataSource([...dataSource, {}])
}
const _handleRemove = (index: number) => {
const arr = [...dataSource];
arr.splice(index, 1);
setDataSource(arr)
}
return (
<Card id={id} title={title}>
<div className={styles.itemTitle}>原订单开票信息 (DPTY12)</div>
<Row gutter={[8, 8]}>
<Col span={12}>
{Col_1.map((item) => (
<div className={styles.baseItem}>
<h5 className={styles.label}>{item.label}</h5>
<h5 className={styles.content}>{data[item.key]}</h5>
</div>
))}
</Col>
<Col span={12}>
{Col_2.map((item) => (
<div className={styles.baseItem}>
<h5 className={styles.label}>{item.label}</h5>
<h5 className={styles.content}>{data[item.key]}</h5>
</div>
))}
</Col>
</Row>
<div className={styles.itemTitle}>原订单发票信息</div>
{data?.invoiceList?.map((item, index) => (
<InvoiceList data={item} key={`invoiceList_${index}`} />
))}
<div className={styles.itemTitle}>新增发票信息</div>
<Row gutter={[8, 8]} className={styles.addInvoice}>
<Col flex='auto'>
<Row gutter={[8, 8]}>
<Col span={6}>
发票号码<span className={styles.required}>*</span>
</Col>
<Col span={6}>
开票日期<span className={styles.required}>*</span>
</Col>
<Col span={6}>
开票金额(元)<span className={styles.required}>*</span>
</Col>
<Col span={6}>
备注<span className={styles.required}>*</span>
</Col>
</Row>
</Col>
<Col flex='32px'></Col>
</Row>
{dataSource.map((item, index) => (
<Row key={`invoiceTable_${index}`} gutter={[8, 8]} className={styles.addInvoiceTable}>
<Col flex='auto'>
<Row gutter={[8, 8]}>
<Col span={6}>
<Form.Item
name={`number`}
rules={[{ required: true, message: '请输入发票号码' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
name={`invoiceDate`}
rules={[{ required: true, message: '请选择日期' }]}
>
<DatePicker style={{ width: '100%' }} />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
name={`invoiceAmount`}
rules={[{ required: true, message: '请输入金额' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
name={`remark`}
>
<Input />
</Form.Item>
</Col>
</Row>
</Col>
<Col flex='32px'>
<Button className={styles.customerButton} icon={<MinusOutlined />} onClick={() => { _handleRemove(index) }} />
</Col>
</Row>
))}
<Button block className={styles.customerButton} type='dashed' icon={<PlusOutlined />} onClick={_handleAdd}>新增发票</Button>
</Card>
);
}
export default InvoiceCard;
import React, { useState, useMemo } from 'react';
import { Form, Popconfirm, Button } from 'antd';
import { getIntl, history } from 'umi';
import { CheckCircleOutlined } from '@ant-design/icons';
import PeripheralLayout from '@/pages/transaction/purchaseAbility/components/detail';
import InvoiceCard from './components/invoiceCard';
const intl = getIntl();
const Detail = () => {
const {
query: {
id,
no
},
pathname,
} = history.location;
const [pathPci] = useState(pathname.split('/')[pathname.split('/').length - 2]);
const [path] = useState(pathname.split('/')[pathname.split('/').length - 1]);
const [dataSource, setDataSource] = useState<any>([{ invoiceList: [{}, {}] }, { invoiceList: [{}] }]);
const [form] = Form.useForm();
const _editAble = useMemo(() => {
return path !== 'preview';
}, [path])
const _tabs = useMemo(() => {
let _list = [];
dataSource.forEach((_, index) => {
_list.push({ id: `invoice_${index}`, title: `发票${index + 1}` })
})
return _list;
}, [dataSource])
const _handleSubmit = () => {
form.validateFields().then(formRes => {
console.log(formRes)
})
}
const _returnTopButton = () => {
return <Button type='primary' icon={<CheckCircleOutlined />} onClick={_handleSubmit}>保存</Button>
}
return (
<div style={{ margin: '-24px -24px 0' }}>
<PeripheralLayout
no={_editAble ? '开具发票' : '发票详情'}
// detail={dataSource?.reconciliationAbstract}
effect={_editAble && _returnTopButton()}
tabLink={_tabs}
components={
<Form form={form}>
{dataSource.map((item, index) => (
<InvoiceCard
id={`invoice_${index}`}
title={`发票${index + 1}`}
data={item}
key={`invoice_${index}`}
formRef={form}
editAble={_editAble} />
))}
</Form>
}
/>
</div>
)
}
export default Detail;
.text {
color: @main-color;
cursor: pointer;
}
.white_bg_card {
background-color: #FFFFFF;
}
This diff is collapsed.
import { getIntl } from 'umi'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ISchema, createFormActions } from '@formily/antd';
const intl = getIntl()
/**
* 开票管理列表页schema
*/
export const schema: ISchema = {
type: 'object',
properties: {
megaLayout: {
type: 'object',
'x-component': 'mega-layout',
properties: {
topLayout: {
type: 'object',
'x-component': 'Mega-Layout',
'x-component-props': {
grid: true,
},
properties: {
ctl: {
type: "object",
"x-component": "exportBtn",
},
orderNo: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderNo' }),
},
},
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
colStyle: {
marginLeft: 20,
},
},
properties: {
orderAbstract: {
type: 'string',
default: undefined,
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderAbstract' }),
allowClear: true,
},
},
"[orderStartTime, orderEndTime]": {
type: 'object',
'x-component': 'RangePicker',
'x-component-props': {
placeholder: [intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderStartTime' }), intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderEndTime' })],
allowClear: true,
},
},
"[payStartTime, payEndTime]": {
type: 'object',
'x-component': 'RangePicker',
'x-component-props': {
placeholder: [intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.payStartTime' }), intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.payEndTime' })],
allowClear: true,
},
},
invoiceStatus: {
type: 'string',
enum: [],
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceStatus' }),
allowClear: true,
},
},
payStatus: {
type: 'string',
enum: [],
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.payStatus' }),
allowClear: true,
},
},
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.submit' }),
},
},
},
},
},
},
},
};
.status_tag {
display: flex;
align-items: center;
.circle {
width: 6px;
height: 6px;
border-radius: 50%;
margin-right: 8px;
}
& > span {
font-size: 12px;
font-weight: 400;
color: #303133;
}
}
/*
* @Description: 状态 tag
*/
import React from 'react';
import classNames from 'classnames';
import styles from './index.less';
export const STATUS_TYPE = ['success', 'warning', 'default', 'danger', 'primary', 'nobility']
export type StatusTagProps = {
/**
* 状态对应颜色
*/
colorMap: {
[key: number]: string,
},
/** 状态 */
status: number,
title: React.ReactNode;
style?: React.CSSProperties,
};
const StatusTag: React.FC<StatusTagProps> = ({ colorMap, status, title, style }) => (
<div className={styles.status_tag} style={style}>
<div className={classNames(styles.circle)} style={{ backgroundColor: colorMap[status] }}></div>
<span>{title}</span>
</div>
);
export default StatusTag;
.upload_invoice {
.upload_btn {
min-width: 80px;
border: none;
background-color: #F4F5F7;
font-size: 12px;
color: #252D37;
}
.upload_file_list {
display: flex;
flex-direction: column;
margin-bottom: 8px;
&_item {
height: 32px;
display: flex;
align-items: center;
.file_type_icon {
margin-right: 8px;
width: 16px;
height: 16px;
}
.file_name {
font-size: 12px;
color: #00A98F;
line-height: 16px;
}
.delete_btn {
margin-left: 8px;
font-size: 12px;
cursor: pointer;
color: #909399;
}
}
}
}
import React from 'react'
import UploadFiles from '@/components/UploadFiles/UploadFiles'
import pdfIcon from '@/assets/imgs/pdf_icon.png';
import photoIcon from '@/assets/imgs/file_photo.png'
import othersIcon from '@/assets/imgs/file_others.png'
import { UploadFile, UploadChangeParam } from 'antd/lib/upload/interface'
import { DeleteOutlined } from '@ant-design/icons'
import styles from './index.less'
interface UploadInvoiceProps {
path: string
name: string
value: string[],
props: {
readOnly: boolean
},
editable: boolean,
mutators: {
change: (params: any) => void
},
}
const UploadInvoice:React.FC<UploadInvoiceProps> & { isFieldComponent: boolean } = (props) => {
const { value = [], mutators, editable } = props
const handleFilesChange = (info: UploadChangeParam) => {
if (info) {
const fileList = info.fileList;
const urlList = fileList.map((file) => file.response?.data).filter((item) => item !== undefined)
mutators.change([...urlList, ...value, ])
}
}
const handleDeleteItem = (imgUrl: string) => {
const newList = value.filter((url) => url !== imgUrl)
mutators.change([...newList])
}
const handleFileRemove = (fileItem: UploadFile) => {
if (value && fileItem.url) {
const filterUrlList = value.filter((imgUrl) => imgUrl !== fileItem.url)
mutators.change([...filterUrlList])
}
}
const getIconByName = (name: string) => {
if (name && typeof name === 'string') {
const tempList = name.split('.')
const fileType = tempList[tempList.length - 1].toLocaleUpperCase()
if (fileType.indexOf('PDF') > -1) {
return pdfIcon
} else if (['JPG', 'PNG', 'GIF', 'JPEG'].includes(fileType)) {
return photoIcon
} else {
return othersIcon
}
}
return othersIcon
}
const formatImgUrl = (url: string): string => {
return (url && typeof url === 'string') ? url.slice(-25) : ''
}
return (
<div className={styles.upload_invoice}>
{
(value && value.length > 0) && (
<div className={styles.upload_file_list}>
{
value.map((item, index) => (
<div className={styles.upload_file_list_item} key={`img_item_${index}`}>
<img className={styles.file_type_icon} src={getIconByName(item)} />
<a
className={styles.file_name}
href={item}
target="_blank"
title={item} rel="noreferrer"
>
{formatImgUrl(item)}
</a>
{
editable && <DeleteOutlined onClick={() => handleDeleteItem(item)} className={styles.delete_btn} />
}
</div>
))
}
</div>
)
}
{
editable && (
<UploadFiles
btnClassName={styles.upload_btn}
showFiles={false}
buttonText='上传'
onChange={handleFilesChange}
onRemove={handleFileRemove}
/>
)
}
</div>
)
}
UploadInvoice.isFieldComponent = true
export default UploadInvoice
.customeFormItem {
margin: 0;
position: 'relative';
.ant-form-item-control {
.ant-form-item-explain-error {
position: absolute;
left: 0;
bottom: 0;
}
}
}
import React, { useRef, useContext } from 'react'
import { Form, Input } from 'antd';
import './index.less'
import { getIntl } from 'umi';
import { PATTERN_MAPS } from '@/constants/regExp';
const intl = getIntl();
export interface ProductTableCellProps {
title: React.ReactNode;
editable: boolean;
children: React.ReactNode;
dataIndex: string;
record: any;
handleSave: (record: any) => Promise<any>;
forceEdit: boolean,
formItem: string,
formItemProps: any,
}
const EditableContext = React.createContext<any>({});
export const ProductEditableRow: React.FC<any> = ({...props }) => {
const [form] = Form.useForm();
const ctx = {
form
}
return (
<Form form={form} component={false}>
<EditableContext.Provider value={ctx}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
export const ProductTableCell:React.FC<ProductTableCellProps> = ({
title,
editable,
children,
dataIndex,
record,
handleSave,
forceEdit,
formItem,
formItemProps={},
...restProps
}) => {
const formItemRef = useRef<any>();
const { form } = useContext(EditableContext);
const save = async e => {
try {
const values = await form.validateFields();
handleSave({ ...record, ...values });
} catch (errInfo) {
console.log('Save failed', errInfo);
}
};
const chooseFormItem = (type) => {
switch(type) {
case 'number': {
return <Input
style={{ width: 60 }}
type='number'
ref={formItemRef}
onChange={save}
{...formItemProps}
id={dataIndex + record.id}
className="purchase_amount_input"
/>
}
}
}
let childNode = children;
if (editable) {
childNode =
<Form.Item
className="customFormItem"
style={{ marginBottom: 0 }}
name={dataIndex}
initialValue={record[dataIndex] || ''}
rules={[
{
required: true,
message: `${title}${intl.formatMessage({ id: 'table.purchase.bixutianxie' })}`,
},
{
pattern: PATTERN_MAPS.decimal,
message: `${title}${intl.formatMessage({ id: 'balance.invoice.quantity.decimal.max', defaultMessage: '最多3位小数' })}`,
},
]}
>
{chooseFormItem(formItem)}
</Form.Item>
}
return <td {...restProps}>{childNode}</td>;
}
ProductTableCell.defaultProps = {}
export default ProductTableCell
.text {
color: @main-color;
cursor: pointer;
}
.white_bg_card {
background-color: #FFFFFF;
}
/**
* 开票查询(SRM)
*/
import React, { useEffect, useRef, useState } from 'react';
import { getIntl, useIntl, history } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Button, DatePicker, Space, Badge, Drawer, message } from 'antd';
import NiceForm from '@/components/NiceForm';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { createFormActions } from '@formily/antd';
import StandardTable from '@/components/StandardTable';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
import { schema } from './schema';
import StatusTag from '../components/StatusTag';
import { fetchInvoiceOptions } from '../../../common';
import useSetSearchValueInTable from '@/hooks/useSetSearchValueInTable';
import { numFormat, priceFormat } from '@/utils/numberFomat';
import {
getSettleAccountsMemberSettlementAccountStatementInvoiceListStatus,
getSettleAccountsMemberSettlementAccountStatementInvoiceList,
} from '@/services/SettleV2Api';
import AuthButton from '@/components/AuthButton';
import './index.less';
import moment from 'moment';
import { usePageStatus } from '@/hooks/usePageStatus';
const intl = getIntl();
const RangePicker = DatePicker.RangePicker;
const formActions = createFormActions();
const InvoiceInquire: React.FC = () => {
const intl = useIntl();
const ref = useRef<any>({});
const { reconciliationNo } = usePageStatus()
const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss'
/**
* @param params
*/
const fetchListData = async params => {
const searchParams = {
...params,
orderByCode: 1,
};
if (reconciliationNo) {
searchParams.reconciliationNo = reconciliationNo
}
const { data } = await getSettleAccountsMemberSettlementAccountStatementInvoiceList(
searchParams,
);
return data;
};
/**
* 搜索
*/
const handleSearch = values => {
ref.current.reload({
...values,
invoiceStartDate: values?.invoiceStartDate ? values?.invoiceStartDate.format(DATE_FORMAT) : undefined,
invoiceEndDate: values?.invoiceEndDate ? values?.invoiceEndDate.format(DATE_FORMAT) : undefined,
});
};
const columns = [
{
title: intl.formatMessage({
id: 'balance.common.columns.productNoticecolumns.orderNo',
}),
dataIndex: 'reconciliationNo',
render: (text, record) => (
<Button
type="link"
onClick={() => {
history.push(`/memberCenter/balance/invoice/detail?reconciliationId=${record.reconciliationId}&id=${record.id}`)
}}
>
{text}
</Button>
),
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderAbstract',
}),
dataIndex: 'reconciliationAbstract',
},
{
title: intl.formatMessage({
id:
'balance.accountsReceivable.invoice.columns.settlementOrderTypeName',
}),
dataIndex: 'reconciliationTypeName',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderTime',
}),
dataIndex: 'createTime',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.payer',
}),
dataIndex: 'payer',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.code',
}),
dataIndex: 'code',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.number',
}),
dataIndex: 'number',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceDate',
}),
dataIndex: 'invoiceDate',
render: date => moment(date).format('YYYY-MM-DD')
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceAmount',
}),
dataIndex: 'invoiceAmount',
render: text =>
`${intl.formatMessage({ id: 'common.money' })} ${priceFormat(text)}`,
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus',
}),
dataIndex: 'examineStatus',
filters: [
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.0',
}),
value: 0,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.1',
}),
value: 1,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.2',
}),
value: 2,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.3',
}),
value: 3,
},
],
onFilter: (value: number, record: any) => record.invoiceStatus == value,
render: (text, record) => {
return (
<StatusTag
title={record.examineStatusName}
status={record.examineStatus}
colorMap={{
0: '#ACAFB3',
1: '#4787F0',
2: '#00A98F',
3: '#E34D59',
}}
/>
);
},
},
];
return (
<PageHeaderWrapper>
<Card className="white_bg_card">
<StandardTable
tableProps={{
rowKey: 'id',
}}
columns={columns as any}
currentRef={ref}
fetchTableData={(params: any) => fetchListData(params)}
controlRender={
<NiceForm
components={{
RangePicker,
}}
initialValues={{}}
actions={formActions}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'megaLayout.reconciliationNo',
FORM_FILTER_PATH,
);
useAsyncSelect(
'examineStatus',
fetchInvoiceOptions(getSettleAccountsMemberSettlementAccountStatementInvoiceListStatus),
);
}}
schema={schema}
onSubmit={handleSearch}
/>
}
/>
</Card>
</PageHeaderWrapper>
);
};
export default InvoiceInquire;
import { getIntl } from 'umi'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ISchema, createFormActions } from '@formily/antd';
const intl = getIntl()
/**
* 开票管理列表页schema
*/
export const schema: ISchema = {
type: 'object',
properties: {
megaLayout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
grid: true,
},
properties: {
reconciliationNo: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
align: 'flex-start',
allowClear: true,
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderNo' }),
},
},
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
justifyContent: 'flex-start'
},
colStyle: {
marginRight: 16,
},
},
properties: {
reconciliationAbstract: {
type: 'string',
default: undefined,
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderAbstract' }),
allowClear: true,
},
},
number: {
type: 'string',
default: undefined,
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceNumber' }),
allowClear: true,
},
},
"[invoiceStartDate, invoiceEndDate]": {
type: 'object',
'x-component': 'RangePicker',
'x-component-props': {
placeholder: [intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceStartDate' }), intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceEndDate' })],
allowClear: true,
style: {
width: 320,
}
},
},
examineStatus: {
type: 'string',
enum: [],
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceStatus' }),
allowClear: true,
},
},
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.submit' }),
},
},
},
},
},
};
import React from 'react'
import styels from './index.less'
const InvoiceDetail: React.FC = () => {
return (
<div>
InvoiceDetail
</div>
)
}
export default InvoiceDetail
.text {
color: @main-color;
cursor: pointer;
}
.white_bg_card {
background-color: #FFFFFF;
}
This diff is collapsed.
import { getIntl } from 'umi'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ISchema, createFormActions } from '@formily/antd';
import moment from 'moment';
const intl = getIntl()
/**
* 开票管理列表页schema
*/
export const schema: ISchema = {
type: 'object',
properties: {
megaLayout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
grid: true,
},
properties: {
reconciliationNo: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
align: 'flex-start',
allowClear: true,
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderNo' }),
},
},
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
justifyContent: 'flex-start'
},
colStyle: {
marginRight: 16,
},
},
properties: {
reconciliationAbstract: {
type: 'string',
default: undefined,
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderAbstract' }),
allowClear: true,
},
},
invoiceNumber: {
type: 'string',
default: undefined,
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceNumber' }),
allowClear: true,
},
},
invoiceTitlte: {
type: 'string',
default: undefined,
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceTitlte' }),
allowClear: true,
},
},
"[startTime, startTime]": {
type: 'object',
'x-component': 'RangePicker',
'x-component-props': {
placeholder: [intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceStartTime' }), intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceEndTime' })],
allowClear: true,
style: {
width: 320,
}
},
},
examineStatus: {
type: 'string',
enum: [],
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.status' }),
allowClear: true,
},
},
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.submit' }),
},
},
},
},
},
};
/** 退回原因 */
export const refuseSchema: ISchema = {
type: 'object',
properties: {
NO_SUBMIT: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
labelAlign: 'top',
},
properties: {
reconciliationId: {
type: 'string',
visible: false,
},
invoiceId: {
type: 'string',
visible: false,
},
returnTime: {
type: 'string',
readOnly: true,
title: '退回时间',
default: moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
},
returnSource: {
type: 'textarea',
title: '退回原因',
"x-component-props": {
with: '100%',
rows: 4,
allowClear: true,
placeholder: '请输入退回原因',
style: {
resize: 'none'
}
},
"x-rules": [
{
required: true,
message: getIntl().formatMessage({ id: 'balance.invoice.returnSource.required', defaultMessage: '请输入退回原因' }),
},
{
limitByte: true,
maxByte: 100,
message: '最大100个字符,50个文字'
}
]
}
}
}
}
}
import React from 'react'
import { useIntl } from 'umi'
import { usePageStatus } from '@/hooks/usePageStatus'
import InvoiceForm, { OperateType } from './invoiceForm'
const InvoiceAdd: React.FC = () => {
const { reconciliationId, id } = usePageStatus()
const intl = useIntl()
return (
<InvoiceForm
title={intl.formatMessage({
id: 'balance.invoice.add.page.title',
defaultMessage: '新增开票',
})}
reconciliationId={Number(reconciliationId)}
id={Number(id)}
type={OperateType.add}
/>
)
}
export default InvoiceAdd
import { priceFormat } from '@/utils/numberFomat';
import { getIntl } from 'umi'
const intl = getIntl()
export const formKeys = [
'reconciliationId',
'reconciliationNo',
'reconciliationAbstract',
'createTime',
'reconciliationTypeName',
'reconciliationType',
'returnResource',
'type',
'bankOfDeposit',
'kind',
'account',
'invoiceTitle',
'address',
'taxNo',
'payer',
'tel',
]
export const reconciliationColumn = [
{
title: intl.formatMessage({
id: 'balance.common.columns.productNoticecolumns.orderNo',
}),
dataIndex: 'reconciliationNo',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderAbstract',
}),
dataIndex: 'reconciliationAbstract',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.settlementOrderTypeName',
}),
dataIndex: 'reconciliationTypeName',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderTime',
}),
dataIndex: 'createTime',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.tax',
}),
dataIndex: 'tax',
render: (_, record) => {
return record.isTaxRate === 1
? `${intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.tax.yes',
})}/${priceFormat(record.taxRate * 100)}%`
: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.tax.none',
});
},
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderAmount',
}),
dataIndex: 'reconciliationMoneyAmount',
render: (text) =>
`${intl.formatMessage({ id: 'common.money' })} ${priceFormat(text)}`,
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceStatus',
}),
dataIndex: 'invoiceStatusName',
},
]
export const statementsColumn = [
{
title: intl.formatMessage({
id: 'balance.invoice.columns.orderNo',
defaultMessage: '订单号'
}),
dataIndex: 'orderNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.deliveryNo',
defaultMessage: '发货单号'
}),
dataIndex: 'deliveryNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.receiveNo',
defaultMessage: '收货单号'
}),
dataIndex: 'receiveNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.productNo',
defaultMessage: '物料编码'
}),
dataIndex: 'productNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.productName',
defaultMessage: '物料名称'
}),
dataIndex: 'productName',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.spec',
defaultMessage: '规格型号'
}),
dataIndex: 'spec',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.category',
defaultMessage: '品类'
}),
dataIndex: 'category',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.brand',
defaultMessage: '品牌'
}),
dataIndex: 'brand',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.unit',
defaultMessage: '单位'
}),
dataIndex: 'unit',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.taxRate',
defaultMessage: '税率'
}),
dataIndex: 'taxRate',
render: (taxRate) => `${taxRate}%`
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.price',
defaultMessage: '单价(含税)'
}),
dataIndex: 'price',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.currentReconciliationQuantity',
defaultMessage: '对账数量'
}),
dataIndex: 'currentReconciliationQuantity',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.currentMoney',
defaultMessage: '对账金额(含税)'
}),
dataIndex: 'currentMoney',
},
]
export const invoiceDetailColumn = [
{
title: intl.formatMessage({
id: 'balance.invoice.columns.orderNo',
defaultMessage: '订单号'
}),
width: 110,
dataIndex: 'orderNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.deliveryNo',
defaultMessage: '发货单号'
}),
width: 110,
dataIndex: 'deliveryNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.receiveNo',
defaultMessage: '收货单号'
}),
width: 110,
dataIndex: 'receiveNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.productNo',
defaultMessage: '物料编码'
}),
dataIndex: 'productNo',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.productName',
defaultMessage: '物料名称'
}),
dataIndex: 'productName',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.spec',
defaultMessage: '规格型号'
}),
dataIndex: 'spec',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.category',
defaultMessage: '品类'
}),
dataIndex: 'category',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.brand',
defaultMessage: '品牌'
}),
dataIndex: 'brand',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.unit',
defaultMessage: '单位'
}),
dataIndex: 'unit',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.taxRate',
defaultMessage: '税率'
}),
dataIndex: 'taxRate',
render: (taxRate) => `${taxRate}%`
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.price',
defaultMessage: '单价(含税)'
}),
dataIndex: 'price',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.price.not',
defaultMessage: '单价(不含税)'
}),
dataIndex: 'priceNoTax',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.quantity',
defaultMessage: '数量'
}),
width: 80,
editable: true,
formItem: 'number',
dataIndex: 'currentNumber',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.moneyAmount',
defaultMessage: '金额(含税)'
}),
dataIndex: 'currentMoneyAmount',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.moneyAmount.not',
defaultMessage: '金额(不含税)'
}),
dataIndex: 'currentMoneyNoTax',
},
{
title: intl.formatMessage({
id: 'balance.invoice.columns.taxAmount',
defaultMessage: '税额'
}),
dataIndex: 'taxMoneyAmount',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.operation',
defaultMessage: '操作'
}),
width: 80,
action: 'delete',
fixed: 'right',
},
]
import React from 'react'
import { useIntl } from 'umi'
import { usePageStatus } from '@/hooks/usePageStatus'
import InvoiceForm, { OperateType } from './invoiceForm'
const InvoiceDetail: React.FC = () => {
const { reconciliationId, id } = usePageStatus()
const intl = useIntl()
return (
<InvoiceForm
title={intl.formatMessage({
id: 'balance.invoice.detail.page.title',
defaultMessage: '发票详情',
})}
reconciliationId={Number(reconciliationId)}
id={Number(id)}
type={OperateType.detail}
/>
)
}
export default InvoiceDetail
import React from 'react'
import { useIntl } from 'umi'
import { usePageStatus } from '@/hooks/usePageStatus'
import InvoiceForm, { OperateType } from './invoiceForm'
const InvoiceEdit: React.FC = () => {
const { reconciliationId, id } = usePageStatus()
const intl = useIntl()
return (
<InvoiceForm
title={intl.formatMessage({
id: 'balance.invoice.edit.page.title',
defaultMessage: '编辑发票',
})}
reconciliationId={Number(reconciliationId)}
id={Number(id)}
type={OperateType.edit}
/>
)
}
export default InvoiceEdit
.text {
color: @main-color;
cursor: pointer;
}
.white_bg_card {
background-color: #FFFFFF;
}
.restContainer {
margin-top: 16px;
.select_btn {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
.select_icon {
width: 16px;
height: 16px;
}
}
.select_statements_button {
display: flex;
height: 32px;
background-color: #FAFBFC;
border-radius: 4px;
border: 1px dashed #EDEEEF;
margin-bottom: 16px;
align-items: center;
justify-content: center;
color: #5C626A;
font-size: 12px;
cursor: pointer;
&_icon {
margin-right: 8px;
font-size: 14px;
}
}
:global {
.ant-card-head {
margin-bottom: 8px;
}
.ant-card-body {
padding-top: 0!important;
padding-bottom: 0!important;
}
.ant-card {
background-color: #FFFFFF;
border-radius: 8px!important;
margin-bottom: 16px!important;
}
.ant-table-expanded-row td {
padding: 0;
}
.ant-input-group-addon {
padding: 0;
border: none;
}
.ant-picker {
border-radius: 4px;
background-color: #F5F6F7!important;
border: none;
&:focus {
box-shadow: none;
}
}
.ant-picker-focused {
border: none;
box-shadow: none;
}
.ant-input {
border: none;
box-shadow: none;
background-color: #F5F6F7!important;
&:focus, &:active {
border: none!important;
box-shadow: none!important;
}
}
.ant-input-status-error {
border: none;
box-shadow: none;
&:focus, &:active {
border: none!important;
box-shadow: none!important;
}
}
}
}
/**
* 开票管理(SRM)
*/
import React, { useRef, useState } from 'react';
import { getIntl, useIntl, history } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Button, DatePicker, Space, message, Modal } from 'antd';
import NiceForm from '@/components/NiceForm';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { createFormActions } from '@formily/antd';
import StandardTable from '@/components/StandardTable';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { schema } from './schema';
import { priceFormat } from '@/utils/numberFomat';
import StatusTag from '../components/StatusTag'
import {
getSettleAccountsMemberSettlementAccountStatementInvoiceList,
postSettleAccountsMemberSettlementAccountStatementSubmit,
postSettleAccountsMemberSettlementAccountStatementDelete,
} from '@/services/SettleV2Api';
import AuthButton from '@/components/AuthButton';
import './index.less';
import { PlusCircleOutlined } from '@ant-design/icons';
import moment from 'moment';
import TableOperation from '@/components/TableOperation';
const intl = getIntl();
const RangePicker = DatePicker.RangePicker;
const formActions = createFormActions();
const InvoiceManage: React.FC = () => {
const intl = useIntl();
const ref = useRef<any>({});
const [pageLoading, setPageLoading] = useState<boolean>(false)
/**
* @param params
*/
const fetchListData = async params => {
setPageLoading(true)
const searchParams = {
...params,
orderByCode: 1,
};
const { data } = await getSettleAccountsMemberSettlementAccountStatementInvoiceList(
searchParams,
);
setPageLoading(false)
return data;
};
/**
* 搜索
*/
const handleSearch = values => {
ref.current.reload({
...values,
invoiceStartDate: values?.invoiceStartDate ? values?.invoiceStartDate.format('YYYY-MM-DD HH:mm:ss') : undefined,
invoiceEndDate: values?.invoiceEndDate ? values?.invoiceEndDate.format('YYYY-MM-DD HH:mm:ss') : undefined,
});
};
/** 提交开票数据 */
const handleSubmit = async (record) => {
const res = await postSettleAccountsMemberSettlementAccountStatementSubmit({ id: record.id })
if (res.code === 1000) {
ref.current && ref.current.reload()
}
}
/** 删除发票 */
const handleDelete = async (record) => {
Modal.confirm({
content: '是否确认删除发票?',
centered: true,
onOk: () => {
return new Promise(async(resolve, reject) => {
try {
const res = await postSettleAccountsMemberSettlementAccountStatementDelete({ invoiceId: record.id })
if (res.code === 1000) {
ref.current && ref.current.reload()
resolve(true)
} else {
reject()
}
} catch (error) {
reject()
}
})
}
})
}
/** 跳转到编辑页面 */
const handleEdit = (record) => {
history.push(`/memberCenter/balance/invoice/edit?reconciliationId=${record.reconciliationId}&id=${record.id}`)
}
const renderOptionButton = (record) => {
// 按钮权限code和操作字符映射
const btnAuthOfOperationTextMap = {
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.1', defaultMessage: '提交' })]: 'invoice.sbumt',
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.2', defaultMessage: '编辑' })]: 'invoice.edit',
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.3', defaultMessage: '删除' })]: 'invoice.del',
}
const buttonGroup = {
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.1', defaultMessage: '提交' })]: record.examineStatus === 0,
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.2', defaultMessage: '编辑' })]: [0, 3].includes(record.examineStatus),
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.3', defaultMessage: '删除' })]: [0, 3].includes(record.examineStatus),
}
const operationHandler = {
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.1', defaultMessage: '提交' })]: () => handleSubmit(record),
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.2', defaultMessage: '编辑' })]: () => handleEdit(record),
[intl.formatMessage({ id: 'balance.invoice.manage.buttonGroup.3', defaultMessage: '删除' })]: () => handleDelete(record),
}
return (
<TableOperation
buttonTextFieldMap={buttonGroup}
operationHandler={operationHandler}
// menuCode="commodityAbility"
buttonPermissionsMap={btnAuthOfOperationTextMap}
/>
)
}
const columns = [
{
title: intl.formatMessage({
id: 'balance.common.columns.productNoticecolumns.orderNo',
}),
dataIndex: 'reconciliationNo',
render: (text, record) => (
<Button
type="link"
onClick={() => {
history.push(`/memberCenter/balance/invoice/detail?reconciliationId=${record.reconciliationId}&id=${record.id}`)
}}
>
{text}
</Button>
),
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderAbstract',
}),
dataIndex: 'reconciliationAbstract',
},
{
title: intl.formatMessage({
id:
'balance.accountsReceivable.invoice.columns.settlementOrderTypeName',
}),
dataIndex: 'reconciliationTypeName',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderTime',
}),
dataIndex: 'createTime',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.payer',
}),
dataIndex: 'payer',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.code',
}),
dataIndex: 'code',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.number',
}),
dataIndex: 'number',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceDate',
}),
dataIndex: 'invoiceDate',
render: invoiceDate => moment(invoiceDate).format('YYYY-MM-DD')
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceAmount',
}),
dataIndex: 'invoiceAmount',
render: text =>
`${intl.formatMessage({ id: 'common.money' })} ${priceFormat(text)}`,
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus',
}),
dataIndex: 'examineStatus',
filters: [
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.0',
}),
value: 0,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.1',
}),
value: 1,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.2',
}),
value: 2,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.examineStatus.3',
}),
value: 3,
},
],
onFilter: (value: number, record: any) => record.invoiceStatus == value,
render: (_, record) => {
return (
<StatusTag
title={record.examineStatusName}
status={record.examineStatus}
colorMap={{
0: '#ACAFB3',
1: '#4787F0',
2: '#00A98F',
3: '#E34D59',
}}
/>
);
},
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.operation',
}),
render: (_, record) => renderOptionButton(record)
},
];
const clickAdd = () => {
history.push('/memberCenter/balance/invoice/add');
};
const controllerBtns = (
<Space>
<AuthButton btnCode="readyAddBill.add">
<Button icon={<PlusCircleOutlined />} type="primary" onClick={clickAdd}>
{intl.formatMessage({
id: 'purchaseRequisition.xinjian',
defaultMessage: '新建',
})}
</Button>
</AuthButton>
</Space>
);
return (
<PageHeaderWrapper>
<Card className="white_bg_card">
<StandardTable
tableProps={{
rowKey: 'id',
}}
loading={pageLoading}
columns={columns as any}
currentRef={ref}
fetchTableData={(params: any) => fetchListData(params)}
controlRender={
<NiceForm
components={{
RangePicker,
}}
expressionScope={{
controllerBtns,
}}
actions={formActions}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'megaLayout.reconciliationNo',
FORM_FILTER_PATH,
);
}}
schema={schema}
onSubmit={handleSearch}
initialValues={{}}
/>
}
/>
</Card>
</PageHeaderWrapper>
);
};
export default InvoiceManage;
This diff is collapsed.
import { useState } from 'react'
import { ISchemaFormActions, ISchemaFormAsyncActions } from '@formily/antd';
import { invoiceDetailColumn } from '../contants';
import ProductTableCell, { ProductEditableRow } from '../../components/ProductTableCell';
import { getIntl } from 'umi';
import { Button } from 'antd';
import { OperateType } from '../invoiceForm';
const intl = getIntl();
// 对象按key排序(运用于商城传过来的阶梯价格排序)
export const sortByKey = (params) => {
let keys = Object.keys(params).sort((x,y)=> parseInt(x) - parseInt(y));
let newParams = {};
keys.forEach((key) => {
newParams[key] = params[key];
});
return newParams;
}
/**
* @param ctx schemaAction
* @param relevanceRef 关联报价商品抽屉的ref
*/
export const useInvoiceDetailTable = (ctx: ISchemaFormActions | ISchemaFormAsyncActions) => {
const invoiceDetailComponents = {
body: {
row: ProductEditableRow,
cell: ProductTableCell
}
}
const handleSave = (row) => {
return new Promise((resolve) => {
const newData = [...ctx.getFieldValue('rows')];
const index = newData.findIndex(item => row.id === item.id);
const item = {...row};
const count = row.currentNumber || 0
item['taxMoneyAmount'] = ((item.price * count) / (1 + (item.taxRate / 100)) * (item.taxRate / 100)).toFixed(2) // 税额
item['currentMoneyAmount'] = (item.price * count).toFixed(2) // 本次开票金额(含税)
item['currentMoneyNoTax'] = ((item.price * count) / (1 + (item.taxRate / 100))).toFixed(2) // 本次开票金额(不含税)
newData[index] = item
ctx.setFieldValue('rows', newData)
resolve({ item, newData })
})
};
const handleDelete = (row) => {
let newData = [...ctx.getFieldValue('rows')];
newData = newData.filter((item) => item.id !== row.id)
ctx.setFieldValue('rows', newData)
}
const invoiceMergeColumns = invoiceDetailColumn.map(col => {
const operateType = ctx.getFieldValue('operateType')
if (operateType === OperateType.detail) {
if (col.action && col.action === 'delete') {
return {
key: 'action'
}
}
return col;
}
if (col.action && col.action === 'delete') {
return {
...col,
render: (_, row) => <Button type='link' onClick={() => handleDelete(row)}>{intl.formatMessage({ id: 'common.button.delete' })}</Button>,
}
}
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => ({
record,
editable: ctx.getFormState().editable === false ? false : col.editable,
dataIndex: col.dataIndex,
title: col.title,
formItem: col.formItem,
// formItemProps: col.formItemProps,
handleSave
}),
};
})
return {
invoiceDetailColumns: invoiceMergeColumns,
invoiceDetailComponents,
}
}
This diff is collapsed.
export interface InvoiceDetailType {
/**
* 开票id
*/
id: number
/**
* 对账单id
*/
reconciliationId: number
/**
* 对账单号
*/
reconciliationNo: string
/**
* 对账单摘要
*/
reconciliationAbstract: string
/**
* 对账单类型
*/
reconciliationType: number
/**
* 对账单类型名称
*/
reconciliationTypeName: string
/**
* 单据时间
*/
createTime: string
/**
* 付款方
*/
payer: string
/**
* 发票种类:1.增值税普通发票(默认)2.增值税专用发票
*/
kind: number
/**
* 发票类型:1.企业(默认)2.个人
*/
type: number
/**
* 发票抬头
*/
invoiceTitle: string
/**
* 纳税号
*/
taxNo: string
/**
* 开户行
*/
bankOfDeposit: string
/**
* 账号
*/
account: string
/**
* 地址
*/
address: string
/**
* 电话
*/
tel: string
/**
* 发票号码
*/
number: string
/**
* 发票代码
*/
code: string
/**
* 开票日期
*/
invoiceDate: string
/**
* 备注
*/
remark: string
/**
* 发票图片 ,String
*/
urlImgs: string[]
/**
* 退回原因
*/
returnResource: string
}
export interface InvoiceRowsType {
/**
* 开票明细id(新增为空,修改不为空)
*/
id?: number
/**
* 开票id
*/
invoiceProveId: number
/**
* 对账单id
*/
reconciliationId: number
/**
* 对账单明细id
*/
reconciliationRowId: number
/**
* 订单编号
*/
orderNo: string
/**
* 发货单号
*/
deliveryNo: string
/**
* 收货单号
*/
receiveNo: string
/**
* 物料编码
*/
productNo: string
/**
* 物料名称
*/
name: string,
productName: string,
/**
* 商品规格
*/
spec?: string
/**
* 商品品类
*/
category?: string
/**
* 商品品牌
*/
brand?: string
/**
* 单位
*/
unit?: string
/**
* 税率(百分比的分子部分)
*/
taxRate: number
/**
* 单价(含税)
*/
price: number
/**
* 单价(不含税)
*/
priceNoTax: number
/**
* 税额
*/
taxMoneyAmount: number
/**
* 本次对账数量
*/
currentQuantity: number
currentReconciliationQuantity: number,
/**
* 本次对账金额(含税)
*/
currentMoney: number
/**
* 本次开票数量
*/
currentNumber: number
/**
* 本次开票金额(含税)
*/
currentMoneyAmount: number
/**
* 本次开票金额(不含税)
*/
currentMoneyNoTax: number
}
/**
* 新增开票表单类型
*/
export interface InvoiceFromValuesType {
/**
* 对账单开票明细列表 ,InvoiceReconciliationRowVO
*/
rows: InvoiceRowsType[]
/**
* 开票id
*/
id?: number
/**
* 对账单id
*/
reconciliationId: number
/**
* 对账单号
*/
reconciliationNo: string
/**
* 对账单摘要
*/
reconciliationAbstract?: string
/**
* 对账单类型
*/
reconciliationType: number
/**
* 对账单类型名称
*/
reconciliationTypeName?: string
/**
* 单据时间
*/
createTime: string
/**
* 付款方
*/
payer?: string
/**
* 发票种类:1.增值税普通发票(默认)2.增值税专用发票
*/
kind?: number
/**
* 发票类型:1.企业(默认)2.个人
*/
type?: number
/**
* 发票抬头
*/
invoiceTitle?: string
/**
* 纳税号
*/
taxNo?: string
/**
* 开户行
*/
bankOfDeposit?: string
/**
* 账号
*/
account?: string
/**
* 地址
*/
address?: string
/**
* 电话
*/
tel?: string
/**
* 发票号码
*/
number: string
/**
* 发票代码
*/
code: string
/**
* 开票日期
*/
invoiceDate: string
/**
* 备注
*/
remark?: string
/**
* 发票图片 ,String
*/
urlImgs?: string[]
/**
* 退回原因
*/
returnResource?: string
}
.text {
color: @main-color;
cursor: pointer;
}
.white_bg_card {
background-color: #FFFFFF;
}
/**
* 待开票(SRM)
*/
import React, { useRef } from 'react';
import { getIntl, useIntl, Link } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Button, DatePicker } from 'antd';
import NiceForm from '@/components/NiceForm';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { createFormActions } from '@formily/antd';
import StandardTable from '@/components/StandardTable';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
import { schema } from './schema';
import StatusTag from '@/components/StatusTag';
import { fetchInvoiceOptions } from '../../../common';
import useSetSearchValueInTable from '@/hooks/useSetSearchValueInTable';
import { priceFormat } from '@/utils/numberFomat';
import {
getSettleAccountsMemberSettlementAccountStatementTobeInvoiceListStatus,
getSettleAccountsMemberSettlementPageInvoicingProcessList,
} from '@/services/SettleV2Api';
import AuthButton from '@/components/AuthButton';
import './index.less';
import moment from 'moment';
const intl = getIntl();
const RangePicker = DatePicker.RangePicker;
const formActions = createFormActions();
const SettlementList: React.FC = () => {
const intl = useIntl();
const ref = useRef<any>({});
/**
* @param params
*/
const fetchListData = async params => {
const searchParams = {
...params,
};
const { data } = await getSettleAccountsMemberSettlementPageInvoicingProcessList(
searchParams,
);
return data;
};
/**
* 搜索
*/
const handleSearch = values => {
ref.current.reload({
...values,
createTimeStart: values?.createTimeStart ? values?.createTimeStart.format('YYYY-MM-DD') : undefined,
createTimeEnd: values?.createTimeEnd ? values?.createTimeEnd.format('YYYY-MM-DD') : undefined,
});
};
const _handleOrderNo = record => {
window.open(
`/memberCenter/balance/businessReconciliation/search/preview?id=${record.reconciliationId}&no=${record.reconciliationNo}`,
);
};
const columns = [
{
title: intl.formatMessage({
id: 'balance.common.columns.productNoticecolumns.orderNo',
}),
dataIndex: 'reconciliationNo',
render: (text, record) => (
<Button
type="link"
onClick={() => {
_handleOrderNo(record);
}}
>
{text}
</Button>
),
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderAbstract',
}),
dataIndex: 'reconciliationAbstract',
},
{
title: intl.formatMessage({
id:
'balance.accountsReceivable.invoice.columns.settlementOrderTypeName',
}),
dataIndex: 'reconciliationTypeName',
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderTime',
}),
dataIndex: 'createTime',
render: createTime => moment(createTime).format('YYYY-MM-DD')
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.tax',
}),
dataIndex: 'tax',
render: (_, record) => {
return record.isTaxRate === 1
? `${intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.tax.yes',
})}/${priceFormat(record.taxRate * 100)}%`
: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.tax.none',
});
},
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.orderAmount',
}),
dataIndex: 'reconciliationMoneyAmount',
render: (text, record) =>
`${intl.formatMessage({ id: 'common.money' })} ${priceFormat(text)}`,
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceStatus',
}),
dataIndex: 'invoiceStatus',
filters: [
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceStatus.0',
}),
value: 0,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceStatus.1',
}),
value: 1,
},
{
text: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.invoiceStatus.2',
}),
value: 2,
},
],
onFilter: (value: number, record: any) => record.invoiceStatus == value,
render: (_, record) => {
return (
<div>
<StatusTag
title={record.invoiceStatusName}
type={{ 0: 'warning', 1: 'success', 2: 'active'}[record.invoiceStatus]}
/>
</div>
);
},
},
{
title: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.operation',
}),
render: (text, record) => {
return (
<Link
to={
record.invoiceStatus === 1
? `/memberCenter/balance/invoice/inquire?reconciliationNo=${record.reconciliationNo}`
: `/memberCenter/balance/invoice/add?reconciliationId=${record.reconciliationId}`
}
>
{record.invoiceStatus === 1
? intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.operation.1',
})
: intl.formatMessage({
id: 'balance.accountsReceivable.invoice.columns.operation.2',
})}
</Link>
);
},
},
];
return (
<PageHeaderWrapper>
<Card className="white_bg_card">
<StandardTable
tableProps={{
rowKey: 'id',
}}
columns={columns as any}
currentRef={ref}
fetchTableData={(params: any) => fetchListData(params)}
controlRender={
<NiceForm
components={{
RangePicker,
}}
actions={formActions}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'megaLayout.reconciliationNo',
FORM_FILTER_PATH,
);
useAsyncSelect(
'invoiceStatus',
fetchInvoiceOptions(getSettleAccountsMemberSettlementAccountStatementTobeInvoiceListStatus),
);
}}
schema={schema}
onSubmit={handleSearch}
initialValues={{}}
onReset={() => {
formActions.setFieldValue('createTimeStart', null);
formActions.setFieldValue('createTimeEnd', null);
}}
/>
}
/>
</Card>
</PageHeaderWrapper>
);
};
export default SettlementList;
import { getIntl } from 'umi'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ISchema, createFormActions } from '@formily/antd';
const intl = getIntl()
/**
* 开票管理列表页schema
*/
export const schema: ISchema = {
type: 'object',
properties: {
megaLayout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
grid: true,
},
properties: {
reconciliationNo: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
align: 'flex-start',
allowClear: true,
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderNo' }),
},
},
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
justifyContent: 'flex-start'
},
colStyle: {
marginRight: 16,
},
},
properties: {
reconciliationAbstract: {
type: 'string',
default: undefined,
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.orderAbstract' }),
allowClear: true,
},
},
"[createTimeStart, createTimeEnd]": {
type: 'object',
'x-component': 'RangePicker',
'x-component-props': {
placeholder: [intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceStartTime' }), intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceEndTime' })],
allowClear: true,
style: {
width: 320,
}
},
},
invoiceStatus: {
type: 'string',
enum: [],
'x-component-props': {
placeholder: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.invoiceStatus' }),
allowClear: true,
},
},
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.schema.submit' }),
},
},
},
},
},
};
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