Commit 9535a1a245bc3526b71054e19e1f372c96b987ff

Authored by boyang
2 parents 9ceeb4da 16152a88

Merge branch 'dev' into 'master'

Dev



See merge request !42
.umirc.ts
@@ -130,11 +130,31 @@ export default defineConfig({ @@ -130,11 +130,31 @@ export default defineConfig({
130 ], 130 ],
131 }, 131 },
132 { 132 {
133 - name: '预存管理',  
134 - path: '/prepaidManage',  
135 - component: './Prepaid', 133 + name: '账户管理',
  134 + path: '/prepaid',
136 icon: 'AccountBookOutlined', 135 icon: 'AccountBookOutlined',
137 access: 'canReadAdminAndFinanceAndSales', 136 access: 'canReadAdminAndFinanceAndSales',
  137 + routes: [
  138 + {
  139 + path: '',
  140 + component: './Prepaid',
  141 + },
  142 + {
  143 + name: '预存充值',
  144 + path: 'recharge',
  145 + component: './Prepaid/PrepaidRecharge',
  146 + },
  147 + {
  148 + name: '账号列表',
  149 + path: 'account',
  150 + component: './Prepaid/PrepaidAccount',
  151 + },
  152 + {
  153 + name: '隐私钱包',
  154 + path: 'privatePocket',
  155 + component: './Prepaid/PrivatePocket',
  156 + },
  157 + ],
138 }, 158 },
139 { 159 {
140 name: '课题组管理', 160 name: '课题组管理',
src/pages/Order/Order/components/CheckModal.tsx
@@ -85,12 +85,37 @@ export default ({ @@ -85,12 +85,37 @@ export default ({
85 // data: { subOrderIds: subOrderIds }, 85 // data: { subOrderIds: subOrderIds },
86 // }); 86 // });
87 87
  88 + // 检查subOrders是否存在且有元素
  89 + if (!subOrders || !subOrders.length) {
  90 + // 如果是预存审核类型,直接返回,不需要处理售后信息
  91 + if (checkType(CHECK_TYPE.PREPAID_AUDIT)) {
  92 + return;
  93 + }
  94 +
  95 + // 对于其他类型,设置一个空的售后信息
  96 + setAfterSalesInfo(
  97 + <div className="my-5">
  98 + <Row gutter={[16, 24]}>
  99 + <Col span={24}>
  100 + <span>暂无售后信息</span>
  101 + </Col>
  102 + </Row>
  103 + </div>,
  104 + );
  105 + return;
  106 + }
  107 +
88 //附件 108 //附件
89 - let annex = subOrders[0].afterSalesAnnexList; 109 + let annex = subOrders[0]?.afterSalesAnnexList || [];
90 let index = 1; 110 let index = 1;
91 let annexLinks = annex?.map((f) => { 111 let annexLinks = annex?.map((f) => {
92 return ( 112 return (
93 - <Button className="p-0 pr-1" type="link" key="key" href={f}> 113 + <Button
  114 + className="p-0 pr-1"
  115 + type="link"
  116 + key={`annex-${index}`}
  117 + href={f}
  118 + >
94 {'附件' + index++} 119 {'附件' + index++}
95 </Button> 120 </Button>
96 ); 121 );
@@ -126,27 +151,36 @@ export default ({ @@ -126,27 +151,36 @@ export default ({
126 useEffect(() => { 151 useEffect(() => {
127 if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) { 152 if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) {
128 setAPopoverTitle('确认发货'); 153 setAPopoverTitle('确认发货');
  154 + } else if (checkType(CHECK_TYPE.PREPAID_AUDIT)) {
  155 + setAPopoverTitle('预存审核');
129 } 156 }
130 getOrderAfterSalesInfo(); 157 getOrderAfterSalesInfo();
131 158
132 let paymentReceiptsImagesList: any[] = []; 159 let paymentReceiptsImagesList: any[] = [];
133 subOrders?.forEach((item: any) => { 160 subOrders?.forEach((item: any) => {
134 - if (item.paymentReceiptAnnexList) {  
135 - paymentReceiptsImagesList.push(...item.paymentReceiptAnnexList); 161 + if (
  162 + item?.paymentReceiptsImages !== null &&
  163 + item?.paymentReceiptsImages !== undefined
  164 + ) {
  165 + paymentReceiptsImagesList.push(...item.paymentReceiptsImages);
136 } 166 }
137 }); 167 });
138 - //去重  
139 - paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)];  
140 setPymentReceiptsImages(paymentReceiptsImagesList); 168 setPymentReceiptsImages(paymentReceiptsImagesList);
141 169
142 - //预存审核的凭证  
143 let proofImages: any[] = []; 170 let proofImages: any[] = [];
  171 + // 从subOrders获取凭证图片
144 subOrders?.forEach((item) => { 172 subOrders?.forEach((item) => {
145 - let images = item.proofImages; 173 + let images = item?.proofImages;
146 if (images !== null && images !== undefined) { 174 if (images !== null && images !== undefined) {
147 proofImages.push(...images); 175 proofImages.push(...images);
148 } 176 }
149 }); 177 });
  178 +
  179 + // 对于预存审核,从data对象中获取凭证图片
  180 + if (checkType(CHECK_TYPE.PREPAID_AUDIT) && data?.proofImages) {
  181 + proofImages = [...data.proofImages];
  182 + }
  183 +
150 setPrepaidProofImages(proofImages); 184 setPrepaidProofImages(proofImages);
151 }, []); 185 }, []);
152 186
@@ -374,12 +408,25 @@ export default ({ @@ -374,12 +408,25 @@ export default ({
374 * @param body 408 * @param body
375 */ 409 */
376 async function doPrepaidAudit(body: any) { 410 async function doPrepaidAudit(body: any) {
377 - const data = await postPrepaidAudit({  
378 - data: body, 411 + // 确保传递了需要审核的记录ID
  412 + const auditData = {
  413 + ...body,
  414 + ids: [data?.id], // 使用当前记录的ID
  415 + checkPassOrReject: body.checkPassOrReject, // 通过或驳回
  416 + checkNotes: body.name, // 审核意见
  417 + };
  418 +
  419 + console.log('预存审核参数:', auditData);
  420 +
  421 + const result = await postPrepaidAudit({
  422 + data: auditData,
379 }); 423 });
380 - if (data.result === RESPONSE_CODE.SUCCESS) {  
381 - message.success(data.message); 424 +
  425 + if (result.result === RESPONSE_CODE.SUCCESS) {
  426 + message.success(result.message);
382 onClose(); 427 onClose();
  428 + } else {
  429 + message.error(result.message || '审核失败');
383 } 430 }
384 } 431 }
385 432
src/pages/Order/OrderList/OrderDrawer.tsx
@@ -3,6 +3,7 @@ import { @@ -3,6 +3,7 @@ import {
3 postCanrdApiUserAddressList, 3 postCanrdApiUserAddressList,
4 postCanrdApiUserDetail, 4 postCanrdApiUserDetail,
5 postCanrdApiUserNowMoneyCheck, 5 postCanrdApiUserNowMoneyCheck,
  6 + postCanrdPrivatePocketPrivateMoneyCheck,
6 postDistrictSelectByLevel, 7 postDistrictSelectByLevel,
7 postDistrictSelectByNameAndLevel, 8 postDistrictSelectByNameAndLevel,
8 postDistrictSelOrderProvince, 9 postDistrictSelOrderProvince,
@@ -230,7 +231,11 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -230,7 +231,11 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
230 231
231 // 查询当前手机号允许使用的预存账号 232 // 查询当前手机号允许使用的预存账号
232 if (phone) { 233 if (phone) {
233 - let res = await postPrepaidPhoneAvailableList({ data: { phone: phone } }); 234 + // 从表单中获取 salesCode
  235 + const salesCode = form.getFieldValue('salesCode');
  236 + let res = await postPrepaidPhoneAvailableList({
  237 + data: { phone: phone, salesCode: salesCode },
  238 + });
234 if (res && res.result === RESPONSE_CODE.SUCCESS) { 239 if (res && res.result === RESPONSE_CODE.SUCCESS) {
235 let uidDetails = res.data; 240 let uidDetails = res.data;
236 for (let detail of uidDetails) { 241 for (let detail of uidDetails) {
@@ -644,6 +649,41 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -644,6 +649,41 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
644 }; 649 };
645 650
646 /** 651 /**
  652 + * 检查隐私钱包余额
  653 + * @param uid 用户ID
  654 + * @param phone 手机号
  655 + * @param subPrice 金额
  656 + */
  657 + const checkPrivateWalletMoney = async (
  658 + uid: any,
  659 + phone: any,
  660 + subPrice: any,
  661 + ) => {
  662 + let res = await postCanrdPrivatePocketPrivateMoneyCheck({
  663 + data: { uid: uid, phone: phone, subPrice: subPrice },
  664 + });
  665 + if (res && res.result === RESPONSE_CODE.SUCCESS && res.data) {
  666 + let data = res.data;
  667 + let isEnough = data.isEnough;
  668 + if (isEnough) {
  669 + return true;
  670 + }
  671 +
  672 + message.error(
  673 + '隐私钱包余额不足,当前预减的金额为:' +
  674 + data.subPrice +
  675 + ',当前隐私钱包余额为:' +
  676 + data.privateMoney,
  677 + );
  678 + return false;
  679 + }
  680 +
  681 + return false;
  682 + };
  683 +
  684 + // 已在prepaidUid字段的onChange处理器中直接实现账户选择逻辑
  685 +
  686 + /**
647 * 总金额改变触发事件 687 * 总金额改变触发事件
648 * 如果是预存单,需要检查余额 688 * 如果是预存单,需要检查余额
649 * @param value 689 * @param value
@@ -890,9 +930,44 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -890,9 +930,44 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
890 if (typeof values.erpCustomerId !== 'string') { 930 if (typeof values.erpCustomerId !== 'string') {
891 values.erpCustomerId = values.erpCustomerId?.id; 931 values.erpCustomerId = values.erpCustomerId?.id;
892 } 932 }
893 - values.province = province;  
894 - values.city = city;  
895 - values.district = district; 933 +
  934 + // Handle the prepaidUid and privatePocket values for API submission
  935 + if (
  936 + values.paymentMethod === 'WITHHOLDING_ADVANCE_DEPOSIT' &&
  937 + values.prepaidUid
  938 + ) {
  939 + console.log('5656原始表单数据:', {
  940 + prepaidUid: values.prepaidUid,
  941 + realPrepaidUid: values.realPrepaidUid,
  942 + privatePocket: values.privatePocket,
  943 + });
  944 +
  945 + // 从选项值中提取原始UID (不包含索引后缀)
  946 + const prepaidUidParts = values.prepaidUid.split('_');
  947 + if (prepaidUidParts.length > 0) {
  948 + // 直接使用第一部分作为实际UID值 (不使用realPrepaidUid)
  949 + values.prepaidUid = parseInt(prepaidUidParts[0], 10);
  950 + console.log('5656使用原始UID进行API提交:', values.prepaidUid);
  951 + }
  952 +
  953 + // 确保privatePocket字段被正确设置
  954 + // 表单中存储的是字符串'true'或'false',需要转换成布尔值
  955 + if (values.privatePocket === 'true') {
  956 + values.privatePocket = true;
  957 + console.log('设置privatePocket=true用于API提交');
  958 + } else {
  959 + values.privatePocket = false;
  960 + console.log('设置privatePocket=false用于API提交');
  961 + }
  962 +
  963 + console.log('最终API提交数据:', {
  964 + prepaidUid: values.prepaidUid,
  965 + privatePocket: values.privatePocket,
  966 + });
  967 + }
  968 +
  969 + console.log(values, '5656values');
  970 +
896 //新增 971 //新增
897 if (optType('add') || optType('copy')) { 972 if (optType('add') || optType('copy')) {
898 res = await postServiceOrderAddOrder({ data: values }); 973 res = await postServiceOrderAddOrder({ data: values });
@@ -1709,6 +1784,10 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1709,6 +1784,10 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1709 rules={[{ required: true, message: '支付方式必填' }]} 1784 rules={[{ required: true, message: '支付方式必填' }]}
1710 disabled={optType('after-sales-check')} 1785 disabled={optType('after-sales-check')}
1711 /> 1786 />
  1787 + {/* 隐藏字段用于存储真实UID和privatePocket标志 */}
  1788 + <ProFormText name="realPrepaidUid" hidden />
  1789 + <ProFormText name="privatePocket" hidden />
  1790 +
1712 <ProFormSelect 1791 <ProFormSelect
1713 name="prepaidUid" 1792 name="prepaidUid"
1714 key="prepaidUid" 1793 key="prepaidUid"
@@ -1716,15 +1795,66 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1716,15 +1795,66 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1716 hidden={paymentMethod !== 'WITHHOLDING_ADVANCE_DEPOSIT'} 1795 hidden={paymentMethod !== 'WITHHOLDING_ADVANCE_DEPOSIT'}
1717 showSearch 1796 showSearch
1718 label="预存账号" 1797 label="预存账号"
1719 - onChange={(value: any) => {  
1720 - //检查用户额度  
1721 - let valid = checkAccountMoney(  
1722 - value,  
1723 - form.getFieldValue('totalPayment'),  
1724 - ); 1798 + onChange={async (value: any, option: any) => {
  1799 + console.log(value, '5656value');
  1800 + console.log(option, '5656option');
  1801 +
  1802 + if (!option) {
  1803 + form.setFieldValue('prepaidUid', undefined);
  1804 + form.setFieldValue('privatePocket', false);
  1805 + return;
  1806 + }
  1807 +
  1808 + // 从选项中获取真实UID和机构信息
  1809 + const selectedData = option || {};
  1810 + const realUid = selectedData.uid;
  1811 + const institution = selectedData.institution;
  1812 + const phone = selectedData.phone;
  1813 +
  1814 + console.log('选中账户信息:', {
  1815 + value: value,
  1816 + realUid: realUid,
  1817 + institution: institution,
  1818 + phone: phone,
  1819 + });
  1820 +
  1821 + // 检查是否是隐私钱包
  1822 + const isPrivacyWallet = institution === '隐私钱包';
  1823 + const totalPayment = form.getFieldValue('totalPayment');
  1824 + let valid;
  1825 +
  1826 + if (isPrivacyWallet) {
  1827 + // 使用隐私钱包检查方式
  1828 + valid = await checkPrivateWalletMoney(
  1829 + realUid,
  1830 + phone,
  1831 + totalPayment,
  1832 + );
  1833 + } else {
  1834 + // 使用普通账户检查方式
  1835 + valid = await checkAccountMoney(realUid, totalPayment);
  1836 + }
  1837 +
1725 if (!valid) { 1838 if (!valid) {
1726 form.setFieldValue('prepaidUid', undefined); 1839 form.setFieldValue('prepaidUid', undefined);
  1840 + form.setFieldValue('privatePocket', false);
  1841 + return;
1727 } 1842 }
  1843 +
  1844 + // 设置真实UID和privatePocket标志
  1845 + form.setFieldValue('realPrepaidUid', realUid);
  1846 + // 存储为字符串'true'或'false',这样在表单中能正确保存
  1847 + form.setFieldValue(
  1848 + 'privatePocket',
  1849 + isPrivacyWallet ? 'true' : 'false',
  1850 + );
  1851 +
  1852 + console.log('设置表单数据:', {
  1853 + prepaidUid: value,
  1854 + realPrepaidUid: realUid,
  1855 + privatePocket: isPrivacyWallet,
  1856 + accountType: isPrivacyWallet ? '隐私钱包' : '普通账户',
  1857 + });
1728 }} 1858 }}
1729 placeholder="请选择预存账号" 1859 placeholder="请选择预存账号"
1730 rules={[ 1860 rules={[
@@ -1770,7 +1900,17 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1770,7 +1900,17 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1770 // }); 1900 // });
1771 // return options; 1901 // return options;
1772 // }} 1902 // }}
1773 - options={accountOptions} 1903 + options={accountOptions.map((item, index) => ({
  1904 + ...item,
  1905 + // Use index to create unique value
  1906 + value: `${item.value}_${index}`,
  1907 + // Store original values as custom attributes
  1908 + data: {
  1909 + uid: item.value,
  1910 + institution: item.institution,
  1911 + index: index,
  1912 + },
  1913 + }))}
1774 /> 1914 />
1775 <ProFormSelect 1915 <ProFormSelect
1776 placeholder="选择是否需要开票" 1916 placeholder="选择是否需要开票"
src/pages/Prepaid/PrepaidAccount/index.less 0 → 100644
  1 +.prepaid-account {
  2 + width: 100%;
  3 + padding: 24px;
  4 +
  5 + td {
  6 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  7 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  8 + 'WenQuanYi Micro Hei', sans-serif;
  9 + font-size: 13px;
  10 + }
  11 +}
src/pages/Prepaid/PrepaidAccount/index.tsx 0 → 100644
  1 +import EllipsisDiv from '@/components/Div/EllipsisDiv';
  2 +import { postCanrdApiUserList } from '@/services';
  3 +import { getUserInfo } from '@/utils/user';
  4 +import { ActionType, ProTable } from '@ant-design/pro-components';
  5 +import { Button } from 'antd';
  6 +import { useRef, useState } from 'react';
  7 +import BalanceChangeRecordsModal from '../components/BalanceChangeRecordsModal';
  8 +import PointsExchangeModal from '../components/PointsExchangeModal';
  9 +import PointsExchangeRecordsModal from '../components/PointsExchangeRecordsModal';
  10 +import { ACCOUNT_COLUMNS } from '../constant';
  11 +import './index.less';
  12 +
  13 +const PrepaidAccountPage = () => {
  14 + const user = getUserInfo();
  15 + const accountActionRef = useRef<ActionType>();
  16 + const [currentOptUserObj, setCurrentOptUserObj] = useState(null);
  17 + const [
  18 + balanceChangeRecordsModalVisible,
  19 + setBalanceChangeRecordsModalVisible,
  20 + ] = useState<boolean>(false);
  21 + const [pointsExchangeModalVisible, setPointsExchangeModalVisible] =
  22 + useState<boolean>(false);
  23 + const [
  24 + pointsExchangeRecordsModalVisible,
  25 + setPointsExchangeRecordsModalVisible,
  26 + ] = useState<boolean>(false);
  27 +
  28 + const reloadAccountTable = () => {
  29 + accountActionRef.current?.reload();
  30 + };
  31 +
  32 + const getTableCellText = (target: any) => {
  33 + if (!target) {
  34 + return '';
  35 + }
  36 +
  37 + if (target.props) {
  38 + return target.props.text;
  39 + }
  40 +
  41 + return target;
  42 + };
  43 +
  44 + const accountColumnsInit = () => {
  45 + let columns = ACCOUNT_COLUMNS.map((item) => {
  46 + let newItem = { ...item };
  47 + let dataIndex = item.dataIndex;
  48 +
  49 + newItem.render = (text, record) => {
  50 + let textValue = record[dataIndex];
  51 + return <EllipsisDiv text={getTableCellText(textValue)} />;
  52 + };
  53 +
  54 + return newItem;
  55 + });
  56 +
  57 + columns.push({
  58 + title: '操作',
  59 + valueType: 'option',
  60 + key: 'option',
  61 + fixed: 'right',
  62 + width: 240,
  63 + render: (text, record) => {
  64 + let btns = [];
  65 + btns.push(
  66 + <Button
  67 + className="p-0 ml-2"
  68 + key="points"
  69 + type="link"
  70 + onClick={() => {
  71 + setCurrentOptUserObj(record);
  72 + setPointsExchangeModalVisible(true);
  73 + }}
  74 + >
  75 + 积分兑换
  76 + </Button>,
  77 + );
  78 + btns.push(
  79 + <Button
  80 + className="p-0"
  81 + key="view"
  82 + type="link"
  83 + onClick={() => {
  84 + setCurrentOptUserObj(record);
  85 + setBalanceChangeRecordsModalVisible(true);
  86 + }}
  87 + >
  88 + 消费记录
  89 + </Button>,
  90 + );
  91 + btns.push(
  92 + <Button
  93 + className="p-0 ml-2"
  94 + key="pointsRecords"
  95 + type="link"
  96 + onClick={() => {
  97 + setCurrentOptUserObj(record);
  98 + setPointsExchangeRecordsModalVisible(true);
  99 + }}
  100 + >
  101 + 积分兑换记录
  102 + </Button>,
  103 + );
  104 + return btns;
  105 + },
  106 + });
  107 +
  108 + return columns;
  109 + };
  110 +
  111 + return (
  112 + <div className="prepaid-account">
  113 + <ProTable
  114 + columns={accountColumnsInit()}
  115 + actionRef={accountActionRef}
  116 + cardBordered
  117 + pagination={{
  118 + pageSize: 10,
  119 + }}
  120 + request={async (params) => {
  121 + const res = await postCanrdApiUserList({
  122 + data: { ...params },
  123 + });
  124 + const data = res?.data?.data || [];
  125 + const targetPhones = [
  126 + '18550286106',
  127 + '15286038815',
  128 + '15202597163',
  129 + '13267086260',
  130 + '15900392469',
  131 + '13529047645',
  132 + ];
  133 +
  134 + const processedData = data.map((item) => {
  135 + const isAdmin = user.roles.includes('ADMIN');
  136 + const isSalesManager = user.roles.includes('SALES_MANAGER');
  137 + if (
  138 + targetPhones.includes(item.phone) &&
  139 + !(isAdmin || isSalesManager)
  140 + ) {
  141 + return {
  142 + ...item,
  143 + nowMoney: '****',
  144 + };
  145 + }
  146 + return item;
  147 + });
  148 + return {
  149 + data: processedData,
  150 + total: res?.data?.total || 0,
  151 + };
  152 + }}
  153 + columnsState={{
  154 + persistenceKey: 'pro-table-singe-account',
  155 + persistenceType: 'localStorage',
  156 + defaultValue: {
  157 + option: { fixed: 'right', disable: true },
  158 + },
  159 + onChange(value) {
  160 + console.log('value: ', value);
  161 + },
  162 + }}
  163 + rowKey="id"
  164 + search={{
  165 + labelWidth: 'auto',
  166 + }}
  167 + options={{
  168 + setting: {
  169 + listsHeight: 400,
  170 + },
  171 + }}
  172 + form={{}}
  173 + dateFormatter="string"
  174 + headerTitle="账号列表"
  175 + scroll={{ x: 1400 }}
  176 + toolBarRender={() => []}
  177 + />
  178 +
  179 + {balanceChangeRecordsModalVisible && (
  180 + <BalanceChangeRecordsModal
  181 + setVisible={setBalanceChangeRecordsModalVisible}
  182 + userInfoObj={currentOptUserObj}
  183 + onClose={() => {
  184 + setBalanceChangeRecordsModalVisible(false);
  185 + reloadAccountTable();
  186 + }}
  187 + />
  188 + )}
  189 +
  190 + {pointsExchangeModalVisible && (
  191 + <PointsExchangeModal
  192 + setVisible={setPointsExchangeModalVisible}
  193 + userInfoObj={
  194 + currentOptUserObj
  195 + ? { ...currentOptUserObj, relationEntityType: 'USER' }
  196 + : { uid: '', relationEntityType: 'USER' }
  197 + }
  198 + onClose={() => {
  199 + setPointsExchangeModalVisible(false);
  200 + reloadAccountTable();
  201 + }}
  202 + />
  203 + )}
  204 +
  205 + {pointsExchangeRecordsModalVisible && (
  206 + <PointsExchangeRecordsModal
  207 + setVisible={setPointsExchangeRecordsModalVisible}
  208 + userInfoObj={
  209 + currentOptUserObj
  210 + ? { ...currentOptUserObj, relationEntityType: 'USER' }
  211 + : { uid: '', relationEntityType: 'USER' }
  212 + }
  213 + onClose={() => {
  214 + setPointsExchangeRecordsModalVisible(false);
  215 + }}
  216 + />
  217 + )}
  218 + </div>
  219 + );
  220 +};
  221 +
  222 +export default PrepaidAccountPage;
src/pages/Prepaid/PrepaidRecharge/index.less 0 → 100644
  1 +.prepaid-recharge {
  2 + width: 100%;
  3 + padding: 24px;
  4 +
  5 + td {
  6 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  7 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  8 + 'WenQuanYi Micro Hei', sans-serif;
  9 + font-size: 13px;
  10 + }
  11 +}
src/pages/Prepaid/PrepaidRecharge/index.tsx 0 → 100644
  1 +import ButtonConfirm from '@/components/ButtomConfirm';
  2 +import EllipsisDiv from '@/components/Div/EllipsisDiv';
  3 +import { RESPONSE_CODE } from '@/constants/enum';
  4 +import { postPrepaidDelete, postPrepaidList } from '@/services';
  5 +import { enumValueToLabel, formatDateTime } from '@/utils';
  6 +import { PlusOutlined } from '@ant-design/icons';
  7 +import { ActionType, ProTable } from '@ant-design/pro-components';
  8 +import { Button, Divider, Image, message } from 'antd';
  9 +import { cloneDeep } from 'lodash';
  10 +import React, { useRef, useState } from 'react';
  11 +import CheckModal from '../../Order/Order/components/CheckModal';
  12 +import { CHECK_TYPE } from '../../Order/constant';
  13 +import RechargePrepaymentModal from '../components/RechargePrepaymentModal';
  14 +import {
  15 + PREPAID_STATUS_OPTIONS,
  16 + SALES_RECHARGE_PREPAYMENT_COLUMNS,
  17 +} from '../constant';
  18 +import './index.less';
  19 +
  20 +const PrepaidRechargePage = () => {
  21 + const prepaidActionRef = useRef<ActionType>();
  22 + const [rechargePrepaymentModalVisible, setRechargePrepaymentModalVisible] =
  23 + useState<boolean>(false);
  24 + const [currentOptPrepaymentObj, setCurrentOptPrepaymentObj] = useState(null);
  25 + const [checkVisible, setCheckVisible] = useState<boolean>(false);
  26 +
  27 + const reloadPrepaidTable = () => {
  28 + prepaidActionRef.current?.reload();
  29 + };
  30 +
  31 + /**
  32 + * 加载预存充值表格的各个列格式
  33 + */
  34 + const prepaidColumnsInit = () => {
  35 + let columns = SALES_RECHARGE_PREPAYMENT_COLUMNS.map((item) => {
  36 + let newItem = { ...item };
  37 + let dataIndex = item.dataIndex;
  38 +
  39 + newItem.render = (text, record) => {
  40 + let textValue = record[dataIndex];
  41 +
  42 + if (dataIndex === 'status') {
  43 + textValue = enumValueToLabel(textValue, PREPAID_STATUS_OPTIONS);
  44 + }
  45 +
  46 + if (dataIndex.endsWith('Time')) {
  47 + textValue = formatDateTime(textValue);
  48 + }
  49 +
  50 + if (
  51 + dataIndex === 'proofImages' &&
  52 + textValue !== null &&
  53 + textValue !== undefined
  54 + ) {
  55 + return (
  56 + <Image.PreviewGroup
  57 + className="mr-10"
  58 + preview={{
  59 + onChange: (current, prev) =>
  60 + console.log(`current index: ${current}, prev index: ${prev}`),
  61 + }}
  62 + >
  63 + {textValue.map((item, index) => (
  64 + <React.Fragment key={index}>
  65 + {index > 0 ? <Divider type="vertical" /> : ''}
  66 + <Image
  67 + className="max-h-[35px] max-w-[45px]"
  68 + src={item}
  69 + title={item}
  70 + />{' '}
  71 + </React.Fragment>
  72 + ))}
  73 + </Image.PreviewGroup>
  74 + );
  75 + }
  76 +
  77 + return <EllipsisDiv text={textValue} />;
  78 + };
  79 +
  80 + return newItem;
  81 + });
  82 +
  83 + columns.push({
  84 + title: '操作',
  85 + valueType: 'option',
  86 + key: 'option',
  87 + fixed: 'right',
  88 + width: 120,
  89 + render: (text, record) => {
  90 + let btns = [];
  91 + let opts = record.operations;
  92 + if (opts?.includes('modify')) {
  93 + btns.push(
  94 + <Button
  95 + className="p-0"
  96 + key="modify"
  97 + type="link"
  98 + onClick={() => {
  99 + setRechargePrepaymentModalVisible(true);
  100 + setCurrentOptPrepaymentObj(cloneDeep(record));
  101 + }}
  102 + >
  103 + 编辑
  104 + </Button>,
  105 + );
  106 + }
  107 +
  108 + if (opts?.includes('audit')) {
  109 + btns.push(
  110 + <Button
  111 + className="p-0"
  112 + key="view"
  113 + type="link"
  114 + onClick={() => {
  115 + setCurrentOptPrepaymentObj(record);
  116 + setCheckVisible(true);
  117 + }}
  118 + >
  119 + 审核
  120 + </Button>,
  121 + );
  122 + }
  123 +
  124 + if (opts?.includes('delete')) {
  125 + btns.push(
  126 + <ButtonConfirm
  127 + key="delete"
  128 + className="p-0"
  129 + title={'确认删除这条预存记录吗?'}
  130 + text="删除"
  131 + onConfirm={async () => {
  132 + let res = await postPrepaidDelete({
  133 + data: { ids: [record.id] },
  134 + });
  135 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  136 + message.success(res.message);
  137 + reloadPrepaidTable();
  138 + }
  139 + }}
  140 + />,
  141 + );
  142 + }
  143 + return btns;
  144 + },
  145 + });
  146 +
  147 + return columns;
  148 + };
  149 +
  150 + return (
  151 + <div className="prepaid-recharge">
  152 + <ProTable
  153 + columns={prepaidColumnsInit()}
  154 + actionRef={prepaidActionRef}
  155 + cardBordered
  156 + pagination={{
  157 + pageSize: 10,
  158 + }}
  159 + request={async (params) => {
  160 + const res = await postPrepaidList({
  161 + data: { ...params },
  162 + });
  163 + return {
  164 + data: res?.data?.data || [],
  165 + total: res?.data?.total || 0,
  166 + };
  167 + }}
  168 + columnsState={{
  169 + persistenceKey: 'pro-table-singe-prepaid',
  170 + persistenceType: 'localStorage',
  171 + defaultValue: {
  172 + option: { fixed: 'right', disable: true },
  173 + },
  174 + onChange(value) {
  175 + console.log('value: ', value);
  176 + },
  177 + }}
  178 + rowKey="id"
  179 + search={{
  180 + labelWidth: 'auto',
  181 + }}
  182 + options={{
  183 + setting: {
  184 + listsHeight: 400,
  185 + },
  186 + }}
  187 + form={{}}
  188 + dateFormatter="string"
  189 + headerTitle="预存充值"
  190 + scroll={{ x: 1400 }}
  191 + toolBarRender={() => [
  192 + <Button
  193 + key="button"
  194 + icon={<PlusOutlined />}
  195 + onClick={() => {
  196 + setCurrentOptPrepaymentObj(null);
  197 + setRechargePrepaymentModalVisible(true);
  198 + }}
  199 + type="primary"
  200 + >
  201 + 新增充值
  202 + </Button>,
  203 + ]}
  204 + />
  205 +
  206 + {rechargePrepaymentModalVisible && (
  207 + <RechargePrepaymentModal
  208 + setVisible={setRechargePrepaymentModalVisible}
  209 + prepaymentObject={currentOptPrepaymentObj}
  210 + onClose={() => {
  211 + setRechargePrepaymentModalVisible(false);
  212 + reloadPrepaidTable();
  213 + }}
  214 + />
  215 + )}
  216 +
  217 + {checkVisible && (
  218 + <CheckModal
  219 + setCheckVisible={setCheckVisible}
  220 + data={currentOptPrepaymentObj}
  221 + subOrders={[]}
  222 + orderCheckType={CHECK_TYPE.PREPAID_AUDIT}
  223 + openOrderDrawer={null}
  224 + onClose={() => {
  225 + setCheckVisible(false);
  226 + reloadPrepaidTable();
  227 + }}
  228 + />
  229 + )}
  230 + </div>
  231 + );
  232 +};
  233 +
  234 +export default PrepaidRechargePage;
src/pages/Prepaid/PrivatePocket/components/AddPrivatePocketModal.tsx 0 → 100644
  1 +import {
  2 + postCanrdApiUserList,
  3 + postCanrdPrivatePocketSave,
  4 + postServiceOrderQuerySalesCode,
  5 +} from '@/services';
  6 +import { getUserInfo } from '@/utils/user';
  7 +import { Form, Modal, Select, message } from 'antd';
  8 +import React, { useEffect, useRef, useState } from 'react';
  9 +
  10 +interface AddPrivatePocketModalProps {
  11 + visible: boolean;
  12 + onCancel: () => void;
  13 + onSuccess: () => void;
  14 +}
  15 +
  16 +interface SalesCodeItem {
  17 + number: string | null;
  18 + userName: string;
  19 +}
  20 +
  21 +interface UserItem {
  22 + uid: string;
  23 + realName: string;
  24 + institution?: string;
  25 + nowMoney?: string | number;
  26 + phone: string;
  27 + [key: string]: any;
  28 +}
  29 +
  30 +const AddPrivatePocketModal: React.FC<AddPrivatePocketModalProps> = ({
  31 + visible,
  32 + onCancel,
  33 + onSuccess,
  34 +}) => {
  35 + const [form] = Form.useForm();
  36 + const [salesCodeList, setSalesCodeList] = useState<SalesCodeItem[]>([]);
  37 + const [loading, setLoading] = useState<boolean>(false);
  38 + const [userList, setUserList] = useState<any[]>([]);
  39 + const [searchKeywords, setSearchKeywords] = useState<string>('');
  40 + const userInfo = getUserInfo();
  41 + const userName = userInfo?.username || '';
  42 + const searchTimerRef = useRef<any>(null);
  43 +
  44 + const fetchSalesCodeList = async () => {
  45 + try {
  46 + const res = await postServiceOrderQuerySalesCode();
  47 + if (res?.data) {
  48 + setSalesCodeList(res.data);
  49 + }
  50 + } catch (error) {
  51 + console.error('获取销售编码列表失败:', error);
  52 + message.error('获取销售编码列表失败');
  53 + }
  54 + };
  55 +
  56 + // Define a function to fetch user list that can be called from multiple places
  57 + const fetchUserList = async (keywords: string) => {
  58 + try {
  59 + if (!keywords || keywords.trim() === '') {
  60 + return [];
  61 + }
  62 +
  63 + const res = await postCanrdApiUserList({
  64 + data: { keywords: keywords, pageSize: 1000000 },
  65 + });
  66 +
  67 + if (res?.data?.data) {
  68 + setUserList(res.data.data);
  69 + }
  70 + return res?.data?.data || [];
  71 + } catch (error) {
  72 + console.error('获取用户列表失败:', error);
  73 + return [];
  74 + }
  75 + };
  76 +
  77 + // Initial fetch when component mounts
  78 + useEffect(() => {
  79 + if (visible) {
  80 + fetchUserList('');
  81 + }
  82 + }, [visible]);
  83 +
  84 + useEffect(() => {
  85 + if (visible) {
  86 + fetchSalesCodeList();
  87 + form.resetFields();
  88 + }
  89 + }, [visible, form]);
  90 +
  91 + const handleSubmit = async () => {
  92 + try {
  93 + const values = await form.validateFields();
  94 + setLoading(true);
  95 +
  96 + const res = await postCanrdPrivatePocketSave({
  97 + data: {
  98 + account: values.account,
  99 + salesCode: values.salesCode,
  100 + createByName: userName,
  101 + },
  102 + });
  103 +
  104 + if (res?.result === 0 || res?.code === 200 || res?.success) {
  105 + message.success('添加隐私钱包成功');
  106 + onSuccess();
  107 + } else {
  108 + message.error(res?.message || '添加失败');
  109 + }
  110 + } catch (error) {
  111 + console.error('添加隐私钱包失败:', error);
  112 + } finally {
  113 + setLoading(false);
  114 + }
  115 + };
  116 +
  117 + // Function to handle search with debounce
  118 + const handleSearch = (value: string) => {
  119 + setSearchKeywords(value);
  120 +
  121 + // Clear any existing timer
  122 + if (searchTimerRef.current) {
  123 + clearTimeout(searchTimerRef.current);
  124 + }
  125 +
  126 + // Set a new timer to fetch users after 1000ms of inactivity
  127 + searchTimerRef.current = setTimeout(() => {
  128 + fetchUserList(value);
  129 + }, 1000);
  130 + };
  131 +
  132 + return (
  133 + <Modal
  134 + title="添加隐私钱包"
  135 + open={visible}
  136 + onCancel={onCancel}
  137 + onOk={handleSubmit}
  138 + confirmLoading={loading}
  139 + destroyOnClose
  140 + >
  141 + <Form form={form} layout="vertical">
  142 + <Form.Item
  143 + name="account"
  144 + label="绑定普通账户"
  145 + rules={[{ required: true, message: '请选择账户' }]}
  146 + >
  147 + <Select
  148 + showSearch
  149 + placeholder="请选择账户"
  150 + optionFilterProp="children"
  151 + defaultActiveFirstOption={false}
  152 + notFoundContent={null}
  153 + filterOption={false} // Disable built-in filtering to use server-side search
  154 + onSearch={handleSearch} // Use the debounced search handler
  155 + onChange={(value) => {
  156 + // When a value is selected, find the corresponding phone from userList
  157 + // or use the value directly if it's a custom entry
  158 +
  159 + // Check if this is a custom entry (value is the same as searchKeywords)
  160 + if (value === searchKeywords && searchKeywords.trim() !== '') {
  161 + form.setFieldsValue({ account: searchKeywords });
  162 + return;
  163 + }
  164 +
  165 + // Find the selected user from userList to get their phone
  166 + const selectedUser = userList.find((user) => user.uid === value);
  167 + if (selectedUser && selectedUser.phone) {
  168 + form.setFieldsValue({ account: selectedUser.phone });
  169 + }
  170 + }}
  171 + dropdownRender={(menu) => (
  172 + <div>
  173 + {menu}
  174 + {searchKeywords.trim() !== '' && (
  175 + <div
  176 + style={{
  177 + padding: '8px',
  178 + cursor: 'pointer',
  179 + borderTop: '1px solid #e8e8e8',
  180 + }}
  181 + onClick={() => {
  182 + form.setFieldsValue({ account: searchKeywords });
  183 + }}
  184 + >
  185 + <span style={{ color: '#333333' }}>{searchKeywords}</span>
  186 + {' | '}
  187 + <span style={{ color: 'orange' }}>自定义</span>
  188 + </div>
  189 + )}
  190 + </div>
  191 + )}
  192 + >
  193 + {userList.map((user: UserItem) => {
  194 + const displayText = `${user.realName || '-'} | ${
  195 + user.institution || '-'
  196 + } | ${user.nowMoney || '0'}¥ | ${user.phone || '-'}`;
  197 + return (
  198 + <Select.Option
  199 + key={user.uid}
  200 + value={user.uid}
  201 + title={displayText}
  202 + >
  203 + <div>
  204 + <span>{displayText}</span>
  205 + </div>
  206 + </Select.Option>
  207 + );
  208 + })}
  209 + </Select>
  210 + </Form.Item>
  211 + <Form.Item
  212 + name="salesCode"
  213 + label="负责销售"
  214 + rules={[{ required: true, message: '请选择负责销售' }]}
  215 + >
  216 + <Select
  217 + placeholder="请选择负责销售"
  218 + showSearch
  219 + optionFilterProp="children"
  220 + filterOption={(input, option) =>
  221 + (option?.label?.toString() || '')
  222 + .toLowerCase()
  223 + .includes(input.toLowerCase())
  224 + }
  225 + options={salesCodeList.map((item) => ({
  226 + value: item.userName,
  227 + label: item.userName,
  228 + }))}
  229 + />
  230 + </Form.Item>
  231 + </Form>
  232 + </Modal>
  233 + );
  234 +};
  235 +
  236 +export default AddPrivatePocketModal;
src/pages/Prepaid/PrivatePocket/constant.tsx 0 → 100644
  1 +export const PRIVATE_POCKET_COLUMNS = [
  2 + {
  3 + title: '用户ID',
  4 + dataIndex: 'uid',
  5 + key: 'uid',
  6 + valueType: 'text',
  7 + hideInTable: true,
  8 + hideInSearch: true,
  9 + },
  10 + {
  11 + title: '普通账户',
  12 + dataIndex: 'account',
  13 + key: 'account',
  14 + valueType: 'text',
  15 + fieldProps: {
  16 + placeholder: '请输入用户账号',
  17 + },
  18 + },
  19 + {
  20 + title: '老师姓名',
  21 + dataIndex: 'realName',
  22 + key: 'realName',
  23 + valueType: 'text',
  24 + hideInSearch: true,
  25 + },
  26 + {
  27 + title: '普通账户余额',
  28 + dataIndex: 'nowMoney',
  29 + key: 'nowMoney',
  30 + valueType: 'money',
  31 + hideInSearch: true,
  32 + },
  33 + {
  34 + title: '隐私钱包余额',
  35 + dataIndex: 'privateMoney',
  36 + key: 'privateMoney',
  37 + valueType: 'money',
  38 + hideInSearch: true,
  39 + },
  40 + {
  41 + title: '负责销售',
  42 + dataIndex: 'salesCode',
  43 + key: 'salesCode',
  44 + valueType: 'text',
  45 + fieldProps: {
  46 + placeholder: '请输入负责销售',
  47 + },
  48 + },
  49 + {
  50 + title: '创建时间',
  51 + dataIndex: 'createTime',
  52 + key: 'createTime',
  53 + valueType: 'dateTime',
  54 + hideInSearch: true,
  55 + },
  56 + {
  57 + title: '创建人',
  58 + dataIndex: 'createByName',
  59 + key: 'createByName',
  60 + valueType: 'text',
  61 + hideInSearch: true,
  62 + },
  63 + // {
  64 + // title: '更新时间',
  65 + // dataIndex: 'updateTime',
  66 + // key: 'updateTime',
  67 + // valueType: 'dateTime',
  68 + // hideInSearch: true,
  69 + // },
  70 +];
src/pages/Prepaid/PrivatePocket/index.less 0 → 100644
  1 +.private-pocket-index {
  2 + width: 100%;
  3 + padding: 24px;
  4 +
  5 + td {
  6 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  7 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  8 + 'WenQuanYi Micro Hei', sans-serif;
  9 + font-size: 13px;
  10 + }
  11 +}
src/pages/Prepaid/PrivatePocket/index.tsx 0 → 100644
  1 +import ButtonConfirm from '@/components/ButtomConfirm';
  2 +import EllipsisDiv from '@/components/Div/EllipsisDiv';
  3 +import { RESPONSE_CODE } from '@/constants/enum';
  4 +import {
  5 + postCanrdPrivatePocketDelete,
  6 + postCanrdPrivatePocketList,
  7 +} from '@/services';
  8 +import { formatDateTime } from '@/utils';
  9 +import { ActionType, ProTable } from '@ant-design/pro-components';
  10 +import { Button, message } from 'antd';
  11 +import { useRef, useState } from 'react';
  12 +import BalanceChangeRecordsModal from '../components/BalanceChangeRecordsModal';
  13 +import AddPrivatePocketModal from './components/AddPrivatePocketModal';
  14 +import { PRIVATE_POCKET_COLUMNS } from './constant';
  15 +import './index.less';
  16 +
  17 +const PrivatePocketPage = () => {
  18 + const actionRef = useRef<ActionType>();
  19 + const [addModalVisible, setAddModalVisible] = useState<boolean>(false);
  20 + const [currentOptRecord, setCurrentOptRecord] = useState(null);
  21 + const [
  22 + balanceChangeRecordsModalVisible,
  23 + setBalanceChangeRecordsModalVisible,
  24 + ] = useState<boolean>(false);
  25 +
  26 + const reloadTable = () => {
  27 + actionRef.current?.reload();
  28 + };
  29 +
  30 + const getTableCellText = (target: any) => {
  31 + if (!target) {
  32 + return '';
  33 + }
  34 +
  35 + if (target.props) {
  36 + return target.props.text;
  37 + }
  38 +
  39 + return target;
  40 + };
  41 +
  42 + const columnsInit = () => {
  43 + let columns = PRIVATE_POCKET_COLUMNS.map((item) => {
  44 + let newItem = { ...item };
  45 + let dataIndex = item.dataIndex;
  46 +
  47 + newItem.render = (text: any, record: any) => {
  48 + let textValue = record[dataIndex];
  49 +
  50 + if (dataIndex.endsWith('Time')) {
  51 + textValue = formatDateTime(textValue);
  52 + }
  53 +
  54 + return <EllipsisDiv text={getTableCellText(textValue)} />;
  55 + };
  56 +
  57 + return newItem;
  58 + });
  59 +
  60 + columns.push({
  61 + title: '操作',
  62 + valueType: 'option',
  63 + key: 'option',
  64 + width: 120,
  65 + render: (text: any, record: any) => {
  66 + let btns = [];
  67 +
  68 + btns.push(
  69 + <Button
  70 + className="p-0"
  71 + key="view"
  72 + type="link"
  73 + onClick={() => {
  74 + setCurrentOptRecord(record);
  75 + setBalanceChangeRecordsModalVisible(true);
  76 + }}
  77 + >
  78 + 消费记录
  79 + </Button>,
  80 + );
  81 +
  82 + btns.push(
  83 + <ButtonConfirm
  84 + key="delete"
  85 + className="p-0"
  86 + title={'确认删除这条隐私钱包记录吗?'}
  87 + text="删除"
  88 + onConfirm={async () => {
  89 + let res = await postCanrdPrivatePocketDelete({
  90 + data: { uid: record.uid },
  91 + });
  92 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  93 + message.success('删除成功');
  94 + reloadTable();
  95 + }
  96 + }}
  97 + />,
  98 + );
  99 +
  100 + return btns;
  101 + },
  102 + });
  103 +
  104 + return columns;
  105 + };
  106 +
  107 + return (
  108 + <div className="private-pocket-index">
  109 + <ProTable
  110 + columns={columnsInit()}
  111 + actionRef={actionRef}
  112 + cardBordered
  113 + pagination={{
  114 + pageSize: 10,
  115 + }}
  116 + request={async (params) => {
  117 + const res = await postCanrdPrivatePocketList({
  118 + data: { ...params },
  119 + });
  120 + const list = res?.data?.data || [];
  121 + return {
  122 + data: list,
  123 + success: true,
  124 + total: res?.data?.total || 0,
  125 + };
  126 + }}
  127 + columnsState={{
  128 + persistenceKey: 'pro-table-private-pocket',
  129 + persistenceType: 'localStorage',
  130 + defaultValue: {
  131 + option: { fixed: 'right', disable: true },
  132 + },
  133 + onChange(value) {
  134 + console.log('value: ', value);
  135 + },
  136 + }}
  137 + rowKey="uid"
  138 + search={{
  139 + labelWidth: 'auto',
  140 + }}
  141 + options={{
  142 + setting: {
  143 + listsHeight: 400,
  144 + },
  145 + }}
  146 + form={{}}
  147 + dateFormatter="string"
  148 + headerTitle="隐私钱包"
  149 + scroll={{ x: 1400 }}
  150 + toolBarRender={() => [
  151 + <Button
  152 + key="add"
  153 + type="primary"
  154 + onClick={() => setAddModalVisible(true)}
  155 + >
  156 + 添加
  157 + </Button>,
  158 + ]}
  159 + />
  160 +
  161 + {addModalVisible && (
  162 + <AddPrivatePocketModal
  163 + visible={addModalVisible}
  164 + onCancel={() => setAddModalVisible(false)}
  165 + onSuccess={() => {
  166 + setAddModalVisible(false);
  167 + reloadTable();
  168 + }}
  169 + />
  170 + )}
  171 +
  172 + {balanceChangeRecordsModalVisible && (
  173 + <BalanceChangeRecordsModal
  174 + setVisible={setBalanceChangeRecordsModalVisible}
  175 + userInfoObj={currentOptRecord}
  176 + onClose={() => {
  177 + setBalanceChangeRecordsModalVisible(false);
  178 + reloadTable();
  179 + }}
  180 + />
  181 + )}
  182 + </div>
  183 + );
  184 +};
  185 +
  186 +export default PrivatePocketPage;
src/pages/Prepaid/components/RechargePrepaymentModal.tsx
@@ -30,6 +30,7 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; { @@ -30,6 +30,7 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; {
30 salesCode: string; 30 salesCode: string;
31 rechargeAmount: number; 31 rechargeAmount: number;
32 notes: string; 32 notes: string;
  33 + rechargeType: string; // 充值类型
33 }>(); 34 }>();
34 const [salesCodeOptions, setSalesCodeOptions] = useState([]); 35 const [salesCodeOptions, setSalesCodeOptions] = useState([]);
35 const [isCreate, setIsCreate] = useState(true); 36 const [isCreate, setIsCreate] = useState(true);
@@ -243,6 +244,7 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; { @@ -243,6 +244,7 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; {
243 }, 244 },
244 }} 245 }}
245 onFinish={async (values) => { 246 onFinish={async (values) => {
  247 + // 所有充值类型都需要凭证
246 if (fileList.length <= 0) { 248 if (fileList.length <= 0) {
247 message.error('凭证不能为空'); 249 message.error('凭证不能为空');
248 return; 250 return;
@@ -278,6 +280,9 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; { @@ -278,6 +280,9 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; {
278 } 280 }
279 } 281 }
280 } 282 }
  283 + // 所有充值类型都传递rechargeType参数
  284 + // 所有充值类型都需要凭证
  285 + // 普通充值流程
281 let res = await postServiceOrderFileProcess({ 286 let res = await postServiceOrderFileProcess({
282 data: formData, 287 data: formData,
283 }); 288 });
@@ -302,6 +307,8 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; { @@ -302,6 +307,8 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; {
302 data: { 307 data: {
303 ...values, 308 ...values,
304 customerName: form.getFieldValue('customerNameString'), 309 customerName: form.getFieldValue('customerNameString'),
  310 + // 传递充值类型参数
  311 + rechargeType: values.rechargeType || 'normal',
305 }, 312 },
306 }); 313 });
307 } else { 314 } else {
@@ -312,7 +319,11 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; { @@ -312,7 +319,11 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; {
312 body.customerName = customerNameString; 319 body.customerName = customerNameString;
313 } 320 }
314 res = await postPrepaidUpdate({ 321 res = await postPrepaidUpdate({
315 - data: body, 322 + data: {
  323 + ...body,
  324 + // 传递充值类型参数
  325 + rechargeType: values.rechargeType || 'normal',
  326 + },
316 }); 327 });
317 } 328 }
318 329
@@ -416,6 +427,16 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; { @@ -416,6 +427,16 @@ export default ({ setVisible, prepaymentObject, onClose }) =&gt; {
416 rules={[{ required: true, message: '销售代表必填' }]} 427 rules={[{ required: true, message: '销售代表必填' }]}
417 options={salesCodeOptions} 428 options={salesCodeOptions}
418 /> 429 />
  430 + <ProFormSelect
  431 + name="rechargeType"
  432 + label="充值类型"
  433 + valueEnum={{
  434 + normal: '普通充值',
  435 + privatePocket: '隐私钱包充值',
  436 + }}
  437 + // No special handling needed for different recharge types now
  438 + rules={[{ required: true, message: '请选择充值类型' }]}
  439 + />
419 <ProFormDigit 440 <ProFormDigit
420 name="rechargeAmount" 441 name="rechargeAmount"
421 label="充值金额(¥)" 442 label="充值金额(¥)"
src/pages/Prepaid/index.less
1 -.prepaid-index td {  
2 - font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,  
3 - 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',  
4 - 'WenQuanYi Micro Hei', sans-serif;  
5 - font-size: 13px; 1 +.prepaid-index {
  2 + width: 100%;
  3 + padding: 24px;
  4 +
  5 + .prepaid-card {
  6 + height: 180px;
  7 + transition: all 0.3s;
  8 +
  9 + &:hover {
  10 + transform: translateY(-5px);
  11 + box-shadow: 0 5px 15px rgba(0, 0, 0, 10%);
  12 + }
  13 +
  14 + .card-content {
  15 + display: flex;
  16 + flex-direction: column;
  17 + align-items: center;
  18 + justify-content: center;
  19 + height: 100%;
  20 +
  21 + .card-icon {
  22 + font-size: 36px;
  23 + margin-bottom: 16px;
  24 + color: #1890ff;
  25 + }
  26 +
  27 + .card-title {
  28 + font-size: 18px;
  29 + font-weight: 500;
  30 + margin-bottom: 12px;
  31 + }
  32 +
  33 + .card-desc {
  34 + color: rgba(0, 0, 0, 45%);
  35 + text-align: center;
  36 + padding: 0 12px;
  37 + }
  38 + }
  39 + }
  40 +
  41 + td {
  42 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  43 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  44 + 'WenQuanYi Micro Hei', sans-serif;
  45 + font-size: 13px;
  46 + }
6 } 47 }
src/pages/Prepaid/index.tsx
1 -import ButtonConfirm from '@/components/ButtomConfirm';  
2 -import EllipsisDiv from '@/components/Div/EllipsisDiv';  
3 -import { RESPONSE_CODE } from '@/constants/enum';  
4 -import {} from '@/pages/Invoice/constant';  
5 import { 1 import {
6 - postCanrdApiUserList,  
7 - postPrepaidDelete,  
8 - postPrepaidList,  
9 -} from '@/services';  
10 -import { enumValueToLabel, formatDateTime } from '@/utils';  
11 -import { getUserInfo } from '@/utils/user';  
12 -import { PlusOutlined } from '@ant-design/icons';  
13 -import { ActionType, ProTable } from '@ant-design/pro-components';  
14 -import { Button, Divider, Image, Tabs, message } from 'antd';  
15 -import { cloneDeep } from 'lodash';  
16 -import React, { useRef, useState } from 'react';  
17 -import CheckModal from '../Order/Order/components/CheckModal';  
18 -import { CHECK_TYPE } from '../Order/constant';  
19 -import BalanceChangeRecordsModal from './components/BalanceChangeRecordsModal';  
20 -import PointsExchangeModal from './components/PointsExchangeModal';  
21 -import PointsExchangeRecordsModal from './components/PointsExchangeRecordsModal';  
22 -import RechargePrepaymentModal from './components/RechargePrepaymentModal';  
23 -import {  
24 - ACCOUNT_COLUMNS,  
25 - PREPAID_STATUS_OPTIONS,  
26 - SALES_RECHARGE_PREPAYMENT_COLUMNS,  
27 -} from './constant'; 2 + CreditCardOutlined,
  3 + MoneyCollectOutlined,
  4 + UserOutlined,
  5 +} from '@ant-design/icons';
  6 +import { Card, Col, Row } from 'antd';
  7 +import { history } from 'umi';
28 import './index.less'; 8 import './index.less';
29 9
30 const PrepaidPage = () => { 10 const PrepaidPage = () => {
31 - const user = getUserInfo();  
32 - const prepaidActionRef = useRef<ActionType>();  
33 - const accountActionRef = useRef<ActionType>();  
34 - const [rechargePrepaymentModalVisible, setRechargePrepaymentModalVisible] =  
35 - useState<boolean>(false);  
36 - const [currentOptPrepaymentObj, setCurrentOptPrepaymentObj] = useState(null);  
37 - const [currentOptUserObj, setCurrentOptUserObj] = useState(null);  
38 - const [checkVisible, setCheckVisible] = useState<boolean>(false);  
39 - const [  
40 - balanceChangeRecordsModalVisible,  
41 - setBalanceChangeRecordsModalVisible,  
42 - ] = useState<boolean>(false);  
43 - const [pointsExchangeModalVisible, setPointsExchangeModalVisible] =  
44 - useState<boolean>(false);  
45 - const [  
46 - pointsExchangeRecordsModalVisible,  
47 - setPointsExchangeRecordsModalVisible,  
48 - ] = useState<boolean>(false);  
49 -  
50 - const reloadPrepaidTable = () => {  
51 - prepaidActionRef.current?.reload();  
52 - };  
53 -  
54 - const reloadAccountTable = () => {  
55 - accountActionRef.current?.reload();  
56 - };  
57 -  
58 - const getTableCellText = (target: any) => {  
59 - if (!target) {  
60 - return '';  
61 - }  
62 -  
63 - if (target.props) {  
64 - return target.props.text;  
65 - }  
66 -  
67 - return target;  
68 - };  
69 -  
70 - /**  
71 - * 加载发票列表表格的各个列格式  
72 - */  
73 - const prepaidColumnsInit = () => {  
74 - let columns = SALES_RECHARGE_PREPAYMENT_COLUMNS.map((item) => {  
75 - let newItem = { ...item };  
76 - let dataIndex = item.dataIndex;  
77 -  
78 - newItem.render = (text, record) => {  
79 - let textValue = record[dataIndex];  
80 -  
81 - if (dataIndex === 'status') {  
82 - textValue = enumValueToLabel(textValue, PREPAID_STATUS_OPTIONS);  
83 - }  
84 -  
85 - if (dataIndex.endsWith('Time')) {  
86 - textValue = formatDateTime(textValue);  
87 - }  
88 -  
89 - if (  
90 - dataIndex === 'proofImages' &&  
91 - textValue !== null &&  
92 - textValue !== undefined  
93 - ) {  
94 - console.log(textValue);  
95 - return (  
96 - <Image.PreviewGroup  
97 - className="mr-10"  
98 - preview={{  
99 - onChange: (current, prev) =>  
100 - console.log(`current index: ${current}, prev index: ${prev}`),  
101 - }}  
102 - >  
103 - {textValue.map((item, index) => (  
104 - <React.Fragment key={index}>  
105 - {index > 0 ? <Divider type="vertical" /> : ''}  
106 - <Image  
107 - className="max-h-[35px] max-w-[45px]"  
108 - src={item}  
109 - title={item}  
110 - />{' '}  
111 - </React.Fragment>  
112 - ))}  
113 - </Image.PreviewGroup>  
114 - );  
115 - }  
116 -  
117 - return <EllipsisDiv text={textValue} />;  
118 - };  
119 -  
120 - return newItem;  
121 - });  
122 -  
123 - columns.push({  
124 - title: '操作',  
125 - valueType: 'option',  
126 - key: 'option',  
127 - fixed: 'right',  
128 - width: 120,  
129 - render: (text, record) => {  
130 - let btns = [];  
131 - let opts = record.operations;  
132 - if (opts?.includes('modify')) {  
133 - btns.push(  
134 - <Button  
135 - className="p-0"  
136 - key="modify"  
137 - type="link"  
138 - onClick={() => {  
139 - setRechargePrepaymentModalVisible(true);  
140 - setCurrentOptPrepaymentObj(cloneDeep(record));  
141 - }}  
142 - >  
143 - 编辑  
144 - </Button>,  
145 - );  
146 - }  
147 -  
148 - if (opts?.includes('audit')) {  
149 - btns.push(  
150 - <Button  
151 - className="p-0"  
152 - key="view"  
153 - type="link"  
154 - onClick={() => {  
155 - setCurrentOptPrepaymentObj(record);  
156 - setCheckVisible(true);  
157 - }}  
158 - >  
159 - 审核  
160 - </Button>,  
161 - );  
162 - }  
163 -  
164 - if (opts?.includes('delete')) {  
165 - btns.push(  
166 - <ButtonConfirm  
167 - key="delete"  
168 - className="p-0"  
169 - title={'确认删除这条预存记录吗?'}  
170 - text="删除"  
171 - onConfirm={async () => {  
172 - let res = await postPrepaidDelete({  
173 - data: { ids: [record.id] },  
174 - });  
175 - if (res && res.result === RESPONSE_CODE.SUCCESS) {  
176 - message.success(res.message);  
177 - reloadPrepaidTable();  
178 - }  
179 - }}  
180 - />,  
181 - );  
182 - }  
183 - return btns;  
184 - },  
185 - });  
186 -  
187 - return columns; 11 + const handleCardClick = (path: string) => {
  12 + history.push(path);
188 }; 13 };
189 14
190 - const accountColumnsInit = () => {  
191 - let columns = ACCOUNT_COLUMNS.map((item) => {  
192 - let newItem = { ...item };  
193 - let dataIndex = item.dataIndex;  
194 -  
195 - newItem.render = (text, record) => {  
196 - let textValue = record[dataIndex];  
197 - return <EllipsisDiv text={getTableCellText(textValue)} />;  
198 - };  
199 -  
200 - return newItem;  
201 - });  
202 -  
203 - columns.push({  
204 - title: '操作',  
205 - valueType: 'option',  
206 - key: 'option',  
207 - fixed: 'right',  
208 - width: 240,  
209 - render: (text, record) => {  
210 - let btns = [];  
211 - btns.push(  
212 - <Button  
213 - className="p-0 ml-2"  
214 - key="points"  
215 - type="link"  
216 - onClick={() => {  
217 - setCurrentOptUserObj(record);  
218 - setPointsExchangeModalVisible(true);  
219 - }} 15 + return (
  16 + <div className="prepaid-index">
  17 + <Row gutter={16}>
  18 + <Col span={8}>
  19 + <Card
  20 + hoverable
  21 + className="prepaid-card"
  22 + onClick={() => handleCardClick('/prepaid/recharge')}
220 > 23 >
221 - 积分兑换  
222 - </Button>,  
223 - );  
224 - btns.push(  
225 - <Button  
226 - className="p-0"  
227 - key="view"  
228 - type="link"  
229 - onClick={() => {  
230 - setCurrentOptUserObj(record);  
231 - setBalanceChangeRecordsModalVisible(true);  
232 - }} 24 + <div className="card-content">
  25 + <CreditCardOutlined className="card-icon" />
  26 + <div className="card-title">预存充值</div>
  27 + <div className="card-desc">管理预存充值记录、审核及编辑操作</div>
  28 + </div>
  29 + </Card>
  30 + </Col>
  31 + <Col span={8}>
  32 + <Card
  33 + hoverable
  34 + className="prepaid-card"
  35 + onClick={() => handleCardClick('/prepaid/account')}
233 > 36 >
234 - 消费记录  
235 - </Button>,  
236 - );  
237 - btns.push(  
238 - <Button  
239 - className="p-0 ml-2"  
240 - key="pointsRecords"  
241 - type="link"  
242 - onClick={() => {  
243 - setCurrentOptUserObj(record);  
244 - setPointsExchangeRecordsModalVisible(true);  
245 - }} 37 + <div className="card-content">
  38 + <UserOutlined className="card-icon" />
  39 + <div className="card-title">账号列表</div>
  40 + <div className="card-desc">查看账户信息、积分兑换及消费记录</div>
  41 + </div>
  42 + </Card>
  43 + </Col>
  44 + <Col span={8}>
  45 + <Card
  46 + hoverable
  47 + className="prepaid-card"
  48 + onClick={() => handleCardClick('/prepaid/privatePocket')}
246 > 49 >
247 - 积分兑换记录  
248 - </Button>,  
249 - );  
250 - return btns;  
251 - },  
252 - });  
253 -  
254 - return columns;  
255 - };  
256 -  
257 - const tabsItems = [  
258 - {  
259 - key: 1,  
260 - label: '预存充值',  
261 - children: (  
262 - <ProTable  
263 - columns={prepaidColumnsInit()}  
264 - actionRef={prepaidActionRef}  
265 - cardBordered  
266 - pagination={{  
267 - pageSize: 10,  
268 - }}  
269 - request={async (params) => {  
270 - const res = await postPrepaidList({  
271 - data: { ...params },  
272 - });  
273 - return {  
274 - data: res?.data?.data || [],  
275 - total: res?.data?.total || 0,  
276 - };  
277 - }}  
278 - columnsState={{  
279 - persistenceKey: 'pro-table-singe-prepaid',  
280 - persistenceType: 'localStorage',  
281 - defaultValue: {  
282 - option: { fixed: 'right', disable: true },  
283 - },  
284 - onChange(value) {  
285 - console.log('value: ', value);  
286 - },  
287 - }}  
288 - rowKey="id"  
289 - search={{  
290 - labelWidth: 'auto',  
291 - }}  
292 - options={{  
293 - setting: {  
294 - listsHeight: 400,  
295 - },  
296 - }}  
297 - form={{}}  
298 - dateFormatter="string"  
299 - headerTitle="预存充值"  
300 - scroll={{ x: 1400 }}  
301 - toolBarRender={() => [  
302 - <Button  
303 - key="button"  
304 - icon={<PlusOutlined />}  
305 - onClick={() => {  
306 - setCurrentOptPrepaymentObj(null);  
307 - setRechargePrepaymentModalVisible(true);  
308 - }}  
309 - type="primary"  
310 - >  
311 - 新增充值  
312 - </Button>,  
313 - ]}  
314 - />  
315 - ),  
316 - },  
317 - {  
318 - key: 2,  
319 - label: '账号列表',  
320 - children: (  
321 - <ProTable  
322 - columns={accountColumnsInit()}  
323 - actionRef={accountActionRef}  
324 - cardBordered  
325 - pagination={{  
326 - pageSize: 10,  
327 - }}  
328 - request={async (params) => {  
329 - const res = await postCanrdApiUserList({  
330 - data: { ...params },  
331 - });  
332 - const data = res?.data?.data || [];  
333 - const targetPhones = [  
334 - '18550286106',  
335 - '15286038815',  
336 - '15202597163',  
337 - '13267086260',  
338 - '15900392469',  
339 - '13529047645',  
340 - ];  
341 -  
342 - const processedData = data.map((item) => {  
343 - const isAdmin = user.roles.includes('ADMIN');  
344 - const isSalesManager = user.roles.includes('SALES_MANAGER');  
345 - if (  
346 - targetPhones.includes(item.phone) &&  
347 - !(isAdmin || isSalesManager)  
348 - ) {  
349 - return {  
350 - ...item,  
351 - nowMoney: '****',  
352 - };  
353 - }  
354 - return item;  
355 - });  
356 - return {  
357 - data: processedData,  
358 - total: res?.data?.total || 0,  
359 - };  
360 - }}  
361 - columnsState={{  
362 - persistenceKey: 'pro-table-singe-account',  
363 - persistenceType: 'localStorage',  
364 - defaultValue: {  
365 - option: { fixed: 'right', disable: true },  
366 - },  
367 - onChange(value) {  
368 - console.log('value: ', value);  
369 - },  
370 - }}  
371 - rowKey="id"  
372 - search={{  
373 - labelWidth: 'auto',  
374 - }}  
375 - options={{  
376 - setting: {  
377 - listsHeight: 400,  
378 - },  
379 - }}  
380 - form={{}}  
381 - dateFormatter="string"  
382 - headerTitle="账号列表"  
383 - scroll={{ x: 1400 }}  
384 - toolBarRender={() => []}  
385 - />  
386 - ),  
387 - },  
388 - ];  
389 - return (  
390 - <div className="prepaid-index">  
391 - <Tabs  
392 - defaultActiveKey="1"  
393 - items={tabsItems}  
394 - onChange={(value) => {  
395 - if (value === '1') {  
396 - reloadPrepaidTable();  
397 - } else {  
398 - reloadAccountTable();  
399 - }  
400 - }}  
401 - />  
402 -  
403 - {rechargePrepaymentModalVisible && (  
404 - <RechargePrepaymentModal  
405 - setVisible={setRechargePrepaymentModalVisible}  
406 - onClose={() => {  
407 - setRechargePrepaymentModalVisible(false);  
408 - reloadPrepaidTable();  
409 - }}  
410 - prepaymentObject={currentOptPrepaymentObj}  
411 - />  
412 - )}  
413 -  
414 - {checkVisible && (  
415 - <CheckModal  
416 - setCheckVisible={(val: boolean) => {  
417 - setCheckVisible(val);  
418 - }}  
419 - data={[currentOptPrepaymentObj]}  
420 - subOrders={[currentOptPrepaymentObj]}  
421 - orderCheckType={CHECK_TYPE.PREPAID_AUDIT}  
422 - openOrderDrawer={false}  
423 - onClose={() => {  
424 - setCheckVisible(false);  
425 - reloadPrepaidTable();  
426 - }}  
427 - />  
428 - )}  
429 -  
430 - {balanceChangeRecordsModalVisible && (  
431 - <BalanceChangeRecordsModal  
432 - setVisible={(val: boolean) => {  
433 - setBalanceChangeRecordsModalVisible(val);  
434 - }}  
435 - userInfoObj={currentOptUserObj}  
436 - onClose={() => {  
437 - setBalanceChangeRecordsModalVisible(false);  
438 - }}  
439 - />  
440 - )}  
441 -  
442 - {pointsExchangeModalVisible && currentOptUserObj && (  
443 - <PointsExchangeModal  
444 - setVisible={(val: boolean) => {  
445 - setPointsExchangeModalVisible(val);  
446 - }}  
447 - userInfoObj={currentOptUserObj}  
448 - onClose={() => {  
449 - setPointsExchangeModalVisible(false);  
450 - reloadAccountTable();  
451 - }}  
452 - />  
453 - )}  
454 -  
455 - {pointsExchangeRecordsModalVisible && currentOptUserObj && (  
456 - <PointsExchangeRecordsModal  
457 - setVisible={(val: boolean) => {  
458 - setPointsExchangeRecordsModalVisible(val);  
459 - }}  
460 - userInfoObj={currentOptUserObj}  
461 - onClose={() => {  
462 - setPointsExchangeRecordsModalVisible(false);  
463 - }}  
464 - />  
465 - )} 50 + <div className="card-content">
  51 + <MoneyCollectOutlined className="card-icon" />
  52 + <div className="card-title">隐私钱包</div>
  53 + <div className="card-desc">管理用户隐私钱包信息</div>
  54 + </div>
  55 + </Card>
  56 + </Col>
  57 + </Row>
466 </div> 58 </div>
467 ); 59 );
468 }; 60 };
src/services/definition.ts
@@ -4849,6 +4849,154 @@ export interface UserNowMoneyCheckRequest { @@ -4849,6 +4849,154 @@ export interface UserNowMoneyCheckRequest {
4849 uid?: number; 4849 uid?: number;
4850 } 4850 }
4851 4851
  4852 +export interface UserPrivateMoneyCheckRequest {
  4853 + /**
  4854 + * @description
  4855 + * 手机号码
  4856 + */
  4857 + phone?: string;
  4858 + /**
  4859 + * @description
  4860 + * 金额
  4861 + */
  4862 + subPrice?: number;
  4863 + /**
  4864 + * @description
  4865 + * 用户ID
  4866 + */
  4867 + uid?: string;
  4868 +}
  4869 +
  4870 +export interface UserPrivatePocketBalanceUpdateRequest {
  4871 + /**
  4872 + * @description
  4873 + * 用户账号
  4874 + */
  4875 + account: string;
  4876 + /**
  4877 + * @description
  4878 + * 创建人
  4879 + */
  4880 + createByName?: string;
  4881 + /**
  4882 + * @description
  4883 + * 用户余额
  4884 + */
  4885 + nowMoney?: number;
  4886 + /**
  4887 + * @description
  4888 + * 隐私余额
  4889 + */
  4890 + privateMoney?: number;
  4891 + /**
  4892 + * @description
  4893 + * 真实姓名
  4894 + */
  4895 + realName?: string;
  4896 + /**
  4897 + * @description
  4898 + * 负责销售
  4899 + */
  4900 + salesCode: string;
  4901 + /**
  4902 + * @description
  4903 + * 用户id
  4904 + * @format int32
  4905 + */
  4906 + uid?: number;
  4907 +}
  4908 +
  4909 +export interface UserPrivatePocketDeleteRequest {
  4910 + /**
  4911 + * @description
  4912 + * 用户id
  4913 + * @format int32
  4914 + */
  4915 + uid: number;
  4916 +}
  4917 +
  4918 +export interface UserPrivatePocketDetailRequest {
  4919 + /**
  4920 + * @description
  4921 + * 用户id
  4922 + * @format int32
  4923 + */
  4924 + uid: number;
  4925 +}
  4926 +
  4927 +export interface UserPrivatePocketListRequest {
  4928 + /**
  4929 + * @description
  4930 + * 用户账号
  4931 + */
  4932 + account?: string;
  4933 + /**
  4934 + * @description
  4935 + * 当前页
  4936 + * @format int32
  4937 + * @example
  4938 + * 1
  4939 + */
  4940 + current?: number;
  4941 + /**
  4942 + * @description
  4943 + * 每页大小
  4944 + * @format int32
  4945 + * @example
  4946 + * 10
  4947 + */
  4948 + pageSize?: number;
  4949 + /**
  4950 + * @description
  4951 + * 真实姓名
  4952 + */
  4953 + realName?: string;
  4954 + /**
  4955 + * @description
  4956 + * 负责销售
  4957 + */
  4958 + salesCode?: string;
  4959 +}
  4960 +
  4961 +export interface UserPrivatePocketUpdateRequest {
  4962 + /**
  4963 + * @description
  4964 + * 用户账号
  4965 + */
  4966 + account: string;
  4967 + /**
  4968 + * @description
  4969 + * 创建人
  4970 + */
  4971 + createByName?: string;
  4972 + /**
  4973 + * @description
  4974 + * 用户余额
  4975 + */
  4976 + nowMoney?: number;
  4977 + /**
  4978 + * @description
  4979 + * 隐私余额
  4980 + */
  4981 + privateMoney?: number;
  4982 + /**
  4983 + * @description
  4984 + * 真实姓名
  4985 + */
  4986 + realName?: string;
  4987 + /**
  4988 + * @description
  4989 + * 负责销售
  4990 + */
  4991 + salesCode: string;
  4992 + /**
  4993 + * @description
  4994 + * 用户id
  4995 + * @format int32
  4996 + */
  4997 + uid?: number;
  4998 +}
  4999 +
4852 export interface View { 5000 export interface View {
4853 contentType?: string; 5001 contentType?: string;
4854 } 5002 }
@@ -5471,6 +5619,11 @@ export interface SalesRechargePrepaymentAuditRequest { @@ -5471,6 +5619,11 @@ export interface SalesRechargePrepaymentAuditRequest {
5471 * 手机号 5619 * 手机号
5472 */ 5620 */
5473 phone?: string; 5621 phone?: string;
  5622 + /**
  5623 + * @description
  5624 + * 销售代表编码
  5625 + */
  5626 + salesCode?: string;
5474 } 5627 }
5475 5628
5476 export interface SalesRechargePrepaymentCreateRequest { 5629 export interface SalesRechargePrepaymentCreateRequest {
@@ -5511,6 +5664,13 @@ export interface SalesRechargePrepaymentCreateRequest { @@ -5511,6 +5664,13 @@ export interface SalesRechargePrepaymentCreateRequest {
5511 rechargeSource?: string; 5664 rechargeSource?: string;
5512 /** 5665 /**
5513 * @description 5666 * @description
  5667 + * 充值类型
  5668 + * @example
  5669 + * normal
  5670 + */
  5671 + rechargeType?: string;
  5672 + /**
  5673 + * @description
5514 * 销售代表 5674 * 销售代表
5515 */ 5675 */
5516 salesCode?: string; 5676 salesCode?: string;
src/services/request.ts
@@ -168,6 +168,12 @@ import type { @@ -168,6 +168,12 @@ import type {
168 UserDetailRequest, 168 UserDetailRequest,
169 UserListRequest, 169 UserListRequest,
170 UserNowMoneyCheckRequest, 170 UserNowMoneyCheckRequest,
  171 + UserPrivateMoneyCheckRequest,
  172 + UserPrivatePocketBalanceUpdateRequest,
  173 + UserPrivatePocketDeleteRequest,
  174 + UserPrivatePocketDetailRequest,
  175 + UserPrivatePocketListRequest,
  176 + UserPrivatePocketUpdateRequest,
171 WarningOrderWhiteListDto, 177 WarningOrderWhiteListDto,
172 WarningUserWhiteListDto, 178 WarningUserWhiteListDto,
173 } from './definition'; 179 } from './definition';
@@ -3142,6 +3148,432 @@ export const postCanrdApiUserNowMoneyCheck = /* #__PURE__ */ (() =&gt; { @@ -3142,6 +3148,432 @@ export const postCanrdApiUserNowMoneyCheck = /* #__PURE__ */ (() =&gt; {
3142 return request; 3148 return request;
3143 })(); 3149 })();
3144 3150
  3151 +/** @description request parameter type for postCanrdPrivatePocketDelete */
  3152 +export interface PostCanrdPrivatePocketDeleteOption {
  3153 + /**
  3154 + * @description
  3155 + * request
  3156 + */
  3157 + body: {
  3158 + /**
  3159 + @description
  3160 + request */
  3161 + request: UserPrivatePocketDeleteRequest;
  3162 + };
  3163 +}
  3164 +
  3165 +/** @description response type for postCanrdPrivatePocketDelete */
  3166 +export interface PostCanrdPrivatePocketDeleteResponse {
  3167 + /**
  3168 + * @description
  3169 + * OK
  3170 + */
  3171 + 200: ServerResult;
  3172 + /**
  3173 + * @description
  3174 + * Created
  3175 + */
  3176 + 201: any;
  3177 + /**
  3178 + * @description
  3179 + * Unauthorized
  3180 + */
  3181 + 401: any;
  3182 + /**
  3183 + * @description
  3184 + * Forbidden
  3185 + */
  3186 + 403: any;
  3187 + /**
  3188 + * @description
  3189 + * Not Found
  3190 + */
  3191 + 404: any;
  3192 +}
  3193 +
  3194 +export type PostCanrdPrivatePocketDeleteResponseSuccess =
  3195 + PostCanrdPrivatePocketDeleteResponse[200];
  3196 +/**
  3197 + * @description
  3198 + * 删除用户隐私钱包
  3199 + * @tags user-private-pocket-controller
  3200 + * @produces *
  3201 + * @consumes application/json
  3202 + */
  3203 +export const postCanrdPrivatePocketDelete = /* #__PURE__ */ (() => {
  3204 + const method = 'post';
  3205 + const url = '/canrd/privatePocket/delete';
  3206 + function request(
  3207 + option: PostCanrdPrivatePocketDeleteOption,
  3208 + ): Promise<PostCanrdPrivatePocketDeleteResponseSuccess> {
  3209 + return requester(request.url, {
  3210 + method: request.method,
  3211 + ...option,
  3212 + }) as unknown as Promise<PostCanrdPrivatePocketDeleteResponseSuccess>;
  3213 + }
  3214 +
  3215 + /** http method */
  3216 + request.method = method;
  3217 + /** request url */
  3218 + request.url = url;
  3219 + return request;
  3220 +})();
  3221 +
  3222 +/** @description request parameter type for postCanrdPrivatePocketDetail */
  3223 +export interface PostCanrdPrivatePocketDetailOption {
  3224 + /**
  3225 + * @description
  3226 + * request
  3227 + */
  3228 + body: {
  3229 + /**
  3230 + @description
  3231 + request */
  3232 + request: UserPrivatePocketDetailRequest;
  3233 + };
  3234 +}
  3235 +
  3236 +/** @description response type for postCanrdPrivatePocketDetail */
  3237 +export interface PostCanrdPrivatePocketDetailResponse {
  3238 + /**
  3239 + * @description
  3240 + * OK
  3241 + */
  3242 + 200: ServerResult;
  3243 + /**
  3244 + * @description
  3245 + * Created
  3246 + */
  3247 + 201: any;
  3248 + /**
  3249 + * @description
  3250 + * Unauthorized
  3251 + */
  3252 + 401: any;
  3253 + /**
  3254 + * @description
  3255 + * Forbidden
  3256 + */
  3257 + 403: any;
  3258 + /**
  3259 + * @description
  3260 + * Not Found
  3261 + */
  3262 + 404: any;
  3263 +}
  3264 +
  3265 +export type PostCanrdPrivatePocketDetailResponseSuccess =
  3266 + PostCanrdPrivatePocketDetailResponse[200];
  3267 +/**
  3268 + * @description
  3269 + * 获取用户隐私钱包详情
  3270 + * @tags user-private-pocket-controller
  3271 + * @produces *
  3272 + * @consumes application/json
  3273 + */
  3274 +export const postCanrdPrivatePocketDetail = /* #__PURE__ */ (() => {
  3275 + const method = 'post';
  3276 + const url = '/canrd/privatePocket/detail';
  3277 + function request(
  3278 + option: PostCanrdPrivatePocketDetailOption,
  3279 + ): Promise<PostCanrdPrivatePocketDetailResponseSuccess> {
  3280 + return requester(request.url, {
  3281 + method: request.method,
  3282 + ...option,
  3283 + }) as unknown as Promise<PostCanrdPrivatePocketDetailResponseSuccess>;
  3284 + }
  3285 +
  3286 + /** http method */
  3287 + request.method = method;
  3288 + /** request url */
  3289 + request.url = url;
  3290 + return request;
  3291 +})();
  3292 +
  3293 +/** @description request parameter type for postCanrdPrivatePocketList */
  3294 +export interface PostCanrdPrivatePocketListOption {
  3295 + /**
  3296 + * @description
  3297 + * request
  3298 + */
  3299 + body: {
  3300 + /**
  3301 + @description
  3302 + request */
  3303 + request: UserPrivatePocketListRequest;
  3304 + };
  3305 +}
  3306 +
  3307 +/** @description response type for postCanrdPrivatePocketList */
  3308 +export interface PostCanrdPrivatePocketListResponse {
  3309 + /**
  3310 + * @description
  3311 + * OK
  3312 + */
  3313 + 200: ServerResult;
  3314 + /**
  3315 + * @description
  3316 + * Created
  3317 + */
  3318 + 201: any;
  3319 + /**
  3320 + * @description
  3321 + * Unauthorized
  3322 + */
  3323 + 401: any;
  3324 + /**
  3325 + * @description
  3326 + * Forbidden
  3327 + */
  3328 + 403: any;
  3329 + /**
  3330 + * @description
  3331 + * Not Found
  3332 + */
  3333 + 404: any;
  3334 +}
  3335 +
  3336 +export type PostCanrdPrivatePocketListResponseSuccess =
  3337 + PostCanrdPrivatePocketListResponse[200];
  3338 +/**
  3339 + * @description
  3340 + * 获取用户隐私钱包列表
  3341 + * @tags user-private-pocket-controller
  3342 + * @produces *
  3343 + * @consumes application/json
  3344 + */
  3345 +export const postCanrdPrivatePocketList = /* #__PURE__ */ (() => {
  3346 + const method = 'post';
  3347 + const url = '/canrd/privatePocket/list';
  3348 + function request(
  3349 + option: PostCanrdPrivatePocketListOption,
  3350 + ): Promise<PostCanrdPrivatePocketListResponseSuccess> {
  3351 + return requester(request.url, {
  3352 + method: request.method,
  3353 + ...option,
  3354 + }) as unknown as Promise<PostCanrdPrivatePocketListResponseSuccess>;
  3355 + }
  3356 +
  3357 + /** http method */
  3358 + request.method = method;
  3359 + /** request url */
  3360 + request.url = url;
  3361 + return request;
  3362 +})();
  3363 +
  3364 +/** @description request parameter type for postCanrdPrivatePocketPrivateMoneyCheck */
  3365 +export interface PostCanrdPrivatePocketPrivateMoneyCheckOption {
  3366 + /**
  3367 + * @description
  3368 + * request
  3369 + */
  3370 + body: {
  3371 + /**
  3372 + @description
  3373 + request */
  3374 + request: UserPrivateMoneyCheckRequest;
  3375 + };
  3376 +}
  3377 +
  3378 +/** @description response type for postCanrdPrivatePocketPrivateMoneyCheck */
  3379 +export interface PostCanrdPrivatePocketPrivateMoneyCheckResponse {
  3380 + /**
  3381 + * @description
  3382 + * OK
  3383 + */
  3384 + 200: ServerResult;
  3385 + /**
  3386 + * @description
  3387 + * Created
  3388 + */
  3389 + 201: any;
  3390 + /**
  3391 + * @description
  3392 + * Unauthorized
  3393 + */
  3394 + 401: any;
  3395 + /**
  3396 + * @description
  3397 + * Forbidden
  3398 + */
  3399 + 403: any;
  3400 + /**
  3401 + * @description
  3402 + * Not Found
  3403 + */
  3404 + 404: any;
  3405 +}
  3406 +
  3407 +export type PostCanrdPrivatePocketPrivateMoneyCheckResponseSuccess =
  3408 + PostCanrdPrivatePocketPrivateMoneyCheckResponse[200];
  3409 +/**
  3410 + * @description
  3411 + * 检查用户隐私钱包余额是否足够
  3412 + * @tags user-private-pocket-controller
  3413 + * @produces *
  3414 + * @consumes application/json
  3415 + */
  3416 +export const postCanrdPrivatePocketPrivateMoneyCheck = /* #__PURE__ */ (() => {
  3417 + const method = 'post';
  3418 + const url = '/canrd/privatePocket/privateMoney/check';
  3419 + function request(
  3420 + option: PostCanrdPrivatePocketPrivateMoneyCheckOption,
  3421 + ): Promise<PostCanrdPrivatePocketPrivateMoneyCheckResponseSuccess> {
  3422 + return requester(request.url, {
  3423 + method: request.method,
  3424 + ...option,
  3425 + }) as unknown as Promise<PostCanrdPrivatePocketPrivateMoneyCheckResponseSuccess>;
  3426 + }
  3427 +
  3428 + /** http method */
  3429 + request.method = method;
  3430 + /** request url */
  3431 + request.url = url;
  3432 + return request;
  3433 +})();
  3434 +
  3435 +/** @description request parameter type for postCanrdPrivatePocketSave */
  3436 +export interface PostCanrdPrivatePocketSaveOption {
  3437 + /**
  3438 + * @description
  3439 + * request
  3440 + */
  3441 + body: {
  3442 + /**
  3443 + @description
  3444 + request */
  3445 + request: UserPrivatePocketUpdateRequest;
  3446 + };
  3447 +}
  3448 +
  3449 +/** @description response type for postCanrdPrivatePocketSave */
  3450 +export interface PostCanrdPrivatePocketSaveResponse {
  3451 + /**
  3452 + * @description
  3453 + * OK
  3454 + */
  3455 + 200: ServerResult;
  3456 + /**
  3457 + * @description
  3458 + * Created
  3459 + */
  3460 + 201: any;
  3461 + /**
  3462 + * @description
  3463 + * Unauthorized
  3464 + */
  3465 + 401: any;
  3466 + /**
  3467 + * @description
  3468 + * Forbidden
  3469 + */
  3470 + 403: any;
  3471 + /**
  3472 + * @description
  3473 + * Not Found
  3474 + */
  3475 + 404: any;
  3476 +}
  3477 +
  3478 +export type PostCanrdPrivatePocketSaveResponseSuccess =
  3479 + PostCanrdPrivatePocketSaveResponse[200];
  3480 +/**
  3481 + * @description
  3482 + * 保存或更新用户隐私钱包
  3483 + * @tags user-private-pocket-controller
  3484 + * @produces *
  3485 + * @consumes application/json
  3486 + */
  3487 +export const postCanrdPrivatePocketSave = /* #__PURE__ */ (() => {
  3488 + const method = 'post';
  3489 + const url = '/canrd/privatePocket/save';
  3490 + function request(
  3491 + option: PostCanrdPrivatePocketSaveOption,
  3492 + ): Promise<PostCanrdPrivatePocketSaveResponseSuccess> {
  3493 + return requester(request.url, {
  3494 + method: request.method,
  3495 + ...option,
  3496 + }) as unknown as Promise<PostCanrdPrivatePocketSaveResponseSuccess>;
  3497 + }
  3498 +
  3499 + /** http method */
  3500 + request.method = method;
  3501 + /** request url */
  3502 + request.url = url;
  3503 + return request;
  3504 +})();
  3505 +
  3506 +/** @description request parameter type for postCanrdPrivatePocketUpdateBalance */
  3507 +export interface PostCanrdPrivatePocketUpdateBalanceOption {
  3508 + /**
  3509 + * @description
  3510 + * request
  3511 + */
  3512 + body: {
  3513 + /**
  3514 + @description
  3515 + request */
  3516 + request: UserPrivatePocketBalanceUpdateRequest;
  3517 + };
  3518 +}
  3519 +
  3520 +/** @description response type for postCanrdPrivatePocketUpdateBalance */
  3521 +export interface PostCanrdPrivatePocketUpdateBalanceResponse {
  3522 + /**
  3523 + * @description
  3524 + * OK
  3525 + */
  3526 + 200: ServerResult;
  3527 + /**
  3528 + * @description
  3529 + * Created
  3530 + */
  3531 + 201: any;
  3532 + /**
  3533 + * @description
  3534 + * Unauthorized
  3535 + */
  3536 + 401: any;
  3537 + /**
  3538 + * @description
  3539 + * Forbidden
  3540 + */
  3541 + 403: any;
  3542 + /**
  3543 + * @description
  3544 + * Not Found
  3545 + */
  3546 + 404: any;
  3547 +}
  3548 +
  3549 +export type PostCanrdPrivatePocketUpdateBalanceResponseSuccess =
  3550 + PostCanrdPrivatePocketUpdateBalanceResponse[200];
  3551 +/**
  3552 + * @description
  3553 + * 更新用户隐私钱包余额
  3554 + * @tags user-private-pocket-controller
  3555 + * @produces *
  3556 + * @consumes application/json
  3557 + */
  3558 +export const postCanrdPrivatePocketUpdateBalance = /* #__PURE__ */ (() => {
  3559 + const method = 'post';
  3560 + const url = '/canrd/privatePocket/updateBalance';
  3561 + function request(
  3562 + option: PostCanrdPrivatePocketUpdateBalanceOption,
  3563 + ): Promise<PostCanrdPrivatePocketUpdateBalanceResponseSuccess> {
  3564 + return requester(request.url, {
  3565 + method: request.method,
  3566 + ...option,
  3567 + }) as unknown as Promise<PostCanrdPrivatePocketUpdateBalanceResponseSuccess>;
  3568 + }
  3569 +
  3570 + /** http method */
  3571 + request.method = method;
  3572 + /** request url */
  3573 + request.url = url;
  3574 + return request;
  3575 +})();
  3576 +
3145 /** @description request parameter type for postCommonAudit */ 3577 /** @description request parameter type for postCommonAudit */
3146 export interface PostCommonAuditOption { 3578 export interface PostCommonAuditOption {
3147 /** 3579 /**