提交 761d6ff3 作者: ZhangLingKun

功能:现金管理

上级 c0d94d57
import { useState } from 'react';
import { Form, Input, message, Modal, Upload, UploadProps } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { UploadFile } from 'antd/es/upload/interface';
// import { GoodsAPI, UserAPI } from '~/api';
interface PropsType {
visible: boolean;
closed: any;
data: any;
}
export const ChangeModal = (props: PropsType) => {
// 父组件传参
const { visible, closed, data } = props;
// 表格事件
const [form] = Form.useForm();
// 图片上传文件列表
const [fileList, setFileList] = useState<UploadFile[]>([]);
// 图片是否放大
const [visibleImg, setVisibleImg] = useState<boolean>(false);
// 当前放大图片
const [currentImgList, setCurrentImgList] = useState<{ src: string }[]>([]);
// 预览图片
const handlePreview = (url: string) => {
setVisibleImg(true);
setCurrentImgList([{ src: url }]);
};
// 关闭图片放大
const setVisibleEvent = () => {
setVisibleImg(false);
};
// 判断文件类型
const beforeUpload: UploadProps['beforeUpload'] = ({ size, type }) => {
const isImage = [
'image/gif',
'image/jpg',
'image/png',
'image/bmp',
'image/jpeg',
'image/webp',
].includes(type);
if (!isImage) {
message.warning('请上传图片').then();
return isImage || Upload.LIST_IGNORE;
}
const isLimit = size / 1024 / 1024 <= 2;
if (!isLimit) {
message.warning('图片最大上传2M').then();
return isLimit || Upload.LIST_IGNORE;
}
};
// 上传图片
const handleUpload: UploadProps['customRequest'] = async ({ file }) => {
const { uid, name } = file as { uid: string; name: string };
const formData = new FormData();
formData.append('uploadFile', file as unknown as string);
const res = await GoodsAPI.commonUpload(formData);
if (res && res.code === '200') {
setFileList([
...fileList,
{
uid,
name,
status: 'done',
url: res.result[0],
},
]);
form.setFieldsValue({
vouchers: [...fileList.map((i) => i.url), res.result[0]],
});
} else {
message.warning(res.message);
}
};
// 删除图片
const handleDelete: UploadProps['onRemove'] = (res) => {
const newFileList = fileList.filter((i) => i.uid !== res.uid);
setFileList(newFileList);
};
// 关闭事件
const handleClosed = () => {
setFileList([]);
form.resetFields();
closed();
};
// 触发表单验证
const handleSubmit = () => {
form
.validateFields()
.then(async (values) => {
const { mallUserId } = data;
const res: any = await UserAPI.bountyModify({
...values,
mallUserId,
});
if (res && res.code === '200') {
message.success('操作成功');
await handleClosed();
} else {
message.warning(res.message);
}
})
.catch((err) => {
message.warning(err.errorFields[0].errors[0]).then();
});
};
return (
<>
<Modal
open={visible}
title='奖励金变更'
onCancel={handleClosed}
destroyOnClose
width={768}
onOk={handleSubmit}
>
<Form name='form' form={form} layout='horizontal' labelWrap>
<Form.Item label='账号信息' labelCol={{ span: 5 }} wrapperCol={{ span: 15 }}>
<div>{`${data.uid}(${data.userName})`}</div>
</Form.Item>
<Form.Item
label='金额变动'
name='money'
rules={[{ required: true, message: '请输入金额' }]}
labelCol={{ span: 5 }}
wrapperCol={{ span: 15 }}
>
<Input
placeholder='正数表示充值,负数为扣除'
maxLength={11}
allowClear
type='number'
onInput={(val: any) => {
if (val.target.value.length > 11) val.target.value = val.target.value.slice(0, 11);
}}
/>
</Form.Item>
<Form.Item
label='相关凭证'
name='vouchers'
labelCol={{ span: 5 }}
wrapperCol={{ span: 15 }}
>
<Upload
listType='picture-card'
fileList={fileList}
beforeUpload={beforeUpload}
onPreview={() => {
handlePreview(fileList[0].url || '');
}}
customRequest={handleUpload}
onRemove={handleDelete}
>
{fileList.length >= 5 ? null : (
<div>
<PlusOutlined />
<div style={{ marginTop: 8 }}>上传图片</div>
</div>
)}
</Upload>
</Form.Item>
<Form.Item label='备注' name='remark' labelCol={{ span: 5 }} wrapperCol={{ span: 15 }}>
<Input.TextArea placeholder='请输入备注' maxLength={50} allowClear />
</Form.Item>
<Form.Item
label='操作人员密码'
name='password'
rules={[{ required: true, message: '请输入密码' }]}
labelCol={{ span: 5 }}
wrapperCol={{ span: 15 }}
>
<Input
placeholder='请输入密码'
maxLength={11}
allowClear
type='password'
autoComplete='new-password'
/>
</Form.Item>
</Form>
</Modal>
</>
);
};
import { useEffect, useState } from 'react';
import qs from 'query-string';
import { Button, Image, message, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
import SearchBox, { searchColumns } from '~/components/search-box';
import { DetailTableType, DetailFormType } from '~/pages/customManage/customMoney/propsType';
// import { UserAPI } from '~/api';
import { ChangeModal } from '~/pages/customManage/customMoney/comp/ChangeModal';
import { moneyFormat } from '~/utils/money';
import { useNavigate, useSearchParams } from 'react-router-dom';
const CustomMoneyDetail = () => {
// 路由操作
const navigate = useNavigate();
// 参数钩子
const [searchParams] = useSearchParams();
// 接收到的参数
const id = searchParams.get('id');
const uid = searchParams.get('uid');
const userName = searchParams.get('userName');
// 是否打开变更弹窗
const [changeVisible, setChangeVisible] = useState<boolean>(false);
// 搜索数据
const [typeOptions, setTypeOptions] = useState<{ name: string; id: number }[]>([]);
// 搜索数据
const [searchColumns, setSearchColumns] = useState<searchColumns[]>([
{
label: '编号',
name: 'payNo',
type: 'input',
placeholder: '请输入交易编号或订单编号',
width: 220,
},
{
label: '日期',
name: 'time',
type: 'rangePicker',
placeholder: '开始时间~结束时间',
},
{
label: '类型',
name: 'type',
type: 'select',
options: [],
placeholder: '请选择变更类型',
},
]);
// 表头
const tableColumns: ColumnsType<DetailTableType> = [
{
title: '交易编号',
dataIndex: 'payNo',
align: 'center',
},
{
title: '交易时间',
dataIndex: 'payTime',
align: 'center',
},
{
title: '相关订单编号',
dataIndex: 'orderTaskNo',
align: 'center',
},
{
title: '相关订单名称',
dataIndex: 'orderTaskName',
align: 'center',
},
{
title: '相关账号',
dataIndex: 'updateUserName',
align: 'center',
},
{
title: '变更类型',
dataIndex: 'payType',
align: 'center',
render: (value) => {
const item = typeOptions.find((i) => i.id === value);
return item ? item.name : value;
},
},
{
title: '变动',
dataIndex: 'amtPaid',
align: 'center',
render: (value) => {
return value > 0 ? `+${moneyFormat(value)}` : moneyFormat(value);
},
},
{
title: '已冻结',
dataIndex: 'cashFreeze',
align: 'center',
render: (value) => {
return moneyFormat(value);
},
},
{
title: '余额',
dataIndex: 'cashAmt',
align: 'center',
render: (value) => {
return moneyFormat(value);
},
},
{
title: '备注',
dataIndex: 'remark',
align: 'center',
},
{
title: '凭证',
dataIndex: 'voucher',
align: 'center',
render: (value) => {
if (value) {
const list = value.split(',');
return (
<div style={{ display: 'flex', justifyContent: 'space-around' }}>
{list.map((i: string, j: number) => (
<Image key={j} style={{ width: '48px', height: '48px' }} src={i} alt='凭证' />
))}
</div>
);
}
return '无';
},
},
];
// 表格数据
const [tableData, setTableData] = useState<DetailTableType[]>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
const [query, setQuery] = useState({});
// 新版通用部分(ES6+ for React) ZhangLK 2022/08/30 Start
// 加载列表
const getTableList = async (value = {}) => {
setTableData([{ id: Number(id) }]);
// 只需要修改这个地方的接口即可
// const res: any = await UserAPI.getBountyFlow({
// mallUserId: Number(id),
// pageNo: pagination.current,
// pageSize: pagination.pageSize,
// ...value,
// });
// if (res && res.code === '200') {
// // console.log("res -->", res);
// const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
// setPagination({
// total: totalCount,
// pageSize,
// current: pageNo,
// totalPage,
// });
// setTableData(list);
// } else {
// message.warning(res.message);
// }
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (val: DetailFormType) => {
// 在这里对提交的数据做处理,如range转为开始和结束时间
const data = Object.fromEntries(
// 过滤为空项
Object.entries({
...val,
startTime: (val.time && val.time[0]) || undefined,
endTime: (val.time && val.time[1]) || undefined,
pageNo: 1,
}).filter((i) => i[1] !== '' && i[1] !== undefined && i[1] !== null),
);
setQuery(data);
getTableList(data).then();
};
// 返回上一页
const handleBack = () => {
navigate(-1);
};
// 获取所有类型
const getTypeAll = async () => {
// const res: any = await UserAPI.getTypeAll();
// if (res.result && res.result.length != 0) {
// const optionList = res.result.map((v: any) => ({
// id: v.code,
// name: v.status,
// }));
// searchColumns.map((v) => {
// if (v.name === 'type') {
// v.options = optionList;
// }
// });
// setSearchColumns([...searchColumns]);
// setTypeOptions(optionList);
// }
};
// componentDidMount
useEffect(() => {
getTypeAll().then();
getTableList().then();
console.log('searchParams --->', searchParams);
}, []);
return (
<>
<SearchBox
search={searchColumns}
searchData={onFinish}
preFixBtn={
<>
<div>
{uid}({userName})
</div>
<Button
type='primary'
onClick={() => {
setChangeVisible(true);
}}
>
奖励金变更
</Button>
<Button className='backButton' onClick={handleBack}>
返回
</Button>
</>
}
/>
<Table
size='small'
rowKey='id'
dataSource={tableData}
columns={tableColumns}
scroll={{ x: 1500 }}
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
onChange: (page, pageSize) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
bordered
/>
<ChangeModal
visible={changeVisible}
closed={() => {
setChangeVisible(false);
getTableList({ ...pagination, ...query }).then();
}}
data={
{
// mallUserId: Number(qs.parse(props.location.search).id),
// uid: qs.parse(props.location.search).uid,
// userName: qs.parse(props.location.search).userName,
}
}
/>
</>
);
};
export default CustomMoneyDetail;
.from-table-wrap{
position: relative;
//padding: 15px 0 0 0;
.header-view{
position: relative;
width: 100%;
min-height: 60px;
height: auto;
background: #fff;
border-radius: 8px;
display: flex;
justify-content: flex-start;
align-content: center;
flex-wrap: wrap;
padding: 15px 20px 5px 20px;
margin: 0 0 10px 0;
.ant-select-selector{
min-width: 200px;
}
.ant-row{
margin-bottom:10px;
}
.add-button{
margin-right: 15px;
}
}
}
.detail-wrap{
position: relative;
width: 100%;
min-height: 60px;
height: auto;
background: #fff;
border-radius: 8px;
padding: 20px 25px;
.ant-descriptions:nth-child(1){
.ant-descriptions-view{
max-width: 600px;
}
}
}
.custom-class{
margin-top: 10vh;
.ant-message-notice-content{
padding: 15px 30px;
position: relative;
pointer-events:none;
span[role="img"]{
display: none;
}
}
.ant-message-notice-content:after{
position: absolute;
pointer-events:auto;
left: 100%;
top: 0px;
content: "X";
border: 1px solid rgba(128,129,133,0.25);
width: 15px;
height: 15px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
font-weight: 900;
transform: scale(1.3,1.1) translateX(-2px);
color: rgba(128,129,133,0.6);
cursor: pointer;
}
}
import { useEffect, useState } from 'react';
import { Button, Table } from 'antd';
import { EditOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import { useNavigate } from 'react-router-dom';
// import { UserAPI } from '@/api';
import SearchBox, { searchColumns } from '~/components/search-box';
// import useOption from '@/common/hook/optionHook';
import { FormType, TableType } from './propsType';
import { moneyFormat } from '~/utils/money';
import qs from 'query-string';
const CustomMoneyView = () => {
// 路由操作
const navigate = useNavigate();
// 搜索数据
const [searchColumns] = useState<searchColumns[]>([
{
label: '用户信息',
name: 'searchKey',
type: 'input',
placeholder: '用户名称/手机号/UID',
width: 180,
},
]);
// 表头
const tableColumns: ColumnsType<TableType> = [
{
title: '用户UID',
dataIndex: 'uid',
align: 'center',
},
{
title: '用户名称',
dataIndex: 'userName',
align: 'center',
render: (_value, record) => {
return record.userName ? record.userName : record.nickName ? record.nickName : `游客用户`;
},
},
{
title: '手机号',
dataIndex: 'phoneNum',
align: 'center',
render: (value) => {
return value || `-`;
},
},
{
title: '已销耗(元)',
dataIndex: 'rebatePaid',
align: 'center',
render: (value) => {
return moneyFormat(value);
},
},
{
title: '已冻结(元)',
dataIndex: 'rebateFreeze',
align: 'center',
render: (value) => {
return moneyFormat(value);
},
},
{
title: '奖励金账户(元)',
dataIndex: 'rcdRebateAmt',
align: 'center',
render: (value) => {
return moneyFormat(value);
},
},
{
title: '操作',
align: 'center',
width: 150,
fixed: 'right',
render: (_value, record, _index) => (
<Button
type='link'
size='small'
icon={<EditOutlined />}
onClick={() => handleDetail(record)}
>
变更
</Button>
),
},
];
// 表格数据
const [tableData, setTableData] = useState<TableType[]>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 按钮权限
// const btnChange = useOption(21101);
// 新版通用部分(ES6+ for React) ZhangLK 2022/08/30 Start
// 加载列表
const getTableList = async (value = {}) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
setTableData([{ id: 1, uid: 'UID1234132', userName: '刘旺' }]);
// 只需要修改这个地方的接口即可
// const res: any = await UserAPI.getBountyManageList({
// pageNo: pagination.current,
// pageSize: pagination.pageSize,
// ...value,
// });
// if (res && res.code === '200') {
// // console.log("res -->", res);
// const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
// setPagination({
// total: totalCount,
// pageSize,
// current: pageNo,
// totalPage,
// });
// setTableData(list);
// } else {
// message.warning(res.message);
// }
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (val: FormType) => {
// 在这里对提交的数据做处理,如range转为开始和结束时间
const data = Object.fromEntries(
// 过滤为空项
Object.entries({
...val,
pageNo: 1,
}).filter((i) => i[1] !== '' && i[1] !== undefined && i[1] !== null),
);
getTableList(data).then();
};
// 跳转详情
const handleDetail = (record: TableType) => {
const search = {
id: record.id,
uid: record.uid,
userName: record.userName ? record.userName : record.nickName ? record.nickName : `游客用户`,
};
navigate(`/customManage/customMoney/detail?${qs.stringify(search)}`);
// console.log(record);
};
// componentDidMount
useEffect(() => {
getTableList().then();
}, []);
return (
<>
<SearchBox search={searchColumns} searchData={onFinish} />
<Table
size='small'
rowKey='id'
dataSource={tableData}
columns={tableColumns}
scroll={{ x: 1500 }}
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
onChange: (page, pageSize) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
bordered
/>
</>
);
};
export default CustomMoneyView;
// 列表筛选表单类型
export interface FormType {
searchKey?: string;
}
// 表格列类型
export interface TableType {
id: number;
phoneNum: string;
rcdRebateAmt: number;
rebateFreeze: number;
rebatePaid: number;
uid: string;
userName: string;
nickName: string;
}
// 详情列表筛选表单类型
export interface DetailFormType {
endTime?: string;
mallUserId?: number;
pageNo?: number;
pageSize?: number;
payNO?: string;
startTime?: string;
type?: number;
time?: string[];
}
// 详情表格列类型
export interface DetailTableType {
amtPaid: number;
cashAmt: number;
cashFreeze: number;
createdTime: string;
id: number;
mallUserId: number;
orderTaskName: string;
orderTaskNo: string;
payNo: string;
payTime: string;
payType: number;
remark: string;
updateUserName: string;
voucher: string;
}
......@@ -31,6 +31,8 @@ import DivideOrder from '~/pages/pointManage/divideOrder';
import DivideRules from '~/pages/pointManage/divideRules';
// 客户列表
import CustomListView from '~/pages/customManage/customList';
import CustomMoneyView from '~/pages/customManage/customMoney';
import CustomMoneyDetail from '~/pages/customManage/customMoney/detail';
// 活动
const ActivityList = React.lazy(() => import('src/pages/activityManage/activityList')); //活动管理
// 服务
......@@ -237,6 +239,25 @@ export const routerList: Array<RouteObjectType> = [
icon: <SolutionOutlined />,
},
},
{
path: '/customManage/customMoney',
element: withLoadingComponent(<CustomMoneyView />),
meta: {
id: 26200,
title: '现金管理',
icon: <SolutionOutlined />,
},
},
{
path: '/customManage/customMoney/detail',
element: withLoadingComponent(<CustomMoneyDetail />),
meta: {
id: 26200,
title: '现金变更',
icon: <SolutionOutlined />,
hidden: true,
},
},
],
},
{
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论