增加发票管理
This commit is contained in:
parent
44eca6fbdf
commit
0ac3163e79
@ -6,11 +6,12 @@ import {
|
|||||||
GlobalData,
|
GlobalData,
|
||||||
GlobalDataAction,
|
GlobalDataAction,
|
||||||
GlobalDataActionType,
|
GlobalDataActionType,
|
||||||
GlobalDispatchContext
|
GlobalDispatchContext,
|
||||||
} from "./context/GlobalContext.ts";
|
} from "./context/GlobalContext.ts";
|
||||||
import {Reducer, useReducer} from "react";
|
import {Reducer, useReducer} from "react";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
|
|
||||||
const globalDataReducer = (state: GlobalData, action: GlobalDataAction) => {
|
const globalDataReducer = (state: GlobalData, action: GlobalDataAction) => {
|
||||||
if (action.type == GlobalDataActionType.REFRESH_SELF) {
|
if (action.type == GlobalDataActionType.REFRESH_SELF) {
|
||||||
if(action.user) {
|
if(action.user) {
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
CheckOutlined,
|
CheckOutlined,
|
||||||
ClockCircleOutlined,
|
ClockCircleOutlined,
|
||||||
CloseCircleOutlined,
|
CloseCircleOutlined,
|
||||||
CreditCardOutlined,
|
CreditCardOutlined, DeleteOutlined,
|
||||||
DownloadOutlined, DownOutlined,
|
DownloadOutlined, DownOutlined,
|
||||||
EditOutlined,
|
EditOutlined,
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
@ -24,10 +24,10 @@ export default function CardProj(props: { item: IProj }) {
|
|||||||
const nav = useNavigate();
|
const nav = useNavigate();
|
||||||
const data = props.item;
|
const data = props.item;
|
||||||
const [messageApi, messageContext] = useMessage();
|
const [messageApi, messageContext] = useMessage();
|
||||||
|
const [projCategoryId, setProjCategoryId] = useState(data.projCategoryId);
|
||||||
const [projCategoryName, setProjCategoryName] = useState(data.projCategoryName);
|
const [projCategoryName, setProjCategoryName] = useState(data.projCategoryName);
|
||||||
const indexListContext = useContext(IndexListContext);
|
const indexListContext = useContext(IndexListContext);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成状态
|
* 生成状态
|
||||||
*/
|
*/
|
||||||
@ -110,7 +110,6 @@ export default function CardProj(props: { item: IProj }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{messageContext}
|
|
||||||
<div className="card-proj">
|
<div className="card-proj">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
@ -181,26 +180,32 @@ export default function CardProj(props: { item: IProj }) {
|
|||||||
url: `/api/proj/update-category/${data.projId}/${e.key}`,
|
url: `/api/proj/update-category/${data.projId}/${e.key}`,
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
messageApi.success('修改成功');
|
messageApi.success('修改成功');
|
||||||
|
setProjCategoryId(e.key);
|
||||||
setProjCategoryName(span.innerText);
|
setProjCategoryName(span.innerText);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
<span onClick={() => {
|
<span>
|
||||||
put<any>({
|
<a href="/#">{projCategoryId ? projCategoryName : '无目录'}</a>
|
||||||
messageApi,
|
|
||||||
url: `/api/proj/cancel-category/${data.projId}`,
|
|
||||||
onSuccess() {
|
|
||||||
messageApi.success('取消成功');
|
|
||||||
setProjCategoryName('');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}}>
|
|
||||||
<a href="/#">{projCategoryName ? projCategoryName : '无目录'}</a>
|
|
||||||
<DownOutlined/>
|
<DownOutlined/>
|
||||||
</span>
|
</span>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
{
|
||||||
|
projCategoryId ? (
|
||||||
|
<DeleteOutlined title="移除目录" onClick={() => {
|
||||||
|
put<any>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/proj/cancel-category/${data.projId}`,
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('取消成功');
|
||||||
|
setProjCategoryId('');
|
||||||
|
setProjCategoryName('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}/>
|
||||||
|
) : <></>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -217,6 +222,7 @@ export default function CardProj(props: { item: IProj }) {
|
|||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{messageContext}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
194
src/components/invoice/InvoiceList.tsx
Normal file
194
src/components/invoice/InvoiceList.tsx
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
import {Button, Dropdown, MenuProps, Modal, Table, TableProps, Tag} from "antd";
|
||||||
|
import {PlusOutlined} from "@ant-design/icons";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {get} from "../../util/AjaxUtils.ts";
|
||||||
|
import {IListPage} from "../../interfaces/listpage/IListPage.ts";
|
||||||
|
import useMessage from "antd/es/message/useMessage";
|
||||||
|
import InvoiceSave from "./InvoiceSave.tsx";
|
||||||
|
|
||||||
|
enum InvoiceStatusEnum {
|
||||||
|
PENDING = 'PENDING',
|
||||||
|
COMPLETE = 'COMPLETE',
|
||||||
|
FAILED = 'FAILED',
|
||||||
|
CANCEL = 'CANCEL',
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataType = {
|
||||||
|
examineOpinion: string;
|
||||||
|
examineUserId: string;
|
||||||
|
examineUserUsername: string;
|
||||||
|
gmtCreate: string;
|
||||||
|
gmtExamine: string;
|
||||||
|
invoiceAccount: string;
|
||||||
|
invoiceAddress: string;
|
||||||
|
invoiceAmount: number;
|
||||||
|
invoiceBank: string;
|
||||||
|
invoiceFileList: string[];
|
||||||
|
invoiceFiles: string;
|
||||||
|
invoiceId: string;
|
||||||
|
invoiceNo: string;
|
||||||
|
invoiceNote: string;
|
||||||
|
invoicePhone: string;
|
||||||
|
invoiceStatus: InvoiceStatusEnum;
|
||||||
|
invoiceTitle: string;
|
||||||
|
orderIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceList() {
|
||||||
|
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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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: 'invoiceAmount',
|
||||||
|
align: 'center',
|
||||||
|
width: 160,
|
||||||
|
render: (value) => {
|
||||||
|
return (value / 100).toFixed(2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'invoiceNote',
|
||||||
|
align: 'center',
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'gmtCreate',
|
||||||
|
align: 'center',
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'invoiceStatus',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
fixed: 'right',
|
||||||
|
render: (value) => {
|
||||||
|
if(value === InvoiceStatusEnum.PENDING) {
|
||||||
|
return <Tag color="magenta">待审核</Tag>
|
||||||
|
}
|
||||||
|
if(value === InvoiceStatusEnum.COMPLETE) {
|
||||||
|
return <Tag color="green">已开票</Tag>
|
||||||
|
}
|
||||||
|
if(value === InvoiceStatusEnum.FAILED) {
|
||||||
|
return <Tag color="red">失败</Tag>
|
||||||
|
}
|
||||||
|
if(value === InvoiceStatusEnum.CANCEL) {
|
||||||
|
return <Tag color="cyan">已取消</Tag>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'operate',
|
||||||
|
align: 'center',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
render: (value, record) => {
|
||||||
|
if(record.invoiceStatus == InvoiceStatusEnum.COMPLETE) {
|
||||||
|
const items: MenuProps['items'] = [];
|
||||||
|
record.invoiceFileList.forEach((item, index) => {
|
||||||
|
items.push({
|
||||||
|
key: index,
|
||||||
|
label: (
|
||||||
|
<a href={item} download target="_blank">下载发票{index + 1}</a>
|
||||||
|
)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<Dropdown menu={{ items }} placement="bottom" arrow>
|
||||||
|
<Button type="link">下载发票</Button>
|
||||||
|
</Dropdown>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
get<IListPage<DataType>>({
|
||||||
|
messageApi,
|
||||||
|
url: '/api/invoice/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 columns={columns} dataSource={dataArray} pagination={
|
||||||
|
{
|
||||||
|
pageSize: 20,
|
||||||
|
onChange: (currentPage) => {
|
||||||
|
setPage(currentPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} scroll={{y: 500}} bordered key="dataTable" rowKey="invoiceId"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Modal open={true}
|
||||||
|
title="申请开票"
|
||||||
|
>
|
||||||
|
<InvoiceSave />
|
||||||
|
</Modal>
|
||||||
|
{messageContext}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
207
src/components/invoice/InvoiceSave.tsx
Normal file
207
src/components/invoice/InvoiceSave.tsx
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
import {Button, Divider, Form, Input, Radio, Space} from "antd";
|
||||||
|
import {useState} from "react";
|
||||||
|
|
||||||
|
type FormFieldType = {
|
||||||
|
invoiceTitle: string;
|
||||||
|
invoiceNo: number;
|
||||||
|
invoiceAddress: string;
|
||||||
|
invoicePhone: string;
|
||||||
|
invoiceAccount: string;
|
||||||
|
invoiceBank: string;
|
||||||
|
content: string;
|
||||||
|
rate: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvoiceSave() {
|
||||||
|
const [form] = Form.useForm<FormFieldType>();
|
||||||
|
const [isSaveInvoiceInfo, setIsSaveInvoiceInfo] = useState(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form
|
||||||
|
name="basic"
|
||||||
|
initialValues={{remember: true}}
|
||||||
|
form={form}
|
||||||
|
>
|
||||||
|
<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="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">
|
||||||
|
<Radio value={1}>A</Radio>
|
||||||
|
<Radio value={2}>B</Radio>
|
||||||
|
<Radio value={3}>C</Radio>
|
||||||
|
<Radio value={4}>D</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>
|
||||||
|
<Radio value={1}>A</Radio>
|
||||||
|
<Radio value={2}>B</Radio>
|
||||||
|
<Radio value={3}>C</Radio>
|
||||||
|
<Radio value={4}>D</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>
|
||||||
|
<Radio value={1}>A</Radio>
|
||||||
|
<Radio value={2}>B</Radio>
|
||||||
|
<Radio value={3}>C</Radio>
|
||||||
|
<Radio value={4}>D</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">保存开票信息 *</td>
|
||||||
|
<td>
|
||||||
|
<Radio.Group defaultValue={isSaveInvoiceInfo} onChange={(e) => {
|
||||||
|
setIsSaveInvoiceInfo(e.target.value)
|
||||||
|
}}>
|
||||||
|
<Radio value={0}>否</Radio>
|
||||||
|
<Radio value={1}>是</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</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'}}>300</span>
|
||||||
|
<Button type="link" size="small">请选择需要开票的订单</Button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">开票备注</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="invoiceBank"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入开票备注'}]}
|
||||||
|
>
|
||||||
|
<Input.TextArea placeholder="请输入开票备注" rows={4}/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -68,8 +68,8 @@ export default function ListProj() {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return projs.map((item, index) => {
|
return projs.map((item) => {
|
||||||
return <CardProj item={item} key={`proj${index}`}/>;
|
return <CardProj item={item} key={new Date().getTime() + ':' + item.projId}/>;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,9 +77,11 @@ export default function ListProj() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
reqData(page);
|
if (indexListContext.categorys) {
|
||||||
renderCategory();
|
reqData(page);
|
||||||
}, [indexListContext.status, indexListContext.categorys, indexListContext.category, keywords, page])
|
renderCategory();
|
||||||
|
}
|
||||||
|
}, [indexListContext.status, indexListContext.categoryChangeCount, indexListContext.category, keywords, page])
|
||||||
|
|
||||||
const renderStatus = () => {
|
const renderStatus = () => {
|
||||||
if (indexListContext.status == 'ALL') {
|
if (indexListContext.status == 'ALL') {
|
||||||
|
@ -25,10 +25,12 @@ export default function MenuTree(props: IMenuTree) {
|
|||||||
if (item.isEdit) {
|
if (item.isEdit) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CheckOutlined className="icon" onClick={() => {
|
<CheckOutlined className="icon" onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
props.handleEditSaveClick(item);
|
props.handleEditSaveClick(item);
|
||||||
}}/>
|
}}/>
|
||||||
<CloseOutlined className="icon" onClick={() => {
|
<CloseOutlined className="icon" onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
props.handleEditCancelClick(item);
|
props.handleEditCancelClick(item);
|
||||||
}}/>
|
}}/>
|
||||||
</>
|
</>
|
||||||
@ -36,13 +38,16 @@ export default function MenuTree(props: IMenuTree) {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EditOutlined className="icon" onClick={() => {
|
<EditOutlined className="icon" onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
props.handleEditClick(item);
|
props.handleEditClick(item);
|
||||||
}}/>
|
}}/>
|
||||||
<PlusOutlined className="icon" onClick={() => {
|
<PlusOutlined className="icon" onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
props.handleAddClick(item);
|
props.handleAddClick(item);
|
||||||
}}/>
|
}}/>
|
||||||
<CloseOutlined className="icon" onClick={() => {
|
<CloseOutlined className="icon" onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
props.handleRemoveClick(item, index, parent);
|
props.handleRemoveClick(item, index, parent);
|
||||||
}}/>
|
}}/>
|
||||||
</>
|
</>
|
||||||
@ -85,7 +90,8 @@ export default function MenuTree(props: IMenuTree) {
|
|||||||
const lis = children.map((item, index) => {
|
const lis = children.map((item, index) => {
|
||||||
const renderChildrenMenu = renderMenu(item.children, item);
|
const renderChildrenMenu = renderMenu(item.children, item);
|
||||||
return (
|
return (
|
||||||
<li className={item.active ? 'active' : ''} key={item.id} onClick={() => {
|
<li className={item.active ? 'active' : ''} key={item.id} onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
props.handleClick(item);
|
props.handleClick(item);
|
||||||
}}>
|
}}>
|
||||||
<div className="menu-title">
|
<div className="menu-title">
|
||||||
|
@ -194,7 +194,7 @@ export default function MenuTreeWithTopButton() {
|
|||||||
...menuTreeArray
|
...menuTreeArray
|
||||||
])
|
])
|
||||||
indexListDispatchContext({
|
indexListDispatchContext({
|
||||||
type: IndexListDataType.CATEGORY,
|
type: IndexListDataType.CATEGORY_DELETE,
|
||||||
value: menus2Dropdowns(menuTreeArray)
|
value: menus2Dropdowns(menuTreeArray)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,16 @@ import {
|
|||||||
message,
|
message,
|
||||||
Radio,
|
Radio,
|
||||||
Spin,
|
Spin,
|
||||||
Upload, UploadFile, UploadProps
|
Upload, UploadProps
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import {
|
import {
|
||||||
ReloadOutlined
|
ReloadOutlined
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useRef, useState} from "react";
|
||||||
import locale from 'antd/locale/zh_CN';
|
import locale from 'antd/locale/zh_CN';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import 'dayjs/locale/zh-cn';
|
import 'dayjs/locale/zh-cn';
|
||||||
import {DevUserId, downloadUrl, get, post, uploadImageUrl} from "../../util/AjaxUtils.ts";
|
import {DevUserId, get, post, uploadImageUrl} from "../../util/AjaxUtils.ts";
|
||||||
import {UploadOutlined} from "@ant-design/icons";
|
import {UploadOutlined} from "@ant-design/icons";
|
||||||
import useMessage from "antd/es/message/useMessage";
|
import useMessage from "antd/es/message/useMessage";
|
||||||
import {errorImage} from "../../util/CommonUtil.ts";
|
import {errorImage} from "../../util/CommonUtil.ts";
|
||||||
@ -70,7 +70,7 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
const [isRechargeMoneyEdit, setIsRechargeMoneyEdit] = useState(false);
|
const [isRechargeMoneyEdit, setIsRechargeMoneyEdit] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [rechargeVoucherArray, setRechargeVoucherArray] = useState<string[]>([]);
|
const [rechargeVoucherArray, setRechargeVoucherArray] = useState<string[]>([]);
|
||||||
const [thirdParty, setThirdParty] = useState('');
|
const [thirdParty, setThirdParty] = useState<ThirdPartyEnum | null>();
|
||||||
const [accountRechargeId, setAccountRechargeId] = useState('');
|
const [accountRechargeId, setAccountRechargeId] = useState('');
|
||||||
const [thirdPartyPayUrl, setThirdPartyPayUrl] = useState('');
|
const [thirdPartyPayUrl, setThirdPartyPayUrl] = useState('');
|
||||||
const [paySystemBank, setPaySystemBank] = useState<PaySystemBank>({
|
const [paySystemBank, setPaySystemBank] = useState<PaySystemBank>({
|
||||||
@ -83,14 +83,18 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
const [countdownTime, setCountdownTime] = useState('');
|
const [countdownTime, setCountdownTime] = useState('');
|
||||||
const [isCountdownTimeout, setIsCountdownTimeout] = useState(false);
|
const [isCountdownTimeout, setIsCountdownTimeout] = useState(false);
|
||||||
const moneyRange: number[] = [0.01, 2000];
|
const moneyRange: number[] = [0.01, 2000];
|
||||||
let countdownInterval: number = -1;
|
const countdownIntervalRef = useRef<number | undefined>();
|
||||||
|
const [refreshQrCodeCount, setRefreshQrCodeCount] = useState(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 倒计时
|
* 倒计时
|
||||||
*/
|
*/
|
||||||
const countdown = () => {
|
const countdown = () => {
|
||||||
if (countdownInterval > -1) {
|
if (countdownIntervalRef.current) {
|
||||||
clearInterval(countdownInterval);
|
clearInterval(countdownIntervalRef.current);
|
||||||
|
}
|
||||||
|
if (thirdParty == ThirdPartyEnum.DGZZ) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
const Time = new Date().getTime();
|
const Time = new Date().getTime();
|
||||||
// 设定计时器的时间为60秒
|
// 设定计时器的时间为60秒
|
||||||
@ -108,11 +112,11 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
if (distance <= 0) {
|
if (distance <= 0) {
|
||||||
setCountdownTime('已失效');
|
setCountdownTime('已失效');
|
||||||
setIsCountdownTimeout(true);
|
setIsCountdownTimeout(true);
|
||||||
clearInterval(countdownInterval);
|
clearInterval(countdownIntervalRef.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 每秒更新一次计时器
|
// 每秒更新一次计时器
|
||||||
countdownInterval = setInterval(() => {
|
countdownIntervalRef.current = setInterval(() => {
|
||||||
updateCountdown();
|
updateCountdown();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
@ -131,10 +135,7 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
onSuccess({data}) {
|
onSuccess({data}) {
|
||||||
setAccountRechargeId(data.accountRechargeId);
|
setAccountRechargeId(data.accountRechargeId);
|
||||||
setThirdPartyPayUrl(data.thirdPartyPayUrl);
|
setThirdPartyPayUrl(data.thirdPartyPayUrl);
|
||||||
clearInterval(countdownInterval);
|
countdown();
|
||||||
if (thirdParty != ThirdPartyEnum.DGZZ) {
|
|
||||||
countdown();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onFinally() {
|
onFinally() {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@ -153,14 +154,16 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
form.setFieldsValue({
|
if (!thirdParty) {
|
||||||
thirdParty: ThirdPartyEnum.DGZZ,
|
getPaySystemBank();
|
||||||
rechargeMoney: 300
|
form.setFieldsValue({
|
||||||
})
|
thirdParty: ThirdPartyEnum.DGZZ,
|
||||||
setThirdParty(ThirdPartyEnum.DGZZ);
|
rechargeMoney: 300
|
||||||
getPaySystemBank();
|
})
|
||||||
|
setThirdParty(ThirdPartyEnum.DGZZ)
|
||||||
|
}
|
||||||
getPay();
|
getPay();
|
||||||
}, []);
|
}, [thirdParty, isRechargeMoneyEdit, refreshQrCodeCount]);
|
||||||
|
|
||||||
|
|
||||||
const renderMoney = () => {
|
const renderMoney = () => {
|
||||||
@ -178,7 +181,6 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
messageApi.error(`金额最大为${moneyRange[1]}`)
|
messageApi.error(`金额最大为${moneyRange[1]}`)
|
||||||
}
|
}
|
||||||
setIsRechargeMoneyEdit(false);
|
setIsRechargeMoneyEdit(false);
|
||||||
getPay();
|
|
||||||
}}>确定</Button>
|
}}>确定</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -277,6 +279,18 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="table-label">银行账号 *</td>
|
||||||
|
<td>
|
||||||
|
<Form.Item
|
||||||
|
name="orgNumber"
|
||||||
|
style={{marginBottom: '0'}}
|
||||||
|
rules={[{required: true, message: '请输入银行账号'}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入银行账号"/>
|
||||||
|
</Form.Item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="table-label">打款时间 *</td>
|
<td className="table-label">打款时间 *</td>
|
||||||
<td>
|
<td>
|
||||||
@ -286,9 +300,10 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
rules={[{required: true, message: '请选择打款时间'}]}
|
rules={[{required: true, message: '请选择打款时间'}]}
|
||||||
>
|
>
|
||||||
<ConfigProvider locale={locale}>
|
<ConfigProvider locale={locale}>
|
||||||
<DatePicker showTime placeholder="请选择打款时间" onChange={(_date, dateString) => {
|
<DatePicker showTime placeholder="请选择打款时间"
|
||||||
form.setFieldValue('rechargeFinalTime', dateString);
|
onChange={(_date, dateString) => {
|
||||||
}}/>
|
form.setFieldValue('rechargeFinalTime', dateString);
|
||||||
|
}}/>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</td>
|
</td>
|
||||||
@ -351,7 +366,7 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
{
|
{
|
||||||
isCountdownTimeout ? (
|
isCountdownTimeout ? (
|
||||||
<div className="qr-timeout" onClick={() => {
|
<div className="qr-timeout" onClick={() => {
|
||||||
getPay()
|
setRefreshQrCodeCount(refreshQrCodeCount + 1);
|
||||||
}}>
|
}}>
|
||||||
<ReloadOutlined/>
|
<ReloadOutlined/>
|
||||||
<span className="label">点击刷新</span>
|
<span className="label">点击刷新</span>
|
||||||
@ -372,7 +387,6 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
initialValues={{remember: true}}
|
initialValues={{remember: true}}
|
||||||
form={form}
|
form={form}
|
||||||
onFinish={() => {
|
onFinish={() => {
|
||||||
|
|
||||||
post<any>({
|
post<any>({
|
||||||
messageApi,
|
messageApi,
|
||||||
url: `/api/pay/pay-account-recharge/${accountRechargeId}`,
|
url: `/api/pay/pay-account-recharge/${accountRechargeId}`,
|
||||||
@ -406,7 +420,6 @@ export default function Payment(props: IPaymentProps) {
|
|||||||
<Radio.Group onChange={(e) => {
|
<Radio.Group onChange={(e) => {
|
||||||
form.setFieldValue('thirdParty', e.target.value);
|
form.setFieldValue('thirdParty', e.target.value);
|
||||||
setThirdParty(e.target.value);
|
setThirdParty(e.target.value);
|
||||||
getPay();
|
|
||||||
}} defaultValue="a">
|
}} defaultValue="a">
|
||||||
<Radio value="微信">微信</Radio>
|
<Radio value="微信">微信</Radio>
|
||||||
<Radio value="支付宝">支付宝</Radio>
|
<Radio value="支付宝">支付宝</Radio>
|
@ -1,14 +1,36 @@
|
|||||||
import './recharge-head.css';
|
import './recharge-head.css';
|
||||||
|
import Payment from "../payment/Payment.tsx";
|
||||||
|
import {Modal} from "antd";
|
||||||
|
import {useState} from "react";
|
||||||
|
|
||||||
export default function RechargeHead() {
|
export default function RechargeHead() {
|
||||||
|
|
||||||
const handleRecharge = () => {
|
const [isPaymentModalOpen, setIsPaymentModalOpen] = useState(false);
|
||||||
console.log('充值');
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="head-item recharge-head">
|
<>
|
||||||
<span onClick={handleRecharge}>充值</span>
|
<div className="head-item recharge-head">
|
||||||
</div>
|
<span onClick={() => {
|
||||||
|
setIsPaymentModalOpen(true);
|
||||||
|
}}>充值</span>
|
||||||
|
</div>
|
||||||
|
<Modal open={isPaymentModalOpen}
|
||||||
|
title="充值"
|
||||||
|
onCancel={() => {
|
||||||
|
setIsPaymentModalOpen(false);
|
||||||
|
}}
|
||||||
|
footer={false}
|
||||||
|
>
|
||||||
|
<Payment
|
||||||
|
handleConfirm={() => {
|
||||||
|
setIsPaymentModalOpen(false);
|
||||||
|
}}
|
||||||
|
handleCancel={() => {
|
||||||
|
setIsPaymentModalOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
import {createContext, Dispatch} from "react";
|
import {createContext, Dispatch} from "react";
|
||||||
|
import {get} from "../util/AjaxUtils.ts";
|
||||||
|
import {MessageInstance} from "antd/es/message/interface";
|
||||||
|
|
||||||
export enum GlobalDataActionType {
|
export enum GlobalDataActionType {
|
||||||
REFRESH_SELF
|
REFRESH_SELF
|
||||||
@ -11,6 +13,28 @@ export interface User {
|
|||||||
hasUserInfo: boolean;
|
hasUserInfo: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function reloadUser(messageApi: MessageInstance, globalDispatchContext: Dispatch<GlobalDataAction>) {
|
||||||
|
return new Promise<any>(resolve => {
|
||||||
|
get<any>({
|
||||||
|
messageApi,
|
||||||
|
url: '/api/user-info/get-user-self',
|
||||||
|
onSuccess({data}) {
|
||||||
|
globalDispatchContext({
|
||||||
|
type: GlobalDataActionType.REFRESH_SELF,
|
||||||
|
user: {
|
||||||
|
balance: (Math.floor(data.accountMoney) / 100).toFixed(2),
|
||||||
|
nickname: data.nickname,
|
||||||
|
username: data.username,
|
||||||
|
hasUserInfo: data.hasUserInfo,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export interface GlobalData {
|
export interface GlobalData {
|
||||||
user: User;
|
user: User;
|
||||||
}
|
}
|
||||||
@ -28,4 +52,5 @@ export const GlobalContext = createContext<GlobalData>({
|
|||||||
hasUserInfo: false
|
hasUserInfo: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export const GlobalDispatchContext = createContext<Dispatch<GlobalDataAction>>(() => {});
|
export const GlobalDispatchContext = createContext<Dispatch<GlobalDataAction>>(() => {
|
||||||
|
});
|
||||||
|
@ -5,7 +5,8 @@ export enum IndexListDataType {
|
|||||||
PROJ,
|
PROJ,
|
||||||
AGENT,
|
AGENT,
|
||||||
CATEGORY,
|
CATEGORY,
|
||||||
CATEGORY_CHANGE
|
CATEGORY_CHANGE,
|
||||||
|
CATEGORY_DELETE
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ListData {
|
export interface ListData {
|
||||||
@ -13,6 +14,7 @@ export interface ListData {
|
|||||||
status?: string;
|
status?: string;
|
||||||
category?: string;
|
category?: string;
|
||||||
categorys?: MenuProps['items'];
|
categorys?: MenuProps['items'];
|
||||||
|
categoryChangeCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ListAction {
|
export interface ListAction {
|
||||||
@ -22,7 +24,8 @@ export interface ListAction {
|
|||||||
|
|
||||||
|
|
||||||
export const IndexListContext = createContext<ListData>({
|
export const IndexListContext = createContext<ListData>({
|
||||||
type: IndexListDataType.PROJ
|
type: IndexListDataType.PROJ,
|
||||||
|
categoryChangeCount: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
export const IndexListDispatchContext = createContext<Dispatch<ListAction>>(() => {
|
export const IndexListDispatchContext = createContext<Dispatch<ListAction>>(() => {
|
||||||
|
@ -2,14 +2,14 @@ import './head.css'
|
|||||||
import BalanceHead from '../../components/balance/BalanceHead.tsx';
|
import BalanceHead from '../../components/balance/BalanceHead.tsx';
|
||||||
import RechargeHead from '../../components/recharge/RechargeHead.tsx';
|
import RechargeHead from '../../components/recharge/RechargeHead.tsx';
|
||||||
import {Divider, Dropdown, MenuProps, message, Modal, Space, Spin} from "antd";
|
import {Divider, Dropdown, MenuProps, message, Modal, Space, Spin} from "antd";
|
||||||
import {DownOutlined, UserOutlined, KeyOutlined, LogoutOutlined} from "@ant-design/icons";
|
import {DownOutlined, UserOutlined, KeyOutlined, LogoutOutlined, AccountBookOutlined} from "@ant-design/icons";
|
||||||
import {useContext, useEffect, useState} from "react";
|
import {useContext, useEffect, useState} from "react";
|
||||||
import {get, put} from "../../util/AjaxUtils.ts";
|
import {put} from "../../util/AjaxUtils.ts";
|
||||||
import {GlobalContext, GlobalDataActionType, GlobalDispatchContext} from "../../context/GlobalContext.ts";
|
import {GlobalContext, GlobalDispatchContext, reloadUser} from "../../context/GlobalContext.ts";
|
||||||
import UserEdit from "../../route/user/UserEdit.tsx";
|
import UserEdit from "../../components/user/UserEdit.tsx";
|
||||||
import PasswordChange from "../../route/password/PasswordChange.tsx";
|
import PasswordChange from "../../components/password/PasswordChange.tsx";
|
||||||
import headRightBg from '../../assets/head-right-bg.png';
|
import headRightBg from '../../assets/head-right-bg.png';
|
||||||
import Payment from "../../route/payment/Payment.tsx";
|
import InvoiceList from "../../components/invoice/InvoiceList.tsx";
|
||||||
|
|
||||||
|
|
||||||
export default function Head() {
|
export default function Head() {
|
||||||
@ -22,24 +22,11 @@ export default function Head() {
|
|||||||
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
|
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
get<any>({
|
reloadUser(messageApi, globalDispatchContext).then((data) => {
|
||||||
messageApi,
|
if (!data.hasUserInfo) {
|
||||||
url: '/api/user-info/get-user-self',
|
setIsSelfModalOpen(true);
|
||||||
onSuccess({data}) {
|
|
||||||
globalDispatchContext({
|
|
||||||
type: GlobalDataActionType.REFRESH_SELF,
|
|
||||||
user: {
|
|
||||||
balance: (Math.floor(data.accountMoney) / 100).toFixed(2),
|
|
||||||
nickname: data.nickname,
|
|
||||||
username: data.username,
|
|
||||||
hasUserInfo: data.hasUserInfo,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if(!data.hasUserInfo) {
|
|
||||||
setIsSelfModalOpen(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}, [globalContext.user]);
|
}, [globalContext.user]);
|
||||||
|
|
||||||
const items: MenuProps['items'] = [
|
const items: MenuProps['items'] = [
|
||||||
@ -47,7 +34,7 @@ export default function Head() {
|
|||||||
key: 'userinfo',
|
key: 'userinfo',
|
||||||
label: (
|
label: (
|
||||||
<div className="dropdown-item">
|
<div className="dropdown-item">
|
||||||
<UserOutlined />
|
<UserOutlined/>
|
||||||
<span className="title">个人信息</span>
|
<span className="title">个人信息</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@ -59,7 +46,7 @@ export default function Head() {
|
|||||||
key: 'changePass',
|
key: 'changePass',
|
||||||
label: (
|
label: (
|
||||||
<div className="dropdown-item">
|
<div className="dropdown-item">
|
||||||
<KeyOutlined />
|
<KeyOutlined/>
|
||||||
<span className="title">修改密码</span>
|
<span className="title">修改密码</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@ -67,11 +54,23 @@ export default function Head() {
|
|||||||
setIsPasswordModalOpen(true);
|
setIsPasswordModalOpen(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'invoice',
|
||||||
|
label: (
|
||||||
|
<div className="dropdown-item">
|
||||||
|
<AccountBookOutlined />
|
||||||
|
<span className="title">发票管理</span>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
onClick: () => {
|
||||||
|
// nav('/invoice-list');
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'logout',
|
key: 'logout',
|
||||||
label: (
|
label: (
|
||||||
<div className="dropdown-item">
|
<div className="dropdown-item">
|
||||||
<LogoutOutlined />
|
<LogoutOutlined/>
|
||||||
<span className="title">退出系统</span>
|
<span className="title">退出系统</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@ -108,12 +107,12 @@ export default function Head() {
|
|||||||
title="个人信息"
|
title="个人信息"
|
||||||
footer={false}
|
footer={false}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
if(!globalContext.user.hasUserInfo) {
|
if (!globalContext.user.hasUserInfo) {
|
||||||
messageApi.info('请完善个人信息');
|
messageApi.info('请完善个人信息');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setIsSelfModalOpen(false)
|
setIsSelfModalOpen(false)
|
||||||
}} >
|
}}>
|
||||||
<UserEdit handleConfirm={(data) => {
|
<UserEdit handleConfirm={(data) => {
|
||||||
modal.confirm({
|
modal.confirm({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
@ -150,7 +149,7 @@ export default function Head() {
|
|||||||
footer={false}
|
footer={false}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setIsPasswordModalOpen(false)
|
setIsPasswordModalOpen(false)
|
||||||
}} >
|
}}>
|
||||||
<PasswordChange handleConfirm={(data) => {
|
<PasswordChange handleConfirm={(data) => {
|
||||||
modal.confirm({
|
modal.confirm({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
@ -183,10 +182,11 @@ export default function Head() {
|
|||||||
}}/>
|
}}/>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal open={true}
|
<Modal open={true}
|
||||||
title="充值"
|
title="发票管理"
|
||||||
|
width={1100}
|
||||||
footer={false}
|
footer={false}
|
||||||
>
|
>
|
||||||
<Payment/>
|
<InvoiceList/>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Spin tip="正在提交..." spinning={loading} fullscreen/>
|
<Spin tip="正在提交..." spinning={loading} fullscreen/>
|
||||||
{contextHolder}
|
{contextHolder}
|
||||||
|
@ -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, MenuProps} from 'antd';
|
import {Breadcrumb, Button, MenuProps} from 'antd';
|
||||||
import {
|
import {
|
||||||
IndexListContext,
|
IndexListContext,
|
||||||
IndexListDataType,
|
IndexListDataType,
|
||||||
@ -28,8 +28,14 @@ export default function Index() {
|
|||||||
state.status = action.value as string;
|
state.status = action.value as string;
|
||||||
} else if (action.type == IndexListDataType.CATEGORY) {
|
} else if (action.type == IndexListDataType.CATEGORY) {
|
||||||
state.categorys = action.value as MenuProps['items'];
|
state.categorys = action.value as MenuProps['items'];
|
||||||
|
state.categoryChangeCount++;
|
||||||
} else if (action.type == IndexListDataType.CATEGORY_CHANGE) {
|
} else if (action.type == IndexListDataType.CATEGORY_CHANGE) {
|
||||||
state.category = action.value as string
|
state.category = action.value as string;
|
||||||
|
state.categoryChangeCount++;
|
||||||
|
} else if (action.type == IndexListDataType.CATEGORY_DELETE) {
|
||||||
|
state.categorys = action.value as MenuProps['items'];
|
||||||
|
state.category = '';
|
||||||
|
state.categoryChangeCount++;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...state
|
...state
|
||||||
@ -37,7 +43,8 @@ export default function Index() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [listData, dispatch] = useReducer<Reducer<ListData, ListAction>>(listReducer, {
|
const [listData, dispatch] = useReducer<Reducer<ListData, ListAction>>(listReducer, {
|
||||||
type: IndexListDataType.PROJ
|
type: IndexListDataType.PROJ,
|
||||||
|
categoryChangeCount: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const [projMenu, setProjMenu] = useState<IMenuWithTopButton>({
|
const [projMenu, setProjMenu] = useState<IMenuWithTopButton>({
|
||||||
@ -126,6 +133,7 @@ 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">
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import './proj-new.css';
|
import './proj-new.css';
|
||||||
import {Link, useNavigate, useParams, useSearchParams} from "react-router-dom";
|
import {Link, useNavigate, useParams, useSearchParams} from "react-router-dom";
|
||||||
import {Breadcrumb, Button, Flex, Form, Input, message, Modal, Spin} from "antd";
|
import {Breadcrumb, Button, Flex, Form, Input, message, Modal, Spin} from "antd";
|
||||||
import {useEffect, useState} from "react";
|
import {useContext, useEffect, useState} from "react";
|
||||||
import {get, post} from "../../util/AjaxUtils.ts";
|
import {get, post} from "../../util/AjaxUtils.ts";
|
||||||
import {IProjCharge, ProjAdditionalType, ProjChargeType} from "../../interfaces/proj/IProj.ts";
|
import {IProjCharge, ProjAdditionalType, ProjChargeType} from "../../interfaces/proj/IProj.ts";
|
||||||
|
import {GlobalDispatchContext, reloadUser} from "../../context/GlobalContext.ts";
|
||||||
|
|
||||||
const {TextArea} = Input;
|
const {TextArea} = Input;
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ type ProjInfo = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function ProjNew() {
|
export default function ProjNew() {
|
||||||
|
const globalDispatchContext = useContext(GlobalDispatchContext);
|
||||||
const nav = useNavigate();
|
const nav = useNavigate();
|
||||||
const pathParams = useParams();
|
const pathParams = useParams();
|
||||||
const [queryParams] = useSearchParams();
|
const [queryParams] = useSearchParams();
|
||||||
@ -156,6 +158,9 @@ export default function ProjNew() {
|
|||||||
onSuccess({data}) {
|
onSuccess({data}) {
|
||||||
setIsEditModalOpen(true);
|
setIsEditModalOpen(true);
|
||||||
setCreateProjId(data.data);
|
setCreateProjId(data.data);
|
||||||
|
reloadUser(messageApi, globalDispatchContext).then(() => {
|
||||||
|
messageApi.success('扣款成功');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onFinally() {
|
onFinally() {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -145,6 +145,5 @@ export const router = createHashRouter([
|
|||||||
{
|
{
|
||||||
path: '/agent-result/:orderId',
|
path: '/agent-result/:orderId',
|
||||||
element: <AgentResult />
|
element: <AgentResult />
|
||||||
}
|
},
|
||||||
// ], {basename: import.meta.env.BASE_URL})
|
|
||||||
])
|
])
|
Loading…
Reference in New Issue
Block a user