Commit 01093727 authored by XieZhiXiong's avatar XieZhiXiong

feat: 对接优惠券发券相关

parent 1c8c5039
...@@ -2,103 +2,144 @@ ...@@ -2,103 +2,144 @@
* @Author: XieZhiXiong * @Author: XieZhiXiong
* @Date: 2021-06-29 09:36:25 * @Date: 2021-06-29 09:36:25
* @LastEditors: XieZhiXiong * @LastEditors: XieZhiXiong
* @LastEditTime: 2021-06-29 14:10:22 * @LastEditTime: 2021-07-28 18:07:52
* @Description: 发券明细 * @Description: 发券明细
*/ */
import React, { useState, useRef } from 'react'; import React, { useState } from 'react';
import { import {
Space, Space,
Button, Button,
Drawer, Drawer,
Modal,
message, message,
} from 'antd'; } from 'antd';
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface'; import { ColumnType } from 'antd/lib/table/interface';
import { createFormActions } from '@formily/antd'; import { createFormActions } from '@formily/antd';
import { DatePicker } from '@formily/antd-components'; import { DatePicker, NumberPicker } from '@formily/antd-components';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'; import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { useAsyncInitSelect } from '@/formSchema/effects/useAsyncInitSelect';
import { FORM_FILTER_PATH } from '@/formSchema/const'; import { FORM_FILTER_PATH } from '@/formSchema/const';
import { PublicApi } from '@/services/api'; import { PublicApi } from '@/services/api';
import { useRowSelectionTable } from '@/hooks/useRowSelectionTable'; import { useRowSelectionTable } from '@/hooks/useRowSelectionTable';
import MellowCard, { MellowCardProps } from '@/components/MellowCard'; import MellowCard, { MellowCardProps } from '@/components/MellowCard';
import NiceForm from '@/components/NiceForm'; import PolymericTable, { FetchParamsType } from '@/components/PolymericTable';
import { querySchema, drawerSchema } from './schema'; import { querySchema, drawerSchema } from './schema';
const { confirm } = Modal;
const outerFormActions = createFormActions(); const outerFormActions = createFormActions();
const drawerFormActions = createFormActions(); const drawerFormActions = createFormActions();
const fetchListData = async (params: any) => { export type SuitableMemberType = {
const payload = { ...params }; /**
const res = await PublicApi.getMemberProcessRuleRolePage(payload); * 会员id
if (res.code === 1000) { */
return res.data; memberId: number,
} /**
return []; * 会员角色id
}; */
roleId: number,
export type ListItemDataType = { /**
* 唯一的id
*/
onlyId: string,
/** /**
* 数据id * 会员名称
*/ */
productId: number, name: string,
/** /**
* 商品图片 * 适用用户
*/ */
productImg: string, memberAgeTypeName: string,
/** /**
* 商品图片 * 会员类型
*/ */
productName: string, memberTypeName: string,
/** /**
* 商品品类 * 会员等级
*/ */
category: string, level: string,
/** /**
* 商品品牌 * 会员角色
*/ */
brand: string, roleName: string,
/** /**
* 商品单位 * 成为会员时间开始
*/ */
unit: string, becomeTimeStart: string,
}
interface IProps extends Omit<MellowCardProps, 'onChange'> {
/** /**
* 商品单价 * 点击确认触发事件,参数待定
*/ */
price: number, onChange?: (value: SuitableMemberType[]) => void,
} }
interface IProps extends MellowCardProps { type ExtraFetchType = FetchParamsType & {
/** /**
* 数据 * 会员id
*/ */
dataSource?: ListItemDataType[]; memberId: number,
/** /**
* 点击确认触发事件,参数待定 * 会员名称
*/ */
onConfirm?: (value: any) => void, name: string,
}; /**
* 会员类型枚举
*/
memberTypeEnum: number,
/**
* 会员等级
*/
level: number,
/**
* 会员id和角色id数组,需要排除的数据
*/
excludeMemberList: {
memberId: number,
roleId: number,
}[],
/**
* 成为会员时间开始
*/
becomeTimeStart: string,
/**
* 成为会员时间结束
*/
becomeTimeEnd: string,
}
const DeliverCoupon: React.FC<IProps> = (props) => { const DeliverCoupon: React.FC<IProps> = (props) => {
const { const {
dataSource, onChange,
...rest ...rest
} = props; } = props;
const ref = useRef<any>({}); const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
const [visibleDrawer, setVisibleDrawer] = useState(false); const [visibleDrawer, setVisibleDrawer] = useState(false);
const [selectedMember, setSelectedMember] = useState<SuitableMemberType[]>([]);
const [rowSelection, RowCtl] = useRowSelectionTable({ customKey: 'roleId', type: 'checkbox' }); const [rowSelection, RowCtl] = useRowSelectionTable({ customKey: 'onlyId', type: 'checkbox' });
const fetchData = async (params: any) => { const fetchSuitableList = async (params: ExtraFetchType) => {
let res = await PublicApi.getMemberAbilityMaintenancePage(params); const payload = { ...params };
return res.data; const res = await PublicApi.postMemberManageMarketingSuitablePage(payload, { ctlType: 'none' });
if (res.code === 1000) {
const { data, ...rest } = res.data;
const newData = data.map((item) => ({
onlyId: `${item.memberId}+${item.roleId}`,
...item,
}));
return {...res.data, data: newData};
}
return { data: [], totalCount: 0 };
}; };
const columns: ColumnType<any>[] = [ const columns: ColumnType<any>[] = [
{ {
title: 'ID', title: 'ID',
dataIndex: 'id', dataIndex: 'memberId',
align: 'center', align: 'center',
}, },
{ {
...@@ -108,28 +149,34 @@ const DeliverCoupon: React.FC<IProps> = (props) => { ...@@ -108,28 +149,34 @@ const DeliverCoupon: React.FC<IProps> = (props) => {
}, },
{ {
title: '适用用户', title: '适用用户',
dataIndex: 'memberTypeName', dataIndex: 'memberAgeTypeName',
}, },
{ {
title: '会员类型', title: '会员类型',
dataIndex: 'registerTime', dataIndex: 'memberTypeName',
}, },
{ {
title: '会员角色', title: '会员角色',
dataIndex: 'registerTime', dataIndex: 'roleName',
}, },
{ {
title: '会员等级', title: '会员等级',
dataIndex: 'registerTime', dataIndex: 'levelTag',
}, },
{ {
title: '成为会员时间', title: '成为会员时间',
dataIndex: 'registerTime', dataIndex: 'becomeTime',
}, },
]; ];
const triggerChange = (value: SuitableMemberType[]) => {
if (onChange) {
onChange(value);
}
};
const outerRowSelection = { const outerRowSelection = {
onChange: (keys: number[]) => { onChange: (keys: string[]) => {
setSelectedRowKeys(keys); setSelectedRowKeys(keys);
}, },
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -141,11 +188,68 @@ const DeliverCoupon: React.FC<IProps> = (props) => { ...@@ -141,11 +188,68 @@ const DeliverCoupon: React.FC<IProps> = (props) => {
const handleConfirm = () => { const handleConfirm = () => {
if (!RowCtl.selectRow.length) { if (!RowCtl.selectRow.length) {
message.warning('请选择会员角色'); message.warning('请选择会员');
return;
} }
setSelectedMember(RowCtl.selectRow);
triggerChange(RowCtl.selectRow);
handleVisibleDrawer(false); handleVisibleDrawer(false);
}; };
const handleBatchDelete = (keys: string[]) => {
if (!keys.length) {
message.warning('请勾选需要删除的会员');
return;
}
confirm({
title: '提示',
icon: <ExclamationCircleOutlined />,
content: `确定需要删除选中的会员吗?`,
onOk() {
const filtered = selectedMember.filter((item) => !keys.includes(item.onlyId));
setSelectedMember(filtered);
triggerChange(filtered);
setSelectedRowKeys([]);
},
});
};
const outerColumns = columns.concat({
title: '操作',
dataIndex: 'option',
render: (_, record) => (
<Button
type="link"
onClick={() => handleBatchDelete([record.onlyId])}
>
删除
</Button>
),
});
// 初始化高级筛选选项
const fetchSelectOptions = async () => {
const res = await PublicApi.postMemberManageMarketingSuitablePageItems(null, {
ctlType: 'none',
});
if (res.code === 1000) {
const { data = {} }: any = res;
const {
memberTypes = [],
levels = [],
suitableMemberTypes = [],
} = data;
return {
memberType: memberTypes.map(item => ({ label: item.memberTypeName, value: item.memberTypeId })),
level: levels.map(item => ({ label: item.levelTag, value: item.level })),
suitableMemberType: suitableMemberTypes.map(item => ({ label: item.name, value: item.value })),
};
}
return {};
};
const ControllerBtns = () => ( const ControllerBtns = () => (
<Space size={16}> <Space size={16}>
<Button <Button
...@@ -156,7 +260,7 @@ const DeliverCoupon: React.FC<IProps> = (props) => { ...@@ -156,7 +260,7 @@ const DeliverCoupon: React.FC<IProps> = (props) => {
选择会员 选择会员
</Button> </Button>
<Button <Button
onClick={() => {}} onClick={() => handleBatchDelete(selectedRowKeys)}
> >
批量删除 批量删除
</Button> </Button>
...@@ -168,33 +272,31 @@ const DeliverCoupon: React.FC<IProps> = (props) => { ...@@ -168,33 +272,31 @@ const DeliverCoupon: React.FC<IProps> = (props) => {
title="发券明细" title="发券明细"
{...rest} {...rest}
> >
<StandardTable <PolymericTable
tableProps={{ rowKey="onlyId"
rowKey: 'validateId', columns={outerColumns}
}} dataSource={selectedMember}
columns={columns} pagination={null}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
rowSelection={outerRowSelection} rowSelection={outerRowSelection}
controlRender={ searchFormProps={{
<NiceForm schema: querySchema,
actions={outerFormActions} components: {
components={{ ControllerBtns,
ControllerBtns, RangePicker: DatePicker.RangePicker,
RangePicker: DatePicker.RangePicker, },
}} effects: ($, actions) => {
onSubmit={values => ref.current.reload(values)} useStateFilterSearchLinkageEffect(
effects={($, actions) => { $,
useStateFilterSearchLinkageEffect( actions,
$, 'name',
actions, FORM_FILTER_PATH,
'name', );
FORM_FILTER_PATH, useAsyncInitSelect(
); ['memberType', 'level', 'suitableMemberType'],
}} fetchSelectOptions,
schema={querySchema} );
/> },
} }}
/> />
<Drawer <Drawer
...@@ -216,30 +318,35 @@ const DeliverCoupon: React.FC<IProps> = (props) => { ...@@ -216,30 +318,35 @@ const DeliverCoupon: React.FC<IProps> = (props) => {
</Button> </Button>
</div> </div>
} }
bodyStyle={{
paddingBottom: 0,
}}
> >
<StandardTable <PolymericTable
tableProps={{ rowKey="onlyId"
rowKey: 'roleId',
}}
columns={columns} columns={columns}
currentRef={ref}
rowSelection={rowSelection} rowSelection={rowSelection}
fetchTableData={(params: any) => fetchListData(params)} fetchDataSource={fetchSuitableList}
controlRender={ defaultPageSize={15}
<NiceForm searchFormProps={{
actions={drawerFormActions} schema: drawerSchema,
onSubmit={values => ref.current.reload(values)} components: {
effects={($, actions) => { NumberPicker,
useStateFilterSearchLinkageEffect( },
$, effects: ($, actions) => {
actions, useStateFilterSearchLinkageEffect(
'name', $,
FORM_FILTER_PATH, actions,
); 'name',
}} FORM_FILTER_PATH,
schema={drawerSchema} );
/> useAsyncInitSelect(
} ['memberType', 'level', 'suitableMemberType'],
fetchSelectOptions,
);
},
}}
full
/> />
</Drawer> </Drawer>
</MellowCard> </MellowCard>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: XieZhiXiong * @Author: XieZhiXiong
* @Date: 2021-06-29 09:36:35 * @Date: 2021-06-29 09:36:35
* @LastEditors: XieZhiXiong * @LastEditors: XieZhiXiong
* @LastEditTime: 2021-06-29 10:18:11 * @LastEditTime: 2021-07-28 17:49:07
* @Description: * @Description:
*/ */
import { ISchema } from '@formily/antd'; import { ISchema } from '@formily/antd';
...@@ -31,7 +31,7 @@ export const querySchema: ISchema = { ...@@ -31,7 +31,7 @@ export const querySchema: ISchema = {
'x-component': 'Search', 'x-component': 'Search',
'x-component-props': { 'x-component-props': {
placeholder: '搜索', placeholder: '搜索',
tip: '输入 优惠劵名称 进行搜索', tip: '输入 会员名称 进行搜索',
}, },
}, },
}, },
...@@ -45,33 +45,48 @@ export const querySchema: ISchema = { ...@@ -45,33 +45,48 @@ export const querySchema: ISchema = {
}, },
}, },
properties: { properties: {
id: { memberId: {
type: 'string', type: 'string',
'x-component-props': { 'x-component-props': {
placeholder: '优惠劵ID', placeholder: '会员ID',
allowClear: true, allowClear: true,
style: {
width: 160,
},
}, },
}, },
'[startTime2, endTime2]': { memberType: {
type: 'object', type: 'string',
'x-component': 'RangePicker', default: undefined,
enum: [],
'x-component-props': { 'x-component-props': {
placeholder: ['劵有效期起始时间', '劵有效期截止时间'], placeholder: '会员类型(所有)',
showTime: true, allowClear: true,
}, },
}, },
type: { level: {
type: 'string', type: 'string',
default: undefined, default: undefined,
enum: [], enum: [],
'x-component-props': { 'x-component-props': {
placeholder: '优惠劵类型(所有)', placeholder: '会员等级(所有)',
allowClear: true, allowClear: true,
}, },
}, },
suitableMemberType: {
type: 'string',
default: undefined,
enum: [],
'x-component-props': {
placeholder: '适用用户(所有)',
allowClear: true,
},
},
'[startTime2, endTime2]': {
type: 'string',
'x-component': 'RangePicker',
'x-component-props': {
placeholder: ['成为会员起始时间', '成为会员截止时间'],
showTime: true,
},
},
submit: { submit: {
'x-component': 'Submit', 'x-component': 'Submit',
'x-mega-props': { 'x-mega-props': {
...@@ -105,17 +120,19 @@ export const drawerSchema: ISchema = { ...@@ -105,17 +120,19 @@ export const drawerSchema: ISchema = {
'x-component': 'Mega-Layout', 'x-component': 'Mega-Layout',
'x-component-props': { 'x-component-props': {
grid: true, grid: true,
full: true,
autoRow: true,
columns: 4, columns: 4,
}, },
properties: { properties: {
id: { memberId: {
type: 'string', type: 'string',
'x-component': 'NumberPicker',
'x-component-props': { 'x-component-props': {
placeholder: '会员ID', placeholder: '会员ID',
allowClear: true,
}, },
}, },
memberType: { memberTypeEnum: {
type: 'string', type: 'string',
default: undefined, default: undefined,
enum: [], enum: [],
...@@ -124,7 +141,7 @@ export const drawerSchema: ISchema = { ...@@ -124,7 +141,7 @@ export const drawerSchema: ISchema = {
allowClear: true, allowClear: true,
}, },
}, },
memberLevel: { level: {
type: 'string', type: 'string',
default: undefined, default: undefined,
enum: [], enum: [],
...@@ -133,7 +150,7 @@ export const drawerSchema: ISchema = { ...@@ -133,7 +150,7 @@ export const drawerSchema: ISchema = {
allowClear: true, allowClear: true,
}, },
}, },
applicable: { suitableMemberType: {
type: 'string', type: 'string',
default: undefined, default: undefined,
enum: [], enum: [],
...@@ -142,7 +159,7 @@ export const drawerSchema: ISchema = { ...@@ -142,7 +159,7 @@ export const drawerSchema: ISchema = {
allowClear: true, allowClear: true,
}, },
}, },
'[startTime2, endTime2]': { '[becomeTimeStart, becomeTimeEnd]': {
type: 'string', type: 'string',
'x-component': 'RangePicker', 'x-component': 'RangePicker',
'x-component-props': { 'x-component-props': {
......
...@@ -2,15 +2,21 @@ ...@@ -2,15 +2,21 @@
* @Author: XieZhiXiong * @Author: XieZhiXiong
* @Date: 2021-06-28 17:51:33 * @Date: 2021-06-28 17:51:33
* @LastEditors: XieZhiXiong * @LastEditors: XieZhiXiong
* @LastEditTime: 2021-07-06 14:07:32 * @LastEditTime: 2021-07-28 17:33:55
* @Description: * @Description: 商家优惠劵发劵
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { import {
Row, Row,
Col, Col,
Spin, Spin,
Button,
message,
} from 'antd'; } from 'antd';
import {
SendOutlined,
} from '@ant-design/icons';
import { history } from 'umi';
import { usePageStatus } from '@/hooks/usePageStatus'; import { usePageStatus } from '@/hooks/usePageStatus';
import { PublicApi } from '@/services/api'; import { PublicApi } from '@/services/api';
import { GetMarketingCouponWaiteExecuteGetResponse } from '@/services/MarketingApi'; import { GetMarketingCouponWaiteExecuteGetResponse } from '@/services/MarketingApi';
...@@ -19,18 +25,21 @@ import AnchorPage from '@/layouts/AnchorPage'; ...@@ -19,18 +25,21 @@ import AnchorPage from '@/layouts/AnchorPage';
import AuditProcess from '@/components/AuditProcess'; import AuditProcess from '@/components/AuditProcess';
import BacisInfo from '../../components/BacisInfo'; import BacisInfo from '../../components/BacisInfo';
import CouponRules from '../../components/CouponRules'; import CouponRules from '../../components/CouponRules';
import DeliverCoupon from '../../components/DeliverCoupon'; import DeliverCoupon, { SuitableMemberType } from '../../components/DeliverCoupon';
const MerchantCouponAnalysisDeliver: React.FC<{}> = () => { const MerchantCouponAnalysisDeliver: React.FC<{}> = () => {
const { id } = usePageStatus(); const { id } = usePageStatus();
const [couponInfo, setCouponInfo] = useState<GetMarketingCouponWaiteExecuteGetResponse>(null); const [couponInfo, setCouponInfo] = useState<GetMarketingCouponWaiteExecuteGetResponse>(null);
const [infoLoading, setInfoLoaading] = useState(false); const [infoLoading, setInfoLoading] = useState(false);
const [submitLoading, setSubmitLoading] = useState(false);
const deliverRef = useRef<SuitableMemberType[]>([]);
const getBasicInfo = () => { const getBasicInfo = () => {
if (!id) { if (!id) {
return; return;
} }
setInfoLoaading(true); setInfoLoading(true);
PublicApi.getMarketingCouponWaiteExecuteGet({ PublicApi.getMarketingCouponWaiteExecuteGet({
id, id,
}).then(res => { }).then(res => {
...@@ -38,7 +47,7 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => { ...@@ -38,7 +47,7 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => {
setCouponInfo(res.data); setCouponInfo(res.data);
} }
}).finally(() => { }).finally(() => {
setInfoLoaading(false); setInfoLoading(false);
}); });
}; };
...@@ -46,6 +55,34 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => { ...@@ -46,6 +55,34 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => {
getBasicInfo(); getBasicInfo();
}, []); }, []);
const handleDeliverChange = (value: SuitableMemberType[]) => {
deliverRef.current = value;
};
const handleSubmit = () => {
if (!id) {
return;
}
if (!deliverRef.current.length) {
message.warning('未选择任何会员');
return;
}
setSubmitLoading(true);
PublicApi.postMarketingCouponWaiteExecuteGrant({
id: +id,
grantMembers: deliverRef.current.map((item) => ({ subMemberId: item.memberId, subRoleId: item.roleId })),
}).then(res => {
if (res.code !== 1000) {
return;
}
setTimeout(() => {
history.goBack();
}, 800);
}).finally(() => {
setSubmitLoading(false);
});
};
const anchorsArr = [ const anchorsArr = [
{ {
key: 'verifySteps', key: 'verifySteps',
...@@ -70,6 +107,16 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => { ...@@ -70,6 +107,16 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => {
<AnchorPage <AnchorPage
title={couponInfo?.name} title={couponInfo?.name}
anchors={anchorsArr} anchors={anchorsArr}
extra={(
<Button
type="primary"
icon={<SendOutlined style={{ transform: `rotate(-45deg)`, position: 'relative', top: -2 }} />}
onClick={handleSubmit}
loading={submitLoading}
>
提交
</Button>
)}
> >
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
{/* 流转记录 */} {/* 流转记录 */}
...@@ -121,6 +168,7 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => { ...@@ -121,6 +168,7 @@ const MerchantCouponAnalysisDeliver: React.FC<{}> = () => {
{/* 优惠券规则 */} {/* 优惠券规则 */}
<Col span={24}> <Col span={24}>
<DeliverCoupon <DeliverCoupon
onChange={handleDeliverChange}
id="deliverCoupon" id="deliverCoupon"
/> />
</Col> </Col>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment