diff --git a/src/components/invoice/InvoiceEdit.tsx b/src/components/invoice/InvoiceEdit.tsx new file mode 100644 index 0000000..03f141f --- /dev/null +++ b/src/components/invoice/InvoiceEdit.tsx @@ -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(); + const [contentArray, setContentArray] = useState([]); + const [rateArray, setRateArray] = useState([]); + const [typeArray, setTypeArray] = useState([]); + 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({ + messageApi, + url: `/api/invoice/get/${props.invoiceId}`, + onSuccess({data}) { + form.setFieldsValue(data); + setOrderAmount((data.invoiceAmount / 100).toFixed(2)); + } + }) + }, []); + + return ( + <> + {messageContext} + {modalContext} +
{ + modal.confirm({ + title: '提示', + content: '确定提交吗?', + okText: '确定', + cancelText: '取消', + okButtonProps: { + style: { + backgroundColor: 'val(--color-primary)' + } + }, + onOk: () => { + put({ + messageApi, + url: `/api/invoice/update/${props.invoiceId}`, + body: values, + onSuccess() { + messageApi.success('提交成功'); + props.handleOk(); + } + }) + } + }); + }} + > + 开票信息 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
公司名称 * + + + +
纳税人识别号 * + + + +
公司地址 * + + + +
联系电话 * + + + +
开户行 * + + + +
开户行账号 * + + + +
开票内容 * + + + + {contentArray.map(item => {item.dataName})} + + + +
开票税率 * + + + {rateArray.map(item => {item.dataName})} + + +
发票类型 * + + + + {typeArray.map(item => {item.dataName})} + + + +
保存开票信息 * + + + + + + +
+ 开票内容 + + + + + + + + + + + + + + + +
开票金额 * + +
+ + {orderAmount} + +
+
+
开票备注 + + + +
+ + + + + + + + + + setIsInvoiceInfoListOpen(false)} + > + { + 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); + }} + /> + + setIsInvoiceOrderListOpen(false)} + > + { + 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); + }} + /> + + + ); +} \ No newline at end of file diff --git a/src/components/invoice/InvoiceList.tsx b/src/components/invoice/InvoiceList.tsx index f503279..218fb38 100644 --- a/src/components/invoice/InvoiceList.tsx +++ b/src/components/invoice/InvoiceList.tsx @@ -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 {useEffect, useState} from "react"; -import {get} from "../../util/AjaxUtils.ts"; +import {useEffect, useRef, useState} from "react"; +import {get, put} from "../../util/AjaxUtils.ts"; import {IListPage} from "../../interfaces/listpage/IListPage.ts"; import useMessage from "antd/es/message/useMessage"; import InvoiceSave from "./InvoiceSave.tsx"; +import InvoiceEdit from "./InvoiceEdit.tsx"; +import InvoiceShow from "./InvoiceShow.tsx"; enum InvoiceStatusEnum { PENDING = 'PENDING', @@ -39,6 +41,10 @@ export default function InvoiceList() { const [page, setPage] = useState(1); const [total, setTotal] = useState(0); const [dataArray, setDataArray] = useState([]); + const [isSaveModalOpen, setIsSaveModalOpen] = useState(false); + const [isEditModalOpen, setIsEditModalOpen] = useState(false); + const [isShowModalOpen, setIsShowModalOpen] = useState(false); + const invoiceId = useRef(''); const columns: TableProps['columns'] = [ { @@ -125,7 +131,55 @@ export default function InvoiceList() { align: 'center', width: 120, fixed: 'right', - render: (value, record) => { + render: (_value, record) => { + if(record.invoiceStatus === InvoiceStatusEnum.PENDING) { + return + + + { + put({ + messageApi, + url: `/api/invoice/update-cancel/${record.invoiceId}`, + onSuccess() { + messageApi.success('取消成功'); + getData(); + } + }) + }} + > + + + + + + } + if(record.invoiceStatus === InvoiceStatusEnum.CANCEL) { + return + } if(record.invoiceStatus == InvoiceStatusEnum.COMPLETE) { const items: MenuProps['items'] = []; record.invoiceFileList.forEach((item, index) => { @@ -146,7 +200,7 @@ export default function InvoiceList() { }, ] - useEffect(() => { + const getData = () => { get>({ messageApi, url: '/api/invoice/listpage/self', @@ -162,6 +216,10 @@ export default function InvoiceList() { setDataArray(data.rows); } }) + } + + useEffect(() => { + getData(); }, [page]); return ( @@ -170,24 +228,59 @@ export default function InvoiceList() {
{ - setPage(currentPage); - } + setPage(currentPage); + }, } } scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceId"/> - setIsSaveModalOpen(false)} > - + { + getData(); + setIsSaveModalOpen(false); + }} + handleCancel={() => { + setIsSaveModalOpen(false); + }} + /> + + setIsEditModalOpen(false)} + > + { + getData(); + setIsEditModalOpen(false); + }} + handleCancel={() => { + setIsEditModalOpen(false); + }} + /> + + setIsShowModalOpen(false)} + > + {messageContext} diff --git a/src/components/invoice/InvoiceSave.tsx b/src/components/invoice/InvoiceSave.tsx index 3fd457d..f2ed40d 100644 --- a/src/components/invoice/InvoiceSave.tsx +++ b/src/components/invoice/InvoiceSave.tsx @@ -1,12 +1,14 @@ import {Button, Divider, Flex, Form, Input, Modal, Radio, Space} from "antd"; 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 InvoiceInfoList from "./info/InvoiceInfoList.tsx"; +import InvoiceOrderList from "./order/InvoiceOrderList.tsx"; +import useModal from "antd/es/modal/useModal"; type FormFieldType = { invoiceTitle: string; - invoiceNo: number; + invoiceNo: string; invoiceAddress: string; invoicePhone: string; invoiceAccount: string; @@ -14,28 +16,38 @@ type FormFieldType = { content: string; rate: string; type: string; + orderIds: string[]; + invoiceNote: string; + isSaveInvoiceInfo: boolean; } -export default function InvoiceSave() { - const [messageApi, messageContext] = useMessage(); - const [form] = Form.useForm(); - const [isSaveInvoiceInfo, setIsSaveInvoiceInfo] = useState(0); +type SaveProps = { + handleOk: () => void; + handleCancel: () => void; +} +export default function InvoiceSave(props: SaveProps) { + const [messageApi, messageContext] = useMessage(); + const [modal, modalContext] = useModal(); + const [form] = Form.useForm(); const [contentArray, setContentArray] = useState([]); const [rateArray, setRateArray] = useState([]); const [typeArray, setTypeArray] = useState([]); + const [isInvoiceInfoListOpen, setIsInvoiceInfoListOpen] = useState(false); + const [isInvoiceOrderListOpen, setIsInvoiceOrderListOpen] = useState(false); + const [orderAmount, setOrderAmount] = useState('0'); useEffect(() => { // 开票内容 - listDictionary('e0251d55-cd52-4f57-be92-b2bef8a6dd62', messageApi).then((data)=>{ + listDictionary('e0251d55-cd52-4f57-be92-b2bef8a6dd62', messageApi).then((data) => { setContentArray([...data]); }) // 开票税率 - listDictionary('b67d5208-db1d-4d0e-99de-cc22d9d50041', messageApi).then((data)=>{ + listDictionary('b67d5208-db1d-4d0e-99de-cc22d9d50041', messageApi).then((data) => { setRateArray([...data]); }) // 开票类型 - listDictionary('e4808c45-64ee-42fa-a413-a470fbdc0aea', messageApi).then((data)=>{ + listDictionary('e4808c45-64ee-42fa-a413-a470fbdc0aea', messageApi).then((data) => { setTypeArray([...data]); }) }, []); @@ -43,10 +55,35 @@ export default function InvoiceSave() { return ( <> {messageContext} + {modalContext}
{ + modal.confirm({ + title: '提示', + content: '确定提交吗?', + okText: '确定', + cancelText: '取消', + okButtonProps: { + style: { + backgroundColor: 'val(--color-primary)' + } + }, + onOk: () => { + post({ + messageApi, + url: '/api/invoice/save', + body: values, + onSuccess() { + messageApi.success('提交成功'); + props.handleOk(); + } + }) + } + }); + }} > 开票信息
@@ -55,6 +92,13 @@ export default function InvoiceSave() { + + + @@ -167,22 +213,27 @@ export default function InvoiceSave() { > - {typeArray.map(item => {item.dataName})} + {typeArray.map(item => {item.dataName})} + @@ -197,22 +248,27 @@ export default function InvoiceSave() {
+ +
公司名称 * @@ -137,7 +181,8 @@ export default function InvoiceSave() { > - {contentArray.map(item => {item.dataName})} + {contentArray.map(item => {item.dataName})} @@ -152,7 +197,8 @@ export default function InvoiceSave() { rules={[{required: true, message: '请选择开票税率'}]} > - {rateArray.map(item => {item.dataName})} + {rateArray.map(item => {item.dataName})}
保存开票信息 * - { - setIsSaveInvoiceInfo(e.target.value) - }}> - - - + + + + + +
开票金额 * -
- - 300 - -
+ +
+ + {orderAmount} + +
+
开票备注 @@ -225,20 +281,61 @@ export default function InvoiceSave() { - + - { + setIsInvoiceInfoListOpen(false); + }} > - + { + 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); + }} + /> + + setIsInvoiceOrderListOpen(false)} + > + { + 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); + }} + /> ); diff --git a/src/components/invoice/InvoiceShow.tsx b/src/components/invoice/InvoiceShow.tsx new file mode 100644 index 0000000..3d3dc8e --- /dev/null +++ b/src/components/invoice/InvoiceShow.tsx @@ -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(null); + const [orderAmount, setOrderAmount] = useState('0'); + + useEffect(() => { + if (!props.invoiceId) { + return; + } + get({ + messageApi, + url: `/api/invoice/get/${props.invoiceId}`, + onSuccess({data}) { + setInvoiceData({ + ...data + }); + setOrderAmount((data.invoiceAmount / 100).toFixed(2)); + } + }) + }, []); + + return ( + <> + {messageContext} + 开票信息 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
公司名称 *{invoiceData?.invoiceTitle}
纳税人识别号 *{invoiceData?.invoiceNo}
公司地址 *{invoiceData?.invoiceAddress}
联系电话 *{invoiceData?.invoicePhone}
开户行 *{invoiceData?.invoiceAccount}
开户行账号 *{invoiceData?.invoiceBank}
开票内容 *{invoiceData?.content}
开票税率 *{invoiceData?.rate}
发票类型 *{invoiceData?.type}
+ 开票内容 + + + + + + + + + + + + + + + +
开票金额 * +
+ + {orderAmount} + +
+
开票备注{invoiceData?.invoiceNote}
+ setIsInvoiceOrderListOpen(false)} + > + + + + ); +} \ No newline at end of file diff --git a/src/components/invoice/info/InvoiceInfoEdit.tsx b/src/components/invoice/info/InvoiceInfoEdit.tsx new file mode 100644 index 0000000..215e7c6 --- /dev/null +++ b/src/components/invoice/info/InvoiceInfoEdit.tsx @@ -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() + + useEffect(() => { + if (!props.invoiceInfoId) { + return; + } + get({ + messageApi, + url: `/api/invoice-info/get/${props.invoiceInfoId}`, + onSuccess({data}) { + form.setFieldsValue(data); + } + }) + }, [props.invoiceInfoId]); + + return ( + <> +
{ + modal.confirm({ + title: '提示', + content: '确定保存吗', + okText: '确定', + cancelText: '取消', + okButtonProps: { + style: { + backgroundColor: 'var(--color-primary)' + } + }, + onOk: () => { + post({ + messageApi, + url: `/api/invoice-info/update/${props.invoiceInfoId}`, + body: values, + onSuccess() { + messageApi.success('保存成功'); + props.handleOk(); + } + }) + } + }) + }} + > + + + + + + + + + + + + + + + + + + + + + + + + + + {messageContext} + {modalContext} + + ) +} \ No newline at end of file diff --git a/src/components/invoice/info/InvoiceInfoList.tsx b/src/components/invoice/info/InvoiceInfoList.tsx index 4dd0f1d..472ebb2 100644 --- a/src/components/invoice/info/InvoiceInfoList.tsx +++ b/src/components/invoice/info/InvoiceInfoList.tsx @@ -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 useMessage from "antd/es/message/useMessage"; -import {useEffect, useState} from "react"; -import {get} from "../../../util/AjaxUtils.ts"; +import {useEffect, useRef, useState} from "react"; +import {del, get} from "../../../util/AjaxUtils.ts"; import {IListPage} from "../../../interfaces/listpage/IListPage.ts"; import InvoiceInfoSave from "./InvoiceInfoSave.tsx"; +import InvoiceInfoEdit from "./InvoiceInfoEdit.tsx"; type DataType = { invoiceTitle: string; @@ -18,11 +19,20 @@ type DataType = { 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 [isInvoiceInfoSaveOpen, setIsInvoiceInfoSaveOpen] = useState(false); + const [isInvoiceInfoEditOpen, setIsInvoiceInfoEditOpen] = useState(false); const [page, setPage] = useState(1); const [total, setTotal] = useState(0); const [dataArray, setDataArray] = useState([]); + const editInvoiceInfoId = useRef(''); + const selectedInvoice = useRef(null); const columns: TableProps['columns'] = [ { @@ -68,18 +78,39 @@ export default function InvoiceInfoList() { align: 'center', width: 100, fixed: 'right', - render: () => { + render: (_value, record) => { return ( - - + + { + del({ + messageApi, + url: `/api/invoice-info/remove/${record.invoiceInfoId}`, + onSuccess() { + messageApi.success('删除成功'); + getData(); + } + }) + }} + > + + ) } }, ] - useEffect(() => { + const getData = () => { get>({ messageApi, url: '/api/invoice-info/listpage/self', @@ -95,6 +126,10 @@ export default function InvoiceInfoList() { setDataArray(data.rows); } }) + } + + useEffect(() => { + getData(); }, [page]); return ( @@ -103,14 +138,14 @@ export default function InvoiceInfoList() {
{ - console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); + onChange: (_selectedRowKeys, selectedRows) => { + selectedInvoice.current = selectedRows[0]; }, } } columns={columns} dataSource={dataArray} pagination={ @@ -123,12 +158,58 @@ export default function InvoiceInfoList() { } } scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceInfoId"/> + + + + + + - { + setIsInvoiceInfoSaveOpen(false) + }} > - + { + getData(); + setIsInvoiceInfoSaveOpen(false); + }} + handleCancel={() => { + setIsInvoiceInfoSaveOpen(false); + }} + /> + + { + setIsInvoiceInfoEditOpen(false) + }} + > + { + getData(); + setIsInvoiceInfoEditOpen(false); + }} + handleCancel={() => { + setIsInvoiceInfoEditOpen(false); + }} + /> {messageContext} diff --git a/src/components/invoice/info/InvoiceInfoSave.tsx b/src/components/invoice/info/InvoiceInfoSave.tsx index 690a17e..e286c72 100644 --- a/src/components/invoice/info/InvoiceInfoSave.tsx +++ b/src/components/invoice/info/InvoiceInfoSave.tsx @@ -1,5 +1,8 @@ import {Button, Flex, Form, Input, Space} from "antd"; 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 = { invoiceTitle: string; @@ -10,8 +13,14 @@ type FormDataType = { 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() return ( @@ -20,8 +29,29 @@ export default function InvoiceInfoSave() { name="basic" layout="vertical" form={form} - onFinish={() => { - + onFinish={(values) => { + modal.confirm({ + title: '提示', + content: '确定保存吗', + okText: '确定', + cancelText: '取消', + okButtonProps: { + style: { + backgroundColor: 'var(--color-primary)' + } + }, + onOk: () => { + post({ + messageApi, + url: '/api/invoice-info/save', + body: values, + onSuccess() { + messageApi.success('保存成功'); + props.handleOk(); + } + }) + } + }) }} > - - + + + {messageContext} + {modalContext} ) } \ No newline at end of file diff --git a/src/components/invoice/order/InvoiceOrderList.tsx b/src/components/invoice/order/InvoiceOrderList.tsx new file mode 100644 index 0000000..43a301a --- /dev/null +++ b/src/components/invoice/order/InvoiceOrderList.tsx @@ -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([]); + const selectedOrders = useRef(null); + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + + const columns: TableProps['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 {record.detail.productDescription} + } + }, + ] + + const getData = () => { + get>({ + 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 ( + <> +
+
+
{ + 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"/> + + + + + + + + + {messageContext} + + ); +} \ No newline at end of file diff --git a/src/components/invoice/order/InvoiceOrderSelectedList.tsx b/src/components/invoice/order/InvoiceOrderSelectedList.tsx new file mode 100644 index 0000000..2943bac --- /dev/null +++ b/src/components/invoice/order/InvoiceOrderSelectedList.tsx @@ -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([]); + + const columns: TableProps['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 {record.detail.productDescription} + } + }, + ] + + useEffect(() => { + get>({ + 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} +
+
+
{ + setPage(currentPage); + } + } + } scroll={{y: 500}} bordered key="dataTable" rowKey="orderId"/> + + + + ); +} \ No newline at end of file diff --git a/src/layout/head/Head.tsx b/src/layout/head/Head.tsx index 64b424d..480937e 100644 --- a/src/layout/head/Head.tsx +++ b/src/layout/head/Head.tsx @@ -20,6 +20,7 @@ export default function Head() { const [loading, setLoading] = useState(false); const [isSelfModalOpen, setIsSelfModalOpen] = useState(false); const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false); + const [isInvoiceModalOpen, setIsInvoiceModalOpen] = useState(false); useEffect(() => { reloadUser(messageApi, globalDispatchContext).then((data) => { @@ -63,7 +64,7 @@ export default function Head() { ), onClick: () => { - // nav('/invoice-list'); + setIsInvoiceModalOpen(true); } }, { @@ -181,10 +182,11 @@ export default function Head() { }); }}/> - setIsInvoiceModalOpen(false)} > diff --git a/src/route/index/Index.tsx b/src/route/index/Index.tsx index afdc7b6..4c1c991 100644 --- a/src/route/index/Index.tsx +++ b/src/route/index/Index.tsx @@ -6,7 +6,7 @@ import MenuWithTopButton from "../../components/menu/MenuWithTopButton.tsx"; import MenuTreeWithTopButton from "../../components/menu/MenuTreeWithTopButton.tsx"; import ListProj from "../../components/list/ListProj.tsx"; import ListProjAgent from "../../components/list/ListProjAgent.tsx"; -import {Breadcrumb, Button, MenuProps} from 'antd'; +import {Breadcrumb, MenuProps} from 'antd'; import { IndexListContext, IndexListDataType, @@ -133,7 +133,6 @@ export default function Index() { list={agentMenu.list} handleListItem={agentMenu.handleListItem} /> -
{ diff --git a/src/route/proj/ProjNew.tsx b/src/route/proj/ProjNew.tsx index 2b35175..9d6118d 100644 --- a/src/route/proj/ProjNew.tsx +++ b/src/route/proj/ProjNew.tsx @@ -94,7 +94,6 @@ export default function ProjNew() { labelCol={{span: 24}} wrapperCol={{span: 24}} style={{width: 500}} - initialValues={{remember: true}} onFinish={(formData) => { setIsCreateModalOpen(true); setProjInfo({