提交 b2587d66 作者: ZhangLingKun

优化:营销管理-积分兑换商品上传

上级 9852b21a
流水线 #8667 已通过 于阶段
in 1 分 1 秒
...@@ -201,3 +201,40 @@ export type activityInviteDetailType = InterListFunction< ...@@ -201,3 +201,40 @@ export type activityInviteDetailType = InterListFunction<
}; };
} }
>; >;
// 后台——添加积分商品
export type insertMallType = InterFunction<
{
goods?: string;
goodsUrl?: string;
id?: number;
needPoints?: number;
},
null
>;
// 后台——修改积分商品
export type updateMallType = InterFunction<
{
goods?: string;
goodsUrl?: string;
id?: number;
needPoints?: number;
},
null
>;
// 积分商城列表
export type getMallListType = InterListFunction<
NonNullable<unknown>,
{
goods: string;
goodsUrl: string;
id: number;
needPoints: number;
}
>;
// 后台——删除积分商品
export type deleteMallType = InterFunction<
{
id: number;
},
null
>;
...@@ -8,10 +8,14 @@ import { ...@@ -8,10 +8,14 @@ import {
activityUpdateType, activityUpdateType,
addActivityType, addActivityType,
DataInfoType, DataInfoType,
deleteMallType,
endActivityType, endActivityType,
getMallListType,
insertMallType,
listActivityPagesType, listActivityPagesType,
SignInListType, SignInListType,
splitCouponDownType, splitCouponDownType,
updateMallType,
} from '../interface/activityManage'; } from '../interface/activityManage';
import axios from '../request'; import axios from '../request';
...@@ -79,4 +83,21 @@ export class ActivityManageAPI { ...@@ -79,4 +83,21 @@ export class ActivityManageAPI {
static activityInviteDetail: activityInviteDetailType = (params) => { static activityInviteDetail: activityInviteDetailType = (params) => {
return axios.post('/userapp/activity/inviteDetail', params); return axios.post('/userapp/activity/inviteDetail', params);
}; };
// 后台——添加积分商品
static insertMall: insertMallType = (params) => {
return axios.post('/oms/pointsMall/insertMall', params);
};
// 后台——修改积分商品
static updateMall: updateMallType = (params) => {
return axios.post('/oms/pointsMall/updateMall', params);
};
// 积分商城列表
static getMallList: getMallListType = (params) => {
return axios.post('/oms/pointsMall/getMallList', params);
};
// 后台——删除积分商品
static deleteMall: deleteMallType = (params) => {
return axios.get('/oms/pointsMall/deleteMall', { params });
};
} }
import React, { useEffect, useState } from 'react';
import { Form, Input, message, Modal, ModalProps } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
import { InterReqType } from '~/api/interface';
import { updateMallType } from '~/api/interface/activityManage';
import { ActivityManageAPI } from '~/api';
// 请求的表单类型
type ReqType = InterReqType<updateMallType>;
const AddEditModalView: React.FC<ModalProps & { data: ReqType; onCancel: () => void }> = ({
open,
title,
onCancel,
data,
}) => {
// 表单数据
const [form] = Form.useForm<ReqType>();
// 店铺图片列表
const [imageList, setImageList] = useState<any>([]);
// 店铺图片列表上传
const imageListChange = (value: any) => {
setImageList(value);
form.setFieldValue('goodsUrl', JSON.stringify(value?.map((i: { url: string }) => i?.url)));
};
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
setImageList([]);
onCancel?.();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
await handleSubmit(values);
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交数据
const handleSubmit = async (values: ReqType) => {
const res = await ActivityManageAPI[data?.id ? 'updateMall' : 'insertMall']({
...data,
...values,
});
if (res && res.code === '200') {
message.success(data?.id ? '修改成功' : '添加成功');
handleCancel();
}
};
// 组件挂载
useEffect(() => {
if (!data) return;
form.setFieldsValue(data);
try {
setImageList(
(JSON.parse(data.goodsUrl || `[]`) || [])?.map((i: { url: string }, j: number) => ({
id: j,
url: i,
})),
);
} catch (e) {
setImageList([]);
}
// console.log('组件挂载 --->', data);
}, [open]);
return (
<Modal open={open} title={title} onCancel={handleCancel} onOk={handleOk}>
<Form form={form} labelCol={{ span: 4 }} wrapperCol={{ span: 14 }}>
<Form.Item
label='商品名称'
name='goods'
rules={[{ required: true, message: '请输入商品名称' }]}
>
<Input placeholder={'请输入商品名称'} maxLength={25} allowClear />
</Form.Item>
<Form.Item
label='商品图片'
name='goodsUrl'
rules={[{ required: true, message: '请上传商品图片' }]}
>
<Uploader
fileUpload
listType='picture-card'
defaultFileList={imageList}
onChange={imageListChange}
fileLength={1}
fileSize={10}
>
<UploadOutlined />
</Uploader>
</Form.Item>
<Form.Item
label='消耗积分'
name='needPoints'
rules={[
{ required: true, message: '请输入消耗积分' },
{ pattern: /^[1-9]\d*$/, message: '请输入正整数' },
{
validator: (_rule, value) => {
if (value > 99999999) {
return Promise.reject('最大不能超过99999999');
}
return Promise.resolve();
},
},
]}
>
<Input placeholder={'请输入消耗积分'} maxLength={25} allowClear type={'number'} />
</Form.Item>
</Form>
</Modal>
);
};
export default AddEditModalView;
import React, { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, message, Modal, Table, Image } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import AddEditModalView from './comp/addEditModal';
import { InterListType, InterReqListType } from '~/api/interface';
import { getMallListType } from '~/api/interface/activityManage';
import { ActivityManageAPI } from '~/api';
// 表格列表
type TableType = InterListType<getMallListType>;
// 搜索表单的类型
type ReqType = InterReqListType<getMallListType>;
// 搜索表单的数据
let query: ReqType = {};
const PointExchangeGoodsPage: React.FC = () => {
// 新增编辑弹窗是否开启
const [addEditShow, setAddEditShow] = useState<boolean>(false);
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 需要编辑的数据
const [recordData, setRecordData] = useState<TableType[0]>();
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// +++++++++++++++++++++++++++++++++++++++++++++++++++ //
// 新版通用部分(ES6+ for React) ZhangLK 2022/08/30 Start
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await ActivityManageAPI.getMallList({
pageNo: pagination.current,
pageSize: pagination.pageSize,
...value,
...query,
});
if (res && res.code === '200') {
const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
setPagination({
total: totalCount,
current: pageNo,
pageSize,
totalPage,
});
setTableData(list || []);
// console.log('加载列表 --->', list);
} else {
message.warning(res.message);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// +++++++++++++++++++++++++++++++++++++++++++++++++++ //
// 删除数据
const handleDelete = (record: TableType[0]) => {
Modal.confirm({
title: '提示',
content: '删除后将无法恢复,请确认是否删除?',
onOk: async () => {
const res = await ActivityManageAPI.deleteMall({ id: record?.id });
if (res && res.code === '200') {
paginationChange(
tableData.length === 1 && pagination.current !== 1
? pagination.current - 1
: pagination.current,
pagination.pageSize,
);
message.success('删除成功');
}
},
});
};
// 转换商品图片数据
const getGoodsUrl = (record: TableType[0]) => {
try {
const image = (JSON.parse(record.goodsUrl || `[]`) || [])?.[0];
return <Image src={image} alt={record.goods} width={35} height={35}></Image>;
} catch (e) {
return `无`;
}
};
// 页面挂载
useEffect(() => {
query = {};
(async () => {
await getTableList();
})();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '序号',
dataIndex: 'accountNo',
align: 'center',
width: '50px',
render: (_text, _record, index) => (pagination.current - 1) * pagination.pageSize + index + 1,
},
{
title: '商品名称',
dataIndex: 'goods',
align: 'center',
},
{
title: '商品图片',
dataIndex: 'goodsUrl',
align: 'center',
render: (_text, record) => getGoodsUrl(record),
},
{
title: '消耗积分',
dataIndex: 'needPoints',
align: 'center',
},
{
title: '操作',
dataIndex: 'id',
align: 'center',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setAddEditShow(true);
setRecordData(record);
}}
>
编辑
</Button>
<Button type={'link'} danger onClick={() => handleDelete(record)}>
删除
</Button>
</>
),
},
];
return (
<>
<SearchBox
child={
<Button type={'primary'} icon={<PlusOutlined />} onClick={() => setAddEditShow(true)}>
添加商品
</Button>
}
search={[
{
label: '商品名称',
name: 'name',
type: 'Input',
placeholder: '请输入活动名称',
maxlength: 20,
},
]}
searchData={onFinish}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1000 }}
bordered
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
<AddEditModalView
open={addEditShow}
title={recordData?.id ? '编辑商品' : '添加商品'}
data={recordData}
onCancel={() => {
setAddEditShow(false);
setRecordData(undefined);
paginationChange(pagination?.current, pagination?.pageSize);
}}
/>
</>
);
};
export default PointExchangeGoodsPage;
...@@ -16,7 +16,7 @@ type DataType = InterDataType<getSuggestionType>[0]; ...@@ -16,7 +16,7 @@ type DataType = InterDataType<getSuggestionType>[0];
const AddSolutionModal: React.FC< const AddSolutionModal: React.FC<
ModalProps & { detail: DetailType; onCancel?: () => void; data?: DataType } ModalProps & { detail: DetailType; onCancel?: () => void; data?: DataType }
> = ({ open, onCancel, data }) => { > = ({ open, title, onCancel, data }) => {
// 表单数据 // 表单数据
const [form] = Form.useForm<ReqType>(); const [form] = Form.useForm<ReqType>();
// 封面图列表 // 封面图列表
...@@ -75,7 +75,7 @@ const AddSolutionModal: React.FC< ...@@ -75,7 +75,7 @@ const AddSolutionModal: React.FC<
setSuggestFileList([{ url: data.suggestFile }]); setSuggestFileList([{ url: data.suggestFile }]);
}, [data]); }, [data]);
return ( return (
<Modal open={open} title={'添加方案'} width={450} onCancel={handleCancel} onOk={handleOk}> <Modal open={open} title={title} width={450} onCancel={handleCancel} onOk={handleOk}>
<Form form={form} labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}> <Form form={form} labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}>
<Form.Item <Form.Item
label='方案标题' label='方案标题'
......
...@@ -125,6 +125,7 @@ const StoreSolutionView: React.FC<{ ...@@ -125,6 +125,7 @@ const StoreSolutionView: React.FC<{
open={isAddSolution} open={isAddSolution}
detail={detail} detail={detail}
data={editData} data={editData}
title={editData?.id ? '编辑方案' : '添加方案'}
onCancel={() => { onCancel={() => {
setIsAddSolution(false); setIsAddSolution(false);
setEditData(undefined); setEditData(undefined);
......
...@@ -37,6 +37,7 @@ import { ...@@ -37,6 +37,7 @@ import {
UsergroupAddOutlined, UsergroupAddOutlined,
ContactsOutlined, ContactsOutlined,
CommentOutlined, CommentOutlined,
DropboxOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Spin } from 'antd'; import { Spin } from 'antd';
...@@ -174,6 +175,7 @@ import CourseCategoryView from '~/pages/pilotTraining/courseCategory'; ...@@ -174,6 +175,7 @@ import CourseCategoryView from '~/pages/pilotTraining/courseCategory';
import NoticeManageView from '~/pages/resourceManage/noticeManage'; import NoticeManageView from '~/pages/resourceManage/noticeManage';
import CustomApplyPage from '~/pages/customManage/customApply'; import CustomApplyPage from '~/pages/customManage/customApply';
import StoreDecoratePage from '~/pages/resourceManage/storeDecorate'; import StoreDecoratePage from '~/pages/resourceManage/storeDecorate';
import PointExchangeGoodsPage from '~/pages/activityManage/pointExchangeGoods';
const AddressManageView = React.lazy(() => import('~/pages/systemManage/addressManage')); const AddressManageView = React.lazy(() => import('~/pages/systemManage/addressManage'));
// const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表 // const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表
...@@ -1049,6 +1051,17 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -1049,6 +1051,17 @@ export const routerList: Array<RouteObjectType> = [
pid: 920, pid: 920,
}, },
}, },
{
path: '/activityManage/pointExchangeGoods',
element: withLoadingComponent(<PointExchangeGoodsPage />),
errorElement: <ErrorPage />,
meta: {
id: 930,
title: '兑换商品',
icon: <DropboxOutlined />,
develop: true,
},
},
], ],
}, },
{ {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论