Commit 379c80fadb924ce41c583bd302fba4012a0cbbd8
1 parent
e7087f45
feat: 用户查询三种方式弹窗
Showing
4 changed files
with
362 additions
and
1 deletions
src/pages/Prepaid/components/PointsExchangeRecordsModal.tsx
0 → 100644
1 | +import { postIntegralUserExchangeRecords } from '@/services'; | ||
2 | +import { formatDateTime } from '@/utils'; | ||
3 | +import { Empty, Modal, Table, Tabs } from 'antd'; | ||
4 | +import React, { useEffect, useState } from 'react'; | ||
5 | +import '../index.less'; | ||
6 | + | ||
7 | +interface PointsExchangeRecordsModalProps { | ||
8 | + setVisible: (visible: boolean) => void; | ||
9 | + userInfoObj: { | ||
10 | + uid: string; | ||
11 | + phone?: string; | ||
12 | + nickname?: string; | ||
13 | + realName?: string; | ||
14 | + [key: string]: any; | ||
15 | + }; | ||
16 | + onClose: () => void; | ||
17 | +} | ||
18 | + | ||
19 | +interface RecordItem { | ||
20 | + createByName: string | null; | ||
21 | + createTime: string; | ||
22 | + delta: number; | ||
23 | + remark: string | null; | ||
24 | + sourceId: string | null; | ||
25 | +} | ||
26 | + | ||
27 | +interface RecordsData { | ||
28 | + exchangeRecords: RecordItem[]; | ||
29 | + collectedRecords: RecordItem[]; | ||
30 | + pendingRecords: RecordItem[]; | ||
31 | +} | ||
32 | + | ||
33 | +const PointsExchangeRecordsModal: React.FC<PointsExchangeRecordsModalProps> = ({ | ||
34 | + setVisible, | ||
35 | + userInfoObj, | ||
36 | + onClose, | ||
37 | +}) => { | ||
38 | + const [activeTab, setActiveTab] = useState<string>('1'); | ||
39 | + const [loading, setLoading] = useState<boolean>(false); | ||
40 | + const [recordsData, setRecordsData] = useState<RecordsData>({ | ||
41 | + exchangeRecords: [], | ||
42 | + collectedRecords: [], | ||
43 | + pendingRecords: [], | ||
44 | + }); | ||
45 | + | ||
46 | + const uid = userInfoObj?.uid; | ||
47 | + const phone = userInfoObj?.phone; | ||
48 | + | ||
49 | + // Function to fetch records data from API | ||
50 | + const fetchRecordsData = async () => { | ||
51 | + try { | ||
52 | + setLoading(true); | ||
53 | + const response = await postIntegralUserExchangeRecords({ | ||
54 | + data: { | ||
55 | + id: Number(uid), | ||
56 | + phone: phone, | ||
57 | + }, | ||
58 | + }); | ||
59 | + | ||
60 | + if (response && response.data) { | ||
61 | + setRecordsData({ | ||
62 | + exchangeRecords: response.data.exchangeRecords || [], | ||
63 | + collectedRecords: response.data.collectedRecords || [], | ||
64 | + pendingRecords: response.data.pendingRecords || [], | ||
65 | + }); | ||
66 | + } | ||
67 | + } catch (error) { | ||
68 | + console.error('Failed to fetch exchange records:', error); | ||
69 | + } finally { | ||
70 | + setLoading(false); | ||
71 | + } | ||
72 | + }; | ||
73 | + | ||
74 | + // Fetch records data when component mounts | ||
75 | + useEffect(() => { | ||
76 | + if (uid || phone) { | ||
77 | + fetchRecordsData(); | ||
78 | + } | ||
79 | + }, [uid, phone]); | ||
80 | + // Exchange records columns | ||
81 | + const exchangeRecordsColumns = [ | ||
82 | + { | ||
83 | + title: '兑换日期', | ||
84 | + dataIndex: 'createTime', | ||
85 | + key: 'createTime', | ||
86 | + render: (text: string) => formatDateTime(text), | ||
87 | + }, | ||
88 | + { | ||
89 | + title: '扣除积分', | ||
90 | + dataIndex: 'delta', | ||
91 | + key: 'delta', | ||
92 | + render: (delta: number) => ( | ||
93 | + <span style={{ color: delta < 0 ? 'red' : 'green' }}>{delta}</span> | ||
94 | + ), | ||
95 | + }, | ||
96 | + { | ||
97 | + title: '操作人', | ||
98 | + dataIndex: 'createByName', | ||
99 | + key: 'createByName', | ||
100 | + render: (text: string | null) => text || '-', | ||
101 | + }, | ||
102 | + { | ||
103 | + title: '积分用途', | ||
104 | + dataIndex: 'remark', | ||
105 | + key: 'remark', | ||
106 | + render: (text: string | null) => text || '-', | ||
107 | + }, | ||
108 | + ]; | ||
109 | + | ||
110 | + // Collected records columns | ||
111 | + const collectedRecordsColumns = [ | ||
112 | + { | ||
113 | + title: '订单号', | ||
114 | + dataIndex: 'sourceId', | ||
115 | + key: 'sourceId', | ||
116 | + render: (text: string | null) => text || '-', | ||
117 | + }, | ||
118 | + { | ||
119 | + title: '领取积分', | ||
120 | + dataIndex: 'delta', | ||
121 | + key: 'delta', | ||
122 | + render: (delta: number) => ( | ||
123 | + <span style={{ color: delta > 0 ? 'green' : 'red' }}>{delta}</span> | ||
124 | + ), | ||
125 | + }, | ||
126 | + { | ||
127 | + title: '领取日期', | ||
128 | + dataIndex: 'createTime', | ||
129 | + key: 'createTime', | ||
130 | + render: (text: string) => formatDateTime(text), | ||
131 | + }, | ||
132 | + ]; | ||
133 | + | ||
134 | + // Pending records columns | ||
135 | + const pendingRecordsColumns = [ | ||
136 | + { | ||
137 | + title: '订单号', | ||
138 | + dataIndex: 'sourceId', | ||
139 | + key: 'sourceId', | ||
140 | + render: (text: string | null) => text || '-', | ||
141 | + }, | ||
142 | + { | ||
143 | + title: '领取积分', | ||
144 | + dataIndex: 'delta', | ||
145 | + key: 'delta', | ||
146 | + render: (delta: number) => ( | ||
147 | + <span style={{ color: delta > 0 ? 'green' : 'red' }}>{delta}</span> | ||
148 | + ), | ||
149 | + }, | ||
150 | + { | ||
151 | + title: '过期日期', | ||
152 | + dataIndex: 'createTime', | ||
153 | + key: 'createTime', | ||
154 | + render: (text: string) => formatDateTime(text), | ||
155 | + }, | ||
156 | + ]; | ||
157 | + | ||
158 | + // Tab items | ||
159 | + const tabItems = [ | ||
160 | + { | ||
161 | + key: '1', | ||
162 | + label: '兑换记录', | ||
163 | + children: ( | ||
164 | + <Table | ||
165 | + columns={exchangeRecordsColumns} | ||
166 | + dataSource={recordsData.exchangeRecords.map((item, index) => ({ | ||
167 | + ...item, | ||
168 | + key: `exchange-${index}`, | ||
169 | + }))} | ||
170 | + pagination={{ pageSize: 5 }} | ||
171 | + loading={loading && activeTab === '1'} | ||
172 | + locale={{ | ||
173 | + emptyText: <Empty description="暂无兑换记录" />, | ||
174 | + }} | ||
175 | + /> | ||
176 | + ), | ||
177 | + }, | ||
178 | + { | ||
179 | + key: '2', | ||
180 | + label: '已领取积分', | ||
181 | + children: ( | ||
182 | + <Table | ||
183 | + columns={collectedRecordsColumns} | ||
184 | + dataSource={recordsData.collectedRecords.map((item, index) => ({ | ||
185 | + ...item, | ||
186 | + key: `collected-${index}`, | ||
187 | + }))} | ||
188 | + pagination={{ pageSize: 5 }} | ||
189 | + loading={loading && activeTab === '2'} | ||
190 | + locale={{ | ||
191 | + emptyText: <Empty description="暂无已领取积分记录" />, | ||
192 | + }} | ||
193 | + /> | ||
194 | + ), | ||
195 | + }, | ||
196 | + { | ||
197 | + key: '3', | ||
198 | + label: '待领取积分', | ||
199 | + children: ( | ||
200 | + <Table | ||
201 | + columns={pendingRecordsColumns} | ||
202 | + dataSource={recordsData.pendingRecords.map((item, index) => ({ | ||
203 | + ...item, | ||
204 | + key: `pending-${index}`, | ||
205 | + }))} | ||
206 | + pagination={{ pageSize: 5 }} | ||
207 | + loading={loading && activeTab === '3'} | ||
208 | + locale={{ | ||
209 | + emptyText: <Empty description="暂无待领取积分记录" />, | ||
210 | + }} | ||
211 | + /> | ||
212 | + ), | ||
213 | + }, | ||
214 | + ]; | ||
215 | + | ||
216 | + return ( | ||
217 | + <Modal | ||
218 | + open={true} | ||
219 | + title="积分兑换记录" | ||
220 | + width={800} | ||
221 | + onCancel={() => { | ||
222 | + setVisible(false); | ||
223 | + onClose(); | ||
224 | + }} | ||
225 | + footer={null} | ||
226 | + destroyOnClose | ||
227 | + > | ||
228 | + <Tabs | ||
229 | + activeKey={activeTab} | ||
230 | + onChange={(key) => setActiveTab(key)} | ||
231 | + items={tabItems} | ||
232 | + /> | ||
233 | + </Modal> | ||
234 | + ); | ||
235 | +}; | ||
236 | + | ||
237 | +export default PointsExchangeRecordsModal; |
src/pages/Prepaid/index.tsx
@@ -17,6 +17,7 @@ import CheckModal from '../Order/Order/components/CheckModal'; | @@ -17,6 +17,7 @@ import CheckModal from '../Order/Order/components/CheckModal'; | ||
17 | import { CHECK_TYPE } from '../Order/constant'; | 17 | import { CHECK_TYPE } from '../Order/constant'; |
18 | import BalanceChangeRecordsModal from './components/BalanceChangeRecordsModal'; | 18 | import BalanceChangeRecordsModal from './components/BalanceChangeRecordsModal'; |
19 | import PointsExchangeModal from './components/PointsExchangeModal'; | 19 | import PointsExchangeModal from './components/PointsExchangeModal'; |
20 | +import PointsExchangeRecordsModal from './components/PointsExchangeRecordsModal'; | ||
20 | import RechargePrepaymentModal from './components/RechargePrepaymentModal'; | 21 | import RechargePrepaymentModal from './components/RechargePrepaymentModal'; |
21 | import { | 22 | import { |
22 | ACCOUNT_COLUMNS, | 23 | ACCOUNT_COLUMNS, |
@@ -39,6 +40,10 @@ const PrepaidPage = () => { | @@ -39,6 +40,10 @@ const PrepaidPage = () => { | ||
39 | ] = useState<boolean>(false); | 40 | ] = useState<boolean>(false); |
40 | const [pointsExchangeModalVisible, setPointsExchangeModalVisible] = | 41 | const [pointsExchangeModalVisible, setPointsExchangeModalVisible] = |
41 | useState<boolean>(false); | 42 | useState<boolean>(false); |
43 | + const [ | ||
44 | + pointsExchangeRecordsModalVisible, | ||
45 | + setPointsExchangeRecordsModalVisible, | ||
46 | + ] = useState<boolean>(false); | ||
42 | 47 | ||
43 | const reloadPrepaidTable = () => { | 48 | const reloadPrepaidTable = () => { |
44 | prepaidActionRef.current?.reload(); | 49 | prepaidActionRef.current?.reload(); |
@@ -198,7 +203,7 @@ const PrepaidPage = () => { | @@ -198,7 +203,7 @@ const PrepaidPage = () => { | ||
198 | valueType: 'option', | 203 | valueType: 'option', |
199 | key: 'option', | 204 | key: 'option', |
200 | fixed: 'right', | 205 | fixed: 'right', |
201 | - width: 200, | 206 | + width: 240, |
202 | render: (text, record) => { | 207 | render: (text, record) => { |
203 | let btns = []; | 208 | let btns = []; |
204 | btns.push( | 209 | btns.push( |
@@ -227,6 +232,19 @@ const PrepaidPage = () => { | @@ -227,6 +232,19 @@ const PrepaidPage = () => { | ||
227 | 消费记录 | 232 | 消费记录 |
228 | </Button>, | 233 | </Button>, |
229 | ); | 234 | ); |
235 | + btns.push( | ||
236 | + <Button | ||
237 | + className="p-0 ml-2" | ||
238 | + key="pointsRecords" | ||
239 | + type="link" | ||
240 | + onClick={() => { | ||
241 | + setCurrentOptUserObj(record); | ||
242 | + setPointsExchangeRecordsModalVisible(true); | ||
243 | + }} | ||
244 | + > | ||
245 | + 积分兑换记录 | ||
246 | + </Button>, | ||
247 | + ); | ||
230 | return btns; | 248 | return btns; |
231 | }, | 249 | }, |
232 | }); | 250 | }); |
@@ -407,6 +425,18 @@ const PrepaidPage = () => { | @@ -407,6 +425,18 @@ const PrepaidPage = () => { | ||
407 | }} | 425 | }} |
408 | /> | 426 | /> |
409 | )} | 427 | )} |
428 | + | ||
429 | + {pointsExchangeRecordsModalVisible && currentOptUserObj && ( | ||
430 | + <PointsExchangeRecordsModal | ||
431 | + setVisible={(val: boolean) => { | ||
432 | + setPointsExchangeRecordsModalVisible(val); | ||
433 | + }} | ||
434 | + userInfoObj={currentOptUserObj} | ||
435 | + onClose={() => { | ||
436 | + setPointsExchangeRecordsModalVisible(false); | ||
437 | + }} | ||
438 | + /> | ||
439 | + )} | ||
410 | </div> | 440 | </div> |
411 | ); | 441 | ); |
412 | }; | 442 | }; |
src/services/definition.ts
@@ -1529,6 +1529,28 @@ export interface ExchangeIntegralDto { | @@ -1529,6 +1529,28 @@ export interface ExchangeIntegralDto { | ||
1529 | remark?: string; | 1529 | remark?: string; |
1530 | } | 1530 | } |
1531 | 1531 | ||
1532 | +export interface ExchangeRecordsRequestDto { | ||
1533 | + createByName?: string; | ||
1534 | + createByNameLike?: string; | ||
1535 | + /** @format date-time */ | ||
1536 | + createTimeGe?: string; | ||
1537 | + /** @format date-time */ | ||
1538 | + createTimeLe?: string; | ||
1539 | + /** @format int32 */ | ||
1540 | + current?: number; | ||
1541 | + /** @format int32 */ | ||
1542 | + end?: number; | ||
1543 | + /** @format int32 */ | ||
1544 | + id?: number; | ||
1545 | + /** @format int32 */ | ||
1546 | + pageSize?: number; | ||
1547 | + phone?: string; | ||
1548 | + /** @format int32 */ | ||
1549 | + start?: number; | ||
1550 | + /** @format int32 */ | ||
1551 | + total?: number; | ||
1552 | +} | ||
1553 | + | ||
1532 | export interface FilePathDto { | 1554 | export interface FilePathDto { |
1533 | url?: string; | 1555 | url?: string; |
1534 | } | 1556 | } |
src/services/request.ts
@@ -57,6 +57,7 @@ import type { | @@ -57,6 +57,7 @@ import type { | ||
57 | DistrictSearchDo, | 57 | DistrictSearchDo, |
58 | Dto, | 58 | Dto, |
59 | ExchangeIntegralDto, | 59 | ExchangeIntegralDto, |
60 | + ExchangeRecordsRequestDto, | ||
60 | FeedbackRegistrationDTO, | 61 | FeedbackRegistrationDTO, |
61 | InventoryMaterialStockReq, | 62 | InventoryMaterialStockReq, |
62 | InvoiceBatchDownloadDto, | 63 | InvoiceBatchDownloadDto, |
@@ -4732,6 +4733,77 @@ export const postIntegralQuerySumByUser = /* #__PURE__ */ (() => { | @@ -4732,6 +4733,77 @@ export const postIntegralQuerySumByUser = /* #__PURE__ */ (() => { | ||
4732 | return request; | 4733 | return request; |
4733 | })(); | 4734 | })(); |
4734 | 4735 | ||
4736 | +/** @description request parameter type for postIntegralUserExchangeRecords */ | ||
4737 | +export interface PostIntegralUserExchangeRecordsOption { | ||
4738 | + /** | ||
4739 | + * @description | ||
4740 | + * dto | ||
4741 | + */ | ||
4742 | + body: { | ||
4743 | + /** | ||
4744 | + @description | ||
4745 | + dto */ | ||
4746 | + dto: ExchangeRecordsRequestDto; | ||
4747 | + }; | ||
4748 | +} | ||
4749 | + | ||
4750 | +/** @description response type for postIntegralUserExchangeRecords */ | ||
4751 | +export interface PostIntegralUserExchangeRecordsResponse { | ||
4752 | + /** | ||
4753 | + * @description | ||
4754 | + * OK | ||
4755 | + */ | ||
4756 | + 200: ServerResult; | ||
4757 | + /** | ||
4758 | + * @description | ||
4759 | + * Created | ||
4760 | + */ | ||
4761 | + 201: any; | ||
4762 | + /** | ||
4763 | + * @description | ||
4764 | + * Unauthorized | ||
4765 | + */ | ||
4766 | + 401: any; | ||
4767 | + /** | ||
4768 | + * @description | ||
4769 | + * Forbidden | ||
4770 | + */ | ||
4771 | + 403: any; | ||
4772 | + /** | ||
4773 | + * @description | ||
4774 | + * Not Found | ||
4775 | + */ | ||
4776 | + 404: any; | ||
4777 | +} | ||
4778 | + | ||
4779 | +export type PostIntegralUserExchangeRecordsResponseSuccess = | ||
4780 | + PostIntegralUserExchangeRecordsResponse[200]; | ||
4781 | +/** | ||
4782 | + * @description | ||
4783 | + * 用户积分兑换记录 | ||
4784 | + * @tags 积分接口 | ||
4785 | + * @produces * | ||
4786 | + * @consumes application/json | ||
4787 | + */ | ||
4788 | +export const postIntegralUserExchangeRecords = /* #__PURE__ */ (() => { | ||
4789 | + const method = 'post'; | ||
4790 | + const url = '/integral/userExchangeRecords'; | ||
4791 | + function request( | ||
4792 | + option: PostIntegralUserExchangeRecordsOption, | ||
4793 | + ): Promise<PostIntegralUserExchangeRecordsResponseSuccess> { | ||
4794 | + return requester(request.url, { | ||
4795 | + method: request.method, | ||
4796 | + ...option, | ||
4797 | + }) as unknown as Promise<PostIntegralUserExchangeRecordsResponseSuccess>; | ||
4798 | + } | ||
4799 | + | ||
4800 | + /** http method */ | ||
4801 | + request.method = method; | ||
4802 | + /** request url */ | ||
4803 | + request.url = url; | ||
4804 | + return request; | ||
4805 | +})(); | ||
4806 | + | ||
4735 | /** @description request parameter type for postKingdeeRepCustomer */ | 4807 | /** @description request parameter type for postKingdeeRepCustomer */ |
4736 | export interface PostKingdeeRepCustomerOption { | 4808 | export interface PostKingdeeRepCustomerOption { |
4737 | /** | 4809 | /** |