Merge branch 'main' of github.com:hainatravel/dashboard
commit
564b959974
@ -1,122 +1,120 @@
|
|||||||
import './App.css';
|
import "./App.css";
|
||||||
import React, {useContext} from 'react';
|
import React, { useContext } from "react";
|
||||||
import {
|
import { HomeOutlined, TeamOutlined, DashboardOutlined, FileProtectOutlined, CustomerServiceTwoTone, SnippetsTwoTone, DollarOutlined, AreaChartOutlined, WechatOutlined, UserOutlined } from "@ant-design/icons";
|
||||||
HomeOutlined,
|
import { Layout, Menu, Image, Spin } from "antd";
|
||||||
TeamOutlined,
|
import { BrowserRouter, Route, Routes, NavLink } from "react-router-dom";
|
||||||
DashboardOutlined,
|
import Home from "./views/Home";
|
||||||
FileProtectOutlined,
|
import Dashboard from "./views/Dashboard";
|
||||||
CustomerServiceTwoTone,
|
import Orders from "./views/Orders";
|
||||||
DollarOutlined,
|
import Orders_sub from "./views/Orders_sub";
|
||||||
AreaChartOutlined,
|
import ProtectedRoute from "./views/ProtectedRoute";
|
||||||
WechatOutlined,
|
import Customer_care_inchina from "./charts/Customer_care_inchina";
|
||||||
UserOutlined
|
import Customer_care_potential from "./charts/Customer_care_potential";
|
||||||
} from '@ant-design/icons';
|
import Customer_care_regular from "./charts/Customer_care_regular";
|
||||||
import {Layout, Menu, Image, Spin} from 'antd';
|
import Wechat_session from "./charts/Wechat_session";
|
||||||
import {BrowserRouter, Route, Routes, NavLink} from "react-router-dom"
|
import WhatsApp_session from "./charts/WhatsApp_session";
|
||||||
import Home from "./views/Home"
|
import Credit_card_bill from "./views/Credit_card_bill";
|
||||||
import Dashboard from "./views/Dashboard"
|
import exchange_rate from "./charts/ExchangeRate";
|
||||||
import Orders from "./views/Orders"
|
import Sale from "./views/Sale";
|
||||||
import Orders_sub from "./views/Orders_sub"
|
import Logo from "./logo.png";
|
||||||
import ProtectedRoute from "./views/ProtectedRoute"
|
import { stores_Context } from "./config";
|
||||||
import Customer_care_inchina from "./charts/Customer_care_inchina"
|
import { observer } from "mobx-react";
|
||||||
import Customer_care_potential from "./charts/Customer_care_potential"
|
import ExchangeRate from "./charts/ExchangeRate";
|
||||||
import Customer_care_regular from "./charts/Customer_care_regular"
|
|
||||||
import Wechat_session from "./charts/Wechat_session"
|
|
||||||
import WhatsApp_session from "./charts/WhatsApp_session"
|
|
||||||
import Credit_card_bill from "./views/Credit_card_bill"
|
|
||||||
import Logo from './logo.png'
|
|
||||||
import {stores_Context} from "./config";
|
|
||||||
import {observer} from "mobx-react";
|
|
||||||
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
const { Content, Footer, Sider } = Layout;
|
||||||
|
const { auth_store } = useContext(stores_Context);
|
||||||
|
|
||||||
|
const menu_items = [
|
||||||
|
{ key: 1, label: <NavLink to="/">主页</NavLink>, icon: <HomeOutlined /> },
|
||||||
|
{
|
||||||
|
key: 2,
|
||||||
|
label: "市场",
|
||||||
|
icon: <AreaChartOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: 21, label: <NavLink to="/orders">订单数据</NavLink>, icon: <FileProtectOutlined /> },
|
||||||
|
{ key: 22, label: <NavLink to="/dashboard">仪表盘</NavLink>, icon: <DashboardOutlined /> },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 5,
|
||||||
|
label: "销售",
|
||||||
|
icon: <SnippetsTwoTone />,
|
||||||
|
children: [{ key: 51, label: <NavLink to="/sale">业绩数据</NavLink> }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 3,
|
||||||
|
label: "客运",
|
||||||
|
icon: <WechatOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: 31, label: <NavLink to="/customer_care_potential">潜力客户</NavLink> },
|
||||||
|
{ key: 32, label: <NavLink to="/customer_care_regular">老客户</NavLink> },
|
||||||
|
{ key: 33, label: <NavLink to="/customer_care_inchina">在华客户</NavLink> },
|
||||||
|
{ key: 34, label: <NavLink to="/wechat_session">微信会话存档</NavLink> },
|
||||||
|
{ key: 35, label: <NavLink to="/whatsapp_session">WhatsApp会话存档</NavLink> },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 4,
|
||||||
|
label: "财务",
|
||||||
|
icon: <DollarOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: 41, label: <NavLink to="/credit_card_bill">信用卡账单</NavLink> },
|
||||||
|
{ key: 42, label: <NavLink to="/exchange_rate">汇率</NavLink> },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const {Content, Footer, Sider} = Layout;
|
return (
|
||||||
const {auth_store} = useContext(stores_Context);
|
<BrowserRouter>
|
||||||
|
<Layout
|
||||||
const menu_items = [
|
style={{
|
||||||
{key: 1, label: <NavLink to="/">主页</NavLink>, icon: <HomeOutlined/>},
|
minHeight: "100vh",
|
||||||
{
|
}}>
|
||||||
key: 2, label: '市场', icon: <AreaChartOutlined/>,
|
<Sider collapsible={true} breakpoint="lg">
|
||||||
children: [
|
<Image src={Logo} preview={false} />
|
||||||
{key: 21, label: <NavLink to="/orders">订单数据</NavLink>, icon: <FileProtectOutlined/>,},
|
<Menu theme="dark" defaultSelectedKeys={["1"]} defaultOpenKeys={["2", "3", "4", "5"]} mode="inline" items={menu_items} />
|
||||||
{key: 22, label: <NavLink to="/dashboard">仪表盘</NavLink>, icon: <DashboardOutlined/>},
|
</Sider>
|
||||||
]
|
<Layout className="site-layout">
|
||||||
},
|
<Content
|
||||||
{
|
style={{
|
||||||
key: 3, label: '客运', icon: <WechatOutlined/>,
|
padding: 16,
|
||||||
children: [
|
minHeight: 480,
|
||||||
{key: 31, label: <NavLink to="/customer_care_potential">潜力客户</NavLink>},
|
}}>
|
||||||
{key: 32, label: <NavLink to="/customer_care_regular">老客户</NavLink>},
|
<Routes>
|
||||||
{key: 33, label: <NavLink to="/customer_care_inchina">在华客户</NavLink>},
|
<Route path="/" element={<Home />} />
|
||||||
{key: 34, label: <NavLink to="/wechat_session">微信会话存档</NavLink>},
|
<Route element={<ProtectedRoute auth={["admin", "director_bu", "marketing"]} />}>
|
||||||
{key: 35, label: <NavLink to="/whatsapp_session">WhatsApp会话存档</NavLink>},
|
<Route path="/orders" element={<Orders />} />
|
||||||
]
|
<Route path="/orders_sub/:ordertype/:ordertype_sub/:ordertype_title" element={<Orders_sub />} />
|
||||||
},
|
<Route path="/dashboard" element={<Dashboard />} />
|
||||||
{
|
</Route>
|
||||||
key: 4,
|
<Route element={<ProtectedRoute auth={["admin", "director_bu", "customer_care"]} />}>
|
||||||
label: '财务',
|
<Route path="/customer_care_inchina" element={<Customer_care_inchina />} />
|
||||||
icon: <DollarOutlined/>,
|
<Route path="/customer_care_regular" element={<Customer_care_regular />} />
|
||||||
children: [
|
<Route path="/customer_care_potential" element={<Customer_care_potential />} />
|
||||||
{key: 41, label: <NavLink to="/credit_card_bill">信用卡账单</NavLink>},
|
<Route path="/whatsapp_session" element={<WhatsApp_session />} />
|
||||||
]
|
<Route path="/wechat_session" element={<Wechat_session />} />
|
||||||
},
|
</Route>
|
||||||
|
<Route element={<ProtectedRoute auth={["admin", "director_bu", "financial"]} />}>
|
||||||
|
<Route path="/credit_card_bill" element={<Credit_card_bill />} />
|
||||||
];
|
<Route path="/exchange_rate" element={<ExchangeRate />} />
|
||||||
|
</Route>
|
||||||
return (
|
<Route element={<ProtectedRoute auth={["admin", "director_bu", "sale"]} />}>
|
||||||
<BrowserRouter>
|
<Route path="/sale" element={<Sale />} />
|
||||||
<Layout
|
</Route>
|
||||||
style={{
|
</Routes>
|
||||||
minHeight: '100vh',
|
</Content>
|
||||||
}}
|
<Footer
|
||||||
>
|
style={{
|
||||||
<Sider collapsible={false} defaultCollapsed={false} breakpoint="lg"
|
textAlign: "center",
|
||||||
collapsedWidth="0">
|
}}>
|
||||||
<Image src={Logo} preview={false}/>
|
<UserOutlined /> {auth_store.user.name} ({auth_store.user.userid})<br />
|
||||||
<Menu theme="dark" defaultSelectedKeys={['1']} defaultOpenKeys={['2', '3','4']} mode="inline"
|
Hainatravel Dashboard ©2022 Created by IT
|
||||||
items={menu_items}/>
|
</Footer>
|
||||||
</Sider>
|
</Layout>
|
||||||
<Layout className="site-layout">
|
</Layout>
|
||||||
<Content style={{
|
</BrowserRouter>
|
||||||
padding: 16,
|
);
|
||||||
minHeight: 480,
|
};
|
||||||
}}>
|
|
||||||
<Routes>
|
|
||||||
<Route path="/" element={<Home/>}/>
|
|
||||||
<Route element={<ProtectedRoute auth={['admin', 'director_bu', 'marketing']}/>}>
|
|
||||||
<Route path="/orders" element={<Orders/>}/>
|
|
||||||
<Route path="/orders_sub/:ordertype/:ordertype_sub/:ordertype_title"
|
|
||||||
element={<Orders_sub/>}/>
|
|
||||||
<Route path="/dashboard" element={<Dashboard/>}/>
|
|
||||||
</Route>
|
|
||||||
<Route element={<ProtectedRoute auth={['admin', 'director_bu', 'customer_care']}/>}>
|
|
||||||
<Route path="/customer_care_inchina" element={<Customer_care_inchina/>}/>
|
|
||||||
<Route path="/customer_care_regular" element={<Customer_care_regular/>}/>
|
|
||||||
<Route path="/customer_care_potential" element={<Customer_care_potential/>}/>
|
|
||||||
<Route path="/whatsapp_session" element={<WhatsApp_session/>}/>
|
|
||||||
<Route path="/wechat_session" element={<Wechat_session/>}/>
|
|
||||||
</Route>
|
|
||||||
<Route element={<ProtectedRoute auth={['admin', 'director_bu', 'financial']}/>}>
|
|
||||||
<Route path="/credit_card_bill" element={<Credit_card_bill/>}/>
|
|
||||||
</Route>
|
|
||||||
</Routes>
|
|
||||||
</Content>
|
|
||||||
<Footer
|
|
||||||
style={{
|
|
||||||
textAlign: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<UserOutlined/> {auth_store.user.name} ({auth_store.user.userid})<br/>
|
|
||||||
Hainatravel Dashboard ©2022 Created by IT
|
|
||||||
</Footer>
|
|
||||||
</Layout>
|
|
||||||
</Layout>
|
|
||||||
</BrowserRouter>
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default observer(App);
|
export default observer(App);
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
import { Table, Button, Space, Radio } from "antd";
|
||||||
|
import { SearchOutlined } from "@ant-design/icons";
|
||||||
|
import GroupSelect from "./GroupSelect";
|
||||||
|
import DatePickerCharts from "./DatePickerCharts";
|
||||||
|
import { stores_Context } from "../config";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import * as comm from "../utils/commons";
|
||||||
|
import { Line } from "@ant-design/charts";
|
||||||
|
import * as config from "../config";
|
||||||
|
|
||||||
|
class ExchangeRate extends Component {
|
||||||
|
static contextType = stores_Context;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { dashboard_store, date_picker_store } = this.context;
|
||||||
|
const { exchangeRate_data } = dashboard_store;
|
||||||
|
const line_data_source = comm.empty(exchangeRate_data.data) ? [] : exchangeRate_data.data.CurrencyData1;
|
||||||
|
const line_config = {
|
||||||
|
data: line_data_source,
|
||||||
|
padding: "auto",
|
||||||
|
xField: "er_date",
|
||||||
|
yField: "er_htrate",
|
||||||
|
seriesField: "er_currency",
|
||||||
|
xAxis: {
|
||||||
|
type: "timeCat",
|
||||||
|
},
|
||||||
|
point: {
|
||||||
|
size: 4,
|
||||||
|
shape: "cicle",
|
||||||
|
},
|
||||||
|
label: {}, //显示标签
|
||||||
|
tooltip: {
|
||||||
|
// customContent: (title, items) => {
|
||||||
|
// const data = items[0]?.data || {};
|
||||||
|
// return `<div>${title}</div><div>${data.seriesField} ${data.yField}</div>`;
|
||||||
|
// },
|
||||||
|
// itemTpl: '<li class="g2-tooltip-list-item"><span style="background-color:{color};" class="g2-tooltip-marker"></span><span class="g2-tooltip-name">{name}</span>: <span class="g2-tooltip-value">{value}</span></li>',
|
||||||
|
customItems: items => {
|
||||||
|
let result_arr = [];
|
||||||
|
items.forEach(item => {
|
||||||
|
item.value = item.data.er_htrate + " | " + item.data.er_bankrate;
|
||||||
|
return result_arr.push(item);
|
||||||
|
});
|
||||||
|
return result_arr; //return [{color:'red',name:'sss',value:22},{color:'red',name:'aaaa',value:22}];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
smooth: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>汇率 HT|Bank</h2>
|
||||||
|
<Space size="large">
|
||||||
|
<DatePickerCharts hide_vs={true} />
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<SearchOutlined />}
|
||||||
|
loading={exchangeRate_data.loading}
|
||||||
|
onClick={() => {
|
||||||
|
exchangeRate_data.asyncFetch(date_picker_store.start_date.format(config.DATE_FORMAT), date_picker_store.end_date.format(config.DATE_FORMAT));
|
||||||
|
}}>
|
||||||
|
统计
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
<Line {...line_config} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default observer(ExchangeRate);
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export const stores_Context = React.createContext();
|
export const stores_Context = React.createContext();
|
||||||
export const DATE_FORMAT = 'YYYY-MM-DD';
|
export const DATE_FORMAT = "YYYY-MM-DD";
|
||||||
export const HT_HOST = 'https://p9axztuwd7x8a7.mycht.cn';
|
//export const HT_HOST = 'https://p9axztuwd7x8a7.mycht.cn';
|
||||||
//export const HT_HOST = 'http://202.103.68.100:890';//889正式库
|
export const HT_HOST = "http://202.103.68.100:890"; //889正式库
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
import { makeAutoObservable, runInAction } from "mobx";
|
||||||
|
import * as dd from "dingtalk-jsapi";
|
||||||
|
import * as config from "../config";
|
||||||
|
import * as comm from "../utils/commons";
|
||||||
|
|
||||||
|
//销售数据
|
||||||
|
class SaleStore {
|
||||||
|
constructor(rootStore) {
|
||||||
|
this.rootStore = rootStore;
|
||||||
|
makeAutoObservable(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = false;
|
||||||
|
active_tab_key = "overview"; //当前选择的标签
|
||||||
|
group_select_mode = false;
|
||||||
|
date_type = "applyDate";
|
||||||
|
groups = ["1,2,28,7"];
|
||||||
|
date_title='date_title';//日期段,只用于显示,防止日期选择控件的变化导致页面刷新
|
||||||
|
|
||||||
|
//选择事业部
|
||||||
|
group_handleChange(value) {
|
||||||
|
this.groups = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//切换标签页
|
||||||
|
onChange_Tabs(active_key) {
|
||||||
|
this.active_tab_key = active_key;
|
||||||
|
//this.getOrderCountByType_sub(ordertype, ordertype_sub, this.active_tab_key_sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
//下单日期或者出发日期
|
||||||
|
onChange_datetype(e) {
|
||||||
|
this.date_type = e.target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取业绩信息
|
||||||
|
getxxxxx(ordertype, ordertype_sub) {
|
||||||
|
// this.loading = true;
|
||||||
|
// const date_picker_store = this.rootStore.date_picker_store;
|
||||||
|
// let url = '/service-web/QueryData/GetOrderCount'
|
||||||
|
// url += `?OrderType=${ordertype}&OrderType_val=${ordertype_sub}`;
|
||||||
|
// url += '&WebCode=' + this.webcode + '&COLI_ApplyDate1=' + date_picker_store.start_date.format(config.DATE_FORMAT) + '&COLI_ApplyDate2=' + date_picker_store.end_date.format(config.DATE_FORMAT) + '%2023:59:59';
|
||||||
|
// if (date_picker_store.start_date_cp && date_picker_store.end_date_cp) {
|
||||||
|
// url += '&COLI_ApplyDateold1=' + date_picker_store.start_date_cp.format(config.DATE_FORMAT) + '&COLI_ApplyDateold2=' + date_picker_store.end_date_cp.format(config.DATE_FORMAT) + '%2023:59:59';
|
||||||
|
// }
|
||||||
|
// fetch(config.HT_HOST + url)
|
||||||
|
// .then((response) => response.json())
|
||||||
|
// .then((json) => {
|
||||||
|
// runInAction(() => {
|
||||||
|
// this.orderCountData_type = this.format_data_source(json, date_picker_store.start_date, date_picker_store.start_date_cp);
|
||||||
|
// this.loading = false;
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .catch((error) => {
|
||||||
|
// this.loading = false;
|
||||||
|
// console.log('fetch data failed', error);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SaleStore;
|
@ -1,298 +1,361 @@
|
|||||||
import React, {Component, useContext} from 'react';
|
import React, { Component, useContext } from "react";
|
||||||
import {observer} from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import {Row, Col, Button, Tabs, Table, Divider} from 'antd';
|
import { Row, Col, Button, Tabs, Table, Divider } from "antd";
|
||||||
import {stores_Context} from '../config'
|
import { stores_Context } from "../config";
|
||||||
import {utils, writeFileXLSX} from "xlsx";
|
import { utils, writeFileXLSX } from "xlsx";
|
||||||
import {NavLink, useNavigate} from "react-router-dom";
|
import { NavLink, useNavigate } from "react-router-dom";
|
||||||
import {
|
import { SlackOutlined, ContainerOutlined, CarryOutOutlined, SearchOutlined, GithubOutlined } from "@ant-design/icons";
|
||||||
SlackOutlined,
|
import BillTypeSelect from "../charts/BillTypeSelect";
|
||||||
ContainerOutlined,
|
import GroupSelect from "../charts/GroupSelect";
|
||||||
CarryOutOutlined,
|
import Business_unit from "../charts/Business_unit";
|
||||||
SearchOutlined,
|
import DatePickerCharts from "../charts/DatePickerCharts";
|
||||||
GithubOutlined
|
import { Line, Pie } from "@ant-design/charts";
|
||||||
} from '@ant-design/icons';
|
import * as comm from "../utils/commons";
|
||||||
import BillTypeSelect from '../charts/BillTypeSelect'
|
|
||||||
import GroupSelect from '../charts/GroupSelect'
|
|
||||||
import Business_unit from '../charts/Business_unit'
|
|
||||||
import DatePickerCharts from '../charts/DatePickerCharts'
|
|
||||||
import {Line} from "@ant-design/charts";
|
|
||||||
import * as comm from '../utils/commons'
|
|
||||||
import * as config from "../config";
|
import * as config from "../config";
|
||||||
|
|
||||||
|
|
||||||
const Credit_card_bill = () => {
|
const Credit_card_bill = () => {
|
||||||
|
const { financial_store, date_picker_store } = useContext(stores_Context);
|
||||||
|
const { bill_type_data, credit_card_data } = financial_store;
|
||||||
|
|
||||||
const {financial_store, date_picker_store} = useContext(stores_Context);
|
const format_data = data => {
|
||||||
const {bill_type_data, credit_card_data} = financial_store;
|
let result = { dataSource: [], columns: [] };
|
||||||
|
if (!comm.empty(data)) {
|
||||||
const format_data = ((data) => {
|
if (date_picker_store.start_date_cp && date_picker_store.end_date_cp) {
|
||||||
let result = {dataSource: [], columns: []}
|
//有比较的数据
|
||||||
if (!comm.empty(data)) {
|
let total_data1 = data.BillTypeDataTotal1;
|
||||||
if (date_picker_store.start_date_cp && date_picker_store.end_date_cp) { //有比较的数据
|
let total_data2 = data.BillTypeDataTotal2;
|
||||||
let total_data1 = data.BillTypeDataTotal1;
|
result.columns = [
|
||||||
let total_data2 = data.BillTypeDataTotal2;
|
{
|
||||||
result.columns = [
|
title: "项目类型",
|
||||||
{
|
children: [
|
||||||
title: '项目类型',
|
{
|
||||||
children: [{
|
title: "",
|
||||||
title: '',
|
dataIndex: "cb_billtype",
|
||||||
dataIndex: 'cb_billtype',
|
render: (text, record) => (
|
||||||
render: (text, record) => <a onClick={() => {
|
<a
|
||||||
credit_card_data.set_bill_filtered(text);//切换到明细页
|
onClick={() => {
|
||||||
credit_card_data.set_active_tab('detail_data');
|
credit_card_data.set_bill_filtered(text); //切换到明细页
|
||||||
}}>{text}</a>
|
credit_card_data.set_active_tab("detail_data");
|
||||||
}],
|
}}>
|
||||||
sorter: (a, b) => a.cb_billtype.localeCompare(b.cb_billtype),
|
{text}
|
||||||
},
|
</a>
|
||||||
{
|
),
|
||||||
title: '美金',
|
},
|
||||||
children: [{
|
],
|
||||||
title: comm.show_vs_tag(total_data1.usd_vs, total_data1.usd_diff, total_data1.cb_usd, total_data2.cb_usd),
|
sorter: (a, b) => a.cb_billtype.localeCompare(b.cb_billtype),
|
||||||
dataIndex: 'cb_usd'
|
},
|
||||||
}],
|
{
|
||||||
},
|
title: "美金",
|
||||||
{
|
children: [
|
||||||
title: '人民币',
|
{
|
||||||
children: [{
|
title: comm.show_vs_tag(total_data1.usd_vs, total_data1.usd_diff, total_data1.cb_usd, total_data2.cb_usd),
|
||||||
title: comm.show_vs_tag(total_data1.rmb_vs, total_data1.rmb_diff, total_data1.cb_rmb, total_data2.cb_rmb),
|
dataIndex: "cb_usd",
|
||||||
dataIndex: 'cb_rmb'
|
},
|
||||||
}],
|
],
|
||||||
},
|
},
|
||||||
];
|
{
|
||||||
for (let item of data.BillTypeData1) {
|
title: "人民币",
|
||||||
for (let item2 of data.BillTypeData2) {
|
children: [
|
||||||
if (item.cb_billtype == item2.cb_billtype) {
|
{
|
||||||
result.dataSource.push({
|
title: comm.show_vs_tag(total_data1.rmb_vs, total_data1.rmb_diff, total_data1.cb_rmb, total_data2.cb_rmb),
|
||||||
key: item.key,
|
dataIndex: "cb_rmb",
|
||||||
cb_billtype: item.cb_billtype,
|
},
|
||||||
groups: item.groups,
|
],
|
||||||
cb_usd: comm.show_vs_tag(item.usd_vs, item.usd_diff, item.cb_usd, item2.cb_usd),
|
},
|
||||||
cb_rmb: comm.show_vs_tag(item.rmb_vs, item.rmb_diff, item.cb_rmb, item2.cb_rmb),
|
];
|
||||||
})
|
for (let item of data.BillTypeData1) {
|
||||||
}
|
for (let item2 of data.BillTypeData2) {
|
||||||
}
|
if (item.cb_billtype == item2.cb_billtype) {
|
||||||
}
|
result.dataSource.push({
|
||||||
} else {
|
key: item.key,
|
||||||
result.columns = [
|
cb_billtype: item.cb_billtype,
|
||||||
{
|
groups: item.groups,
|
||||||
title: '项目类型',
|
cb_usd: comm.show_vs_tag(item.usd_vs, item.usd_diff, item.cb_usd, item2.cb_usd),
|
||||||
children: [{
|
cb_rmb: comm.show_vs_tag(item.rmb_vs, item.rmb_diff, item.cb_rmb, item2.cb_rmb),
|
||||||
title: '',
|
});
|
||||||
dataIndex: 'cb_billtype',
|
}
|
||||||
render: (text, record) => <a onClick={() => {
|
}
|
||||||
credit_card_data.set_bill_filtered(text);//切换到明细页
|
}
|
||||||
credit_card_data.set_active_tab('detail_data');
|
} else {
|
||||||
}}>{text}</a>
|
result.columns = [
|
||||||
}],
|
{
|
||||||
sorter: (a, b) => a.cb_billtype.localeCompare(b.cb_billtype),
|
title: "项目类型",
|
||||||
},
|
children: [
|
||||||
{
|
{
|
||||||
title: '美金',
|
title: "",
|
||||||
children: [{title: data.BillTypeDataTotal1.cb_usd, dataIndex: 'cb_usd'}],
|
dataIndex: "cb_billtype",
|
||||||
sorter: (a, b) => parseFloat(b.cb_usd.replace(/,/g, '')) - parseFloat(a.cb_usd.replace(/,/g, '')),
|
render: (text, record) => (
|
||||||
},
|
<a
|
||||||
{
|
onClick={() => {
|
||||||
title: '人民币',
|
credit_card_data.set_bill_filtered(text); //切换到明细页
|
||||||
children: [{title: data.BillTypeDataTotal1.cb_rmb, dataIndex: 'cb_rmb'}],
|
credit_card_data.set_active_tab("detail_data");
|
||||||
sorter: (a, b) => parseFloat(b.cb_rmb.replace(/,/g, '')) - parseFloat(a.cb_rmb.replace(/,/g, '')),
|
}}>
|
||||||
},
|
{text}
|
||||||
]
|
</a>
|
||||||
result.dataSource = data.BillTypeData1;
|
),
|
||||||
}
|
},
|
||||||
}
|
],
|
||||||
return result;
|
sorter: (a, b) => a.cb_billtype.localeCompare(b.cb_billtype),
|
||||||
})
|
},
|
||||||
|
{
|
||||||
const filters_array = (data_array) => {
|
title: "美金",
|
||||||
return comm.unique(data_array).map(item => {
|
children: [{ title: data.BillTypeDataTotal1.cb_usd, dataIndex: "cb_usd" }],
|
||||||
return {text: item, value: item}
|
sorter: (a, b) => parseFloat(b.cb_usd.replace(/,/g, "")) - parseFloat(a.cb_usd.replace(/,/g, "")),
|
||||||
});
|
},
|
||||||
}
|
{
|
||||||
|
title: "人民币",
|
||||||
|
children: [{ title: data.BillTypeDataTotal1.cb_rmb, dataIndex: "cb_rmb" }],
|
||||||
|
sorter: (a, b) => parseFloat(b.cb_rmb.replace(/,/g, "")) - parseFloat(a.cb_rmb.replace(/,/g, "")),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
result.dataSource = data.BillTypeData1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
const format_data_detail = ((data) => {
|
const filters_array = data_array => {
|
||||||
let result = {dataSource: [], columns: []}
|
return comm.unique(data_array).map(item => {
|
||||||
if (!comm.empty(data)) {
|
return { text: item, value: item };
|
||||||
let show_vs = false;
|
});
|
||||||
let usd_totle1, usd_totle2, usd_diff, usd_vs, rmb_totle1, rmb_totle2, rmb_diff, rmb_vs = 0;
|
};
|
||||||
usd_totle1 = Math.round(data.billdate1.reduce((a, b) => a + b.cb_usd, 0));
|
|
||||||
rmb_totle1 = Math.round(data.billdate1.reduce((a, b) => a + b.cb_rmb, 0));
|
|
||||||
if (date_picker_store.start_date_cp && date_picker_store.end_date_cp) { //有比较的数据
|
|
||||||
show_vs = true;
|
|
||||||
//计算汇总的变化
|
|
||||||
usd_totle2 = Math.round(data.billdate2.reduce((a, b) => a + b.cb_usd, 0));
|
|
||||||
usd_diff = usd_totle1 - usd_totle2;
|
|
||||||
usd_vs = comm.formatPercent(usd_diff / usd_totle1);
|
|
||||||
rmb_totle2 = Math.round(data.billdate2.reduce((a, b) => a + b.cb_rmb, 0));
|
|
||||||
rmb_diff = rmb_totle1 - rmb_totle2;
|
|
||||||
rmb_vs = comm.formatPercent(rmb_diff / rmb_totle1);
|
|
||||||
}
|
|
||||||
if (show_vs) { //有比较的数据
|
|
||||||
result.dataSource.push(...data.billdate1, ...data.billdate2);
|
|
||||||
} else {
|
|
||||||
result.dataSource.push(...data.billdate1);
|
|
||||||
}
|
|
||||||
result.columns = [
|
|
||||||
{
|
|
||||||
title: '项目类型',
|
|
||||||
children: [{
|
|
||||||
title: '',
|
|
||||||
dataIndex: 'cb_billtype',
|
|
||||||
}],
|
|
||||||
sorter: (a, b) => a.cb_billtype.localeCompare(b.cb_billtype),
|
|
||||||
filters: filters_array(result.dataSource.map((item) => {
|
|
||||||
return item.cb_billtype
|
|
||||||
})),
|
|
||||||
filteredValue: credit_card_data.filteredValue || null,
|
|
||||||
onFilter: (value, record) => record.cb_billtype.indexOf(value) === 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '项目',
|
|
||||||
children: [{
|
|
||||||
title: '',
|
|
||||||
dataIndex: 'cb_bill',
|
|
||||||
}],
|
|
||||||
sorter: (a, b) => a.cb_bill.localeCompare(b.cb_bill),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '美金',
|
|
||||||
children: [{
|
|
||||||
title: show_vs ? comm.show_vs_tag(usd_vs, usd_diff, usd_totle1, usd_totle2) : usd_totle1,
|
|
||||||
dataIndex: 'cb_usd'
|
|
||||||
}],
|
|
||||||
sorter: (a, b) => b.cb_usd - a.cb_usd,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '人民币',
|
|
||||||
children: [{
|
|
||||||
title: show_vs ? comm.show_vs_tag(rmb_vs, rmb_diff, rmb_totle1, rmb_totle2) : rmb_totle1,
|
|
||||||
dataIndex: 'cb_rmb'
|
|
||||||
}],
|
|
||||||
sorter: (a, b) => b.cb_rmb - a.cb_rmb,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
const format_data_detail = data => {
|
||||||
title: '交易日期',
|
let result = { dataSource: [], columns: [] };
|
||||||
children: [{title: '', dataIndex: 'cb_datetime'}],
|
if (!comm.empty(data)) {
|
||||||
},
|
let show_vs = false;
|
||||||
{
|
let usd_totle1,
|
||||||
title: '账期',
|
usd_totle2,
|
||||||
children: [{title: '', dataIndex: 'cb_billdate'}],
|
usd_diff,
|
||||||
},
|
usd_vs,
|
||||||
{
|
rmb_totle1,
|
||||||
title: '事业部',
|
rmb_totle2,
|
||||||
children: [{title: '', dataIndex: 'cb_business_unit'}],
|
rmb_diff,
|
||||||
sorter: (a, b) => a.cb_business_unit.localeCompare(b.cb_business_unit),
|
rmb_vs = 0;
|
||||||
},
|
usd_totle1 = Math.round(data.billdate1.reduce((a, b) => a + b.cb_usd, 0));
|
||||||
{
|
rmb_totle1 = Math.round(data.billdate1.reduce((a, b) => a + b.cb_rmb, 0));
|
||||||
title: '小组',
|
if (date_picker_store.start_date_cp && date_picker_store.end_date_cp) {
|
||||||
children: [{title: '', dataIndex: 'cb_group'}],
|
//有比较的数据
|
||||||
sorter: (a, b) => a.cb_group.localeCompare(b.cb_group),
|
show_vs = true;
|
||||||
},
|
//计算汇总的变化
|
||||||
]
|
usd_totle2 = Math.round(data.billdate2.reduce((a, b) => a + b.cb_usd, 0));
|
||||||
|
usd_diff = usd_totle1 - usd_totle2;
|
||||||
|
usd_vs = comm.formatPercent(usd_diff / usd_totle1);
|
||||||
|
rmb_totle2 = Math.round(data.billdate2.reduce((a, b) => a + b.cb_rmb, 0));
|
||||||
|
rmb_diff = rmb_totle1 - rmb_totle2;
|
||||||
|
rmb_vs = comm.formatPercent(rmb_diff / rmb_totle1);
|
||||||
|
}
|
||||||
|
if (show_vs) {
|
||||||
|
//有比较的数据
|
||||||
|
result.dataSource.push(...data.billdate1, ...data.billdate2);
|
||||||
|
} else {
|
||||||
|
result.dataSource.push(...data.billdate1);
|
||||||
|
}
|
||||||
|
result.columns = [
|
||||||
|
{
|
||||||
|
title: "项目类型",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
dataIndex: "cb_billtype",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sorter: (a, b) => a.cb_billtype.localeCompare(b.cb_billtype),
|
||||||
|
filters: filters_array(
|
||||||
|
result.dataSource.map(item => {
|
||||||
|
return item.cb_billtype;
|
||||||
|
})
|
||||||
|
),
|
||||||
|
filteredValue: credit_card_data.filteredValue || null,
|
||||||
|
onFilter: (value, record) => record.cb_billtype.indexOf(value) === 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "项目",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
dataIndex: "cb_bill",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sorter: (a, b) => a.cb_bill.localeCompare(b.cb_bill),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "美金",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: show_vs ? comm.show_vs_tag(usd_vs, usd_diff, usd_totle1, usd_totle2) : usd_totle1,
|
||||||
|
dataIndex: "cb_usd",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sorter: (a, b) => b.cb_usd - a.cb_usd,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "人民币",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: show_vs ? comm.show_vs_tag(rmb_vs, rmb_diff, rmb_totle1, rmb_totle2) : rmb_totle1,
|
||||||
|
dataIndex: "cb_rmb",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sorter: (a, b) => b.cb_rmb - a.cb_rmb,
|
||||||
|
},
|
||||||
|
|
||||||
}
|
{
|
||||||
|
title: "交易日期",
|
||||||
|
children: [{ title: "", dataIndex: "cb_datetime" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "账期",
|
||||||
|
children: [{ title: "", dataIndex: "cb_billdate" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "事业部",
|
||||||
|
children: [{ title: "", dataIndex: "cb_business_unit" }],
|
||||||
|
sorter: (a, b) => a.cb_business_unit.localeCompare(b.cb_business_unit),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "小组",
|
||||||
|
children: [{ title: "", dataIndex: "cb_group" }],
|
||||||
|
sorter: (a, b) => a.cb_group.localeCompare(b.cb_group),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
})
|
};
|
||||||
|
|
||||||
const credit_card_bills = !comm.empty(credit_card_data.data) ? format_data_detail(credit_card_data.data) : format_data_detail([]);
|
//格式化数据,饼图只支持数字模式
|
||||||
const credit_card_bills_by_type = !comm.empty(credit_card_data.data_by_type) ? format_data(credit_card_data.data_by_type) : format_data([]);
|
const format_data_for_pie = data => {
|
||||||
|
let result_arr = [];
|
||||||
|
if (!comm.empty(data)) {
|
||||||
|
data.map(item => {
|
||||||
|
item.cb_usd_number = parseFloat(item.cb_usd.replace(/,/g, ""));
|
||||||
|
result_arr.push(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result_arr;
|
||||||
|
};
|
||||||
|
|
||||||
const line_config = {
|
const credit_card_bills = !comm.empty(credit_card_data.data) ? format_data_detail(credit_card_data.data) : format_data_detail([]);
|
||||||
data: credit_card_bills.dataSource,
|
const credit_card_bills_by_type = !comm.empty(credit_card_data.data_by_type) ? format_data(credit_card_data.data_by_type) : format_data([]);
|
||||||
padding: 'auto',
|
|
||||||
xField: 'cb_datetime',
|
|
||||||
yField: 'cb_usd',
|
|
||||||
seriesField: 'groups',
|
|
||||||
xAxis: {
|
|
||||||
type: 'timeCat',
|
|
||||||
},
|
|
||||||
point: {
|
|
||||||
size: 4,
|
|
||||||
shape: 'cicle',
|
|
||||||
},
|
|
||||||
label: {},//显示标签
|
|
||||||
legend: {
|
|
||||||
itemValue: {
|
|
||||||
formatter: (text, item) => {
|
|
||||||
const items = credit_card_bills.dataSource.filter((d) => d.groups === item.value);//按站点筛选
|
|
||||||
return items.length ? Math.round(items.reduce((a, b) => a + b.cb_usd, 0)) : '';//计算总数
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// tooltip: {
|
|
||||||
// customContent: (title, items) => {
|
|
||||||
// const data = items[0]?.data || {};
|
|
||||||
// return `<div>${title}</div><div>${data.seriesField} ${data.yField}</div>`;
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
smooth: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
const pie_config = {
|
||||||
<div>
|
appendPadding: 10,
|
||||||
<Row>
|
data: [],
|
||||||
<Col span={11}>
|
angleField: "cb_usd_number",
|
||||||
<h2>信用卡账单</h2>
|
colorField: "cb_billtype",
|
||||||
</Col>
|
radius: 0.8,
|
||||||
<Col span={10}>
|
label: {
|
||||||
<Row>
|
type: "outer",
|
||||||
<Col span={12}>
|
content: "{name} \n {percentage}",
|
||||||
<BillTypeSelect store={bill_type_data} show_all={true}/>
|
},
|
||||||
<Business_unit store={credit_card_data} show_all={true}/>
|
tooltip: {
|
||||||
{/*<GroupSelect store={credit_card_data} show_all={true}/>*/}
|
customItems: items => {
|
||||||
</Col>
|
let result_arr = [];
|
||||||
<Col span={12}>
|
items.forEach(item => {
|
||||||
<DatePickerCharts/>
|
item.value = "$" + item.data.cb_usd + " | ¥" + item.data.cb_rmb;
|
||||||
</Col>
|
return result_arr.push(item);
|
||||||
</Row>
|
});
|
||||||
</Col>
|
return result_arr;
|
||||||
<Col span={1}></Col>
|
},
|
||||||
<Col span={2}>
|
},
|
||||||
<Button type="primary" icon={<SearchOutlined/>} size='large' loading={credit_card_data.loading}
|
legend: false, //不显示图例
|
||||||
onClick={() => {
|
interactions: [
|
||||||
financial_store.get_credit_card_bills();
|
{
|
||||||
financial_store.get_credit_card_bills_by_type();
|
type: "element-selected",
|
||||||
financial_store.set_bill_filtered(false);
|
},
|
||||||
}}>统计</Button>
|
{
|
||||||
</Col>
|
type: "element-active",
|
||||||
</Row>
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
<Row>
|
return (
|
||||||
<Col span={24}>
|
<div>
|
||||||
<Line {...line_config} />
|
<Row>
|
||||||
</Col>
|
<Col span={11}>
|
||||||
<Col className="gutter-row" span={24}>
|
<h2>信用卡账单</h2>
|
||||||
<Tabs activeKey={credit_card_data.active_tab} onChange={credit_card_data.set_active_tab}>
|
</Col>
|
||||||
<Tabs.TabPane tab={<span><CarryOutOutlined/>项目汇总</span>} key="summarized_data">
|
<Col span={10}>
|
||||||
<Table id="table_by_type" dataSource={credit_card_bills_by_type.dataSource}
|
<Row>
|
||||||
columns={credit_card_bills_by_type.columns}
|
<Col span={12}>
|
||||||
pagination={false}
|
<BillTypeSelect store={bill_type_data} show_all={true} />
|
||||||
size="small"/>
|
<Business_unit store={credit_card_data} show_all={true} />
|
||||||
<Divider orientation="right"><a
|
</Col>
|
||||||
onClick={() => {
|
<Col span={12}>
|
||||||
const wb = utils.table_to_book(document.getElementById("table_by_type").getElementsByTagName('table')[0]);
|
<DatePickerCharts />
|
||||||
writeFileXLSX(wb, "项目汇总.xlsx");
|
</Col>
|
||||||
}}>导出excel</a></Divider>
|
</Row>
|
||||||
</Tabs.TabPane>
|
</Col>
|
||||||
<Tabs.TabPane tab={<span><ContainerOutlined/>明细</span>} key="detail_data">
|
<Col span={1}></Col>
|
||||||
<Table id="table_by_detail" dataSource={credit_card_bills.dataSource}
|
<Col span={2}>
|
||||||
columns={credit_card_bills.columns}
|
<Button
|
||||||
pagination={false}
|
type="primary"
|
||||||
onChange={credit_card_data.set_table_handleChange}
|
icon={<SearchOutlined />}
|
||||||
size="small"/>
|
size="large"
|
||||||
<Divider orientation="right"><a
|
loading={credit_card_data.loading}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const wb = utils.table_to_book(document.getElementById("table_by_detail").getElementsByTagName('table')[0]);
|
financial_store.get_credit_card_bills();
|
||||||
writeFileXLSX(wb, "明细.xlsx");
|
financial_store.get_credit_card_bills_by_type();
|
||||||
}}>导出excel</a></Divider>
|
financial_store.set_bill_filtered(false);
|
||||||
</Tabs.TabPane>
|
}}>
|
||||||
</Tabs>
|
统计
|
||||||
</Col>
|
</Button>
|
||||||
</Row>
|
</Col>
|
||||||
</div>
|
</Row>
|
||||||
);
|
|
||||||
|
|
||||||
}
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={format_data_for_pie(credit_card_data.data_by_type.BillTypeData1)} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={format_data_for_pie(credit_card_data.data_by_type.BillTypeData2)} />
|
||||||
|
</Col>
|
||||||
|
<Col className="gutter-row" span={24}>
|
||||||
|
<Tabs activeKey={credit_card_data.active_tab} onChange={credit_card_data.set_active_tab}>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<CarryOutOutlined />
|
||||||
|
项目汇总
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="summarized_data">
|
||||||
|
<Table id="table_by_type" dataSource={credit_card_bills_by_type.dataSource} columns={credit_card_bills_by_type.columns} pagination={false} size="small" />
|
||||||
|
<Divider orientation="right">
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_by_type").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "项目汇总.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<ContainerOutlined />
|
||||||
|
明细
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="detail_data">
|
||||||
|
<Table id="table_by_detail" dataSource={credit_card_bills.dataSource} columns={credit_card_bills.columns} pagination={false} onChange={credit_card_data.set_table_handleChange} size="small" />
|
||||||
|
<Divider orientation="right">
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_by_detail").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "明细.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default observer(Credit_card_bill);
|
export default observer(Credit_card_bill);
|
||||||
|
@ -1,38 +1,39 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import {Col, Row} from "antd";
|
import { Col, Row } from "antd";
|
||||||
import OrdersTempTable from "../charts/OrdersTempTable";
|
import OrdersTempTable from "../charts/OrdersTempTable";
|
||||||
import MobileDeal from "../charts/MobileDeal";
|
import MobileDeal from "../charts/MobileDeal";
|
||||||
import Orders from "../charts/Orders";
|
import Orders from "../charts/Orders";
|
||||||
|
import ExchangeRate from "../charts/ExchangeRate";
|
||||||
|
|
||||||
class Dashboard extends Component {
|
class Dashboard extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props) {
|
render() {
|
||||||
super(props);
|
return (
|
||||||
}
|
<div>
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
|
<Orders />
|
||||||
|
</Col>
|
||||||
|
|
||||||
render() {
|
<Col span={24}>
|
||||||
|
<ExchangeRate />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<OrdersTempTable />
|
||||||
|
</Col>
|
||||||
|
|
||||||
return (
|
<Col span={12}>
|
||||||
<div>
|
<MobileDeal />
|
||||||
<div
|
</Col>
|
||||||
>
|
</Row>
|
||||||
<Row gutter={[16, {xs: 8, sm: 16, md: 24, lg: 32}]}>
|
</div>
|
||||||
<Col className="gutter-row" span={24}>
|
</div>
|
||||||
<Orders/>
|
);
|
||||||
</Col>
|
}
|
||||||
<Col className="gutter-row" span={12}>
|
|
||||||
<OrdersTempTable/>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col className="gutter-row" span={12}>
|
|
||||||
<MobileDeal/>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
</Row>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Dashboard;
|
export default Dashboard;
|
||||||
|
@ -1,278 +1,521 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import {Row, Col, Button, Tabs, Table} from 'antd';
|
import { Row, Col, Button, Tabs, Table, Divider } from "antd";
|
||||||
import {
|
import { ContainerOutlined, CarryOutOutlined, BlockOutlined, SmileOutlined, TagsOutlined, GlobalOutlined, SearchOutlined, FullscreenOutlined, DingtalkOutlined } from "@ant-design/icons";
|
||||||
ContainerOutlined, CarryOutOutlined, BlockOutlined,
|
import { stores_Context } from "../config";
|
||||||
SmileOutlined, TagsOutlined, GlobalOutlined,
|
import { Line, Pie } from "@ant-design/charts";
|
||||||
SearchOutlined,
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
import {stores_Context} from '../config'
|
|
||||||
import {Line} from "@ant-design/charts";
|
|
||||||
import SiteSelect from "../charts/SiteSelect";
|
import SiteSelect from "../charts/SiteSelect";
|
||||||
import {observer} from 'mobx-react';
|
import { observer } from "mobx-react";
|
||||||
import DatePickerCharts from '../charts/DatePickerCharts'
|
import DatePickerCharts from "../charts/DatePickerCharts";
|
||||||
import * as config from "../config";
|
import * as config from "../config";
|
||||||
import {NavLink} from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
import * as comm from "../utils/commons"
|
import * as comm from "../utils/commons";
|
||||||
|
import { utils, writeFileXLSX } from "xlsx";
|
||||||
|
|
||||||
class Orders extends Component {
|
class Orders extends Component {
|
||||||
|
static contextType = stores_Context;
|
||||||
|
|
||||||
static contextType = stores_Context;
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props) {
|
// componentDidMount() {
|
||||||
super(props);
|
// const {orders_store} = this.context;
|
||||||
}
|
// orders_store.getOrderCount();
|
||||||
|
// orders_store.onChange_Tabs(orders_store.active_tab_key);
|
||||||
|
// }
|
||||||
|
|
||||||
// componentDidMount() {
|
format_data(data) {
|
||||||
// const {orders_store} = this.context;
|
const { date_picker_store, orders_store } = this.context;
|
||||||
// orders_store.getOrderCount();
|
let result = { dataSource: [], columns: [] };
|
||||||
// orders_store.onChange_Tabs(orders_store.active_tab_key);
|
if (!comm.empty(data)) {
|
||||||
// }
|
let ordercountTotal1 = data.ordercountTotal1;
|
||||||
|
let ordercountTotal2 = data.ordercountTotal2;
|
||||||
|
if (date_picker_store.start_date_cp && date_picker_store.end_date_cp) {
|
||||||
|
//有比较的数据
|
||||||
|
result.columns = [
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
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>
|
||||||
|
),
|
||||||
|
dataIndex: "OrderType",
|
||||||
|
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),
|
||||||
|
dataIndex: "OrderCount",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "成交数",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: comm.show_vs_tag(ordercountTotal1.CJCount_vs, ordercountTotal1.CJCount_diff, ordercountTotal1.CJCount, ordercountTotal2.CJCount),
|
||||||
|
dataIndex: "CJCount",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "成交人数",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: comm.show_vs_tag(ordercountTotal1.CJPersonNum_vs, ordercountTotal1.CJPersonNum_diff, ordercountTotal1.CJPersonNum, ordercountTotal2.CJPersonNum),
|
||||||
|
dataIndex: "CJPersonNum",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "成交率",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: comm.show_vs_tag(ordercountTotal1.CJrate_vs, ordercountTotal1.CJrate_diff, ordercountTotal1.CJrate, ordercountTotal2.CJrate),
|
||||||
|
dataIndex: "CJrate",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "成交毛利(预计)",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: comm.show_vs_tag(ordercountTotal1.YJLY_vs, ordercountTotal1.YJLY_diff, ordercountTotal1.YJLY, ordercountTotal2.YJLY),
|
||||||
|
dataIndex: "YJLY",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: "单个订单价值",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: comm.show_vs_tag(ordercountTotal1.Ordervalue_vs, ordercountTotal1.Ordervalue_diff, ordercountTotal1.Ordervalue, ordercountTotal2.Ordervalue),
|
||||||
|
dataIndex: "Ordervalue",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
for (let item of data.ordercount1) {
|
||||||
|
for (let item2 of data.ordercount2) {
|
||||||
|
if (item.OrderType == item2.OrderType) {
|
||||||
|
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),
|
||||||
|
CJCount: comm.show_vs_tag(item.CJCount_vs, item.CJCount_diff, item.CJCount, item2.CJCount),
|
||||||
|
CJPersonNum: comm.show_vs_tag(item.CJPersonNum_vs, item.CJPersonNum_diff, item.CJPersonNum, item2.CJPersonNum),
|
||||||
|
CJrate: comm.show_vs_tag(item.CJrate_vs, item.CJrate_diff, item.CJrate, item2.CJrate),
|
||||||
|
YJLY: comm.show_vs_tag(item.YJLY_vs, item.YJLY_diff, item.YJLY, item2.YJLY),
|
||||||
|
Ordervalue: comm.show_vs_tag(item.Ordervalue_vs, item.Ordervalue_diff, item.Ordervalue, item2.Ordervalue),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.columns = [
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: (
|
||||||
|
<span>
|
||||||
|
<div>
|
||||||
|
{date_picker_store.start_date.format(config.DATE_FORMAT)}~{date_picker_store.end_date.format(config.DATE_FORMAT)}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
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, "")),
|
||||||
|
},
|
||||||
|
|
||||||
format_data(data) {
|
{
|
||||||
const {date_picker_store, orders_store} = this.context;
|
title: "单个订单价值",
|
||||||
let result = {dataSource: [], columns: []}
|
children: [{ title: ordercountTotal1.Ordervalue, dataIndex: "Ordervalue" }],
|
||||||
if (!comm.empty(data)) {
|
sorter: (a, b) => parseFloat(b.Ordervalue.replace(/,/g, "")) - parseFloat(a.Ordervalue.replace(/,/g, "")),
|
||||||
let ordercountTotal1 = data.ordercountTotal1;
|
},
|
||||||
let ordercountTotal2 = data.ordercountTotal2;
|
];
|
||||||
if (date_picker_store.start_date_cp && date_picker_store.end_date_cp) { //有比较的数据
|
result.dataSource = data.ordercount1;
|
||||||
result.columns = [
|
}
|
||||||
{
|
}
|
||||||
title: '',
|
return result;
|
||||||
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>,
|
|
||||||
dataIndex: 'OrderType',
|
|
||||||
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),
|
|
||||||
dataIndex: 'OrderCount'
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '成交数',
|
|
||||||
children: [{
|
|
||||||
title: comm.show_vs_tag(ordercountTotal1.CJCount_vs, ordercountTotal1.CJCount_diff, ordercountTotal1.CJCount, ordercountTotal2.CJCount),
|
|
||||||
dataIndex: 'CJCount'
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '成交人数',
|
|
||||||
children: [{
|
|
||||||
title: comm.show_vs_tag(ordercountTotal1.CJPersonNum_vs, ordercountTotal1.CJPersonNum_diff, ordercountTotal1.CJPersonNum, ordercountTotal2.CJPersonNum),
|
|
||||||
dataIndex: 'CJPersonNum'
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '成交率',
|
|
||||||
children: [{
|
|
||||||
title: comm.show_vs_tag(ordercountTotal1.CJrate_vs, ordercountTotal1.CJrate_diff, ordercountTotal1.CJrate, ordercountTotal2.CJrate),
|
|
||||||
dataIndex: 'CJrate'
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '成交毛利(预计)',
|
|
||||||
children: [{
|
|
||||||
title: comm.show_vs_tag(ordercountTotal1.YJLY_vs, ordercountTotal1.YJLY_diff, ordercountTotal1.YJLY, ordercountTotal2.YJLY),
|
|
||||||
dataIndex: 'YJLY'
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
render() {
|
||||||
title: '单个订单价值',
|
const { orders_store } = this.context;
|
||||||
children: [{
|
const table_data = orders_store.orderCountData_Form ? this.format_data(orders_store.orderCountData_Form) : [];
|
||||||
title: comm.show_vs_tag(ordercountTotal1.Ordervalue_vs, ordercountTotal1.Ordervalue_diff, ordercountTotal1.Ordervalue, ordercountTotal2.Ordervalue),
|
const data_source = orders_store.orderCountData ? orders_store.orderCountData : [];
|
||||||
dataIndex: 'Ordervalue'
|
const avg_line_y = data_source.length ? Math.round(data_source.reduce((a, b) => a + b.yField, 0) / data_source.length) : 0; //平均值,显示一条平均线
|
||||||
}],
|
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;
|
||||||
];
|
|
||||||
for (let item of data.ordercount1) {
|
|
||||||
for (let item2 of data.ordercount2) {
|
|
||||||
if (item.OrderType == item2.OrderType) {
|
|
||||||
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),
|
|
||||||
CJCount: comm.show_vs_tag(item.CJCount_vs, item.CJCount_diff, item.CJCount, item2.CJCount),
|
|
||||||
CJPersonNum: comm.show_vs_tag(item.CJPersonNum_vs, item.CJPersonNum_diff, item.CJPersonNum, item2.CJPersonNum),
|
|
||||||
CJrate: comm.show_vs_tag(item.CJrate_vs, item.CJrate_diff, item.CJrate, item2.CJrate),
|
|
||||||
YJLY: comm.show_vs_tag(item.YJLY_vs, item.YJLY_diff, item.YJLY, item2.YJLY),
|
|
||||||
Ordervalue: comm.show_vs_tag(item.Ordervalue_vs, item.Ordervalue_diff, item.Ordervalue, item2.Ordervalue),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result.columns =
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: '',
|
|
||||||
children: [{
|
|
||||||
title: <span><div>{date_picker_store.start_date.format(config.DATE_FORMAT)}~{date_picker_store.end_date.format(config.DATE_FORMAT)}</div></span>,
|
|
||||||
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) => b.YJLY - a.YJLY,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
const config = {
|
||||||
title: '单个订单价值',
|
data: data_source,
|
||||||
children: [{title: ordercountTotal1.Ordervalue, dataIndex: 'Ordervalue'}],
|
padding: "auto",
|
||||||
sorter: (a, b) => b.Ordervalue - a.Ordervalue,
|
xField: "xField",
|
||||||
},
|
yField: "yField",
|
||||||
];
|
seriesField: "seriesField",
|
||||||
result.dataSource = data.ordercount1;
|
xAxis: {
|
||||||
}
|
type: "timeCat",
|
||||||
}
|
},
|
||||||
return result;
|
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: {
|
||||||
|
// customContent: (title, items) => {
|
||||||
|
// const data = items[0]?.data || {};
|
||||||
|
// return `<div>${title}</div><div>${data.seriesField} ${data.yField}</div>`;
|
||||||
|
// }
|
||||||
|
title: (title, datum) => {
|
||||||
|
return title + " " + comm.getWeek(datum.xField); //显示周几
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
return (
|
||||||
const {orders_store} = this.context;
|
<div>
|
||||||
const table_data = orders_store.orderCountData_Form ? this.format_data(orders_store.orderCountData_Form) : [];
|
<Row>
|
||||||
const data_source = orders_store.orderCountData ? orders_store.orderCountData : [];
|
<Col span={14}></Col>
|
||||||
const avg_line_y=data_source.length ? Math.round((data_source.reduce((a, b) => a + b.yField, 0))/data_source.length):0;//平均值,显示一条平均线
|
<Col span={2}>
|
||||||
const config = {
|
<SiteSelect store={orders_store} />
|
||||||
data: data_source,
|
</Col>
|
||||||
padding: 'auto',
|
<Col span={6}>
|
||||||
xField: 'xField',
|
<DatePickerCharts />
|
||||||
yField: 'yField',
|
</Col>
|
||||||
seriesField: 'seriesField',
|
<Col span={2}>
|
||||||
xAxis: {
|
<Button
|
||||||
type: 'timeCat',
|
type="primary"
|
||||||
},
|
icon={<SearchOutlined />}
|
||||||
point: {
|
loading={orders_store.loading}
|
||||||
size: 4,
|
onClick={() => {
|
||||||
shape: 'cicle',
|
orders_store.getOrderCount();
|
||||||
},
|
orders_store.onChange_Tabs(orders_store.active_tab_key);
|
||||||
annotations: [
|
}}>
|
||||||
{
|
统计
|
||||||
type: 'text',
|
</Button>
|
||||||
position: ['start', avg_line_y],
|
</Col>
|
||||||
content: avg_line_y,
|
</Row>
|
||||||
offsetX: -15,
|
<Row gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||||
style: {
|
<Col span={24}>
|
||||||
fill: '#F4664A',
|
<Line {...config} />
|
||||||
textBaseline: 'bottom',
|
</Col>
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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: {
|
|
||||||
// customContent: (title, items) => {
|
|
||||||
// const data = items[0]?.data || {};
|
|
||||||
// return `<div>${title}</div><div>${data.seriesField} ${data.yField}</div>`;
|
|
||||||
// }
|
|
||||||
title: (title, datum) => {
|
|
||||||
return title+' '+ comm.getWeek(datum.xField);//显示周几
|
|
||||||
},
|
|
||||||
},
|
|
||||||
smooth: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
<Col span={24}>
|
||||||
|
<Tabs activeKey={orders_store.active_tab_key} onChange={active_key => orders_store.onChange_Tabs(active_key)}>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<ContainerOutlined />
|
||||||
|
来源类型
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="Form">
|
||||||
|
<Table id="table_to_xlsx_form" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_form").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "来源类型.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<CarryOutOutlined />
|
||||||
|
产品类型
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="Product">
|
||||||
|
<Table id="table_to_xlsx_product" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_product").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "产品类型.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<SmileOutlined />
|
||||||
|
国籍
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="Country">
|
||||||
|
<Table id="table_to_xlsx_country" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_country").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "国籍.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<TagsOutlined />
|
||||||
|
线路
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="line">
|
||||||
|
<Table id="table_to_xlsx_line" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_line").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "线路.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<GlobalOutlined />
|
||||||
|
目的地
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="city">
|
||||||
|
<Table id="table_to_xlsx_city" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_city").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "目的地.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<BlockOutlined />
|
||||||
|
页面类型
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="LineClass">
|
||||||
|
<Table id="table_to_xlsx_LineClass" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_LineClass").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "页面类型.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<FullscreenOutlined />
|
||||||
|
客群类别
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="GuestGroupType">
|
||||||
|
<Table id="table_to_xlsx_GuestGroupType" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_GuestGroupType").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "客群类别.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<DingtalkOutlined />
|
||||||
|
出行动机
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="TravelMotivation">
|
||||||
|
<Table id="table_to_xlsx_TravelMotivation" dataSource={table_data.dataSource} columns={table_data.columns} size="small" pagination={false} />
|
||||||
|
<Divider orientation="right" plain>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const wb = utils.table_to_book(document.getElementById("table_to_xlsx_TravelMotivation").getElementsByTagName("table")[0]);
|
||||||
|
writeFileXLSX(wb, "出行动机.xlsx");
|
||||||
|
}}>
|
||||||
|
导出excel
|
||||||
|
</a>
|
||||||
|
</Divider>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...pie_config} data={pie_data2} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
export default observer(Orders);
|
||||||
<div>
|
|
||||||
<Row>
|
|
||||||
<Col span={14}>
|
|
||||||
</Col>
|
|
||||||
<Col span={2}>
|
|
||||||
<SiteSelect store={orders_store}/>
|
|
||||||
</Col>
|
|
||||||
<Col span={6}>
|
|
||||||
<DatePickerCharts/>
|
|
||||||
</Col>
|
|
||||||
<Col span={2}>
|
|
||||||
<Button type="primary" icon={<SearchOutlined/>} loading={orders_store.loading} onClick={() => {
|
|
||||||
orders_store.getOrderCount();
|
|
||||||
orders_store.onChange_Tabs(orders_store.active_tab_key);
|
|
||||||
}}>统计</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row gutter={[16, {xs: 8, sm: 16, md: 24, lg: 32}]}>
|
|
||||||
|
|
||||||
<Col span={24}>
|
|
||||||
<Line {...config} />
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col span={24}>
|
|
||||||
<Tabs activeKey={orders_store.active_tab_key}
|
|
||||||
onChange={(active_key) => orders_store.onChange_Tabs(active_key)}>
|
|
||||||
<Tabs.TabPane tab={<span><ContainerOutlined/>来源类型</span>} key="Form">
|
|
||||||
<Table dataSource={table_data.dataSource} columns={table_data.columns} size="small"/>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
<Tabs.TabPane tab={<span><CarryOutOutlined/>产品类型</span>} key="Product">
|
|
||||||
<Table dataSource={table_data.dataSource} columns={table_data.columns} size="small"/>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
<Tabs.TabPane tab={<span><SmileOutlined/>国籍</span>} key="Country">
|
|
||||||
<Table dataSource={table_data.dataSource} columns={table_data.columns} size="small"/>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
<Tabs.TabPane tab={<span><TagsOutlined/>线路</span>} key="line">
|
|
||||||
<Table dataSource={table_data.dataSource} columns={table_data.columns} size="small"/>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
<Tabs.TabPane tab={<span><GlobalOutlined/>目的地</span>} key="city">
|
|
||||||
<Table dataSource={table_data.dataSource} columns={table_data.columns} size="small"/>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
<Tabs.TabPane tab={<span><BlockOutlined/>页面类型</span>} key="LineClass">
|
|
||||||
<Table dataSource={table_data.dataSource} columns={table_data.columns} size="small"/>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
</Tabs>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
</Row>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export
|
|
||||||
default
|
|
||||||
|
|
||||||
observer(Orders);
|
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
import React, { useContext, useEffect } from "react";
|
||||||
|
import { Row, Col, Button, Tabs, Table, Space, Radio } from "antd";
|
||||||
|
import { ContainerOutlined, SearchOutlined } from "@ant-design/icons";
|
||||||
|
import { stores_Context } from "../config";
|
||||||
|
import { Line } from "@ant-design/charts";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import DatePickerCharts from "../charts/DatePickerCharts";
|
||||||
|
import { NavLink, useParams } from "react-router-dom";
|
||||||
|
import * as comm from "../utils/commons";
|
||||||
|
import * as config from "../config";
|
||||||
|
import GroupSelect from "../charts/GroupSelect";
|
||||||
|
|
||||||
|
const Sale = () => {
|
||||||
|
const { sale_store, date_picker_store } = useContext(stores_Context);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col span={13}></Col>
|
||||||
|
<Col span={8}>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<GroupSelect store={sale_store} />
|
||||||
|
<Radio.Group value={sale_store.date_type} onChange={e => sale_store.onChange_datetype(e)}>
|
||||||
|
<Radio value="applyDate">下单日期</Radio>
|
||||||
|
<Radio value="startDate">走团日期</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<DatePickerCharts />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
<Col span={1}></Col>
|
||||||
|
<Col span={2}>
|
||||||
|
<Button type="primary" icon={<SearchOutlined />} loading={sale_store.loading} onClick={() => {}}>
|
||||||
|
统计
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col className="gutter-row" span={24}>
|
||||||
|
{/* <Line {...line} /> */}
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col className="gutter-row" span={24}>
|
||||||
|
<Tabs activeKey={sale_store.active_tab_key} onChange={active_key => sale_store.onChange_Tabs(active_key)}>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<ContainerOutlined />
|
||||||
|
概览
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="overview">
|
||||||
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
|
{sale_store.date_title}
|
||||||
|
{/* <Table
|
||||||
|
dataSource={table_data.dataSource}
|
||||||
|
columns={table_data.columns}
|
||||||
|
size="small"
|
||||||
|
rowKey={record => record.key}
|
||||||
|
expandable={{
|
||||||
|
expandedRowRender: record => <pre>{record.COLI_OrderDetailText}</pre>,
|
||||||
|
}}
|
||||||
|
/> */}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<ContainerOutlined />
|
||||||
|
国籍
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
key="page">
|
||||||
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
|
{sale_store.date_title}
|
||||||
|
{/* <Table dataSource={table_data_p.dataSource} rowKey={record => record.key} columns={table_data_p.columns} size="small" /> */}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default observer(Sale);
|
Loading…
Reference in New Issue