完成发票管理
This commit is contained in:
parent
3e56632e34
commit
8ec42c9d82
354
src/components/invoice/InvoiceEdit.tsx
Normal file
354
src/components/invoice/InvoiceEdit.tsx
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
import {Button, Divider, Flex, Form, Input, Modal, Radio, Space} from "antd";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {listDictionary, IDictionary, get, put} from "../../util/AjaxUtils.ts";
|
||||||
|
import useMessage from "antd/es/message/useMessage";
|
||||||
|
import InvoiceInfoList from "./info/InvoiceInfoList.tsx";
|
||||||
|
import InvoiceOrderList from "./order/InvoiceOrderList.tsx";
|
||||||
|
import useModal from "antd/es/modal/useModal";
|
||||||
|
|
||||||
|
type FormFieldType = {
|
||||||
|
invoiceTitle: string;
|
||||||
|
invoiceNo: string;
|
||||||
|
invoiceAddress: string;
|
||||||
|
invoicePhone: string;
|
||||||
|
invoiceAccount: string;
|
||||||
|
invoiceBank: string;
|
||||||
|
content: string;
|
||||||
|
rate: string;
|
||||||
|
type: string;
|
||||||
|
orderIds: string[];
|
||||||
|
invoiceNote: string;
|
||||||
|
isSaveInvoiceInfo: boolean;
|
||||||
|
invoiceAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type EditProps = {
|
||||||
|
invoiceId: string;
|
||||||
|
handleOk: () => void;
|
||||||
|
handleCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceEdit(props: EditProps) {
|
||||||
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [modal, modalContext] = useModal();
|
||||||
|
const [form] = Form.useForm<FormFieldType>();
|
||||||
|
const [contentArray, setContentArray] = useState<IDictionary[]>([]);
|
||||||
|
const [rateArray, setRateArray] = useState<IDictionary[]>([]);
|
||||||
|
const [typeArray, setTypeArray] = useState<IDictionary[]>([]);
|
||||||
|
const [isInvoiceInfoListOpen, setIsInvoiceInfoListOpen] = useState(false);
|
||||||
|
const [isInvoiceOrderListOpen, setIsInvoiceOrderListOpen] = useState(false);
|
||||||
|
const [orderAmount, setOrderAmount] = useState('0');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(!props.invoiceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 开票内容
|
||||||
|
listDictionary('e0251d55-cd52-4f57-be92-b2bef8a6dd62', messageApi).then((data) => {
|
||||||
|
setContentArray([...data]);
|
||||||
|
})
|
||||||
|
// 开票税率
|
||||||
|
listDictionary('b67d5208-db1d-4d0e-99de-cc22d9d50041', messageApi).then((data) => {
|
||||||
|
setRateArray([...data]);
|
||||||
|
})
|
||||||
|
// 开票类型
|
||||||
|
listDictionary('e4808c45-64ee-42fa-a413-a470fbdc0aea', messageApi).then((data) => {
|
||||||
|
setTypeArray([...data]);
|
||||||
|
})
|
||||||
|
get<FormFieldType>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/invoice/get/${props.invoiceId}`,
|
||||||
|
onSuccess({data}) {
|
||||||
|
form.setFieldsValue(data);
|
||||||
|
setOrderAmount((data.invoiceAmount / 100).toFixed(2));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{messageContext}
|
||||||
|
{modalContext}
|
||||||
|
<Form
|
||||||
|
name="basic"
|
||||||
|
initialValues={{isSaveInvoiceInfo: 0}}
|
||||||
|
form={form}
|
||||||
|
onFinish={(values) => {
|
||||||
|
modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定提交吗?',
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
okButtonProps: {
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'val(--color-primary)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onOk: () => {
|
||||||
|
put<any>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/invoice/update/${props.invoiceId}`,
|
||||||
|
body: values,
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('提交成功');
|
||||||
|
props.handleOk();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Divider orientation="left" plain>开票信息</Divider>
|
||||||
|
<table className="pay-table">
|
||||||
|
<colgroup>
|
||||||
|
<col width="120"/>
|
||||||
|
<col/>
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button type="link" onClick={() => {
|
||||||
|
setIsInvoiceInfoListOpen(true);
|
||||||
|
}}>选择开票信息</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">公司名称 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoiceTitle"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入公司名称'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入公司名称"/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">纳税人识别号 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoiceNo"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入纳税人识别号'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入纳税人识别号"/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">公司地址 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoiceAddress"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入公司地址'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入公司地址"/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">联系电话 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoicePhone"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入联系电话'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入联系电话"/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开户行 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoiceAccount"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入开户行'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入开户行"/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开户行账号 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoiceBank"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入开户行账号'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入开户行账号"/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票内容 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="content"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请选择开票内容'}]}
|
||||||
|
>
|
||||||
|
<Radio.Group>
|
||||||
|
<Space direction="vertical">
|
||||||
|
{contentArray.map(item => <Radio value={item.dataName}
|
||||||
|
key={item.dataId}>{item.dataName}</Radio>)}
|
||||||
|
</Space>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票税率 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="rate"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请选择开票税率'}]}
|
||||||
|
>
|
||||||
|
<Radio.Group>
|
||||||
|
{rateArray.map(item => <Radio value={item.dataName}
|
||||||
|
key={item.dataId}>{item.dataName}</Radio>)}
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">发票类型 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="type"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请选择发票类型'}]}
|
||||||
|
>
|
||||||
|
<Radio.Group>
|
||||||
|
<Space direction="vertical">
|
||||||
|
{typeArray.map(item => <Radio value={item.dataName}
|
||||||
|
key={item.dataId}>{item.dataName}</Radio>)}
|
||||||
|
</Space>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">保存开票信息 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="isSaveInvoiceInfo"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
>
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value={0}>否</Radio>
|
||||||
|
<Radio value={1}>是</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<Divider orientation="left" plain>开票内容</Divider>
|
||||||
|
<table className="pay-table">
|
||||||
|
<colgroup>
|
||||||
|
<col width="120"/>
|
||||||
|
<col/>
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票金额 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="orderIds"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请选择开票金额'}]}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span>¥</span>
|
||||||
|
<span style={{fontSize: '20px', fontWeight: 'bold'}}>{orderAmount}</span>
|
||||||
|
<Button type="link" size="small" onClick={() => {
|
||||||
|
setIsInvoiceOrderListOpen(true);
|
||||||
|
}}>请选择需要开票的订单</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票备注</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoiceNote"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
>
|
||||||
|
<Input.TextArea placeholder="请输入开票备注" rows={4}/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<Form.Item style={{marginBottom: '0'}}>
|
||||||
|
<Flex justify="center" style={{marginTop: '15px'}}>
|
||||||
|
<Space>
|
||||||
|
<Button type="primary" htmlType="submit" style={{
|
||||||
|
backgroundColor: 'var(--color-primary)'
|
||||||
|
}}>提交</Button>
|
||||||
|
<Button type="default" onClick={() => {
|
||||||
|
props.handleCancel();
|
||||||
|
}}>返回</Button>
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
<Modal open={isInvoiceInfoListOpen}
|
||||||
|
title="开票信息"
|
||||||
|
width={1000}
|
||||||
|
footer={false}
|
||||||
|
onCancel={() => setIsInvoiceInfoListOpen(false)}
|
||||||
|
>
|
||||||
|
<InvoiceInfoList
|
||||||
|
handleOk={(selectedInvoice) => {
|
||||||
|
form.setFieldsValue({
|
||||||
|
invoiceTitle: selectedInvoice.invoiceTitle,
|
||||||
|
invoiceNo: selectedInvoice.invoiceNo,
|
||||||
|
invoiceAddress: selectedInvoice.invoiceAddress,
|
||||||
|
invoicePhone: selectedInvoice.invoicePhone,
|
||||||
|
invoiceAccount: selectedInvoice.invoiceAccount,
|
||||||
|
invoiceBank: selectedInvoice.invoiceBank
|
||||||
|
});
|
||||||
|
setIsInvoiceInfoListOpen(false);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsInvoiceInfoListOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
<Modal open={isInvoiceOrderListOpen}
|
||||||
|
title="开票订单"
|
||||||
|
width={1000}
|
||||||
|
footer={false}
|
||||||
|
onCancel={() => setIsInvoiceOrderListOpen(false)}
|
||||||
|
>
|
||||||
|
<InvoiceOrderList
|
||||||
|
selectedOrderIds={form.getFieldValue('orderIds')}
|
||||||
|
handleOk={(selectedOrders) => {
|
||||||
|
let totalAmount = 0;
|
||||||
|
const orderIds: string[] = [];
|
||||||
|
selectedOrders.forEach((item) => {
|
||||||
|
totalAmount += item.totalAmount;
|
||||||
|
orderIds.push(item.orderId);
|
||||||
|
});
|
||||||
|
setOrderAmount((totalAmount / 100).toFixed(2));
|
||||||
|
setIsInvoiceOrderListOpen(false);
|
||||||
|
form.setFieldValue('orderIds', orderIds);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsInvoiceOrderListOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
import {Button, Dropdown, MenuProps, Modal, Table, TableProps, Tag} from "antd";
|
import {Button, Dropdown, Flex, MenuProps, Modal, Popconfirm, Space, Table, TableProps, Tag} from "antd";
|
||||||
import {PlusOutlined} from "@ant-design/icons";
|
import {PlusOutlined} from "@ant-design/icons";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useRef, useState} from "react";
|
||||||
import {get} from "../../util/AjaxUtils.ts";
|
import {get, put} from "../../util/AjaxUtils.ts";
|
||||||
import {IListPage} from "../../interfaces/listpage/IListPage.ts";
|
import {IListPage} from "../../interfaces/listpage/IListPage.ts";
|
||||||
import useMessage from "antd/es/message/useMessage";
|
import useMessage from "antd/es/message/useMessage";
|
||||||
import InvoiceSave from "./InvoiceSave.tsx";
|
import InvoiceSave from "./InvoiceSave.tsx";
|
||||||
|
import InvoiceEdit from "./InvoiceEdit.tsx";
|
||||||
|
import InvoiceShow from "./InvoiceShow.tsx";
|
||||||
|
|
||||||
enum InvoiceStatusEnum {
|
enum InvoiceStatusEnum {
|
||||||
PENDING = 'PENDING',
|
PENDING = 'PENDING',
|
||||||
@ -39,6 +41,10 @@ export default function InvoiceList() {
|
|||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [dataArray, setDataArray] = useState<DataType[]>([]);
|
const [dataArray, setDataArray] = useState<DataType[]>([]);
|
||||||
|
const [isSaveModalOpen, setIsSaveModalOpen] = useState(false);
|
||||||
|
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||||
|
const [isShowModalOpen, setIsShowModalOpen] = useState(false);
|
||||||
|
const invoiceId = useRef('');
|
||||||
|
|
||||||
const columns: TableProps<DataType>['columns'] = [
|
const columns: TableProps<DataType>['columns'] = [
|
||||||
{
|
{
|
||||||
@ -125,7 +131,55 @@ export default function InvoiceList() {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
width: 120,
|
width: 120,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
render: (value, record) => {
|
render: (_value, record) => {
|
||||||
|
if(record.invoiceStatus === InvoiceStatusEnum.PENDING) {
|
||||||
|
return <Flex justify="center">
|
||||||
|
<Space>
|
||||||
|
<Button type="link" style={{
|
||||||
|
color: 'var(--color-dark)',
|
||||||
|
padding: '0'
|
||||||
|
}} onClick={() => {
|
||||||
|
invoiceId.current = record.invoiceId;
|
||||||
|
setIsShowModalOpen(true);
|
||||||
|
}}>查看</Button>
|
||||||
|
<Popconfirm
|
||||||
|
title={false}
|
||||||
|
placement="right"
|
||||||
|
description="确定取消吗?"
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
okButtonProps={{
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'var(--color-primary)'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onConfirm={() => {
|
||||||
|
put<any>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/invoice/update-cancel/${record.invoiceId}`,
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('取消成功');
|
||||||
|
getData();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button type="link" danger style={{
|
||||||
|
padding: '0'
|
||||||
|
}}>取消</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
if(record.invoiceStatus === InvoiceStatusEnum.CANCEL) {
|
||||||
|
return <Button type="link" style={{
|
||||||
|
padding: '0'
|
||||||
|
}} onClick={() => {
|
||||||
|
invoiceId.current = record.invoiceId;
|
||||||
|
setIsEditModalOpen(true);
|
||||||
|
}}>编辑</Button>
|
||||||
|
}
|
||||||
if(record.invoiceStatus == InvoiceStatusEnum.COMPLETE) {
|
if(record.invoiceStatus == InvoiceStatusEnum.COMPLETE) {
|
||||||
const items: MenuProps['items'] = [];
|
const items: MenuProps['items'] = [];
|
||||||
record.invoiceFileList.forEach((item, index) => {
|
record.invoiceFileList.forEach((item, index) => {
|
||||||
@ -146,7 +200,7 @@ export default function InvoiceList() {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
useEffect(() => {
|
const getData = () => {
|
||||||
get<IListPage<DataType>>({
|
get<IListPage<DataType>>({
|
||||||
messageApi,
|
messageApi,
|
||||||
url: '/api/invoice/listpage/self',
|
url: '/api/invoice/listpage/self',
|
||||||
@ -162,6 +216,10 @@ export default function InvoiceList() {
|
|||||||
setDataArray(data.rows);
|
setDataArray(data.rows);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getData();
|
||||||
}, [page]);
|
}, [page]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -170,24 +228,59 @@ export default function InvoiceList() {
|
|||||||
<div className="mod-list">
|
<div className="mod-list">
|
||||||
<div className="table-btn-group" style={{marginBottom: '15px'}}>
|
<div className="table-btn-group" style={{marginBottom: '15px'}}>
|
||||||
<Button value="small" onClick={() => {
|
<Button value="small" onClick={() => {
|
||||||
|
setIsSaveModalOpen(true);
|
||||||
}}><PlusOutlined/> 新增</Button>
|
}}><PlusOutlined/> 新增</Button>
|
||||||
</div>
|
</div>
|
||||||
<Table columns={columns} dataSource={dataArray} pagination={
|
<Table columns={columns} dataSource={dataArray} pagination={
|
||||||
{
|
{
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
|
total: total,
|
||||||
onChange: (currentPage) => {
|
onChange: (currentPage) => {
|
||||||
setPage(currentPage);
|
setPage(currentPage);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
} scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceId"/>
|
} scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceId"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal open={true}
|
<Modal open={isSaveModalOpen}
|
||||||
title="申请开票"
|
title="申请开票"
|
||||||
footer={false}
|
footer={false}
|
||||||
|
onCancel={() => setIsSaveModalOpen(false)}
|
||||||
>
|
>
|
||||||
<InvoiceSave />
|
<InvoiceSave
|
||||||
|
handleOk={() => {
|
||||||
|
getData();
|
||||||
|
setIsSaveModalOpen(false);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsSaveModalOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
<Modal open={isEditModalOpen}
|
||||||
|
title="修改开票信息"
|
||||||
|
footer={false}
|
||||||
|
onCancel={() => setIsEditModalOpen(false)}
|
||||||
|
>
|
||||||
|
<InvoiceEdit
|
||||||
|
invoiceId={invoiceId.current}
|
||||||
|
handleOk={() => {
|
||||||
|
getData();
|
||||||
|
setIsEditModalOpen(false);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsEditModalOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
<Modal open={isShowModalOpen}
|
||||||
|
title="查看开票信息"
|
||||||
|
footer={false}
|
||||||
|
onCancel={() => setIsShowModalOpen(false)}
|
||||||
|
>
|
||||||
|
<InvoiceShow
|
||||||
|
invoiceId={invoiceId.current}
|
||||||
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
{messageContext}
|
{messageContext}
|
||||||
</>
|
</>
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import {Button, Divider, Flex, Form, Input, Modal, Radio, Space} from "antd";
|
import {Button, Divider, Flex, Form, Input, Modal, Radio, Space} from "antd";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {listDictionary, IDictionary} from "../../util/AjaxUtils.ts";
|
import {listDictionary, IDictionary, post} from "../../util/AjaxUtils.ts";
|
||||||
import useMessage from "antd/es/message/useMessage";
|
import useMessage from "antd/es/message/useMessage";
|
||||||
import InvoiceInfoList from "./info/InvoiceInfoList.tsx";
|
import InvoiceInfoList from "./info/InvoiceInfoList.tsx";
|
||||||
|
import InvoiceOrderList from "./order/InvoiceOrderList.tsx";
|
||||||
|
import useModal from "antd/es/modal/useModal";
|
||||||
|
|
||||||
type FormFieldType = {
|
type FormFieldType = {
|
||||||
invoiceTitle: string;
|
invoiceTitle: string;
|
||||||
invoiceNo: number;
|
invoiceNo: string;
|
||||||
invoiceAddress: string;
|
invoiceAddress: string;
|
||||||
invoicePhone: string;
|
invoicePhone: string;
|
||||||
invoiceAccount: string;
|
invoiceAccount: string;
|
||||||
@ -14,28 +16,38 @@ type FormFieldType = {
|
|||||||
content: string;
|
content: string;
|
||||||
rate: string;
|
rate: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
orderIds: string[];
|
||||||
|
invoiceNote: string;
|
||||||
|
isSaveInvoiceInfo: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function InvoiceSave() {
|
type SaveProps = {
|
||||||
const [messageApi, messageContext] = useMessage();
|
handleOk: () => void;
|
||||||
const [form] = Form.useForm<FormFieldType>();
|
handleCancel: () => void;
|
||||||
const [isSaveInvoiceInfo, setIsSaveInvoiceInfo] = useState(0);
|
}
|
||||||
|
|
||||||
|
export default function InvoiceSave(props: SaveProps) {
|
||||||
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [modal, modalContext] = useModal();
|
||||||
|
const [form] = Form.useForm<FormFieldType>();
|
||||||
const [contentArray, setContentArray] = useState<IDictionary[]>([]);
|
const [contentArray, setContentArray] = useState<IDictionary[]>([]);
|
||||||
const [rateArray, setRateArray] = useState<IDictionary[]>([]);
|
const [rateArray, setRateArray] = useState<IDictionary[]>([]);
|
||||||
const [typeArray, setTypeArray] = useState<IDictionary[]>([]);
|
const [typeArray, setTypeArray] = useState<IDictionary[]>([]);
|
||||||
|
const [isInvoiceInfoListOpen, setIsInvoiceInfoListOpen] = useState(false);
|
||||||
|
const [isInvoiceOrderListOpen, setIsInvoiceOrderListOpen] = useState(false);
|
||||||
|
const [orderAmount, setOrderAmount] = useState('0');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 开票内容
|
// 开票内容
|
||||||
listDictionary('e0251d55-cd52-4f57-be92-b2bef8a6dd62', messageApi).then((data)=>{
|
listDictionary('e0251d55-cd52-4f57-be92-b2bef8a6dd62', messageApi).then((data) => {
|
||||||
setContentArray([...data]);
|
setContentArray([...data]);
|
||||||
})
|
})
|
||||||
// 开票税率
|
// 开票税率
|
||||||
listDictionary('b67d5208-db1d-4d0e-99de-cc22d9d50041', messageApi).then((data)=>{
|
listDictionary('b67d5208-db1d-4d0e-99de-cc22d9d50041', messageApi).then((data) => {
|
||||||
setRateArray([...data]);
|
setRateArray([...data]);
|
||||||
})
|
})
|
||||||
// 开票类型
|
// 开票类型
|
||||||
listDictionary('e4808c45-64ee-42fa-a413-a470fbdc0aea', messageApi).then((data)=>{
|
listDictionary('e4808c45-64ee-42fa-a413-a470fbdc0aea', messageApi).then((data) => {
|
||||||
setTypeArray([...data]);
|
setTypeArray([...data]);
|
||||||
})
|
})
|
||||||
}, []);
|
}, []);
|
||||||
@ -43,10 +55,35 @@ export default function InvoiceSave() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{messageContext}
|
{messageContext}
|
||||||
|
{modalContext}
|
||||||
<Form
|
<Form
|
||||||
name="basic"
|
name="basic"
|
||||||
initialValues={{remember: true}}
|
initialValues={{isSaveInvoiceInfo: 0}}
|
||||||
form={form}
|
form={form}
|
||||||
|
onFinish={(values) => {
|
||||||
|
modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定提交吗?',
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
okButtonProps: {
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'val(--color-primary)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onOk: () => {
|
||||||
|
post<any>({
|
||||||
|
messageApi,
|
||||||
|
url: '/api/invoice/save',
|
||||||
|
body: values,
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('提交成功');
|
||||||
|
props.handleOk();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Divider orientation="left" plain>开票信息</Divider>
|
<Divider orientation="left" plain>开票信息</Divider>
|
||||||
<table className="pay-table">
|
<table className="pay-table">
|
||||||
@ -55,6 +92,13 @@ export default function InvoiceSave() {
|
|||||||
<col/>
|
<col/>
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button type="link" onClick={() => {
|
||||||
|
setIsInvoiceInfoListOpen(true);
|
||||||
|
}}>选择开票信息</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="table-label">公司名称 *</td>
|
<td className="table-label">公司名称 *</td>
|
||||||
<td>
|
<td>
|
||||||
@ -137,7 +181,8 @@ export default function InvoiceSave() {
|
|||||||
>
|
>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Space direction="vertical">
|
<Space direction="vertical">
|
||||||
{contentArray.map(item => <Radio value={item.dataName}>{item.dataName}</Radio>)}
|
{contentArray.map(item => <Radio value={item.dataName}
|
||||||
|
key={item.dataId}>{item.dataName}</Radio>)}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -152,7 +197,8 @@ export default function InvoiceSave() {
|
|||||||
rules={[{required: true, message: '请选择开票税率'}]}
|
rules={[{required: true, message: '请选择开票税率'}]}
|
||||||
>
|
>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
{rateArray.map(item => <Radio value={item.dataName}>{item.dataName}</Radio>)}
|
{rateArray.map(item => <Radio value={item.dataName}
|
||||||
|
key={item.dataId}>{item.dataName}</Radio>)}
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</td>
|
</td>
|
||||||
@ -167,22 +213,27 @@ export default function InvoiceSave() {
|
|||||||
>
|
>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Space direction="vertical">
|
<Space direction="vertical">
|
||||||
{typeArray.map(item => <Radio value={item.dataName}>{item.dataName}</Radio>)}
|
{typeArray.map(item => <Radio value={item.dataName}
|
||||||
|
key={item.dataId}>{item.dataName}</Radio>)}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td className="table-label">保存开票信息 *</td>
|
<td className="table-label">保存开票信息 *</td>
|
||||||
<td>
|
<td>
|
||||||
<Radio.Group defaultValue={isSaveInvoiceInfo} onChange={(e) => {
|
<Form.Item
|
||||||
setIsSaveInvoiceInfo(e.target.value)
|
name="isSaveInvoiceInfo"
|
||||||
}}>
|
style={{marginBottom: '0'}}
|
||||||
<Radio value={0}>否</Radio>
|
>
|
||||||
<Radio value={1}>是</Radio>
|
<Radio.Group>
|
||||||
</Radio.Group>
|
<Radio value={0}>否</Radio>
|
||||||
|
<Radio value={1}>是</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -197,22 +248,27 @@ export default function InvoiceSave() {
|
|||||||
<tr>
|
<tr>
|
||||||
<td className="table-label">开票金额 *</td>
|
<td className="table-label">开票金额 *</td>
|
||||||
<td>
|
<td>
|
||||||
<div>
|
<Form.Item
|
||||||
<span>¥</span>
|
name="orderIds"
|
||||||
<span style={{fontSize: '20px', fontWeight: 'bold'}}>300</span>
|
style={{marginBottom: '0'}}
|
||||||
<Button type="link" size="small" onClick={() => {
|
rules={[{required: true, message: '请选择开票金额'}]}
|
||||||
|
>
|
||||||
}}>请选择需要开票的订单</Button>
|
<div>
|
||||||
</div>
|
<span>¥</span>
|
||||||
|
<span style={{fontSize: '20px', fontWeight: 'bold'}}>{orderAmount}</span>
|
||||||
|
<Button type="link" size="small" onClick={() => {
|
||||||
|
setIsInvoiceOrderListOpen(true);
|
||||||
|
}}>请选择需要开票的订单</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="table-label">开票备注</td>
|
<td className="table-label">开票备注</td>
|
||||||
<td>
|
<td>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="invoiceBank"
|
name="invoiceNote"
|
||||||
style={{marginBottom: '0'}}
|
style={{marginBottom: '0'}}
|
||||||
rules={[{required: true, message: '请输入开票备注'}]}
|
|
||||||
>
|
>
|
||||||
<Input.TextArea placeholder="请输入开票备注" rows={4}/>
|
<Input.TextArea placeholder="请输入开票备注" rows={4}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -225,20 +281,61 @@ export default function InvoiceSave() {
|
|||||||
<Space>
|
<Space>
|
||||||
<Button type="primary" htmlType="submit" style={{
|
<Button type="primary" htmlType="submit" style={{
|
||||||
backgroundColor: 'var(--color-primary)'
|
backgroundColor: 'var(--color-primary)'
|
||||||
}} onClick={() => {
|
|
||||||
|
|
||||||
}}>提交</Button>
|
}}>提交</Button>
|
||||||
<Button type="default">返回</Button>
|
<Button type="default" onClick={() => {
|
||||||
|
props.handleCancel();
|
||||||
|
}}>返回</Button>
|
||||||
</Space>
|
</Space>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
<Modal open={true}
|
<Modal open={isInvoiceInfoListOpen}
|
||||||
title="开票信息"
|
title="开票信息"
|
||||||
width={1000}
|
width={1000}
|
||||||
footer={false}
|
footer={false}
|
||||||
|
onCancel={() => {
|
||||||
|
setIsInvoiceInfoListOpen(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<InvoiceInfoList/>
|
<InvoiceInfoList
|
||||||
|
handleOk={(selectedInvoice) => {
|
||||||
|
form.setFieldsValue({
|
||||||
|
invoiceTitle: selectedInvoice.invoiceTitle,
|
||||||
|
invoiceNo: selectedInvoice.invoiceNo,
|
||||||
|
invoiceAddress: selectedInvoice.invoiceAddress,
|
||||||
|
invoicePhone: selectedInvoice.invoicePhone,
|
||||||
|
invoiceAccount: selectedInvoice.invoiceAccount,
|
||||||
|
invoiceBank: selectedInvoice.invoiceBank
|
||||||
|
});
|
||||||
|
setIsInvoiceInfoListOpen(false);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsInvoiceInfoListOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
<Modal open={isInvoiceOrderListOpen}
|
||||||
|
title="开票订单"
|
||||||
|
width={1000}
|
||||||
|
footer={false}
|
||||||
|
onCancel={() => setIsInvoiceOrderListOpen(false)}
|
||||||
|
>
|
||||||
|
<InvoiceOrderList
|
||||||
|
handleOk={(selectedOrders) => {
|
||||||
|
let totalAmount = 0;
|
||||||
|
const orderIds: string[] = [];
|
||||||
|
selectedOrders.forEach((item) => {
|
||||||
|
totalAmount += item.totalAmount;
|
||||||
|
orderIds.push(item.orderId);
|
||||||
|
});
|
||||||
|
setOrderAmount((totalAmount / 100).toFixed(2));
|
||||||
|
setIsInvoiceOrderListOpen(false);
|
||||||
|
form.setFieldValue('orderIds', orderIds);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsInvoiceOrderListOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
132
src/components/invoice/InvoiceShow.tsx
Normal file
132
src/components/invoice/InvoiceShow.tsx
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import {Button, Divider, Modal} from "antd";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {get} from "../../util/AjaxUtils.ts";
|
||||||
|
import useMessage from "antd/es/message/useMessage";
|
||||||
|
import InvoiceInfoSelectedList from "./order/InvoiceOrderSelectedList.tsx"
|
||||||
|
|
||||||
|
type DataType = {
|
||||||
|
invoiceTitle: string;
|
||||||
|
invoiceNo: string;
|
||||||
|
invoiceAddress: string;
|
||||||
|
invoicePhone: string;
|
||||||
|
invoiceAccount: string;
|
||||||
|
invoiceBank: string;
|
||||||
|
content: string;
|
||||||
|
rate: string;
|
||||||
|
type: string;
|
||||||
|
orderIds: string[];
|
||||||
|
invoiceNote: string;
|
||||||
|
isSaveInvoiceInfo: boolean;
|
||||||
|
invoiceAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShowProps = {
|
||||||
|
invoiceId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceShow(props: ShowProps) {
|
||||||
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [isInvoiceOrderListOpen, setIsInvoiceOrderListOpen] = useState(false);
|
||||||
|
const [invoiceData, setInvoiceData] = useState<DataType | null>(null);
|
||||||
|
const [orderAmount, setOrderAmount] = useState('0');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!props.invoiceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
get<DataType>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/invoice/get/${props.invoiceId}`,
|
||||||
|
onSuccess({data}) {
|
||||||
|
setInvoiceData({
|
||||||
|
...data
|
||||||
|
});
|
||||||
|
setOrderAmount((data.invoiceAmount / 100).toFixed(2));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{messageContext}
|
||||||
|
<Divider orientation="left" plain>开票信息</Divider>
|
||||||
|
<table className="pay-table">
|
||||||
|
<colgroup>
|
||||||
|
<col width="120"/>
|
||||||
|
<col/>
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">公司名称 *</td>
|
||||||
|
<td>{invoiceData?.invoiceTitle}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">纳税人识别号 *</td>
|
||||||
|
<td>{invoiceData?.invoiceNo}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">公司地址 *</td>
|
||||||
|
<td>{invoiceData?.invoiceAddress}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">联系电话 *</td>
|
||||||
|
<td>{invoiceData?.invoicePhone}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开户行 *</td>
|
||||||
|
<td>{invoiceData?.invoiceAccount}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开户行账号 *</td>
|
||||||
|
<td>{invoiceData?.invoiceBank}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票内容 *</td>
|
||||||
|
<td>{invoiceData?.content}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票税率 *</td>
|
||||||
|
<td>{invoiceData?.rate}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">发票类型 *</td>
|
||||||
|
<td>{invoiceData?.type}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<Divider orientation="left" plain>开票内容</Divider>
|
||||||
|
<table className="pay-table">
|
||||||
|
<colgroup>
|
||||||
|
<col width="120"/>
|
||||||
|
<col/>
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票金额 *</td>
|
||||||
|
<td>
|
||||||
|
<div>
|
||||||
|
<span>¥</span>
|
||||||
|
<span style={{fontSize: '20px', fontWeight: 'bold'}}>{orderAmount}</span>
|
||||||
|
<Button type="link" size="small" onClick={() => {
|
||||||
|
setIsInvoiceOrderListOpen(true);
|
||||||
|
}}>查看开票的订单</Button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票备注</td>
|
||||||
|
<td>{invoiceData?.invoiceNote}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<Modal open={isInvoiceOrderListOpen}
|
||||||
|
title="开票订单"
|
||||||
|
width={1000}
|
||||||
|
footer={false}
|
||||||
|
onCancel={() => setIsInvoiceOrderListOpen(false)}
|
||||||
|
>
|
||||||
|
<InvoiceInfoSelectedList invoiceId={props.invoiceId}/>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
128
src/components/invoice/info/InvoiceInfoEdit.tsx
Normal file
128
src/components/invoice/info/InvoiceInfoEdit.tsx
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import {Button, Flex, Form, Input, Space} from "antd";
|
||||||
|
import {useForm} from "antd/es/form/Form";
|
||||||
|
import useModal from "antd/es/modal/useModal";
|
||||||
|
import {get, post} from "../../../util/AjaxUtils.ts";
|
||||||
|
import useMessage from "antd/es/message/useMessage";
|
||||||
|
import {useEffect} from "react";
|
||||||
|
|
||||||
|
type FormDataType = {
|
||||||
|
invoiceTitle: string;
|
||||||
|
invoicePhone: string;
|
||||||
|
invoiceNo: string;
|
||||||
|
invoiceBank: string;
|
||||||
|
invoiceAddress: string;
|
||||||
|
invoiceAccount: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EditProps {
|
||||||
|
invoiceInfoId: string;
|
||||||
|
handleOk: () => void;
|
||||||
|
handleCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceInfoSave(props: EditProps) {
|
||||||
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [modal, modalContext] = useModal();
|
||||||
|
const [form] = useForm<FormDataType>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!props.invoiceInfoId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
get<FormDataType>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/invoice-info/get/${props.invoiceInfoId}`,
|
||||||
|
onSuccess({data}) {
|
||||||
|
form.setFieldsValue(data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [props.invoiceInfoId]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form
|
||||||
|
name="basic"
|
||||||
|
layout="vertical"
|
||||||
|
form={form}
|
||||||
|
onFinish={(values) => {
|
||||||
|
modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定保存吗',
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
okButtonProps: {
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'var(--color-primary)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onOk: () => {
|
||||||
|
post<any>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/invoice-info/update/${props.invoiceInfoId}`,
|
||||||
|
body: values,
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('保存成功');
|
||||||
|
props.handleOk();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="公司名称"
|
||||||
|
name="invoiceTitle"
|
||||||
|
rules={[{required: true, message: '请输入公司名称'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入公司名称"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="纳税人识别号"
|
||||||
|
name="invoiceNo"
|
||||||
|
rules={[{required: true, message: '请输入纳税人识别号'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入纳税人识别号"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="公司地址"
|
||||||
|
name="invoiceAddress"
|
||||||
|
rules={[{required: true, message: '请输入公司地址'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入公司地址"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="公司电话"
|
||||||
|
name="invoicePhone"
|
||||||
|
rules={[{required: true, message: '请输入公司电话'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入公司电话"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="开户行"
|
||||||
|
name="invoiceBank"
|
||||||
|
rules={[{required: true, message: '请输入开户行'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入开户行"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="开户行账号"
|
||||||
|
name="invoiceAccount"
|
||||||
|
rules={[{required: true, message: '请输入开户行账号'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入开户行账号"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Flex justify="center">
|
||||||
|
<Space size={5}>
|
||||||
|
<Button type="primary" htmlType="submit"
|
||||||
|
style={{backgroundColor: 'var(--color-primary)'}}>保存</Button>
|
||||||
|
<Button type="default" onClick={() => {
|
||||||
|
props.handleCancel();
|
||||||
|
}}>关闭</Button>
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
|
</Form>
|
||||||
|
{messageContext}
|
||||||
|
{modalContext}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
import {Button, Modal, Space, Table, TableProps} from "antd";
|
import {Button, Flex, Modal, Popconfirm, Space, Table, TableProps} from "antd";
|
||||||
import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons";
|
||||||
import useMessage from "antd/es/message/useMessage";
|
import useMessage from "antd/es/message/useMessage";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useRef, useState} from "react";
|
||||||
import {get} from "../../../util/AjaxUtils.ts";
|
import {del, get} from "../../../util/AjaxUtils.ts";
|
||||||
import {IListPage} from "../../../interfaces/listpage/IListPage.ts";
|
import {IListPage} from "../../../interfaces/listpage/IListPage.ts";
|
||||||
import InvoiceInfoSave from "./InvoiceInfoSave.tsx";
|
import InvoiceInfoSave from "./InvoiceInfoSave.tsx";
|
||||||
|
import InvoiceInfoEdit from "./InvoiceInfoEdit.tsx";
|
||||||
|
|
||||||
type DataType = {
|
type DataType = {
|
||||||
invoiceTitle: string;
|
invoiceTitle: string;
|
||||||
@ -18,11 +19,20 @@ type DataType = {
|
|||||||
creator: string;
|
creator: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function InvoiceInfoList() {
|
interface ListProps {
|
||||||
|
handleOk: (selectedInvoice: DataType) => void;
|
||||||
|
handleCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceInfoList(props: ListProps) {
|
||||||
const [messageApi, messageContext] = useMessage();
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [isInvoiceInfoSaveOpen, setIsInvoiceInfoSaveOpen] = useState(false);
|
||||||
|
const [isInvoiceInfoEditOpen, setIsInvoiceInfoEditOpen] = useState(false);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [dataArray, setDataArray] = useState<DataType[]>([]);
|
const [dataArray, setDataArray] = useState<DataType[]>([]);
|
||||||
|
const editInvoiceInfoId = useRef('');
|
||||||
|
const selectedInvoice = useRef<DataType | null>(null);
|
||||||
|
|
||||||
const columns: TableProps<DataType>['columns'] = [
|
const columns: TableProps<DataType>['columns'] = [
|
||||||
{
|
{
|
||||||
@ -68,18 +78,39 @@ export default function InvoiceInfoList() {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
width: 100,
|
width: 100,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
render: () => {
|
render: (_value, record) => {
|
||||||
return (
|
return (
|
||||||
<Space size={5}>
|
<Space size={5}>
|
||||||
<Button type="primary" size="small"><EditOutlined/></Button>
|
<Button type="primary" size="small" onClick={() => {
|
||||||
<Button size="small"><DeleteOutlined/></Button>
|
editInvoiceInfoId.current = record.invoiceInfoId;
|
||||||
|
setIsInvoiceInfoEditOpen(true);
|
||||||
|
}}><EditOutlined/></Button>
|
||||||
|
<Popconfirm
|
||||||
|
placement="right"
|
||||||
|
title={false}
|
||||||
|
description="确定删除吗?"
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
onConfirm={() => {
|
||||||
|
del<any>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/invoice-info/remove/${record.invoiceInfoId}`,
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('删除成功');
|
||||||
|
getData();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button type="primary" size="small" danger><DeleteOutlined/></Button>
|
||||||
|
</Popconfirm>
|
||||||
</Space>
|
</Space>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
useEffect(() => {
|
const getData = () => {
|
||||||
get<IListPage<DataType>>({
|
get<IListPage<DataType>>({
|
||||||
messageApi,
|
messageApi,
|
||||||
url: '/api/invoice-info/listpage/self',
|
url: '/api/invoice-info/listpage/self',
|
||||||
@ -95,6 +126,10 @@ export default function InvoiceInfoList() {
|
|||||||
setDataArray(data.rows);
|
setDataArray(data.rows);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getData();
|
||||||
}, [page]);
|
}, [page]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -103,14 +138,14 @@ export default function InvoiceInfoList() {
|
|||||||
<div className="mod-list">
|
<div className="mod-list">
|
||||||
<div className="table-btn-group" style={{marginBottom: '15px'}}>
|
<div className="table-btn-group" style={{marginBottom: '15px'}}>
|
||||||
<Button value="small" onClick={() => {
|
<Button value="small" onClick={() => {
|
||||||
|
setIsInvoiceInfoSaveOpen(true);
|
||||||
}}><PlusOutlined/> 新增</Button>
|
}}><PlusOutlined/> 新增</Button>
|
||||||
</div>
|
</div>
|
||||||
<Table rowSelection={
|
<Table rowSelection={
|
||||||
{
|
{
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => {
|
onChange: (_selectedRowKeys, selectedRows) => {
|
||||||
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
|
selectedInvoice.current = selectedRows[0];
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} columns={columns} dataSource={dataArray} pagination={
|
} columns={columns} dataSource={dataArray} pagination={
|
||||||
@ -123,12 +158,58 @@ export default function InvoiceInfoList() {
|
|||||||
}
|
}
|
||||||
} scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceInfoId"/>
|
} scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceInfoId"/>
|
||||||
</div>
|
</div>
|
||||||
|
<Flex justify="center">
|
||||||
|
<Space size={5}>
|
||||||
|
<Button type="primary"
|
||||||
|
style={{backgroundColor: 'var(--color-primary)'}}
|
||||||
|
onClick={() => {
|
||||||
|
if (!selectedInvoice.current) {
|
||||||
|
messageApi.error('请选择开票信息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
props.handleOk(selectedInvoice.current);
|
||||||
|
}}
|
||||||
|
>确定</Button>
|
||||||
|
<Button type="default" onClick={() => {
|
||||||
|
props.handleCancel();
|
||||||
|
}}>关闭</Button>
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
</div>
|
</div>
|
||||||
<Modal open={true}
|
<Modal open={isInvoiceInfoSaveOpen}
|
||||||
title="新增"
|
title="新增"
|
||||||
footer={false}
|
footer={false}
|
||||||
|
onCancel={() => {
|
||||||
|
setIsInvoiceInfoSaveOpen(false)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<InvoiceInfoSave/>
|
<InvoiceInfoSave
|
||||||
|
handleOk={() => {
|
||||||
|
getData();
|
||||||
|
setIsInvoiceInfoSaveOpen(false);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsInvoiceInfoSaveOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
<Modal open={isInvoiceInfoEditOpen}
|
||||||
|
title="编辑"
|
||||||
|
footer={false}
|
||||||
|
onCancel={() => {
|
||||||
|
setIsInvoiceInfoEditOpen(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<InvoiceInfoEdit
|
||||||
|
invoiceInfoId={editInvoiceInfoId.current}
|
||||||
|
handleOk={() => {
|
||||||
|
getData();
|
||||||
|
setIsInvoiceInfoEditOpen(false);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsInvoiceInfoEditOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
{messageContext}
|
{messageContext}
|
||||||
</>
|
</>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import {Button, Flex, Form, Input, Space} from "antd";
|
import {Button, Flex, Form, Input, Space} from "antd";
|
||||||
import {useForm} from "antd/es/form/Form";
|
import {useForm} from "antd/es/form/Form";
|
||||||
|
import useModal from "antd/es/modal/useModal";
|
||||||
|
import {post} from "../../../util/AjaxUtils.ts";
|
||||||
|
import useMessage from "antd/es/message/useMessage";
|
||||||
|
|
||||||
type FormDataType = {
|
type FormDataType = {
|
||||||
invoiceTitle: string;
|
invoiceTitle: string;
|
||||||
@ -10,8 +13,14 @@ type FormDataType = {
|
|||||||
invoiceAccount: string;
|
invoiceAccount: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function InvoiceInfoSave() {
|
interface SaveProps {
|
||||||
|
handleOk: () => void;
|
||||||
|
handleCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceInfoSave(props: SaveProps) {
|
||||||
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [modal, modalContext] = useModal();
|
||||||
const [form] = useForm<FormDataType>()
|
const [form] = useForm<FormDataType>()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -20,8 +29,29 @@ export default function InvoiceInfoSave() {
|
|||||||
name="basic"
|
name="basic"
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
form={form}
|
form={form}
|
||||||
onFinish={() => {
|
onFinish={(values) => {
|
||||||
|
modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定保存吗',
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
okButtonProps: {
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'var(--color-primary)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onOk: () => {
|
||||||
|
post<any>({
|
||||||
|
messageApi,
|
||||||
|
url: '/api/invoice-info/save',
|
||||||
|
body: values,
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('保存成功');
|
||||||
|
props.handleOk();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@ -68,11 +98,16 @@ export default function InvoiceInfoSave() {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Flex justify="center">
|
<Flex justify="center">
|
||||||
<Space size={5}>
|
<Space size={5}>
|
||||||
<Button type="primary" htmlType="submit" style={{backgroundColor: 'var(--color-primary)'}}>保存</Button>
|
<Button type="primary" htmlType="submit"
|
||||||
<Button type="default" onClick={() => {}}>关闭</Button>
|
style={{backgroundColor: 'var(--color-primary)'}}>保存</Button>
|
||||||
|
<Button type="default" onClick={() => {
|
||||||
|
props.handleCancel();
|
||||||
|
}}>关闭</Button>
|
||||||
</Space>
|
</Space>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Form>
|
</Form>
|
||||||
|
{messageContext}
|
||||||
|
{modalContext}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
200
src/components/invoice/order/InvoiceOrderList.tsx
Normal file
200
src/components/invoice/order/InvoiceOrderList.tsx
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import {Button, Flex, Space, Table, TableProps, Tooltip} from "antd";
|
||||||
|
import useMessage from "antd/es/message/useMessage";
|
||||||
|
import {useEffect, useRef, useState} from "react";
|
||||||
|
import {get} from "../../../util/AjaxUtils.ts";
|
||||||
|
import {IListPage} from "../../../interfaces/listpage/IListPage.ts";
|
||||||
|
|
||||||
|
type DetailDataType = {
|
||||||
|
productType: string;
|
||||||
|
quantity: number;
|
||||||
|
unitPrice: number;
|
||||||
|
notes: string;
|
||||||
|
productDescription: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataType = {
|
||||||
|
orderId: string;
|
||||||
|
orderNo: string;
|
||||||
|
totalAmount: number;
|
||||||
|
detail: DetailDataType;
|
||||||
|
orderStatus: string;
|
||||||
|
gmtCreate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ListProps {
|
||||||
|
selectedOrderIds?: string[];
|
||||||
|
handleOk: (selectedOrders: DataType[]) => void;
|
||||||
|
handleCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceInfoList(props: ListProps) {
|
||||||
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [total, setTotal] = useState(0);
|
||||||
|
const [dataArray, setDataArray] = useState<DataType[]>([]);
|
||||||
|
const selectedOrders = useRef<DataType[] | null>(null);
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||||
|
|
||||||
|
const columns: TableProps<DataType>['columns'] = [
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
dataIndex: 'orderNo',
|
||||||
|
align: 'center',
|
||||||
|
width: 250,
|
||||||
|
fixed: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '总金额',
|
||||||
|
dataIndex: 'totalAmount',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
fixed: 'left',
|
||||||
|
render: (value) => {
|
||||||
|
return (value / 100).toFixed(2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单状态',
|
||||||
|
dataIndex: 'orderStatus',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (value) => {
|
||||||
|
if(value === 'COMPLETE') {
|
||||||
|
return '完成';
|
||||||
|
}
|
||||||
|
if(value === 'CHARGEBACK') {
|
||||||
|
return '已退款';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'gmtCreate',
|
||||||
|
align: 'center',
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '产品类型',
|
||||||
|
dataIndex: 'detail.productType',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (_value, record) => {
|
||||||
|
if(record.detail.productType === 'PROJ') {
|
||||||
|
return '项目创建'
|
||||||
|
}
|
||||||
|
if(record.detail.productType === 'AGENT') {
|
||||||
|
return '项目代理'
|
||||||
|
}
|
||||||
|
return record.detail.productType
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数量',
|
||||||
|
dataIndex: 'detail.quantity',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (_value, record) => {
|
||||||
|
return record.detail.quantity
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '单价',
|
||||||
|
dataIndex: 'detail.unitPrice',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (_value, record) => {
|
||||||
|
return (record.detail.unitPrice / 100).toFixed(2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单备注',
|
||||||
|
dataIndex: 'detail.notes',
|
||||||
|
align: 'center',
|
||||||
|
width: 120,
|
||||||
|
render: (_value, record) => {
|
||||||
|
return record.detail.notes
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
dataIndex: 'detail.productDescription',
|
||||||
|
align: 'center',
|
||||||
|
width: 200,
|
||||||
|
ellipsis: {
|
||||||
|
showTitle: false,
|
||||||
|
},
|
||||||
|
render: (_value, record) => {
|
||||||
|
return <Tooltip placement="top" title={record.detail.productDescription}>{record.detail.productDescription}</Tooltip>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const getData = () => {
|
||||||
|
get<IListPage<DataType>>({
|
||||||
|
messageApi,
|
||||||
|
url: '/api/order/listpage/complete/no-invoiced/self',
|
||||||
|
config: {
|
||||||
|
params: {
|
||||||
|
page: page,
|
||||||
|
rows: 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess({data}) {
|
||||||
|
setPage(data.page);
|
||||||
|
setTotal(data.total);
|
||||||
|
setDataArray(data.rows);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getData();
|
||||||
|
if(props.selectedOrderIds && props.selectedOrderIds.length > 0) {
|
||||||
|
setSelectedRowKeys(props.selectedOrderIds)
|
||||||
|
}
|
||||||
|
}, [page]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="invoice-list-container">
|
||||||
|
<div className="mod-list">
|
||||||
|
<Table rowSelection={
|
||||||
|
{
|
||||||
|
selectedRowKeys,
|
||||||
|
onChange: (selectedRowKeys, selectedRows) => {
|
||||||
|
setSelectedRowKeys(selectedRowKeys);
|
||||||
|
selectedOrders.current = selectedRows;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} columns={columns} dataSource={dataArray} pagination={
|
||||||
|
{
|
||||||
|
pageSize: 20,
|
||||||
|
total: total,
|
||||||
|
onChange: (currentPage) => {
|
||||||
|
setPage(currentPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} scroll={{y: 500}} bordered key="dataTable" rowKey="orderId"/>
|
||||||
|
</div>
|
||||||
|
<Flex justify="center">
|
||||||
|
<Space size={5}>
|
||||||
|
<Button type="primary"
|
||||||
|
style={{backgroundColor: 'var(--color-primary)'}}
|
||||||
|
onClick={() => {
|
||||||
|
if (!selectedOrders.current) {
|
||||||
|
messageApi.error('请选择开票订单');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
props.handleOk(selectedOrders.current);
|
||||||
|
}}
|
||||||
|
>确定</Button>
|
||||||
|
<Button type="default" onClick={() => {
|
||||||
|
props.handleCancel();
|
||||||
|
}}>关闭</Button>
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
|
</div>
|
||||||
|
{messageContext}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
164
src/components/invoice/order/InvoiceOrderSelectedList.tsx
Normal file
164
src/components/invoice/order/InvoiceOrderSelectedList.tsx
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import {Table, TableProps, Tooltip} from "antd";
|
||||||
|
import useMessage from "antd/es/message/useMessage";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {get} from "../../../util/AjaxUtils.ts";
|
||||||
|
import {IListPage} from "../../../interfaces/listpage/IListPage.ts";
|
||||||
|
|
||||||
|
type DetailDataType = {
|
||||||
|
productType: string;
|
||||||
|
quantity: number;
|
||||||
|
unitPrice: number;
|
||||||
|
notes: string;
|
||||||
|
productDescription: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataType = {
|
||||||
|
orderId: string;
|
||||||
|
orderNo: string;
|
||||||
|
totalAmount: number;
|
||||||
|
detail: DetailDataType;
|
||||||
|
orderStatus: string;
|
||||||
|
gmtCreate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ListProps {
|
||||||
|
invoiceId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceInfoSelectedList(props: ListProps) {
|
||||||
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [total, setTotal] = useState(0);
|
||||||
|
const [dataArray, setDataArray] = useState<DataType[]>([]);
|
||||||
|
|
||||||
|
const columns: TableProps<DataType>['columns'] = [
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
dataIndex: 'orderNo',
|
||||||
|
align: 'center',
|
||||||
|
width: 250,
|
||||||
|
fixed: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '总金额',
|
||||||
|
dataIndex: 'totalAmount',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
fixed: 'left',
|
||||||
|
render: (value) => {
|
||||||
|
return (value / 100).toFixed(2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单状态',
|
||||||
|
dataIndex: 'orderStatus',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (value) => {
|
||||||
|
if(value === 'COMPLETE') {
|
||||||
|
return '完成';
|
||||||
|
}
|
||||||
|
if(value === 'CHARGEBACK') {
|
||||||
|
return '已退款';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'gmtCreate',
|
||||||
|
align: 'center',
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '产品类型',
|
||||||
|
dataIndex: 'detail.productType',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (_value, record) => {
|
||||||
|
if(record.detail.productType === 'PROJ') {
|
||||||
|
return '项目创建'
|
||||||
|
}
|
||||||
|
if(record.detail.productType === 'AGENT') {
|
||||||
|
return '项目代理'
|
||||||
|
}
|
||||||
|
return record.detail.productType
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数量',
|
||||||
|
dataIndex: 'detail.quantity',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (_value, record) => {
|
||||||
|
return record.detail.quantity
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '单价',
|
||||||
|
dataIndex: 'detail.unitPrice',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (_value, record) => {
|
||||||
|
return (record.detail.unitPrice / 100).toFixed(2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单备注',
|
||||||
|
dataIndex: 'detail.notes',
|
||||||
|
align: 'center',
|
||||||
|
width: 120,
|
||||||
|
render: (_value, record) => {
|
||||||
|
return record.detail.notes
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
dataIndex: 'detail.productDescription',
|
||||||
|
align: 'center',
|
||||||
|
width: 200,
|
||||||
|
ellipsis: {
|
||||||
|
showTitle: false,
|
||||||
|
},
|
||||||
|
render: (_value, record) => {
|
||||||
|
return <Tooltip placement="top" title={record.detail.productDescription}>{record.detail.productDescription}</Tooltip>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
get<IListPage<DataType>>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/order/listpage/complete/self?invoiceId=${props.invoiceId}`,
|
||||||
|
config: {
|
||||||
|
params: {
|
||||||
|
page: page,
|
||||||
|
rows: 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess({data}) {
|
||||||
|
setPage(data.page);
|
||||||
|
setTotal(data.total);
|
||||||
|
setDataArray(data.rows);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [page]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{messageContext}
|
||||||
|
<div className="invoice-list-container">
|
||||||
|
<div className="mod-list">
|
||||||
|
<Table columns={columns} dataSource={dataArray} pagination={
|
||||||
|
{
|
||||||
|
pageSize: 20,
|
||||||
|
total: total,
|
||||||
|
onChange: (currentPage) => {
|
||||||
|
setPage(currentPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} scroll={{y: 500}} bordered key="dataTable" rowKey="orderId"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -20,6 +20,7 @@ export default function Head() {
|
|||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [isSelfModalOpen, setIsSelfModalOpen] = useState(false);
|
const [isSelfModalOpen, setIsSelfModalOpen] = useState(false);
|
||||||
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
|
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
|
||||||
|
const [isInvoiceModalOpen, setIsInvoiceModalOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
reloadUser(messageApi, globalDispatchContext).then((data) => {
|
reloadUser(messageApi, globalDispatchContext).then((data) => {
|
||||||
@ -63,7 +64,7 @@ export default function Head() {
|
|||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
// nav('/invoice-list');
|
setIsInvoiceModalOpen(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -181,10 +182,11 @@ export default function Head() {
|
|||||||
});
|
});
|
||||||
}}/>
|
}}/>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal open={true}
|
<Modal open={isInvoiceModalOpen}
|
||||||
title="发票管理"
|
title="发票管理"
|
||||||
width={1100}
|
width={1100}
|
||||||
footer={false}
|
footer={false}
|
||||||
|
onCancel={() => setIsInvoiceModalOpen(false)}
|
||||||
>
|
>
|
||||||
<InvoiceList/>
|
<InvoiceList/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -6,7 +6,7 @@ import MenuWithTopButton from "../../components/menu/MenuWithTopButton.tsx";
|
|||||||
import MenuTreeWithTopButton from "../../components/menu/MenuTreeWithTopButton.tsx";
|
import MenuTreeWithTopButton from "../../components/menu/MenuTreeWithTopButton.tsx";
|
||||||
import ListProj from "../../components/list/ListProj.tsx";
|
import ListProj from "../../components/list/ListProj.tsx";
|
||||||
import ListProjAgent from "../../components/list/ListProjAgent.tsx";
|
import ListProjAgent from "../../components/list/ListProjAgent.tsx";
|
||||||
import {Breadcrumb, Button, MenuProps} from 'antd';
|
import {Breadcrumb, MenuProps} from 'antd';
|
||||||
import {
|
import {
|
||||||
IndexListContext,
|
IndexListContext,
|
||||||
IndexListDataType,
|
IndexListDataType,
|
||||||
@ -133,7 +133,6 @@ export default function Index() {
|
|||||||
list={agentMenu.list}
|
list={agentMenu.list}
|
||||||
handleListItem={agentMenu.handleListItem}
|
handleListItem={agentMenu.handleListItem}
|
||||||
/>
|
/>
|
||||||
<Button>发票管理</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="right">
|
<div className="right">
|
||||||
{
|
{
|
||||||
|
@ -94,7 +94,6 @@ export default function ProjNew() {
|
|||||||
labelCol={{span: 24}}
|
labelCol={{span: 24}}
|
||||||
wrapperCol={{span: 24}}
|
wrapperCol={{span: 24}}
|
||||||
style={{width: 500}}
|
style={{width: 500}}
|
||||||
initialValues={{remember: true}}
|
|
||||||
onFinish={(formData) => {
|
onFinish={(formData) => {
|
||||||
setIsCreateModalOpen(true);
|
setIsCreateModalOpen(true);
|
||||||
setProjInfo({
|
setProjInfo({
|
||||||
|
Loading…
Reference in New Issue
Block a user