import React , { Component } from "react" ;
import { Row , Col , Tabs , Table , Divider , Spin } from "antd" ;
import { ContainerOutlined , BlockOutlined , SmileOutlined , TagsOutlined , GlobalOutlined , FullscreenOutlined , DingtalkOutlined , CarryOutOutlined , CoffeeOutlined , ClockCircleOutlined , HeartOutlined , IdcardOutlined , ContactsOutlined } from "@ant-design/icons" ;
import { stores _Context } from "../config" ;
import { Line , Pie } from "@ant-design/charts" ;
import { observer } from "mobx-react" ;
import * as config from "../config" ;
import { NavLink } from "react-router-dom" ;
import * as comm from "../utils/commons" ;
import { utils , writeFileXLSX } from "xlsx" ;
import DateGroupRadio from '../components/DateGroupRadio' ;
import SearchForm from './../components/search/SearchForm' ;
import { TableExportBtn } from './../components/Data' ;
class Orders extends Component {
static contextType = stores _Context ;
constructor ( props ) {
super ( props ) ;
}
format _data ( data ) {
const { date _picker _store , orders _store } = this . context ;
const result = { dataSource : [ ] , columns : [ ] } ;
if ( ! comm . empty ( data ) ) {
const ordercountTotal1 = data . ordercountTotal1 ;
const ordercountTotal2 = data . ordercountTotal2 ;
if ( date _picker _store . start _date _cp && date _picker _store . end _date _cp ) {
// 有比较的数据
result . columns = [
{
title : '#' ,
fixed : 'left' ,
children : [
{
title : (
< span >
< div >
{ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date . format ( config . DATE _FORMAT ) }
< / div >
< div >
{ date _picker _store . start _date _cp . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date _cp . format ( config . DATE _FORMAT ) }
< / div >
< / span >
) ,
titleX : ` ${ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ ${ date _picker _store . end _date . format ( config . DATE _FORMAT ) } vs ${ date _picker _store . start _date _cp . format (
config . DATE _FORMAT
) } ~ $ { date _picker _store . end _date _cp . format ( config . DATE _FORMAT ) } ` ,
dataIndex : 'OrderType' ,
fixed : 'left' ,
render : ( text , record ) => < NavLink to = { ` /orders_sub/ ${ orders _store . active _tab _key } / ${ record . OrderTypeSN } / ${ record . OrderType } ` } > { text } < / NavLink > ,
} ,
] ,
} ,
{
title : '数量' ,
children : [
{
title : comm . show _vs _tag ( ordercountTotal1 . OrderCount _vs , ordercountTotal1 . OrderCount _diff , ordercountTotal1 . OrderCount , ordercountTotal2 . OrderCount ) ,
titleX : [ ordercountTotal1 . OrderCount , ordercountTotal2 . OrderCount ] . join ( ' vs ' ) ,
dataIndex : 'OrderCount' ,
} ,
] ,
} ,
{
title : '成交数' ,
children : [
{
title : comm . show _vs _tag ( ordercountTotal1 . CJCount _vs , ordercountTotal1 . CJCount _diff , ordercountTotal1 . CJCount , ordercountTotal2 . CJCount ) ,
titleX : [ ordercountTotal1 . CJCount , ordercountTotal2 . CJCount ] . join ( ' vs ' ) ,
dataIndex : 'CJCount' ,
} ,
] ,
} ,
{
title : '成交人数' ,
children : [
{
title : comm . show _vs _tag ( ordercountTotal1 . CJPersonNum _vs , ordercountTotal1 . CJPersonNum _diff , ordercountTotal1 . CJPersonNum , ordercountTotal2 . CJPersonNum ) ,
titleX : [ ordercountTotal1 . CJPersonNum , ordercountTotal2 . CJPersonNum ] . join ( ' vs ' ) ,
dataIndex : 'CJPersonNum' ,
} ,
] ,
} ,
{
title : '成交率' ,
children : [
{
title : comm . show _vs _tag ( ordercountTotal1 . CJrate _vs , ordercountTotal1 . CJrate _diff , ordercountTotal1 . CJrate , ordercountTotal2 . CJrate ) ,
titleX : [ ordercountTotal1 . CJrate , ordercountTotal2 . CJrate ] . join ( ' vs ' ) ,
dataIndex : 'CJrate' ,
} ,
] ,
} ,
{
title : '成交毛利(预计)' ,
children : [
{
title : comm . show _vs _tag ( ordercountTotal1 . YJLY _vs , ordercountTotal1 . YJLY _diff , ordercountTotal1 . YJLY , ordercountTotal2 . YJLY ) ,
titleX : [ ordercountTotal1 . YJLY , ordercountTotal2 . YJLY ] . join ( ' vs ' ) ,
dataIndex : 'YJLY' ,
} ,
] ,
} ,
{
title : '单个订单价值' ,
children : [
{
title : comm . show _vs _tag ( ordercountTotal1 . Ordervalue _vs , ordercountTotal1 . Ordervalue _diff , ordercountTotal1 . Ordervalue , ordercountTotal2 . Ordervalue ) ,
titleX : [ ordercountTotal1 . Ordervalue , ordercountTotal2 . Ordervalue ] . join ( ' vs ' ) ,
dataIndex : 'Ordervalue' ,
} ,
] ,
} ,
] ;
// 1.找出两个数组OrderType相同的数据做比较显示 2.找出两组数据OrderType都不相同的数据做显示
let has _same _type = false ; // 数组1在数组2中是否找到相同的类型
for ( const item of data . ordercount1 ) {
has _same _type = false ;
// 数组1在数组2中相同的类型
for ( const item2 of data . ordercount2 ) {
if ( item . OrderType === item2 . OrderType ) {
has _same _type = true ;
result . dataSource . push ( {
key : item . key ,
OrderType : item . OrderType ,
OrderTypeSN : item . OrderTypeSN ,
OrderCount : comm . show _vs _tag ( item . OrderCount _vs , item . OrderCount _diff , item . OrderCount , item2 . OrderCount ) ,
OrderCount _X : ( [ item . OrderCount , item2 . OrderCount ] . join ( ' vs ' ) ) ,
CJCount : comm . show _vs _tag ( item . CJCount _vs , item . CJCount _diff , item . CJCount , item2 . CJCount ) ,
CJCount _X : ( [ item . CJCount , item2 . CJCount ] . join ( ' vs ' ) ) ,
CJPersonNum : comm . show _vs _tag ( item . CJPersonNum _vs , item . CJPersonNum _diff , item . CJPersonNum , item2 . CJPersonNum ) ,
CJPersonNum _X : ( [ item . CJPersonNum , item2 . CJPersonNum ] . join ( ' vs ' ) ) ,
CJrate : comm . show _vs _tag ( item . CJrate _vs , item . CJrate _diff , item . CJrate , item2 . CJrate ) ,
CJrate _X : ( [ item . CJrate , item2 . CJrate ] . join ( ' vs ' ) ) ,
YJLY : comm . show _vs _tag ( item . YJLY _vs , item . YJLY _diff , item . YJLY , item2 . YJLY ) ,
YJLY _X : ( [ item . YJLY , item2 . YJLY ] . join ( ' vs ' ) ) ,
Ordervalue : comm . show _vs _tag ( item . Ordervalue _vs , item . Ordervalue _diff , item . Ordervalue , item2 . Ordervalue ) ,
Ordervalue _X : ( [ item . Ordervalue , item2 . Ordervalue ] . join ( ' vs ' ) ) ,
} ) ;
}
}
// 数组1中不在数组2的类型
if ( has _same _type === false ) {
result . dataSource . push ( {
key : item . key ,
OrderType : item . OrderType ,
OrderTypeSN : item . OrderTypeSN ,
OrderCount : comm . show _vs _tag ( comm . formatPercent ( item . OrderCount ) , item . OrderCount , item . OrderCount , 0 ) ,
OrderCount _X : ( [ item . OrderCount , 0 ] . join ( ' vs ' ) ) ,
CJCount : comm . show _vs _tag ( comm . formatPercent ( item . CJCount ) , item . CJCount , item . CJCount , 0 ) ,
CJCount _X : ( [ item . CJCount , 0 ] . join ( ' vs ' ) ) ,
CJPersonNum : comm . show _vs _tag ( comm . formatPercent ( item . CJPersonNum ) , item . CJPersonNum , item . CJPersonNum , 0 ) ,
CJPersonNum _X : ( [ item . CJPersonNum , 0 ] . join ( ' vs ' ) ) ,
CJrate : comm . show _vs _tag ( item . CJrate , item . CJrate , item . CJrate , 0 ) ,
CJrate _X : ( [ item . CJrate , 0 ] . join ( ' vs ' ) ) ,
YJLY : comm . show _vs _tag ( comm . formatPercent ( item . YJLY ) , item . YJLY , item . YJLY , 0 ) ,
YJLY _X : ( [ item . YJLY , 0 ] . join ( ' vs ' ) ) ,
Ordervalue : comm . show _vs _tag ( comm . formatPercent ( item . Ordervalue ) , item . Ordervalue , item . Ordervalue , 0 ) ,
Ordervalue _X : ( [ item . Ordervalue , 0 ] . join ( ' vs ' ) ) ,
} ) ;
}
}
// 数组2中不在数组1的类型
for ( const item2 of data . ordercount2 ) {
has _same _type = false ;
for ( const item of data . ordercount1 ) {
if ( item . OrderType === item2 . OrderType ) {
has _same _type = true ;
}
}
if ( has _same _type === false ) {
result . dataSource . push ( {
key : item2 . key ,
OrderType : item2 . OrderType ,
OrderTypeSN : item2 . OrderTypeSN ,
OrderCount : comm . show _vs _tag ( comm . formatPercent ( - item2 . OrderCount ) , - item2 . OrderCount , 0 , item2 . OrderCount ) ,
OrderCount _X : ( [ 0 , item2 . OrderCount ] . join ( ' vs ' ) ) ,
CJCount : comm . show _vs _tag ( comm . formatPercent ( - item2 . CJCount ) , - item2 . CJCount , 0 , item2 . CJCount ) ,
CJCount _X : ( [ 0 , item2 . CJCount ] . join ( ' vs ' ) ) ,
CJPersonNum : comm . show _vs _tag ( comm . formatPercent ( - item2 . CJPersonNum ) , - item2 . CJPersonNum , 0 , item2 . CJPersonNum ) ,
CJPersonNum _X : ( [ 0 , item2 . CJPersonNum ] . join ( ' vs ' ) ) ,
CJrate : comm . show _vs _tag ( - item2 . CJrate , - item2 . CJrate , 0 , item2 . CJrate ) ,
CJrate _X : ( [ 0 , item2 . CJrate ] . join ( ' vs ' ) ) ,
YJLY : comm . show _vs _tag ( comm . formatPercent ( - item2 . YJLY ) , - item2 . YJLY , 0 , item2 . YJLY ) ,
YJLY _X : ( [ 0 , item2 . YJLY ] . join ( ' vs ' ) ) ,
Ordervalue : comm . show _vs _tag ( comm . formatPercent ( - item2 . Ordervalue ) , - item2 . Ordervalue , 0 , item2 . Ordervalue ) ,
Ordervalue _X : ( [ 0 , item2 . Ordervalue ] . join ( ' vs ' ) ) ,
} ) ;
}
}
} else {
result . columns = [
{
title : "#" ,
fixed : 'left' ,
children : [
{
title : (
< span >
< div >
{ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date . format ( config . DATE _FORMAT ) }
< / div >
< / span >
) ,
titleX : ` ${ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ ${ date _picker _store . end _date . format ( config . DATE _FORMAT ) } ` ,
fixed : 'left' ,
dataIndex : "OrderType" ,
render : ( text , record ) => < NavLink to = { ` /orders_sub/ ${ orders _store . active _tab _key } / ${ record . OrderTypeSN } / ${ record . OrderType } ` } > { text } < / NavLink > ,
} ,
] ,
} ,
{
title : "数量" ,
children : [ { title : ordercountTotal1 . OrderCount , dataIndex : "OrderCount" } ] ,
sorter : ( a , b ) => b . OrderCount - a . OrderCount ,
} ,
{
title : "成交数" ,
children : [ { title : ordercountTotal1 . CJCount , dataIndex : "CJCount" } ] ,
sorter : ( a , b ) => b . CJCount - a . CJCount ,
} ,
{
title : "成交人数" ,
children : [ { title : ordercountTotal1 . CJPersonNum , dataIndex : "CJPersonNum" } ] ,
sorter : ( a , b ) => b . CJPersonNum - a . CJPersonNum ,
} ,
{
title : "成交率" ,
children : [ { title : ordercountTotal1 . CJrate , dataIndex : "CJrate" } ] ,
sorter : ( a , b ) => parseInt ( b . CJrate ) - parseInt ( a . CJrate ) ,
} ,
{
title : "成交毛利(预计)" ,
children : [ { title : ordercountTotal1 . YJLY , dataIndex : "YJLY" } ] ,
sorter : ( a , b ) => parseFloat ( b . YJLY . replace ( /,/g , "" ) ) - parseFloat ( a . YJLY . replace ( /,/g , "" ) ) ,
} ,
{
title : "单个订单价值" ,
children : [ { title : ordercountTotal1 . Ordervalue , dataIndex : "Ordervalue" } ] ,
sorter : ( a , b ) => parseFloat ( b . Ordervalue . replace ( /,/g , "" ) ) - parseFloat ( a . Ordervalue . replace ( /,/g , "" ) ) ,
} ,
] ;
result . dataSource = data . ordercount1 ;
}
}
return result ;
}
render ( ) {
const { orders _store , date _picker _store } = this . context ;
const table _data = orders _store . orderCountData _Form ? this . format _data ( orders _store . orderCountData _Form ) : [ ] ;
const data _source = orders _store . orderCountData ? orders _store . orderCountData : [ ] ;
const avg _line _y = Math . round ( orders _store . avgLine1 ) ;
const pie _data = comm . empty ( orders _store . orderCountData _Form ) ? [ ] : orders _store . orderCountData _Form . ordercount1 ; // 饼图的显示
const pie _data2 = comm . empty ( orders _store . orderCountData _Form ) ? [ ] : orders _store . orderCountData _Form . ordercount2 ;
const config = {
data : data _source ,
padding : "auto" ,
xField : "xField" ,
yField : "yField" ,
seriesField : "seriesField" ,
// xAxis: {
// type: "timeCat",
// },
point : {
size : 4 ,
shape : "cicle" ,
} ,
annotations : [
{
type : "text" ,
position : [ "start" , avg _line _y ] ,
content : avg _line _y ,
offsetX : - 15 ,
style : {
fill : "#F4664A" ,
textBaseline : "bottom" ,
} ,
} ,
{
type : "line" ,
start : [ - 10 , avg _line _y ] ,
end : [ "max" , avg _line _y ] ,
style : {
stroke : "#F4664A" ,
lineDash : [ 2 , 2 ] ,
} ,
} ,
] ,
label : { } , // 显示标签
legend : {
itemValue : {
formatter : ( text , item ) => {
const items = data _source . filter ( d => d . seriesField === item . value ) ; // 按站点筛选
return items . length ? items . reduce ( ( a , b ) => a + b . yField , 0 ) : "" ; // 计算总数
} ,
} ,
} ,
tooltip : {
customItems : ( originalItems ) => {
// process originalItems,
return originalItems . map ( ele => ( { ... ele , name : ele . data ? . seriesField || ele . data ? . xField } ) ) ;
} ,
title : ( title , datum ) => {
let ret = title ;
switch ( orders _store . lineChartXGroup ) {
case 'day' :
ret = ` ${ title } ${ comm . getWeek ( datum . xField ) } ` ; // 显示周几
break ;
default :
break ;
}
return ret ;
} ,
} ,
// smooth: true,
} ;
const pie _config = {
appendPadding : 10 ,
data : [ ] ,
angleField : "OrderCount" ,
colorField : "OrderType" ,
radius : 0.8 ,
label : {
type : "outer" ,
content : "{name} {value} \n {percentage}" ,
} ,
legend : false , // 不显示图例
interactions : [
{
type : "element-selected" ,
} ,
{
type : "element-active" ,
} ,
] ,
} ;
const tableProps = {
dataSource : table _data . dataSource ,
columns : table _data . columns ,
size : 'small' ,
pagination : false ,
scroll : { x : ( 100 * ( table _data . columns . length ) ) } ,
loading : orders _store . loading ,
} ;
return (
< div >
< Row gutter = { 16 } className = { date _picker _store . siderBroken ? "" : "sticky-top" } >
< Col className = "gutter-row" span = { 24 } >
< SearchForm
defaultValue = { {
initialValue : {
... date _picker _store . formValues ,
... orders _store . searchValues ,
} ,
shows : [ 'DateType' , 'DepartmentList' , 'WebCode' , 'IncludeTickets' , 'dates' ] ,
fieldProps : {
DepartmentList : { show _all : false , mode : 'multiple' } ,
WebCode : { show _all : false , mode : 'multiple' } ,
years : { hide _vs : true } ,
} ,
} }
onSubmit = { ( _err , obj , form , str ) => {
orders _store . setSearchValues ( obj , form ) ;
orders _store . getOrderCount ( ) ;
orders _store . onChange _Tabs ( orders _store . active _tab _key ) ;
} }
/ >
< / Col >
< / Row >
< Row gutter = { [ 16 , { sm : 16 , lg : 32 } ] } >
< Col span = { 24 } style = { { textAlign : 'right' } } >
< DateGroupRadio
visible = { data _source . length !== 0 }
dataRaw = { orders _store . orderCountDataRaw }
onChange = { orders _store . onChangeDateGroup }
value = { orders _store . lineChartXGroup }
dataMapper = { orders _store . orderCountDataMapper }
fieldMapper = { orders _store . orderCountDataFieldMapper }
/ >
< / Col >
< Col span = { 24 } >
< Spin spinning = { orders _store . loading } >
< Line { ...config } / >
< / Spin >
< / Col >
< Col span = { 24 } >
< Tabs
activeKey = { orders _store . active _tab _key }
onChange = { ( active _key ) => orders _store . onChange _Tabs ( active _key ) }
items = { [
{
key : 'Form' ,
label : (
< span >
< ContainerOutlined / >
来源类型
< / span >
) ,
} ,
{
key : 'Product' ,
label : (
< span >
< CarryOutOutlined / >
产品类型
< / span > ) ,
} ,
{
key : 'Country' ,
label : (
< span >
< SmileOutlined / >
国籍
< / span >
) ,
} ,
{
key : 'line' ,
label : (
< span >
< TagsOutlined / >
线路
< / span >
) ,
} ,
{
key : 'city' ,
label : (
< span >
< GlobalOutlined / >
目的地
< / span >
) ,
} ,
{
key : 'LineClass' ,
label : (
< span >
< BlockOutlined / >
页面类型
< / span >
) ,
} ,
{
key : 'GuestGroupType' ,
label : (
< span >
< FullscreenOutlined / >
客群类别
< / span >
) ,
} ,
{
key : 'TravelMotivation' ,
label : (
< span >
< DingtalkOutlined / >
出行动机
< / span >
) ,
} ,
{
key : 'ToB' ,
label : (
< span >
< ContactsOutlined / >
客运类别
< / span >
) ,
} ,
{ key : 'FoodRequirement' , label : ( < span > < CoffeeOutlined / > 饮食要求 < / span > ) , } ,
{ key : 'hobbies' , label : ( < span > < HeartOutlined / > 兴趣爱好 < / span > ) , } ,
{ key : 'ages' , label : ( < span > < IdcardOutlined / > 年龄段 < / span > ) , } ,
] . map ( ( ele ) => {
return {
... ele ,
children : (
< >
< Table sticky id = { ` table_to_xlsx_ ${ ele . key } ` } { ...tableProps } / >
< Divider orientation = "right" plain >
< TableExportBtn label = { ele . key } { ... { columns : tableProps.columns , dataSource : tableProps.dataSource }} / >
< / Divider >
< / >
) ,
} ;
} ) }
/ >
< Row >
< Col sm = { 24 } lg = { 12 } >
< Pie { ...pie_config } data = { pie _data } / >
< / Col >
< Col sm = { 24 } lg = { 12 } >
< Pie { ...pie_config } data = { pie _data2 } / >
< / Col >
< / Row >
< / Col >
< / Row >
< / div >
) ;
}
}
export default observer ( Orders ) ;