Commit 79cf06a8 authored by 前端-黄佳鑫's avatar 前端-黄佳鑫

feat(营销活动监控): 布局完成

parent 4ae8d60b
......@@ -5,7 +5,7 @@
* @LastEditTime: 2021-08-26 16:31:22
*/
// import CommodityRoute from './commodityRoute' // 商品能力路由
// import MemberRoute from './memberRoute' // 会员能力路由
import MemberRoute from './memberRoute' // 会员能力路由
// import ShopRoute from './shopRoute' // 店铺能力路由
// import ChannelRoute from './channelRoute' // 渠道能力路由
// import TranactionRoute from './tranactionRoute' // 交易能力路由
......@@ -32,7 +32,7 @@ const homeRoute = {
key: 'home',
component: '@/pages/home',
};
const routes = isDev ? [ homeRoute, marketingRoute ] : asyncRoutes;
const routes = isDev ? [ homeRoute, marketingRoute, MemberRoute ] : asyncRoutes;
const memberCenterRoute = {
path: '/memberCenter',
......
......@@ -112,6 +112,7 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
const animationFrameId = requestAnimationFrame(() => {
setSelectedKeys(keys);
});
(location.pathname === '/memberCenter/marketingAbility/selfManagementMonitor') && handleMenuCollapse(true)
return () =>
window.cancelAnimationFrame &&
......
......@@ -2,9 +2,13 @@ import React from 'react';
export interface CardType {
/** 瞄点id */
id?: string,
/** 标题 */
title?: string,
/** 按钮组件 */
extra?: React.ReactNode,
/** 背景颜色 */
backgroundColor?: string,
}
......
......@@ -19,7 +19,7 @@ const AuditLayout: React.FC<AutditLayoutProps> = (props: any) => {
const handleSubmit = useCallback(async () => {
await form.validateFields().then(res => {
PublicApi.postTransactionNotarizeEnquiryQuotedPriceAffirm({ id, state: res.state, audit: res.audit }).then(res => {
PublicApi.postTransactionNotarizeEnquiryQuotedPriceAffirm({ id, state: res.state, auditOpinion: res.audit }).then(res => {
if (res.code !== 1000) {
setLoading(false)
return
......
......@@ -12,7 +12,7 @@ export interface cardProps {
/** body样式修改 */
bodyStyle?: CSSProperties,
/** calssName */
classNames?: string
classNames?: string,
}
const CardLayout: React.FC<cardProps> = (props: any) => {
......
.cardLayout {
margin-bottom: 16px !important;
.product_wrap {
display: flex;
align-items: center;
padding: 12px 16px;
border: 1px solid #EDEEEF;
border-radius: 4px;
.product_img {
height: 32px;
width: 32px;
overflow: hidden;
border-radius: 4px;
margin-right: 12px;
}
.product_item {
.product_item_title {
color: #252D37;
margin-bottom: 0;
}
.product_item_progress {
color: #EB9B00;
}
}
}
}
import React from 'react';
import { Row, Col, Image } from 'antd';
import style from './index.less';
import CardLayout from '../../../selfManagement/readySubmitExamine/components/card';
const ActivityProductList = () => {
return (
<CardLayout
title='活动商品列表 (28)'
id='activityProductList'
weight
classNames={style.cardLayout}
>
<Row gutter={[16, 16]}>
<Col xl={{ span: 8 }} span={12}>
<div className={style.product_wrap}>
<div className={style.product_img}>
<Image width={32} height={32} src='https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' />
</div>
<div className={style.product_item}>
<h5 className={style.product_item_title}>进口头层黄牛皮荔枝纹/红色/XL</h5>
<span className={style.product_item_progress}>50%</span>
</div>
</div>
</Col>
<Col xl={{ span: 8 }} span={12}>
<div className={style.product_wrap}>
<div className={style.product_img}>
<Image width={32} height={32} src='https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' />
</div>
<div className={style.product_item}>
<h5 className={style.product_item_title}>进口头层黄牛皮荔枝纹/红色/XL</h5>
<span className={style.product_item_progress}>50%</span>
</div>
</div>
</Col>
<Col xl={{ span: 8 }} span={12}>
<div className={style.product_wrap}>
<div className={style.product_img}>
<Image width={32} height={32} src='https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' />
</div>
<div className={style.product_item}>
<h5 className={style.product_item_title}>进口头层黄牛皮荔枝纹/红色/XL</h5>
<span className={style.product_item_progress}>50%</span>
</div>
</div>
</Col>
<Col xl={{ span: 8 }} span={12}>
<div className={style.product_wrap}>
<div className={style.product_img}>
<Image width={32} height={32} src='https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' />
</div>
<div className={style.product_item}>
<h5 className={style.product_item_title}>进口头层黄牛皮荔枝纹/红色/XL</h5>
<span className={style.product_item_progress}>50%</span>
</div>
</div>
</Col>
<Col xl={{ span: 8 }} span={12}>
<div className={style.product_wrap}>
<div className={style.product_img}>
<Image width={32} height={32} src='https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' />
</div>
<div className={style.product_item}>
<h5 className={style.product_item_title}>进口头层黄牛皮荔枝纹/红色/XL</h5>
<span className={style.product_item_progress}>50%</span>
</div>
</div>
</Col>
<Col xl={{ span: 8 }} span={12}>
<div className={style.product_wrap}>
<div className={style.product_img}>
<Image width={32} height={32} src='https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' />
</div>
<div className={style.product_item}>
<h5 className={style.product_item_title}>进口头层黄牛皮荔枝纹/红色/XL</h5>
<span className={style.product_item_progress}>50%</span>
</div>
</div>
</Col>
</Row>
</CardLayout>
)
}
export default ActivityProductList;
......@@ -3,7 +3,7 @@ import { Progress } from 'antd';
import style from './index.less';
const ActivityTypeLayout = () => {
const [dataSource, setDataSource] = useState([1, 2])
const [dataSource, setDataSource] = useState([1, 2, 3, 4])
return (
<div className={style.list_box}>
<div className={style.list_items} style={{ width: dataSource.length * 320 + 'px' }}>
......
import React from 'react';
import { Row, Col, Badge, Space, Divider, Typography } from 'antd';
import CardLayout from '../../../selfManagement/readySubmitExamine/components/card';
import DonutChart from 'bizcharts/lib/plots/DonutChart';
import style from './index.less';
interface AnalysisLayoutProps {
/** 标题 */
title?: string,
}
const AnalysisLayout: React.FC<AnalysisLayoutProps> = (props: any) => {
const { title } = props;
const data = [
{
type: "新用户",
value: 27,
},
{
type: "老用户",
value: 25,
},
{
type: "新会员",
value: 18,
},
{
type: "老会员",
value: 15,
},
];
return (
<CardLayout
weight
title={title}
classNames={style.cardLayout}
bodyStyle={{
padding: '0px 16px 16px'
}}
>
<DonutChart
data={data || []}
title={null}
autoFit
description={null}
height={180}
radius={1}
innerRadius={0.75}
padding="auto"
angleField="value"
colorField="type"
pieStyle={{ stroke: "white", lineWidth: 4 }}
label={null}
color={['#00A98F', '#007BFC', '#EB9B00', '#EF3346']}
statistic={{
title: {
formatter: (text) => {
return '用户总数'
},
offsetY: -10,
style: {
fontSize: "12px",
color: "#91959B",
},
},
content: {
formatter: (text) => {
return '5,000.00'
},
style: {
fontWeight: '400',
fontSize: "24px",
color: "#303133",
},
}
}}
legend={{
visible: false,
}}
/>
<Row gutter={[16, 16]} style={{ marginTop: '26px' }}>
<Col span={12}>
<Space size={12}>
<Badge color='#00A98F' text='新用户' />
<Divider type="vertical" />
<Typography.Text type='secondary'>20%</Typography.Text>
<Typography.Text>12</Typography.Text>
</Space>
</Col>
<Col span={12}>
<Space size={12}>
<Badge color='#EB9B00' text='新会员' />
<Divider type="vertical" />
<Typography.Text type='secondary'>20%</Typography.Text>
<Typography.Text>12</Typography.Text>
</Space>
</Col>
<Col span={12}>
<Space size={12}>
<Badge color='#007BFC' text='老用户' />
<Divider type="vertical" />
<Typography.Text type='secondary'>20%</Typography.Text>
<Typography.Text>12</Typography.Text>
</Space>
</Col>
<Col span={12}>
<Space size={12}>
<Badge color='#EF3346' text='老会员' />
<Divider type="vertical" />
<Typography.Text type='secondary'>20%</Typography.Text>
<Typography.Text>12</Typography.Text>
</Space>
</Col>
</Row>
</CardLayout>
)
}
export default AnalysisLayout;
.extraLayout {
margin-bottom: 16px;
:global {
.ant-card-extra {
padding: 0 0;
}
}
}
import React from 'react';
import { Radio, Badge, Space } from 'antd';
import { Axis, Chart } from 'bizcharts';
import LineAdvance from 'bizcharts/lib/geometry/LineAdvance';
import CardLayout from '@/pages/transaction/components/card';
import style from './index.less';
interface ChartLineAdvanceProps {
/** 数据 */
// data?: any[]
/** 标题 */
title?: string,
/** 类型 */
type?: 'lineAdvance' | 'lineInterval' | {} & string,
}
const ChartLineAdvance: React.FC<ChartLineAdvanceProps> = (props: any) => {
const { title, type = 'lineAdvance' } = props;
const scale = {
count: {
min: 0,
tickInterval: 200,
}
}
const data = [
{
dateTime: '01:00',
count: 900,
},
{
dateTime: '02:00',
count: 900,
},
{
dateTime: '03:00',
count: 900,
},
{
dateTime: '04:00',
count: 900,
},
{
dateTime: '05:00',
count: 900,
},
{
dateTime: '06:00',
count: 900,
},
{
dateTime: '07:00',
count: 900,
},
{
dateTime: '08:00',
count: 900,
},
{
dateTime: '09:00',
count: 900,
},
{
dateTime: '10:00',
count: 900,
},
{
dateTime: '11:00',
count: 900,
},
{
dateTime: '12:00',
count: 900,
},
{
dateTime: '13:00',
count: 888,
},
{
dateTime: '14:00',
count: 900,
},
{
dateTime: '15:00',
count: 880,
},
{
dateTime: '16:00',
count: 900,
},
{
dateTime: '17:00',
count: 870,
},
{
dateTime: '18:00',
count: 990,
},
{
dateTime: '19:00',
count: 950,
},
{
dateTime: '20:00',
count: 850,
},
{
dateTime: '21:00',
count: 650,
},
{
dateTime: '22:00',
count: 500,
},
{
dateTime: '23:00',
count: 500,
},
{
dateTime: '24:00',
count: 1000,
},
]
/** 类型 */
const extraButtonType = <Space>
{type === 'lineInterval' && (
<>
<Badge color='green' text='购买金额' />
<Badge color='blue' text='订单数量' />
</>
)}
<Radio.Group defaultValue={1} size="small">
<Radio.Button value={1}>今日</Radio.Button>
<Radio.Button value={2}>最近7日</Radio.Button>
<Radio.Button value={3}>全部</Radio.Button>
</Radio.Group>
</Space>
return (
<div className={style.extraLayout}>
<CardLayout
id='chartLineAdvance'
title={title}
extra={extraButtonType}
>
<Chart autoFit height={239} data={data} scale={scale}>
<Axis name="dateTime" visible={true} />
<Axis name="count" visible={true} />
<LineAdvance
position="dateTime*count"
color='#00A98F'
point
area
shape="smooth"
/>
</Chart>
</CardLayout>
</div>
)
}
export default ChartLineAdvance;
.cardLayout {
margin-bottom: 16px !important;
.dataLayout_wrap {
padding: 8px 16px;
background-color: #F5F6F7;
border-radius: 4px;
.dataLayout_wran {
color: #91959B;
margin-bottom: 0;
padding: 8px 0px 7px;
}
.dataLayout_item {
display: flex;
align-items: center;
justify-content: space-between;
.dataLayout_num {
font-size: 20px;
color: #1F2C3D;
margin-bottom: 0;
}
.dataLayout_value {
width: 47px;
height: 16px;
color: #EF3346;
background-color: #FFF0F2;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
.info_icon_style {
font-size: 10px;
color: #EF3346;
}
}
}
}
}
import React from 'react';
import { Row, Col } from 'antd';
import style from './index.less';
import CardLayout from '../../../selfManagement/readySubmitExamine/components/card';
import { CaretUpOutlined } from '@ant-design/icons';
const DataLayout = () => {
return (
<CardLayout
weight
title='当前商品数据'
classNames={style.cardLayout}
>
<Row gutter={[16, 16]}>
<Col xl={{ span: 6 }} span={12}>
<div className={style.dataLayout_wrap}>
<h5 className={style.dataLayout_wran}>今日参与客户数 (人)</h5>
<div className={style.dataLayout_item}>
<h4 className={style.dataLayout_num}>10</h4>
<div className={style.dataLayout_value}><CaretUpOutlined className={style.info_icon_style} />25%</div>
</div>
</div>
</Col>
<Col xl={{ span: 6 }} span={12}>
<div className={style.dataLayout_wrap}>
<h5 className={style.dataLayout_wran}>今日订单数 (单)</h5>
<div className={style.dataLayout_item}>
<h4 className={style.dataLayout_num}>10</h4>
<div className={style.dataLayout_value}><CaretUpOutlined className={style.info_icon_style} />25%</div>
</div>
</div>
</Col>
<Col xl={{ span: 6 }} span={12}>
<div className={style.dataLayout_wrap}>
<h5 className={style.dataLayout_wran}>今日购买数量 (件)</h5>
<div className={style.dataLayout_item}>
<h4 className={style.dataLayout_num}>200</h4>
<div className={style.dataLayout_value}><CaretUpOutlined className={style.info_icon_style} />25%</div>
</div>
</div>
</Col>
<Col xl={{ span: 6 }} span={12}>
<div className={style.dataLayout_wrap}>
<h5 className={style.dataLayout_wran}>今日购买金额 (元)</h5>
<div className={style.dataLayout_item}>
<h4 className={style.dataLayout_num}>1,000.00</h4>
<div className={style.dataLayout_value}><CaretUpOutlined className={style.info_icon_style} />25%</div>
</div>
</div>
</Col>
</Row>
</CardLayout>
)
}
export default DataLayout;
.cardLayout {
margin-bottom: 16px !important;
min-height: 320px;
.sourceLayout_wrap {
// width: 176px;
height: 64px;
display: flex;
padding: 16px;
background: #FAFBFC;
border-radius: 4px;
}
}
import React from 'react';
import { Row, Col, Space, Avatar, Typography } from 'antd';
import CardLayout from '../../../selfManagement/readySubmitExamine/components/card';
import style from './index.less';
const SourceLayout = () => {
return (
<CardLayout
title='当前商品用户来源分析'
weight
classNames={style.cardLayout}
>
<Row gutter={[16, 16]}>
<Col xl={{ span: 12 }} span={24}>
<div className={style.sourceLayout_wrap}>
<Space>
<div className={style.sourceLayout_avatar}>
<Avatar shape="square" size={32}>Logo</Avatar>
</div>
<div className={style.sourceLayout_content}>
<div className={style.sourceLayout_content_title}>WEB 企业商城</div>
<div className={style.sourceLayout_content_data}>
<Space>
<Typography.Text type='success'>15%</Typography.Text>
<Typography.Text type='secondary'>456人</Typography.Text>
</Space>
</div>
</div>
</Space>
</div>
</Col>
<Col xl={{ span: 12 }} span={24}>
<div className={style.sourceLayout_wrap}>
<Space>
<div className={style.sourceLayout_avatar}>
<Avatar shape="square" size={32}>Logo</Avatar>
</div>
<div className={style.sourceLayout_content}>
<div className={style.sourceLayout_content_title}>WEB 企业商城</div>
<div className={style.sourceLayout_content_data}>
<Space>
<Typography.Text type='success'>15%</Typography.Text>
<Typography.Text type='secondary'>456人</Typography.Text>
</Space>
</div>
</div>
</Space>
</div>
</Col>
<Col xl={{ span: 12 }} span={24}>
<div className={style.sourceLayout_wrap}>
<Space>
<div className={style.sourceLayout_avatar}>
<Avatar shape="square" size={32}>Logo</Avatar>
</div>
<div className={style.sourceLayout_content}>
<div className={style.sourceLayout_content_title}>WEB 企业商城</div>
<div className={style.sourceLayout_content_data}>
<Space>
<Typography.Text type='success'>15%</Typography.Text>
<Typography.Text type='secondary'>456人</Typography.Text>
</Space>
</div>
</div>
</Space>
</div>
</Col>
<Col xl={{ span: 12 }} span={24}>
<div className={style.sourceLayout_wrap}>
<Space>
<div className={style.sourceLayout_avatar}>
<Avatar shape="square" size={32}>Logo</Avatar>
</div>
<div className={style.sourceLayout_content}>
<div className={style.sourceLayout_content_title}>WEB 企业商城</div>
<div className={style.sourceLayout_content_data}>
<Space>
<Typography.Text type='success'>15%</Typography.Text>
<Typography.Text type='secondary'>456人</Typography.Text>
</Space>
</div>
</div>
</Space>
</div>
</Col>
</Row>
</CardLayout>
)
}
export default SourceLayout;
......@@ -4,6 +4,11 @@ import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ActivityLayout from './components/activityLayout';
import ProductListLayout from './components/productListLayout';
import ActivityTypeLayout from './components/activityTypeLayout';
import ActivityProductList from './components/activityProductList';
import DataLayout from './components/dataLayout';
import ChartLineAdvance from './components/chartLineAdvance';
import SourceLayout from './components/sourceLayout';
import AnalysisLayout from './components/analysisLayout';
const SelfManagementMonitor = () => {
return (
......@@ -12,6 +17,21 @@ const SelfManagementMonitor = () => {
<Row gutter={[16, 16]}>
<Col xl={{ span: 18 }} span={14}>
<ActivityTypeLayout />
<ActivityProductList />
<DataLayout />
<ChartLineAdvance title='当前商品客户趋势分析' />
<ChartLineAdvance title='当前商品活动效果趋势分析' type='lineInterval' />
<Row gutter={[16, 16]}>
<Col span={8}>
<SourceLayout />
</Col>
<Col span={8}>
<AnalysisLayout title='当前商品用户类型分析' />
</Col>
<Col span={8}>
<AnalysisLayout title='当前商品会员等级分析' />
</Col>
</Row>
</Col>
<Col xl={{ span: 6 }} span={10}>
<ProductListLayout />
......
......@@ -94,7 +94,7 @@ const AnchorModal: React.FC<AnchorModalProps> = (props: any) => {
/**查询品类树 */
const searchCategoryTree = (id: any) => {
return new Promise(resolve => {
PublicApi.getProductPlatformGetCategoryTree({ rootNodeId: id }).then(res => {
PublicApi.getProductCustomerGetCustomerCategoryTree({ rootNodeId: id }).then(res => {
if (res.code === 1000) {
resolve(res.data)
}
......
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