Commit 033cd60f authored by 前端-钟卫鹏's avatar 前端-钟卫鹏
parents 543344d2 999b1347
.textOverflowMulti2(@line: 3) {
display: -webkit-box;
/* autoprefixer: off */
-webkit-box-orient:vertical;
/* autoprefixer: on */
-webkit-line-clamp: @line;
overflow: hidden;
}
.section {
display: flex;
flex-direction: row;
align-items: center;
padding: 16px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px 0 rgba(0,0,0,0.04);
transition: width 0.5s;
overflow: hidden;
width: 72px;
height: 72px;
border: 1px solid transparent;
.img {
width: 40px;
height: 40px;
margin-right: 16px;
flex-shrink: 0;
}
&:hover {
width: 384px;
border: 1px solid @primary-color;
}
.info {
display: flex;
flex-direction: column;
flex: 1;
.titleContainer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.title {
font-size: 14px;
color: #252D37;
flex: 1;
.textOverflowMulti2(1)
}
}
.footer {
margin-top: 4px;
overflow: hidden;
.id {
margin-right: 16px;
font-size: 12px;
color: #909399;
}
}
}
}
.indeterminate {
border: 1px solid #1890ff;
}
.active {
width: 384px;
border: 1px solid @primary-color;
}
import React from 'react';
import StatusTag from '@/components/StatusTag';
import cx from 'classnames';
import styles from './activityItem.less';
interface Iprops {
id: number,
activityName: string,
activityTypeName: string,
statusName: string,
isActive: boolean,
onSelect?: ( (id: number) => void) | null,
hasChildSelected?: boolean,
activityImage: string,
}
const ActivityItem: React.FC<Iprops> = (props: Iprops) => {
const { id, activityName, activityTypeName, statusName, isActive = false, onSelect = null, hasChildSelected = false, activityImage } = props;
const triggerSelect = () => {
onSelect?.(id);
};
const mergeClasses = cx(styles.section, {
[styles.indeterminate]: hasChildSelected,
[styles.active]: isActive,
})
return (
<div onClick={triggerSelect} className={mergeClasses}>
<img className={styles.img} src={activityImage}/>
<div className={styles.info}>
<div className={styles.titleContainer}>
<span className={styles.title}>{activityName}</span>
<StatusTag title={statusName} type="success" />
</div>
<div className={styles.footer}>
<span className={styles.id}>ID: {id}</span>
<StatusTag type="default" title={activityTypeName} />
</div>
</div>
</div>
);
};
export default ActivityItem;
.productImg {
width: 64px;
height: 64px;
border-radius: 8px;
overflow: hidden;
}
.productName {
font-size: 14px;
color: #252D37;
line-height: 20px
}
.priceInfo {
font-size: 14px;
color: #D32F2F;
.unit {
color: #909399;
font-size: 12px;
}
}
.container {
display: flex;
flex-direction: column;
height: 100%;
.form {}
.table {
display: flex;
flex-direction: row;
align-items: center;
.activeItem + .activeItem {
margin-left: 8px;
}
}
.expandableTable {
margin-top: 16px;
}
.pagination {
margin-top: auto;
display: flex;
flex-direction: row-reverse;
}
}
.drawerFooter {
display: flex;
flex-direction: row-reverse;
}
/* eslint-disable react/display-name */
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Drawer, Table, Button, Space, Pagination, Spin } from 'antd';
import NiceForm from '@/components/NiceForm';
import { createFormActions } from '@formily/antd';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { unstable_batchedUpdates as batchedUpdates } from 'react-dom';
import { ColumnsType } from 'antd/es/table';
import { GetMarketingPlatformActivityListAdornResponseDetail } from '@/services/MaketingV2Api';
import StatusTag from '@/components/StatusTag';
import schema from './schema';
import styles from './activityProductDrawer.less';
import ActivityItem from './activityItem';
const actions = createFormActions();
interface Iprops {
visible: boolean,
onCancel: (() => void) | null,
fetchData?: ((params: any) => Promise<any>) | null,
onOk?: ((data: any) => void) | null,
/** 传入的已选择的活动商品 */
products: any[],
activityImage: string,
mode?: 'radio' | 'checked',
}
type SubmitType = {
id: number,
activityName: string,
}
const columns: ColumnsType<GetMarketingPlatformActivityListAdornResponseDetail["productList"][0]> = [
{
title: '商品信息',
dataIndex: 'productInfo',
render: (_text, _record) => {
return (
<Space align="center">
<img src={_record.productImgUrl} className={styles.productImg} />
<span className={styles.productName}>{_record.productName}</span>
</Space>
);
}
},
{
title: '品类',
dataIndex:'category',
render: (_text) => {
return <StatusTag title={_text} type="default" />;
}
},
{
title: '品牌',
dataIndex: 'brand'
},
{
title: '商家名称',
dataIndex: 'memberName',
},
{
title: '单价',
dataIndex: 'unit',
render: (_text, _record) => {
return (
<div className={styles.priceInfo}>
<span>{_record.price}</span>
<span className={styles.unit}>({_record.unit})</span>
</div>
);
}
},
{
title: '活动价',
dataIndex: 'activityPrice',
render: (_text, _record) => {
return (
<div className={styles.priceInfo}>
<span>{_record.activityPrice}</span>
<span className={styles.unit}>({_record.unit})</span>
</div>
);
}
}
];
const ActivityProductDrawer: React.FC<Iprops> = (props: Iprops) => {
const { visible, onCancel, fetchData = null, onOk, products = [], activityImage, mode = 'checked' } = props;
const [current, setPage] = useState<number>(1);
const [currentPageSize, setPageSize] = useState<number>(10);
const [dataSource, setDataSource] = useState<GetMarketingPlatformActivityListAdornResponseDetail[]>([]);
const [totalCount, setTotalCount] = useState<number>(0);
const [selectedKey, setSelectKey] = useState<number | null>(null);
const [selectedActivityProductList, setSelectedActivityProductList] = useState<GetMarketingPlatformActivityListAdornResponseDetail["productList"]>();
const [checkedProduct, setCheckedProduct] = useState<GetMarketingPlatformActivityListAdornResponseDetail["productList"]>([]);
const [loading, setLoading] = useState<boolean>(false);
const selectedRowKeys = useMemo(() => checkedProduct.map((_item) => `${_item.activityId!}-${_item.id!}`), [checkedProduct]);
const fetchList = useCallback(async (params: any) => {
if (fetchData === null) {
return;
}
setLoading(true);
const { data, code } = await fetchData(params);
if (code === 1000) {
batchedUpdates(() => {
setLoading(false);
setDataSource(data.data);
setTotalCount(data.totalCount);
});
}
}, [fetchData]);
useEffect(() => {
if (!visible) {
return ;
}
setCheckedProduct(products);
fetchList({ current, pageSize: currentPageSize });
}, [current, currentPageSize, visible,]);
const onSubmit = (value: SubmitType) => {
console.log(value);
fetchList({ current, pageSize: currentPageSize, ...value });
};
const onReset = () => {
// actions.reset();
fetchList({ current, pageSize: currentPageSize });
};
// useEffect(() => {})
const handleCancel = () => {
onCancel?.();
};
const onChange = (page: number, pageSize?: number) => {
batchedUpdates(() => {
setPage(page);
setPageSize(pageSize || 10);
});
};
const onSelect = (id: number) => {
setSelectKey(id);
const target = dataSource.filter((_item) => _item.id === id)[0];
setSelectedActivityProductList(target.productList);
};
const handleOk = () => {
onOk?.(checkedProduct);
};
const handleRowSelect = (record: GetMarketingPlatformActivityListAdornResponseDetail["productList"][0], selected: boolean, selectedRows: GetMarketingPlatformActivityListAdornResponseDetail["productList"]) => {
if (mode === 'checked') {
if (selected) {
setCheckedProduct((prev) => prev.concat(record));
} else {
const key = `${record.activityId!}-${record.id!}`;
setCheckedProduct((prev) => prev.filter((_item) => {
const tempKey = `${_item.activityId}-${_item.id}`;
return key !== tempKey;
}));
}
return;
}
setCheckedProduct([record]);
};
const rowSelection = {
type: mode,
onSelect: handleRowSelect,
selectedRowKeys: selectedRowKeys
};
const drawerStyle = { background: '#FAFBFC' };
return (
<Drawer
onClose={handleCancel}
headerStyle={drawerStyle}
bodyStyle={drawerStyle}
footerStyle={drawerStyle}
title="选择活动商品"
visible={visible}
width={950}
footer={
<div className={styles.drawerFooter}>
<Space>
<Button onClick={handleCancel}>取消</Button>
<Button onClick={handleOk}>确定</Button>
</Space>
</div>
}
>
<div className={styles.container}>
<div className={styles.form}>
<NiceForm
schema={schema}
actions={actions}
onReset={onReset}
onSubmit={onSubmit}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, 'id', FORM_FILTER_PATH);
}}
></NiceForm>
</div>
<div className={styles.table}>
{
dataSource?.map((_item) => {
const { outerStatusName, id, activityName, activityTypeName } = _item;
const isActive = selectedKey === id;
const hasChildSelected = selectedRowKeys.some((_rowKey) => _rowKey.split("-")[0] === id.toString());
return (
<div key={_item.id} className={styles.activeItem}>
<ActivityItem
onSelect={onSelect}
isActive={isActive}
id={id}
activityName={activityName}
statusName={outerStatusName}
activityTypeName={activityTypeName}
hasChildSelected={hasChildSelected}
activityImage={activityImage}
/>
</div>
);
})
}
</div>
<div className={styles.expandableTable}>
<Table
rowSelection={rowSelection as any}
rowKey={(_record) => `${_record.activityId!}-${_record.id!}` }
loading={loading}
columns={columns} dataSource={selectedActivityProductList}></Table>
</div>
<div className={styles.pagination}>
<Pagination pageSize={currentPageSize} current={current} showQuickJumper total={totalCount} onChange={onChange}/>
</div>
</div>
</Drawer>
);
};
export default ActivityProductDrawer;
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ISchema } from '@formily/antd';
const schema: ISchema = {
type: 'object',
properties: {
megaLayout: {
type: 'object',
'x-component': 'mega-layout',
properties: {
id: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
placeholder: '搜索',
align: 'flex-left',
tip: '输入活动ID进行搜索',
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
grid: true,
full: true,
aotoRow: true,
},
properties: {
activityName: {
type: 'string',
"x-component-props": {
placeholder: '活动名称'
}
},
activityType: {
type: 'string',
enum: [],
"x-component-props": {
placeholder: '活动类型'
}
},
'[startTime, endTime]': {
"x-mega-props": {
span: 2,
},
type: 'daterange',
'x-component-props': {
placeholder: ['活动开始时间', "活动结束时间"]
}
},
product: {
type: 'string',
"x-component-props": {
placeholder: '活动名称'
}
},
merchantName: {
type: 'string',
"x-component-props": {
placeholder: '商家名称'
}
},
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: '查询',
},
},
},
},
},
},
},
};
export default schema;
......@@ -13,8 +13,8 @@ import Search from '@/components/NiceForm/components/Search';
import Submit from '@/components/NiceForm/components/Submit'
import StatusTag from '@/components/StatusTag'
import CouponPlatformIcon from '@/pages/pageCustomized/icons/coupon_platform.png';
import CouponShopIcon from '@/pages/pageCustomized/icons/coupon_shop.png';
import CouponPlatformIcon from '@/assets/couponIcons/coupon_platform.png';
import CouponShopIcon from '@/assets/couponIcons/coupon_shop.png';
import * as tableSchemas from './schema';
......@@ -33,9 +33,9 @@ interface CouponsDrawerProps {
}
const CouponsDrawer: React.FC<CouponsDrawerProps> = (props: CouponsDrawerProps) => {
const { visible, onClose, onConfirm, selectId, belongType } = props;
const { visible, onClose, onConfirm, selectId } = props;
const { query: { shopId } }: any = history.location
const [type, setType] = useState(belongType || 1);
const [type, setType] = useState(2);
const [selectedRowKeys, setSelectedRowKeys] = useState<any>(selectId ? [selectId] : []);
const [selectedRows, setSelectedRows] = useState<any>([]);
const ref = useRef<any>({});
......@@ -129,16 +129,7 @@ const CouponsDrawer: React.FC<CouponsDrawerProps> = (props: CouponsDrawerProps)
const fetchTableData = async (params: any) => {
const _params = { ...params, shopId };
let _fetch: any;
switch (type) {
case 1:
_fetch = PublicApi.getMarketingCouponPlatformActivityPageSelectPage
break;
case 2:
_fetch = PublicApi.getMarketingCouponPlatformActivityPageSelectMerchantPage
break;
}
const { data } = await _fetch(_params);
const { data } = await PublicApi.getMarketingCouponActivityPageSelectPage(_params);
return data;
}
const rowSelection: any = {
......@@ -197,22 +188,22 @@ const CouponsDrawer: React.FC<CouponsDrawerProps> = (props: CouponsDrawerProps)
span: 16
}
}}
formilyChilds={{
children: (
<div style={{ textAlign: 'right' }}>
<Radio.Group
options={options}
onChange={_onRadioChange}
value={type}
optionType="button"
/>
</div>
),
layouts: {
order: 2,
span: 8
}
}}
// formilyChilds={{
// children: (
// <div style={{ textAlign: 'right' }}>
// <Radio.Group
// options={options}
// onChange={_onRadioChange}
// value={type}
// optionType="button"
// />
// </div>
// ),
// layouts: {
// order: 2,
// span: 8
// }
// }}
/>
</Drawer>
)
......
......@@ -79,13 +79,6 @@ export const CouponSchema2: ISchema = {
allowClear: true,
},
},
memberName: {
type: 'string',
'x-component-props': {
placeholder: '商家名称',
allowClear: true,
},
},
sumbit: {
'x-component': 'Submit',
'x-mega-props': {
......
......@@ -4,7 +4,7 @@ import { cloneDeep } from 'lodash';
import { updatePageConfig, STATE_PROPS, SelectedInfoType, PageConfigType } from '@lingxi-disign/core';
import { useSelector } from '@lingxi-disign/react';
import * as MarketingConfigs from '../../../mobileTemplate/shopTemplateEdit/page_config';
import * as MarketingConfigs from '../../../mobileTemplate/shopTemplateEdit/marketing_config';
import styles from './index.less';
......
import {
ComponentSchemaType,
PROPS_SETTING_TYPES,
PROPS_TYPES,
} from '@lingxi-disign/core';
const BottomNavigation: ComponentSchemaType = {
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const BottomNavigationItems: ComponentSchemaType = {
fatherNodesRule: ['BottomNavigation.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.bottomNavigationItems,
},
},
};
export default {
BottomNavigation,
'BottomNavigation.Items': BottomNavigationItems,
};
import {
ComponentSchemaType,
PROPS_SETTING_TYPES,
PROPS_TYPES,
} from '@lingxi-disign/core';
const CouponsModal: ComponentSchemaType = {
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.couponsModal,
},
},
};
const CouponsItem: ComponentSchemaType = {
fatherNodesRule: ['CouponsModal.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.marketingCardCoupon,
},
},
};
export default {
CouponsModal,
'CouponsModal.CouponsItem': CouponsItem,
};
import {
ComponentSchemaType,
PROPS_SETTING_TYPES,
PROPS_TYPES,
} from '@lingxi-disign/core';
const MarketingCard: ComponentSchemaType = {
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const Header: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.marketingCardHeader,
},
},
};
const ShopHeader: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.marketingCardHeader,
},
},
};
const CommonContainer: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const VerticalContainer: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const CollageContainer: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const PackageContainer: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const PackageContainerTabs: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.PackageContainer.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const PackageContainerTabsTabPane: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.PackageContainerTabs.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
},
};
const DetailItem: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.PackageContainer.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.marketingCardDetailItem,
},
},
};
const CollageContainerItem: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.CollageContainer.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.marketingCardGood,
},
},
};
const GoodsItem: ComponentSchemaType = {
fatherNodesRule: [
'MarketingCard.CommonContainer.children',
'MarketingCard.PackageContainerTabsTabPane.children',
],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.marketingCardGood,
},
},
};
const CouponsItem: ComponentSchemaType = {
fatherNodesRule: ['MarketingCard.CommonContainer.children'],
propsConfig: {
children: {
label: '内容',
type: PROPS_TYPES.string,
},
componentType: {
type: PROPS_SETTING_TYPES.marketingCardCoupon,
},
},
};
export default {
MarketingCard,
'MarketingCard.Header': Header,
'MarketingCard.ShopHeader': ShopHeader,
'MarketingCard.CommonContainer': CommonContainer,
'MarketingCard.VerticalContainer': VerticalContainer,
'MarketingCard.CollageContainer': CollageContainer,
'MarketingCard.PackageContainer': PackageContainer,
'MarketingCard.PackageContainerTabs': PackageContainerTabs,
'MarketingCard.PackageContainerTabsTabPane': PackageContainerTabsTabPane,
'MarketingCard.DetailItem': DetailItem,
'MarketingCard.CollageContainerItem': CollageContainerItem,
'MarketingCard.GoodsItem': GoodsItem,
'MarketingCard.CouponsItem': CouponsItem,
};
......@@ -47,6 +47,9 @@ import MobileShopHeader from './MobileShopHeader'
import MobileNavCard from './MobileNavCard'
import Banner from './Banner'
import MobileShopCommodity from './MobileShopCommodity'
import CouponsModal from './CouponsModal'
import MarketingCard from './MarketingCard'
import BottomNavigation from './BottomNavigation'
export default {
View,
......@@ -89,4 +92,7 @@ export default {
...MobileNavCard,
...Banner,
...MobileShopCommodity,
...CouponsModal,
...MarketingCard,
...BottomNavigation
}
......@@ -6,15 +6,18 @@ import cx from 'classnames'
import { Tabs } from 'antd'
import StyleSettings from './styleSettings'
import PropsSettings from './propsSettings'
import { LAYOUT_TYPE } from '@/constants'
import styles from './index.less'
type SettingPanelType = {
selectedInfo: SelectedInfoType,
pageConfig: PageConfigType,
}
interface MobileSettingPanelProps {
shopId: number
shopId: number,
layoutType: LAYOUT_TYPE
}
const { TabPane } = Tabs
......@@ -34,7 +37,6 @@ const MobileSettingPanel: React.FC<MobileSettingPanelProps> = (props)=> {
setNewSelectInfo(updateSelectInfo)
}
}
updateSelectInfo()
}, [selectedInfo, pageConfig])
......@@ -47,7 +49,7 @@ const MobileSettingPanel: React.FC<MobileSettingPanelProps> = (props)=> {
{
(propsConfig && propsConfig.componentType) && (
<TabPane tab="编辑" key="props">
<PropsSettings selectedInfo={newSelectInfo} {...props} />
<PropsSettings selectedInfo={newSelectInfo} pageConfig={pageConfig} {...props} />
</TabPane>
)
}
......
@import "../../common.less";
.bottomNavigationClient {
&-box {
margin-bottom: 16px;
:global {
.ant-upload {
width: 100%;
}
}
&-label {
font-size: 12px;
color: #91959B;
margin-bottom: 8px;
}
&-icon {
height: 96px;
background-color: #FAFBFC;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
&>img {
width: 40px;
height: 40px;
}
&-add{
font-size: 40px;
}
&:hover {
.bottomNavigationClient-box-icon-cover {
display: block;
}
}
&-cover {
position: absolute;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, .1);
display: none;
z-index: 1;
&-delete {
position: absolute;
right: 10px;
top: 10px;
font-size: 20px;
color: #fff;
}
&-bottom {
position: absolute;
height: 24px;
line-height: 24px;
text-align: center;
background-color: rgba(0, 0, 0, 0.24);
font-size: 12px;
color: #fff;
width: 100%;
bottom: 0;
left: 0;
}
}
}
}
}
import React, { useMemo } from 'react';
import { Input, Select } from 'antd';
import { PlusCircleOutlined, DeleteOutlined } from '@ant-design/icons';
import { changeProps } from '@lingxi-disign/core';
import UploadImage from '@/components/UploadImage';
import uploadImgIcon from '@/assets/icons/upload_img_icon.svg'
import styles from './index.less';
interface BottomNavigationClientProps {
// 默认icon
defaultIcon?: any,
// 选中icon
selectIcon?: any,
// 导航标题
name?: any,
// 链接类型
/** 类型:1-首页 2-分类 3-进货单 4-工作台 5-我的 6-找现货 7-找供应 8-求购 9-换积分 10-找店铺 */
type?: any,
// 当前选中组件的key
selectedKey?: any,
// 1.B端 2.C端 3.SRM
property?: 1 | 2 | 3
}
const RedirectTypeList_B = [
{
value: 1,
label: '首页',
},
{
value: 2,
label: '分类',
},
{
value: 3,
label: '进货单',
},
{
value: 4,
label: '消息',
},
{
value: 5,
label: '我的',
},
{
value: 6,
label: '找现货',
},
{
value: 7,
label: '找供应',
},
{
value: 8,
label: '换积分',
},
{
value: 9,
label: '找店铺',
},
];
const RedirectTypeList_C = [
{
value: 1,
label: '首页',
},
{
value: 2,
label: '分类',
},
{
value: 3,
label: '购物车',
},
{
value: 4,
label: '我的',
},
{
value: 5,
label: '消息',
},
{
value: 6,
label: '积分兑换',
},
{
value: 7,
label: '在线客服',
},
];
const BottomNavigationClient: React.FC<BottomNavigationClientProps> = (props: BottomNavigationClientProps) => {
const { defaultIcon, selectIcon, name, type, property = 2, selectedKey } = props;
const _isNull = (list) => {
let _number = 0;
for (let key in list) {
if (list[key]) {
_number += 1
}
}
return _number === list.length ? false : true;
}
const _onChangeName = (e: any) => {
const _val = e.target.value;
changeProps({
title: _val || '',
props: Object.assign({ ...props }, { name: _val, isnull: _isNull([defaultIcon, selectIcon, _val, type]) })
});
}
const _onChangeType = (value: any) => {
changeProps({
props: Object.assign({ ...props }, { type: value, isnull: _isNull([defaultIcon, selectIcon, name, value]) })
});
}
const _onChangeDefaultIcon = (url: any) => {
changeProps({
props: Object.assign({ ...props }, { defaultIcon: url, isnull: _isNull([url, selectIcon, name, type]) })
});
}
const _onChangeSelectIcon = (url: any) => {
changeProps({
props: Object.assign({ ...props }, { selectIcon: url, isnull: _isNull([defaultIcon, url, name, type]) })
});
}
const RedirectTypeList = useMemo(() => {
if(property === 1){
return RedirectTypeList_B
}else if(property === 2){
return RedirectTypeList_C
}
}, [property])
return (
<div className={styles['bottomNavigationClient']}>
<div className={styles['bottomNavigationClient-box']}>
<div className={styles['bottomNavigationClient-box-label']}>名称</div>
<Input key={`${selectedKey}-name`} defaultValue={name} onBlur={_onChangeName} />
</div>
<div className={styles['bottomNavigationClient-box']}>
<div className={styles['bottomNavigationClient-box-label']}>链接</div>
<Select key={`${selectedKey}-type`} defaultValue={type} onChange={_onChangeType} style={{ width: '100%' }} >
{
RedirectTypeList?.map(selectItem => <Select.Option value={selectItem.value} key={`redirect_type_${selectItem.value}`}>{selectItem.label}</Select.Option>)
}
</Select>
</div>
<div className={styles['bottomNavigationClient-box']}>
<div className={styles['bottomNavigationClient-box-label']}>图标-默认</div>
{defaultIcon ? (
<div className={styles['bottomNavigationClient-box-icon']}>
<img src={defaultIcon} />
<div className={styles['bottomNavigationClient-box-icon-cover']}>
<UploadImage
onChange={(url) => { _onChangeDefaultIcon(url) }}
listType="text"
>
<div className={styles['bottomNavigationClient-box-icon-cover-bottom']}>
添加图像
</div>
<DeleteOutlined className={styles['bottomNavigationClient-box-icon-cover-delete']} onClick={(e) => { e.stopPropagation(); e.preventDefault(); _onChangeDefaultIcon('') }} />
</UploadImage>
</div>
</div>
) : (
<UploadImage
onChange={(url) => { _onChangeDefaultIcon(url) }}
listType="text"
>
<div className={styles['bottomNavigationClient-box-icon']}>
<img src={uploadImgIcon} className={styles['bottomNavigationClient-box-icon-add']} />
<div className={styles['bottomNavigationClient-box-icon-cover']}>
<div className={styles['bottomNavigationClient-box-icon-cover-bottom']}>
添加图像
</div>
</div>
</div>
</UploadImage>
)}
</div>
<div className={styles['bottomNavigationClient-box']}>
<div className={styles['bottomNavigationClient-box-label']}>图标-选中</div>
{selectIcon ? (
<div className={styles['bottomNavigationClient-box-icon']}>
<img src={selectIcon} />
<div className={styles['bottomNavigationClient-box-icon-cover']}>
<UploadImage
onChange={(url) => { _onChangeSelectIcon(url) }}
listType="text"
>
<div className={styles['bottomNavigationClient-box-icon-cover-bottom']}>
添加图像
</div>
<DeleteOutlined className={styles['bottomNavigationClient-box-icon-cover-delete']} onClick={(e) => { e.stopPropagation(); e.preventDefault(); _onChangeSelectIcon('') }} />
</UploadImage>
</div>
</div>
) : (
<UploadImage
onChange={(url) => { _onChangeSelectIcon(url) }}
listType="text"
>
<div className={styles['bottomNavigationClient-box-icon']}>
<img src={uploadImgIcon} className={styles['bottomNavigationClient-box-icon-add']} />
<div className={styles['bottomNavigationClient-box-icon-cover']}>
<div className={styles['bottomNavigationClient-box-icon-cover-bottom']}>
添加图像
</div>
</div>
</div>
</UploadImage>
)}
</div>
</div>
)
}
export default BottomNavigationClient
@import "../../common.less";
.couponsModal {
&-box {
margin-bottom: 16px;
&-label {
font-size: 12px;
color: #91959B;
margin-bottom: 8px;
}
&-icon {
height: 96px;
background-color: #FAFBFC;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
&>img {
width: 40px;
height: 40px;
}
}
}
}
import React, { useEffect } from 'react';
import { Input } from 'antd';
import { changeProps, changeStylesByKey } from '@lingxi-disign/core';
import styles from './index.less';
interface CouponsModalProps {
// 自定title
title?: string
// 当前选中组件的key
selectedKey?: any
}
const CouponsModal: React.FC<CouponsModalProps> = (props: CouponsModalProps) => {
const { title, selectedKey } = props;
useEffect(() => {
changeStylesByKey({
key: '8',
style: {
display: 'block'
}
})
return () => {
changeStylesByKey({
key: '8',
style: {
display: 'none'
}
})
}
}, [])
const _onChangeTitle = (e: any) => {
const _val = e.target.value;
changeProps({
props: Object.assign({ ...props }, { title: _val })
})
}
return (
<div className={styles['couponsModal']}>
<div className={styles['couponsModal-box']}>
<div className={styles['couponsModal-box-label']}>标题</div>
<Input key={`${selectedKey}-title`} defaultValue={title} onBlur={_onChangeTitle} />
</div>
</div>
);
}
export default CouponsModal;
@import "../../common.less";
.marketingCardCoupon {
&-box {
margin-top: 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
font-size: 12px;
&-label {
color: #91959B;
width: 80px;
}
&-content {
flex: 1;
color: #303133;
}
}
}
import React, { useState, useEffect } from 'react';
import { Button } from 'antd';
import { changeProps, changeStylesByKey } from '@lingxi-disign/core';
import moment from 'moment';
import { formatTimeString } from '@/utils'
import { priceFormat } from '@/utils/numberFomat'
import { PublicApi } from '@/services/api';
import CouponsDrawer from '@/pages/editor/components/drawer/couponsDrawer';
import styles from './index.less';
interface MarketingCardCouponProps {
id?: number,
belongType?: 1 | 2,
// 当前选中组件的key
selectedKey?: any,
}
const MarketingCardCoupon: React.FC<MarketingCardCouponProps> = (props: MarketingCardCouponProps) => {
const { id, belongType, selectedKey } = props;
const [drawerVisible, setDrawerVisible] = useState(false);
const [record, setRecord] = useState<any>();
useEffect(() => {
changeStylesByKey({
key: '8',
style: {
display: 'block'
}
})
return () => {
changeStylesByKey({
key: '8',
style: {
display: 'none'
}
})
}
}, [])
const _onClose = () => {
setDrawerVisible(false);
}
useEffect(() => {
if (id && id != record?.id) {
PublicApi.postMarketingCouponPlatformActivityPageSelectDetail({ couponList: [{ couponType: belongType, id: id }] }).then((res) => {
if (res.code === 1000) {
setRecord(res.data[0]);
}else{
setRecord('')
}
}).catch(_ => setRecord(''))
}else if(!id){
setRecord('');
}
}, [id, belongType])
const _onChooseConfirm = (record) => {
setRecord(record);
changeProps({
title: record?.name,
props: Object.assign({ ...props }, { ...record, expiredDay: moment(record?.releaseTimeEnd || moment()).diff(moment(), 'days'), isnull: false })
})
_onClose();
}
return (
<div className={styles['marketingCardCoupon']}>
<Button onClick={() => { setDrawerVisible(true) }}>选择</Button>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>优惠券ID:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.id}</div>
</div>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>优惠券名称:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.name}</div>
</div>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>类型:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.typeName}</div>
</div>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>领劵方式:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.getWayName}</div>
</div>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>商家名称:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.belongName}</div>
</div>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>面额:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.denomination ? `¥ ${priceFormat(record?.denomination)}` : ''}</div>
</div>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>使用条件:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.useConditionMoney ? `满 ${record?.useConditionMoney} 元使用` : ''}</div>
</div>
<div className={styles['marketingCardCoupon-box']}>
<div className={styles['marketingCardCoupon-box-label']}>有效期:</div>
<div className={styles['marketingCardCoupon-box-content']}>{record?.releaseTimeStart ? `${formatTimeString(record?.releaseTimeStart)} 至 ${formatTimeString(record?.releaseTimeEnd)}` : ''}</div>
</div>
<CouponsDrawer
visible={drawerVisible}
belongType={belongType}
onClose={_onClose}
onConfirm={_onChooseConfirm}
selectId={id}
/>
</div>
);
}
export default MarketingCardCoupon;
@import "../../common.less";
.suggestProductCommodity {
&-box {
margin-bottom: 16px;
&-label {
font-size: 12px;
color: #91959B;
margin-bottom: 8px;
}
}
&-detail {
height: 80px;
border: 1px solid #F7F8FA;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 6px 8px;
margin-bottom: 16px;
position: relative;
overflow: hidden;
img {
height: 60px;
width: 60px;
margin-right: 10px;
}
&-right {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
&-title {
color: #303133;
font-size: 12px;
word-break: break-all;
overflow: hidden; // 超出的文本隐藏
text-overflow: ellipsis;
display: -webkit-box; // 将对象作为弹性伸缩盒子模型显示。
-webkit-box-orient: vertical; //从上到下垂直排列子元素(设置伸缩盒子的子元素排列方式)
-webkit-line-clamp: 2; // 结合上面两个属性,表示显示的行数。
}
&-price {
color: #D32F2F;
font-size: 14px;
}
}
&:hover {
.suggestProductCommodity-detail-cover {
display: block;
}
}
&-cover {
position: absolute;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, .1);
display: none;
z-index: 1;
cursor: pointer;
&-bottom {
position: absolute;
height: 24px;
line-height: 24px;
text-align: center;
background-color: rgba(0, 0, 0, 0.24);
font-size: 12px;
color: #fff;
width: 100%;
bottom: 0;
left: 0;
}
}
}
&-activityList {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-bottom: 8px;
cursor: pointer;
img {
width: 24px;
height: 24px;
}
&-name {
flex: 1;
font-size: 12px;
color: #303133;
margin: 0 8px;
word-break: break-all;
overflow: hidden; // 超出的文本隐藏
text-overflow: ellipsis;
}
}
}
.site-tag-plus {
background: #fff;
border-style: dashed;
}
.edit-tag {
user-select: none;
}
.tag-input {
width: 78px;
margin-right: 8px;
vertical-align: top;
}
@import "../../common.less";
.marketingCardHeader {
&-box {
margin-bottom: 16px;
:global {
.ant-upload {
width: 100%;
}
}
&-label {
font-size: 12px;
color: #91959B;
margin-bottom: 8px;
}
&-icon {
height: 96px;
background-color: #FAFBFC;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
&>img {
width: 40px;
height: 40px;
border-radius: 50%;
}
&-add {
font-size: 40px;
}
&:hover {
.marketingCardHeader-box-icon-cover {
display: block;
}
}
&-cover {
position: absolute;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, .1);
display: none;
z-index: 1;
&-delete {
position: absolute;
right: 10px;
top: 10px;
font-size: 20px;
color: #fff;
}
&-bottom {
position: absolute;
height: 24px;
line-height: 24px;
text-align: center;
background-color: rgba(0, 0, 0, 0.24);
font-size: 12px;
color: #fff;
width: 100%;
bottom: 0;
left: 0;
}
}
}
}
}
import React from 'react';
import { Input } from 'antd';
import { PlusCircleOutlined, DeleteOutlined } from '@ant-design/icons';
import { changeProps } from '@lingxi-disign/core';
import UploadImage from '@/components/UploadImage';
import { LAYOUT_TYPE } from '@/constants'
import ICONS_CONFIG from '../../../../components/mobileClientEditLeft/iconsConfig';
import styles from './index.less';
interface MarketingCardHeaderProps {
// 活动类型
type: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19,
// 自定title
title?: string,
// 自定info
explain?: string,
// 自定icon
icon?: any,
// 倒计时数组[时,分,秒]
countDown?: string[],
selectedKey?: any,
layoutType: LAYOUT_TYPE
}
const MarketingCardHeader: React.FC<MarketingCardHeaderProps> = (props: MarketingCardHeaderProps) => {
const { type, title, explain, icon, selectedKey, layoutType } = props;
const _defaultInfo = ICONS_CONFIG.filter((item) => item.type === type)[0]
const _onChangeTitle = (e: any) => {
const _val = e.target.value;
changeProps({
props: Object.assign({ ...props }, { title: _val })
});
}
const _onChangeExplain = (e: any) => {
const _val = e.target.value;
changeProps({
props: Object.assign({ ...props }, { explain: _val })
});
}
const _onChangeIcon = (url: any) => {
changeProps({
props: Object.assign({ ...props }, { icon: url })
});
}
return (
<div className={styles['marketingCardHeader']}>
<div className={styles['marketingCardHeader-box']}>
<div className={styles['marketingCardHeader-box-label']}>标题</div>
<Input key={`${selectedKey}-title`} defaultValue={title || _defaultInfo?.title} onBlur={_onChangeTitle} />
</div>
{
layoutType !== LAYOUT_TYPE.shop && (
<div className={styles['marketingCardHeader-box']}>
<div className={styles['marketingCardHeader-box-label']}>标题说明</div>
<Input key={`${selectedKey}-explain`} defaultValue={explain || _defaultInfo?.explain} onBlur={_onChangeExplain} />
</div>
)
}
<div className={styles['marketingCardHeader-box']}>
<div className={styles['marketingCardHeader-box-label']}>图标</div>
{icon ? (
<div className={styles['marketingCardHeader-box-icon']}>
<img src={icon} />
<div className={styles['marketingCardHeader-box-icon-cover']}>
<UploadImage
onChange={(url) => { _onChangeIcon(url) }}
listType="text"
>
<div className={styles['marketingCardHeader-box-icon-cover-bottom']}>
添加图像
</div>
</UploadImage>
<DeleteOutlined className={styles['marketingCardHeader-box-icon-cover-delete']} onClick={() => { _onChangeIcon('') }} />
</div>
</div>
) : (
<UploadImage
onChange={(url) => { _onChangeIcon(url) }}
listType="text"
>
<div className={styles['marketingCardHeader-box-icon']}>
<img src={_defaultInfo.icon} />
<div className={styles['marketingCardHeader-box-icon-cover']}>
<div className={styles['marketingCardHeader-box-icon-cover-bottom']}>
添加图像
</div>
</div>
</div>
</UploadImage>
)}
</div>
</div>
);
}
export default MarketingCardHeader;
import React from 'react'
import { SelectedInfoType, PROPS_SETTING_TYPES } from '@lingxi-disign/core';
import { SelectedInfoType, PROPS_SETTING_TYPES, PageConfigType } from '@lingxi-disign/core';
import HeaderNav from './components/headerNav'
import Banner from './components/banner'
import QuickNav from './components/quickNav'
......@@ -9,18 +9,26 @@ import BottomNavigation from './components/bottomNavigation'
import MobileChannelGoods from './components/channelGoods'
import MobileChannelInformation from './components/channelInformation'
import CardNavItem from './components/cardNavItem'
import CouponsModal from './components/couponsModal'
import MarketingCardCoupon from './components/marketingCardCoupon';
import MarketingCardGood from './components/marketingCardGood'
import MarketingCardHeader from './components/marketingCardHeader'
import BottomNavigationClient from './components/bottomNavigationClient'
import { LAYOUT_TYPE } from '@/constants'
import styles from './index.less'
interface PropsSettingsPropsType {
selectedInfo: SelectedInfoType | undefined,
pageConfig: PageConfigType,
layoutType: LAYOUT_TYPE,
shopId: number,
}
const PropsSettings: React.FC<PropsSettingsPropsType> = (props) => {
const { selectedInfo, } = props
const { selectedInfo, pageConfig } = props
const renderSettingItem = () => {
const { props: initProps, propsConfig } = selectedInfo || {};
const { props: initProps, propsConfig, parentKey } = selectedInfo || {};
const _props = { ...initProps, ...props, selectedKey: selectedInfo?.selectedKey }
const componentType = propsConfig?.componentType
......@@ -46,6 +54,20 @@ const PropsSettings: React.FC<PropsSettingsPropsType> = (props) => {
return <BottomNavigation {..._props} />
case PROPS_SETTING_TYPES.mobileNavCardNavItem:
return <CardNavItem {..._props} />
case PROPS_SETTING_TYPES.couponsModal:
return <CouponsModal {..._props} />
case PROPS_SETTING_TYPES.marketingCardHeader:
return <MarketingCardHeader {..._props} />
case PROPS_SETTING_TYPES.marketingCardCoupon:
return <MarketingCardCoupon />
case PROPS_SETTING_TYPES.marketingCardGood:
case PROPS_SETTING_TYPES.marketingCardDetailItem:
const _parentKey: any = parentKey;
const _type = pageConfig?.[_parentKey]?.props?.type;
const _exType = pageConfig?.[_parentKey]?.props?.exType;
return <MarketingCardGood {..._props} actType={_type} exType={_exType} pageConfig={pageConfig} />
case PROPS_SETTING_TYPES.bottomNavigationItems:
return <BottomNavigationClient {..._props} />
default:
return null
}
......
import { PROPS_SETTING_TYPES, PageConfigType } from '@lingxi-disign/core'
import categoryNavTemplateDefault from './img/category_template_default.png'
import RED_PACKAGE from './img/red_package.png';
export const defaultConfig: PageConfigType = {
export const mallLayoutConfig : PageConfigType = {
'0': {
componentName: 'MallLayout',
props: {
......@@ -13,7 +14,7 @@ export const defaultConfig: PageConfigType = {
"paddingBottom": "50px",
}
},
childNodes: ['1', '2', '4', '6']
childNodes: ['1', '2', '4']
},
'1': {
componentName: 'MobileShopHeader',
......@@ -80,6 +81,9 @@ export const defaultConfig: PageConfigType = {
isnull: false,
},
},
}
export const defaultConfig: PageConfigType = {
'6': {
componentName: 'MobileShopCommodity',
title: '推荐商品',
......@@ -100,135 +104,50 @@ export const defaultConfig: PageConfigType = {
dataList: '${item.dataList}',
num: '${item.num}',
},
}
}
export const mallLayoutConfig = {
key: "0",
"0": {
"componentName": "MallLayout",
"props": {
"style": {
"width": "100%",
"minHeight": "100%",
"background": "#F7F8FA",
"overflowX": "hidden",
"paddingBottom": "50px",
}
},
"childNodes": ["1", "2", "5"]
},
}
export const mobileShopHeaderNav = {
key: "1",
"1": {
"componentName": "MobileShopHeaderNav",
"componentType": PROPS_SETTING_TYPES.mobileShopHeaderNav,
"title": "背景图编辑",
"canEdit": true,
"canHide": false,
"props": {},
}
}
export const divWrap = {
key: "2",
"2": {
"componentName": "div",
"props": {
"style": {
position: "relative",
marginTop: -24,
backgroundColor: "#FFF",
borderTopLeftRadius: '16px',
borderTopRightRadius: '16px',
zIndex: 6,
padding: '2px 4px',
}
'8': {
title: '优惠券弹窗',
componentName: 'CouponsModal',
props: {
style: {
display: "none",
position: 'absolute',
backgroundImage: `url(${RED_PACKAGE})`,
width: 312,
height: 425,
top: 0,
left: 0,
bottom: 0,
right: 0,
margin: 'auto',
zIndex: 1,
},
},
"childNodes": ["3", "4"]
}
}
export const mobileBanner = {
key: "3",
"3": {
"componentName": "MobileBanner",
"componentType": PROPS_SETTING_TYPES.mobileBanner,
"title": "轮播广告",
"canEdit": true,
"canHide": false,
"props": {
dataList: []
}
}
}
export const mobileQuickNav = {
key: "4",
"4": {
"componentName": "MobileQuickNav",
"componentType": PROPS_SETTING_TYPES.mobileQuickNav,
"title": "导航模块",
"canEdit": true,
"canHide": false,
"props": {
dataList: [
{
"id":1,
"expand":false,
"icon":"https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/c5d66f1488cc47d0a73279ce1ef11c991610677462848.png",
"type":1,
"name":"商城",
"url":""
},
{
"id":2,
"expand":false,
"icon":"https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/9f105bdebcfb4010b5827f7b64fb53281610696444606.png",
"type":2,
"name":"分类",
"url":""
},
{
"id":3,
"expand":false,
"icon":"https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/d4383c684c6e4707b405f46f281796d71610696469970.png",
"type":3,
"name":"积分兑换",
"url":""
},
{
"id":4,
"expand":false,
"icon":"https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/d4383c684c6e4707b405f46f281796d71610696469970.png",
"type":4,
"name":"公司介绍",
"url":""
},
{
"id":5,
"expand":false,
"icon":"https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/441a66ebeb3b45e6a64ecfa9977f411c1610696489991.png",
"type":5,
"name":"成为会员",
"url":""
},
]
}
}
}
export const mobileShopCommodityList = {
key: "5",
"5": {
"componentName": "MobileShopCommodityList",
"componentType": PROPS_SETTING_TYPES.mobileShopCommodity,
"title": "商品推荐",
"canEdit": true,
"canHide": false,
"props": {}
}
childNodes: [],
childComponentName: 'CouponsModal.CouponsItem',
addBtnText: '添加优惠券',
canEdit: true,
canHide: false,
},
// '9': {
// title: '底部标签栏',
// componentName: 'BottomNavigation',
// props: {},
// childNodes: ['10'],
// childComponentName: 'BottomNavigation.Items',
// addBtnText: '添加标签',
// maxLength: 5,
// },
// '10': {
// loop: '${bottom}',
// title: '${item.name}',
// componentName: 'BottomNavigation.Items',
// props: {
// defaultIcon: '${item.defaultIcon}',
// selectIcon: '${item.selectIcon}',
// name: '${item.name}',
// type: '${item.type}',
// isnull: false,
// },
// },
}
......@@ -26,7 +26,11 @@ const CouponItem = (props) => {
<div className={styles.couponItemRight}>
<div className={styles.couponItemRight_type}>{fieldListData.typeName}</div>
<div className={styles.couponItemRight_info}>{fieldListData.name}</div>
<div className={styles.couponItemRight_date}>{format(fieldListData.effectiveTimeStart)}-{format(fieldListData.effectiveTimeEnd)}</div>
{ fieldListData.effectiveType === 1 ? (
<div className={styles.couponItemRight_date}>{format(fieldListData.effectiveTimeStart)}-{format(fieldListData.effectiveTimeEnd)}</div>
) : (
<div className={styles.couponItemRight_date}>{fieldListData.invalidDay}&nbsp;</div>
)}
</div>
</Col>
</Row>
......
......@@ -55,7 +55,7 @@ export interface ProductLayoutProps {
/** 最外层标号 */
index: number,
/** list 数据 */
list: ListProps[],
list: any[],
/** 删除某一个 */
onDeletion: (_index: number) => void,
/** 输入数量或者套餐价格 */
......@@ -73,6 +73,8 @@ const ProductLayout: React.FC<ProductLayoutProps> = (props: any) => {
onEntry(name, Number(e.target.value), _index)
}
console.log(list)
return (
<Fragment>
{/* 套餐价格 */}
......@@ -118,7 +120,7 @@ const ProductLayout: React.FC<ProductLayoutProps> = (props: any) => {
)}
{remind.value !== 1 && (
<div className={style.couponLayout_contenxt}>
<Row style={{ height: '100%' }} wrap={false}>
<Row style={{ height: '100%', marginLeft: 10 }} wrap={false}>
<Col flex='none'>
<div className={style.couponLayout_item_left}>
<p>¥<span>{_item.denomination}</span></p>
......
......@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import { Drawer, Button, Form, message } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import CollapseLayout from './components/collapseLayout';
import { isEmpty } from 'lodash';
import { isArray, isEmpty } from 'lodash';
import ProductLayout from './components/productLayout';
import CouponsLayout from '@/pages/transaction/marketingAbility/selfManagement/readySubmitExamine/components/couponsLayout';
......@@ -24,8 +24,7 @@ type RemindLayoutProps = {
message?: { [key: number]: string },
}
interface ListModalLayoutProps {
idNotInList?: number[],
interface CouponsListLayoutProps {
/** messges */
remind?: RemindLayoutProps,
/** 数据回显 */
......@@ -34,8 +33,6 @@ interface ListModalLayoutProps {
title?: string,
/** 显示隐藏 */
visible?: boolean,
/** 适用商城 */
shopIdList?: number[],
/** 关闭 */
onClose?: () => void,
/** 确定 */
......@@ -48,21 +45,11 @@ interface CouponGroupListProps {
/** 换购门槛优惠门槛数量或金额 */
limitValue?: number,
/** 明细 */
list?: {
id?: number,
/** 活动商品id */
activityGoodsId?: number,
/** 优惠券id */
couponId: number,
/** 优惠券名称 */
couponName: string,
/** 赠送数量 */
num?: number,
}[]
list?: any[]
}
const CouponsListLayout: React.FC<ListModalLayoutProps> = (props: any) => {
const { idNotInList, remind, value, shopIdList, title, visible, onClose, onConfirm } = props;
const CouponsListLayout: React.FC<CouponsListLayoutProps> = (props: any) => {
const { remind, value, title, visible, onClose, onConfirm } = props;
const [form] = Form.useForm();
const [couponSource, setCouponSource] = useState<CouponGroupListProps[]>([]);
const [tableModalVisible, setTableModalVisible] = useState<boolean>(false);
......@@ -83,35 +70,114 @@ const CouponsListLayout: React.FC<ListModalLayoutProps> = (props: any) => {
}
/** 组合数据到dataSource */
const handleComposed = (selectRowRecord?: any) => {
const fields: CouponGroupListProps[] = [...couponSource];
fields[idx].groupNo = (idx + 1);
if (isArray(selectRowRecord)) {
fields[idx].list = [...selectRowRecord]
}
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
[`dataSource_${idx}`]: fields[idx].list,
[`limitValue_${_index}`]: item.limitValue,
[`num_${_index}_${__index}`]: _item.num,
})
})
})
setCouponSource(fields);
}
const handleCouponSubmit = (selectRowRecord: any) => {
console.log(selectRowRecord, 10086)
if (isEmpty(selectRowRecord)) {
message.warning(remind.message[1])
return
}
handleComposed(selectRowRecord)
toggle(false);
}
const handleClick = () => {
console.log('提交')
form.validateFields().then(_res => {
if (isEmpty(_res)) {
message.warning(remind.message[2])
return
}
onConfirm(couponSource)
})
}
/** 删除一个 */
const handleDeletion = (index: number) => {
console.log(index)
const fields = [...couponSource];
fields.splice(index, 1);
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
[`limitValue_${_index}`]: item.limitValue,
[`num_${_index}_${__index}`]: _item.num,
})
})
})
setCouponSource(fields);
}
/** 选择搭配优惠券 */
const handleCollocation = (_idx: number) => {
const fields = [...couponSource];
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
[`limitValue_${_index}`]: item.limitValue,
[`num_${_index}_${__index}`]: _item.num,
})
})
})
setIdx(_idx);
toggle(true)
}
/** 输入一个价格或者数量 */
const handleEntryNumber = (index: number, name: string, num: number, _index?: number) => {
console.log(index, name, num, _index)
const fields: CouponGroupListProps[] = [...couponSource];
if (name === 'limitValue') {
fields[index][name] = Number(num);
} else {
fields[index].list[_index][name] = Number(num);
}
setCouponSource(fields)
}
/** 删除一个赠送优惠券 */
const handleDeletionColloCation = (index: number, _index: number) => {
console.log(index, _index)
const fields: CouponGroupListProps[] = [...couponSource];
fields[index].list.splice(_index, 1);
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
[`limitValue_${_index}`]: item.limitValue,
[`num_${_index}_${__index}`]: _item.num,
})
})
})
setCouponSource(fields);
}
useEffect(() => {
const fields = [...value];
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
[`dataSource_${_index}`]: fields[_index].list,
[`limitValue_${_index}`]: item.limitValue,
[`num_${_index}_${__index}`]: _item.num,
})
})
})
setCouponSource(value);
}, [value])
return (
<Drawer
width={600}
......@@ -169,6 +235,7 @@ const CouponsListLayout: React.FC<ListModalLayoutProps> = (props: any) => {
visible={tableModalVisible}
onClose={() => toggle(false)}
onSubmit={handleCouponSubmit}
value={couponSource[idx]}
/>
</Drawer>
)
......
......@@ -110,8 +110,14 @@ const ListModalLayout: React.FC<ListModalLayoutProps> = (props: any) => {
}
})]
}
form.setFieldsValue({
[`dataSource_${idx}`]: fields[idx].list,
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
[`dataSource_${idx}`]: fields[idx].list,
[`limitValue_${_index}`]: item.limitValue,
[`num_${_index}_${__index}`]: _item.num,
})
})
})
setDataSource(fields);
}
......@@ -162,7 +168,6 @@ const ListModalLayout: React.FC<ListModalLayoutProps> = (props: any) => {
const handleDeletion = (index: number) => {
const fields = [...dataSource];
fields.splice(index, 1);
form.resetFields()
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
......@@ -195,7 +200,6 @@ const ListModalLayout: React.FC<ListModalLayoutProps> = (props: any) => {
const handleDeletionColloCation = (index: number, _index: number) => {
const fields: GoodsSubsidiaryListProps[] = [...dataSource];
fields[index].list.splice(_index, 1);
form.resetFields()
fields.forEach((item, _index) => {
item.list.forEach((_item, __index) => {
form.setFieldsValue({
......
......@@ -2,13 +2,14 @@ import React, { useEffect, useMemo, useState } from 'react';
import { Button, message, Table, Form, FormInstance } from 'antd';
import { Columns } from './columns';
import { EventEmitter } from '@umijs/hooks/lib/useEventEmitter'
import CardLayout from '../card';
import CardLayout from '../../selfManagement/readySubmitExamine/components/card';
import { PlusOutlined } from '@ant-design/icons';
import { isEmpty } from 'lodash';
import { PublicApi } from '@/services/api';
import ListModalLayout from '@/pages/transaction/marketingAbility/components/listModalLayout';
import CollocationLayout from '@/pages/transaction/marketingAbility/components/collocationLayout';
import { remindLayout, RemindLayoutProps } from '@/pages/transaction/marketingAbility/paltformSign/readySubmitExamine/components/productListLayout/remind';
import CouponsListLayout from '@/pages/transaction/marketingAbility/components/couponsListLayout';
type optionProps = {
/** key */
......@@ -21,16 +22,20 @@ type optionProps = {
interface ProductListProps {
/** 活动id */
activityId?: number,
activityId?: any,
form?: FormInstance,
/** umi-hooks */
focus$?: EventEmitter<void>,
/** 适用商城 */
shopIdList?: number[],
/** 接口 */
fieldApi?: () => Promise<unknown>,
/** 活动规则 -> 有则不调用form.getFieldValue */
getActivityDefinedBO?: any,
}
const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
const { activityId, form, focus$, shopIdList } = props;
const { activityId, form, focus$, shopIdList, fieldApi, getActivityDefinedBO } = props;
const [value, setValue] = useState<number>(1);
const [productVisible, setProductVisible] = useState<boolean>(false);
const [listModalVisible, setListModalVisible] = useState<boolean>(false);
......@@ -69,15 +74,16 @@ const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
/** 设置搭配 */
const handlCollocation = (record: any) => {
const tableRecord: any = {...record}
if (tableRecord.goodsSubsidiaryGroupList !== undefined) {
const tableRecord: any = { ...record }
if (remind.value !== 1 && tableRecord.couponGroupList !== undefined) {
setCollocation(tableRecord.couponGroupList)
} else if (remind.value === 1 && tableRecord.goodsSubsidiaryGroupList !== undefined) {
setCollocation(tableRecord.goodsSubsidiaryGroupList)
} else {
setCollocation([])
}
setSkuId(tableRecord.skuId)
setListModalVisible(true);
console.log(record)
}
const columns = useMemo(() => {
......@@ -85,7 +91,7 @@ const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
}, [value, dataSource])
const toggle = (flag: boolean) => {
const activityDefinedBO = form.getFieldValue('activityDefinedBO');
const activityDefinedBO = form.getFieldValue('activityDefinedBO') || getActivityDefinedBO;
if (isEmpty(shopIdList)) {
message.warning('请选择适用商城!');
return
......@@ -121,12 +127,12 @@ const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
}
useEffect(() => {
if (activityId) {
PublicApi.getMarketingMerchantActivityDetailGoodsPage({ current: '1', pageSize: '999', activityId }).then(res => {
if (!isEmpty(activityId)) {
fieldApi({ current: '1', pageSize: '999', ...activityId }).then(res => {
if (res.code !== 1000) {
return
}
const activityDefinedBO = form.getFieldValue('activityDefinedBO');
const activityDefinedBO = form.getFieldValue('activityDefinedBO') || getActivityDefinedBO;
if (value === 6) {
setRemind(remindLayout(value, activityDefinedBO.giveType, activityDefinedBO.giftType));
}
......@@ -143,12 +149,13 @@ const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
setIdNotInList([...idNotInList, ...res.data.data.map(item => item.skuId)])
})
}
}, [activityId])
}, [!isEmpty(activityId)])
useEffect(() => {
handlesStFieldsValue()
}, [dataSource])
/** 设置搭配商品 */
const handleConfirm = (params: any) => {
const fields = [...dataSource];
fields.forEach(item => {
......@@ -160,6 +167,18 @@ const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
setDataSource(fields)
}
/** 设置优惠券 */
const handleCouponConfirm = (params: any) => {
const fields = [...dataSource];
fields.forEach(item => {
if (item.skuId === skuId) {
item.couponGroupList = [...params]
}
})
setListModalVisible(false)
setDataSource(fields)
}
return (
<CardLayout
id="productListLayout"
......@@ -187,7 +206,7 @@ const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
onConfirm={handleSelectActiveProducts}
/>
{/* 设置搭配商品 */}
{(!isEmpty(remind) && remind.value !== 1) && (
{(!isEmpty(remind) && remind.value === 1) && (
<ListModalLayout
title={remind.modalTitle}
remind={remind}
......@@ -199,6 +218,17 @@ const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
value={collocation}
/>
)}
{/* 设置优惠券 */}
{(!isEmpty(remind) && remind.value !== 1) && (
<CouponsListLayout
title={remind.modalTitle}
remind={remind}
visible={listModalVisible}
onClose={() => setListModalVisible(false)}
onConfirm={handleCouponConfirm}
value={collocation}
/>
)}
</Form.Item>
</CardLayout>
)
......
import React, { Fragment, useCallback, useState } from 'react';
import { Button, message } from 'antd';
import React, { useCallback, useState } from 'react';
import { Button, Form } from 'antd';
import { history, Prompt } from 'umi';
import { useEventEmitter } from '@umijs/hooks';
import { Context } from '@/pages/transaction/components/detailLayout/components/context';
import PeripheralLayout from '@/pages/transaction/components/detailLayout';
import ProgressLayout from '@/pages/transaction/components/detailLayout/components/progressLayout';
......@@ -14,8 +15,8 @@ import ActivityUserLayout from '../../components/activityUserLayout';
import DemandLayout from '../../components/demandLayout';
import { PublicApi } from '@/services/api';
import { isEmpty } from 'lodash';
import ProductListLayout from './components/productListLayout';
import { SaveOutlined } from '@ant-design/icons';
import ProductListLayout from '../../components/productListLayout';
const TABLINK = [
{ id: 'progressLayout', title: '流转进度' },
......@@ -30,15 +31,20 @@ const TABLINK = [
const DetialLayout = () => {
const { query: { activityId, signUpId }, pathname } = history.location;
const [path] = useState(pathname.split('/')[pathname.split('/').length - 1]);
const focus$ = useEventEmitter();
const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(false)
const [unsaved, setUnsaved] = useState<boolean>(false);
const [productList, setProductList] = useState<any[]>([]);
const [shopIdList, setShopIdList] = useState<number[]>([]);
const [signUpIds, setSignUpIds] = useState<number>();
const format = (text, fmt?: string) => {
return <>{moment(text).format(fmt || "YYYY-MM-DD HH:mm:ss")}</>
}
const [dataSource, setDataSource] = useState<any>({});
const [basicEffect, setBasicEffect] = useState<any>([]);
const [generalEffect, setGeneralEffect] = useState<any>([]);
const [activityDefinedBO, setActivityDefinedBO] = useState<any>({});
const handleBasicEffect = (data: any) => {
setBasicEffect([
......@@ -72,7 +78,7 @@ const DetialLayout = () => {
}
}
const fetchDataSource = useCallback(async () => {
const fetchDataSource = async () => {
await PublicApi.getMarketingPlatformActivitySignupDetail({ activityId }).then((res: any) => {
if (res.code !== 1000) {
return
......@@ -89,27 +95,51 @@ const DetialLayout = () => {
})
})
data.externalLogStates = externalLogStates;
const option: any = { value: data.activityType };
focus$.emit(option)
setDataSource(data);
handleBasicEffect(data)
handleBasicEffect(data);
setShopIdList(data.shopList.map(item => { return item.shopId }));
setActivityDefinedBO(data.activityDefinedBO)
handleGeneralEffect(data.activityDefinedBO, data.activityType)
setSignUpIds(signUpId)
}).catch(() => { })
}, [])
}
useEffect(() => {
fetchDataSource();
// handleGeneralEffect(_data);
}, [])
const handleSubmit = useCallback(async () => {
const params: any = {
activityId,
productList,
}
signUpId !== null && (params.id = signUpId)
if (!isEmpty(productList)) {
const handleSubmit = () => {
form.validateFields().then(res => {
const param: any = {
activityId,
productList: res.productList.map(item => {
if (item.couponGroupList) {
return {
...item,
couponGroupList: item.couponGroupList.map(_item => {
return {
..._item,
list: _item.list.map(__item => {
return {
activityGoodsId: item.productId,
couponId: __item.id,
couponName: __item.name,
num: __item.num,
}
})
}
})
}
}
return item
})
}
signUpId !== null && (param.id = signUpId);
setLoading(true)
const fieldApi = (path === 'add' ? PublicApi.postMarketingPlatformActivitySignupSave : PublicApi.postMarketingPlatformActivitySignupUpdate)
fieldApi({ ...params }).then(res => {
fieldApi({ ...param }).then(res => {
if (res.code !== 1000) {
setLoading(false)
return
......@@ -120,17 +150,7 @@ const DetialLayout = () => {
}).catch(_err => {
setLoading(false)
})
} else {
message.warn('请选择活动商品!')
}
}, [productList])
const handleGetDataSoure = (e) => {
if (!unsaved) {
setUnsaved(true)
}
setProductList([...e])
})
}
return (
......@@ -150,7 +170,14 @@ const DetialLayout = () => {
</Button>
}
components={
<Fragment>
<Form
form={form}
onValuesChange={() => {
if (!unsaved) {
setUnsaved(true)
}
}}
>
<ProgressLayout />
<BasicLayout effect={basicEffect} />
<GeneralLayout
......@@ -159,11 +186,11 @@ const DetialLayout = () => {
anchor="activityRuleLayout"
effect={generalEffect}
/>
<ProductListLayout signUpId={signUpId !== 'null' && signUpId} data={dataSource} getDataSource={handleGetDataSoure} />
<ProductListLayout getActivityDefinedBO={activityDefinedBO} activityId={signUpIds && { signUpId: signUpIds }} form={form} focus$={focus$} shopIdList={shopIdList} fieldApi={PublicApi.getMarketingPlatformActivitySignupDetailGoodsPage} />
<ActivityUserLayout dataScoure={dataSource} />
<DemandLayout storeList={dataSource.shopList} />
<RecordLyout />
</Fragment>
</Form>
}
/>
<Prompt when={unsaved} message="您还有未保存的内容,是否确定要离开?" />
......
......@@ -32,15 +32,15 @@ export const remindLayout = (int, giveType?, giftType?) => {
label: {
1: '优惠门槛',
2: giveType === 1 ? '元' : '个',
3: '赠送商品',
3: giveType === 1 ? '赠送商品' : '赠送优惠券',
4: '赠送数量',
5: '买',
6: '',
},
message: {
1: '请选择赠送商品!',
2: '请设置赠送商品!',
3: '请选择赠送商品!',
1: giveType === 1 ? '请选择赠送商品!' : '请选择赠送优惠券!',
2: giveType === 1 ? '请设置赠送商品!' : '请设置赠送优惠券!',
3: giveType === 1 ? '请选择赠送商品!' : '请选择赠送优惠券!',
4: '请输入优惠门槛!',
5: '请输入赠送数量!',
}
......
......@@ -286,7 +286,7 @@ export const GeneralEffect = (int, data) => {
return [
{
col: [
{ label: '每日秒杀时间段', extra: `${format(data.startTime, 'HH:mm:ss')}~${format(data.endTime, 'HH:mm:ss')}` },
{ label: '每日秒杀时间段', extra: <>{format(data.startTime, 'HH:mm:ss')}~{format(data.endTime, 'HH:mm:ss')}</>},
{ label: '活动描述', extra: data.describe }
]
},
......@@ -363,13 +363,13 @@ export const GeneralEffect = (int, data) => {
return [
{
col: [
{ label: '抽取用户时间', extra: '' },
{ label: '抽取用户时间', extra: data.extractAttemptUserTime && format(data.extractAttemptUserTime, 'YYYY-MM-DD HH:mm:ss') },
{ label: '活动描述', extra: data.describe },
]
},
{
col: [
{ label: '试用结束时间', extra: '' },
{ label: '试用结束时间', extra: data.attemptEndTime && format(data.attemptEndTime, 'YYYY-MM-DD HH:mm:ss') },
]
}
]
......
......@@ -7,7 +7,7 @@ import PeripheralLayout from '@/pages/transaction/components/detailLayout';
import BasicInfoLayout from './components/basicInfoLayout';
import RulesLayout from './components/rulesLayout';
import ShopLayout from './components/shopLayout';
import ProductListLayout from './components/productListLayout';
import ProductListLayout from '../../components/productListLayout';
import PartakeUserLayout from './components/partakeUserLayout';
import moment from 'moment';
import { PublicApi } from '@/services/api';
......@@ -96,7 +96,42 @@ const AddedMarketing = () => {
oldMember: (res.allUser.includes(4) ? 1 : 0),
memberLevelList,
shopList: res.shopList,
productList: res.productList
productList: res.productList.map(item => {
if (item.couponGroupList) {
return {
...item,
couponGroupList: item.couponGroupList.map(_item => {
return {
..._item,
list: _item.list.map(__item => {
return {
activityGoodsId: item.productId,
couponId: __item.id,
couponName: __item.name,
num: __item.num,
}
})
}
})
}
}
return item
})
}
if (res['activityDefinedBO']['assembleTime']) {
params['activityDefinedBO'].assembleTime = Number(moment(res['activityDefinedBO']['assembleTime']).format('x'));
}
if (res['activityDefinedBO']['startTime']) {
params['activityDefinedBO']['startTime'] = Number(moment(res['activityDefinedBO']['startTime']).format('x'));
}
if (res['activityDefinedBO']['endTime']) {
params['activityDefinedBO']['endTime'] = Number(moment(res['activityDefinedBO']['endTime']).format('x'));
}
if (res['activityDefinedBO']['extractAttemptUserTime']) {
params['activityDefinedBO']['extractAttemptUserTime'] = Number(moment(res['activityDefinedBO']['extractAttemptUserTime']).format('x'));
}
if (res['activityDefinedBO']['attemptEndTime']) {
params['activityDefinedBO']['attemptEndTime'] = Number(moment(res['activityDefinedBO']['attemptEndTime']).format('x'));
}
setLoading(true)
path !== 'add' && (params.id = id);
......@@ -126,6 +161,21 @@ const AddedMarketing = () => {
}
})[0]
focus$.emit(option)
if (data['activityDefinedBO']['assembleTime']) {
data['activityDefinedBO']['assembleTime'] = moment(data['activityDefinedBO']['assembleTime']);
}
if (data['activityDefinedBO']['startTime']) {
data['activityDefinedBO']['startTime'] = moment(data['activityDefinedBO']['startTime']);
}
if (data['activityDefinedBO']['endTime']) {
data['activityDefinedBO']['endTime'] = moment(data['activityDefinedBO']['endTime']);
}
if (data['activityDefinedBO']['extractAttemptUserTime']) {
data['activityDefinedBO']['extractAttemptUserTime'] = moment(data['activityDefinedBO']['extractAttemptUserTime']);
}
if (data['activityDefinedBO']['attemptEndTime']) {
data['activityDefinedBO']['attemptEndTime'] = moment(data['activityDefinedBO']['attemptEndTime']);
}
form.setFieldsValue({
allUser: [data.newUser && 1, data.oldUser && 2, data.newMember && 3, data.oldMember && 4],
activityDefinedBO: data.activityDefinedBO,
......@@ -179,7 +229,7 @@ const AddedMarketing = () => {
<BasicInfoLayout form={form} focus$={focus$} />
<RulesLayout form={form} focus$={focus$} />
<ShopLayout onGetShopList={handleGetShopList} onSetShopList={shopList} />
<ProductListLayout activityId={activityId} form={form} focus$={focus$} shopIdList={shopIdList} />
<ProductListLayout activityId={activityId && { activityId: activityId }} form={form} focus$={focus$} shopIdList={shopIdList} fieldApi={PublicApi.getMarketingMerchantActivityDetailGoodsPage} />
<PartakeUserLayout onGetLevel={handleGetLevel} onSetLevel={memberLevelList} setMemberType={memberType} />
</Form>
}
......
import React, { useEffect, useState } from 'react';
import { Drawer, Space, Form, Select, Input, Button, Row, Col, Checkbox, Empty } from 'antd';
import { Drawer, Space, Form, Select, Input, Button, Row, Col, Checkbox, Empty, Pagination } from 'antd';
import { CaretDownOutlined } from '@ant-design/icons';
import { PublicApi } from '@/services/api';
import CouponItem from '@/pages/transaction/marketingAbility/components/couponItem';
import styles from './index.less';
import { isEmpty } from 'lodash';
interface CouponsLayoutProps {
/** 显示 */
......@@ -12,10 +13,12 @@ interface CouponsLayoutProps {
onClose?: () => void,
/** 提交 */
onSubmit?: (e: any) => void,
/** 已选择的id */
value?: any,
}
const CouponsLayout: React.FC<CouponsLayoutProps> = (props: any) => {
const { visible, onClose, onSubmit } = props;
const { visible, onClose, onSubmit, value } = props;
const [form] = Form.useForm();
const [state, setState] = useState({
filterSearch: false
......@@ -24,9 +27,11 @@ const CouponsLayout: React.FC<CouponsLayoutProps> = (props: any) => {
current: 1,
pageSize: 10,
})
const [total, setTotal] = useState<number>(0);
const [couponList, setCouponList] = useState<any[]>([]);
const [chekedId, setCheckedId] = useState<number[]>([]); // 已选择的优惠券
const [couponsList, setCouponsList] = useState<any[]>([]);
const [selectCouponList, setSelectCouponList] = useState<any[]>([]); // checkbox 勾选到的数据 需要去重
const [couponsList, setCouponsList] = useState<any[]>([]); // 提交的优惠券
const changeFilterVisible = () => {
setState({
filterSearch: !state.filterSearch,
......@@ -40,8 +45,9 @@ const CouponsLayout: React.FC<CouponsLayoutProps> = (props: any) => {
if (res.code !== 1000) {
return
}
const { data } = res.data
const { data, totalCount } = res.data
setCouponList(data)
setTotal(totalCount)
})
})
}
......@@ -56,7 +62,7 @@ const CouponsLayout: React.FC<CouponsLayoutProps> = (props: any) => {
if (visible) {
handleSubmit()
}
}, [visible])
}, [visible, params])
const handleOnOk = () => {
onSubmit(couponsList)
......@@ -75,17 +81,39 @@ const CouponsLayout: React.FC<CouponsLayoutProps> = (props: any) => {
)
}
const _setCheckList = (_e, item: any) => {
const ids = [...chekedId]
const _setCheckList = (_e, _item) => {
const ids = [...chekedId];
const selcetLits = [...selectCouponList];
if (!ids.includes(_e)) {
setCouponsList([...couponsList, item])
setCheckedId([...chekedId, _e])
setCheckedId([...ids, _e])
setSelectCouponList([...selcetLits, _item])
} else {
setCouponsList(couponsList.filter(_item => _item.couponId !== _e))
setCheckedId(ids.filter(_item => _item !== _e));
setSelectCouponList(selcetLits.filter(_item => _item.id !== _e))
}
}
useEffect(() => {
const newData = selectCouponList.filter(_item => chekedId.includes(_item.id));
console.log(newData, 98)
setCouponsList(newData)
}, [chekedId])
useEffect(() => {
if (!isEmpty(value)) {
const newChekedId = value.list.map((_item: any) => _item.id);
setCheckedId(newChekedId)
setSelectCouponList(value.list)
}
}, [value])
const handlePagination = (page, pageSize) => {
setParams({
current: page,
pageSize: pageSize,
})
}
return (
<Drawer
width={630}
......@@ -93,6 +121,7 @@ const CouponsLayout: React.FC<CouponsLayoutProps> = (props: any) => {
visible={visible}
onClose={onClose}
footer={renderFooter()}
destroyOnClose
>
<Form
form={form}
......@@ -150,6 +179,9 @@ const CouponsLayout: React.FC<CouponsLayoutProps> = (props: any) => {
</Col>
)
})}
<Col span={24} style={{ display: 'flex' ,justifyContent: 'flex-end'}}>
<Pagination size="small" total={total} current={params.current} onChange={handlePagination}/>
</Col>
</Row>
)}
</Form>
......
......@@ -29,6 +29,7 @@ import * as EnhanceV2Api from './EnhanceV2Api';
import * as MessageV2 from './MessageV2Api';
import * as LogiticsV2 from './LogiticsV2Api';
import * as MarketingApi from './MarketingApi';
import * as MaketingV2Api from './MaketingV2Api'
import * as AfterServiceV2Api from './AfterServiceV2Api';
......@@ -72,5 +73,6 @@ export const PublicApi = {
...MessageV2,
...LogiticsV2,
...MarketingApi,
...MaketingV2Api,
...AfterServiceV2Api,
}
......@@ -31,6 +31,7 @@ const tokenList = [
{ name: 'MessageV2', token: '69a667ec9861e8bdc25b89238d0b908a2123d9fce26e72fec3cdf6cd0b1f2681', categoryIds: [0], }, // 消息中心v2
{ name: 'LogiticsV2', token: '732fb8e33970ff5dee830423a630e8e85c3ef3293abba7581b16749dfce8608b', categoryIds: [0], }, // 物流能力v2
{ name: 'Marketing', token: 'd952d25c4e8272a6dff69245dbddf983dc886521e2623464e476922fc95f43af', categoryIds: [0], }, // 营销能力
{ name: 'MaketingV2', token: 'f6d5cee2383ca203dfa2882b84dfa02a1d79de3c3ad892b42f030437fdc5ea21', categoryIds: [0] }, // 营销活动v2
{ name: 'AfterServiceV2', token: '58748fc89dcdb33ec5cac520c00293ba92abca362a8ddb979df589effd0db9bd', categoryIds: [0], }, // 售后能力V2
]
......
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