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 | 17 | import { CHECK_TYPE } from '../Order/constant'; |
18 | 18 | import BalanceChangeRecordsModal from './components/BalanceChangeRecordsModal'; |
19 | 19 | import PointsExchangeModal from './components/PointsExchangeModal'; |
20 | +import PointsExchangeRecordsModal from './components/PointsExchangeRecordsModal'; | |
20 | 21 | import RechargePrepaymentModal from './components/RechargePrepaymentModal'; |
21 | 22 | import { |
22 | 23 | ACCOUNT_COLUMNS, |
... | ... | @@ -39,6 +40,10 @@ const PrepaidPage = () => { |
39 | 40 | ] = useState<boolean>(false); |
40 | 41 | const [pointsExchangeModalVisible, setPointsExchangeModalVisible] = |
41 | 42 | useState<boolean>(false); |
43 | + const [ | |
44 | + pointsExchangeRecordsModalVisible, | |
45 | + setPointsExchangeRecordsModalVisible, | |
46 | + ] = useState<boolean>(false); | |
42 | 47 | |
43 | 48 | const reloadPrepaidTable = () => { |
44 | 49 | prepaidActionRef.current?.reload(); |
... | ... | @@ -198,7 +203,7 @@ const PrepaidPage = () => { |
198 | 203 | valueType: 'option', |
199 | 204 | key: 'option', |
200 | 205 | fixed: 'right', |
201 | - width: 200, | |
206 | + width: 240, | |
202 | 207 | render: (text, record) => { |
203 | 208 | let btns = []; |
204 | 209 | btns.push( |
... | ... | @@ -227,6 +232,19 @@ const PrepaidPage = () => { |
227 | 232 | 消费记录 |
228 | 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 | 248 | return btns; |
231 | 249 | }, |
232 | 250 | }); |
... | ... | @@ -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 | 440 | </div> |
411 | 441 | ); |
412 | 442 | }; | ... | ... |
src/services/definition.ts
... | ... | @@ -1529,6 +1529,28 @@ export interface ExchangeIntegralDto { |
1529 | 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 | 1554 | export interface FilePathDto { |
1533 | 1555 | url?: string; |
1534 | 1556 | } | ... | ... |
src/services/request.ts
... | ... | @@ -57,6 +57,7 @@ import type { |
57 | 57 | DistrictSearchDo, |
58 | 58 | Dto, |
59 | 59 | ExchangeIntegralDto, |
60 | + ExchangeRecordsRequestDto, | |
60 | 61 | FeedbackRegistrationDTO, |
61 | 62 | InventoryMaterialStockReq, |
62 | 63 | InvoiceBatchDownloadDto, |
... | ... | @@ -4732,6 +4733,77 @@ export const postIntegralQuerySumByUser = /* #__PURE__ */ (() => { |
4732 | 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 | 4807 | /** @description request parameter type for postKingdeeRepCustomer */ |
4736 | 4808 | export interface PostKingdeeRepCustomerOption { |
4737 | 4809 | /** | ... | ... |