增加发票管理

This commit is contained in:
WenC 2024-04-03 18:33:37 +08:00
parent 0ac3163e79
commit 3e56632e34
6 changed files with 287 additions and 16 deletions

View File

@ -185,6 +185,7 @@ export default function InvoiceList() {
</div> </div>
<Modal open={true} <Modal open={true}
title="申请开票" title="申请开票"
footer={false}
> >
<InvoiceSave /> <InvoiceSave />
</Modal> </Modal>

View File

@ -1,5 +1,8 @@
import {Button, Divider, Form, Input, Radio, Space} from "antd"; import {Button, Divider, Flex, Form, Input, Modal, Radio, Space} from "antd";
import {useState} from "react"; import {useEffect, useState} from "react";
import {listDictionary, IDictionary} from "../../util/AjaxUtils.ts";
import useMessage from "antd/es/message/useMessage";
import InvoiceInfoList from "./info/InvoiceInfoList.tsx";
type FormFieldType = { type FormFieldType = {
invoiceTitle: string; invoiceTitle: string;
@ -14,11 +17,32 @@ type FormFieldType = {
} }
export default function InvoiceSave() { export default function InvoiceSave() {
const [messageApi, messageContext] = useMessage();
const [form] = Form.useForm<FormFieldType>(); const [form] = Form.useForm<FormFieldType>();
const [isSaveInvoiceInfo, setIsSaveInvoiceInfo] = useState(0); const [isSaveInvoiceInfo, setIsSaveInvoiceInfo] = useState(0);
const [contentArray, setContentArray] = useState<IDictionary[]>([]);
const [rateArray, setRateArray] = useState<IDictionary[]>([]);
const [typeArray, setTypeArray] = useState<IDictionary[]>([]);
useEffect(() => {
// 开票内容
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]);
})
}, []);
return ( return (
<> <>
{messageContext}
<Form <Form
name="basic" name="basic"
initialValues={{remember: true}} initialValues={{remember: true}}
@ -113,10 +137,7 @@ export default function InvoiceSave() {
> >
<Radio.Group> <Radio.Group>
<Space direction="vertical"> <Space direction="vertical">
<Radio value={1}>A</Radio> {contentArray.map(item => <Radio value={item.dataName}>{item.dataName}</Radio>)}
<Radio value={2}>B</Radio>
<Radio value={3}>C</Radio>
<Radio value={4}>D</Radio>
</Space> </Space>
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>
@ -131,10 +152,7 @@ export default function InvoiceSave() {
rules={[{required: true, message: '请选择开票税率'}]} rules={[{required: true, message: '请选择开票税率'}]}
> >
<Radio.Group> <Radio.Group>
<Radio value={1}>A</Radio> {rateArray.map(item => <Radio value={item.dataName}>{item.dataName}</Radio>)}
<Radio value={2}>B</Radio>
<Radio value={3}>C</Radio>
<Radio value={4}>D</Radio>
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>
</td> </td>
@ -148,10 +166,9 @@ export default function InvoiceSave() {
rules={[{required: true, message: '请选择发票类型'}]} rules={[{required: true, message: '请选择发票类型'}]}
> >
<Radio.Group> <Radio.Group>
<Radio value={1}>A</Radio> <Space direction="vertical">
<Radio value={2}>B</Radio> {typeArray.map(item => <Radio value={item.dataName}>{item.dataName}</Radio>)}
<Radio value={3}>C</Radio> </Space>
<Radio value={4}>D</Radio>
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>
</td> </td>
@ -183,7 +200,9 @@ export default function InvoiceSave() {
<div> <div>
<span></span> <span></span>
<span style={{fontSize: '20px', fontWeight: 'bold'}}>300</span> <span style={{fontSize: '20px', fontWeight: 'bold'}}>300</span>
<Button type="link" size="small"></Button> <Button type="link" size="small" onClick={() => {
}}></Button>
</div> </div>
</td> </td>
</tr> </tr>
@ -201,7 +220,26 @@ export default function InvoiceSave() {
</tr> </tr>
</tbody> </tbody>
</table> </table>
<Form.Item style={{marginBottom: '0'}}>
<Flex justify="center" style={{marginTop: '15px'}}>
<Space>
<Button type="primary" htmlType="submit" style={{
backgroundColor: 'var(--color-primary)'
}} onClick={() => {
}}></Button>
<Button type="default"></Button>
</Space>
</Flex>
</Form.Item>
</Form> </Form>
<Modal open={true}
title="开票信息"
width={1000}
footer={false}
>
<InvoiceInfoList/>
</Modal>
</> </>
); );
} }

View File

@ -0,0 +1,136 @@
import {Button, Modal, Space, Table, TableProps} from "antd";
import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons";
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";
import InvoiceInfoSave from "./InvoiceInfoSave.tsx";
type DataType = {
invoiceTitle: string;
invoicePhone: string;
invoiceNo: string;
invoiceInfoId: string;
invoiceBank: string;
invoiceAddress: string;
invoiceAccount: string;
gmtCreate: number;
creator: string;
}
export default function InvoiceInfoList() {
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: 'invoiceTitle',
align: 'center',
width: 180,
fixed: 'left'
},
{
title: '纳税人识别号',
dataIndex: 'invoiceNo',
align: 'center',
width: 180
},
{
title: '公司地址',
dataIndex: 'invoiceAddress',
align: 'center',
width: 180
},
{
title: '联系电话',
dataIndex: 'invoicePhone',
align: 'center',
width: 180
},
{
title: '开户行',
dataIndex: 'invoiceBank',
align: 'center',
width: 180
},
{
title: '开户行账号',
dataIndex: 'invoiceAccount',
align: 'center',
width: 180
},
{
title: '操作',
dataIndex: 'option',
align: 'center',
width: 100,
fixed: 'right',
render: () => {
return (
<Space size={5}>
<Button type="primary" size="small"><EditOutlined/></Button>
<Button size="small"><DeleteOutlined/></Button>
</Space>
)
}
},
]
useEffect(() => {
get<IListPage<DataType>>({
messageApi,
url: '/api/invoice-info/listpage/self',
config: {
params: {
page: page,
rows: 20
}
},
onSuccess({data}) {
setPage(data.page);
setTotal(data.total);
setDataArray(data.rows);
}
})
}, [page]);
return (
<>
<div className="invoice-list-container">
<div className="mod-list">
<div className="table-btn-group" style={{marginBottom: '15px'}}>
<Button value="small" onClick={() => {
}}><PlusOutlined/> </Button>
</div>
<Table rowSelection={
{
type: 'radio',
onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
},
}
} columns={columns} dataSource={dataArray} pagination={
{
pageSize: 20,
total: total,
onChange: (currentPage) => {
setPage(currentPage);
}
}
} scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceInfoId"/>
</div>
</div>
<Modal open={true}
title="新增"
footer={false}
>
<InvoiceInfoSave/>
</Modal>
{messageContext}
</>
);
}

View File

@ -0,0 +1,78 @@
import {Button, Flex, Form, Input, Space} from "antd";
import {useForm} from "antd/es/form/Form";
type FormDataType = {
invoiceTitle: string;
invoicePhone: string;
invoiceNo: string;
invoiceBank: string;
invoiceAddress: string;
invoiceAccount: string;
}
export default function InvoiceInfoSave() {
const [form] = useForm<FormDataType>()
return (
<>
<Form
name="basic"
layout="vertical"
form={form}
onFinish={() => {
}}
>
<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={() => {}}></Button>
</Space>
</Flex>
</Form>
</>
)
}

View File

@ -384,7 +384,6 @@ export default function Payment(props: IPaymentProps) {
<Spin tip="正在提交..." spinning={isLoading}> <Spin tip="正在提交..." spinning={isLoading}>
<Form <Form
name="basic" name="basic"
initialValues={{remember: true}}
form={form} form={form}
onFinish={() => { onFinish={() => {
post<any>({ post<any>({

View File

@ -18,6 +18,13 @@ type Req<T> = {
onFinally?(): void; onFinally?(): void;
} }
export interface IDictionary {
dataId: string;
dataParentId: string;
dataName: string;
dataCode: string;
}
axios.interceptors.request.use(config => { axios.interceptors.request.use(config => {
if (config.method === 'get') { if (config.method === 'get') {
config.data = {unused: 0} // 这个是关键点解决get 请求添加不上content_type config.data = {unused: 0} // 这个是关键点解决get 请求添加不上content_type
@ -39,6 +46,18 @@ export function uploadFileUrl() {
return `${Axios.defaults?.baseURL}/api/file/v2/upload-file`; return `${Axios.defaults?.baseURL}/api/file/v2/upload-file`;
} }
export async function listDictionary(parentId: string, messageApi: MessageInstance) {
return new Promise<IDictionary[]>(resolve => {
get<IDictionary[]>({
messageApi,
url: `/api/data/listbyparentid/${parentId}`,
onSuccess({data}) {
resolve(data);
}
})
})
}
export function get<T>(req: Req<T>) { export function get<T>(req: Req<T>) {
req.onBefore?.(); req.onBefore?.();
Axios.get<T>(req.url, req.config).then(res => { Axios.get<T>(req.url, req.config).then(res => {