完成统计页,待后端上线
parent
b30fbc9fb9
commit
eac61bc7ba
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,13 @@
|
||||||
export interface StatResponse {
|
export interface StatResponse {
|
||||||
/**
|
|
||||||
* 当yearly=true时,此处会返回12项,对应12个月;否则按日返回
|
|
||||||
*/
|
|
||||||
departmentStats: Array<DepartmentStat[]>;
|
|
||||||
invoiceKindsStats: InvoiceKindsStat[];
|
invoiceKindsStats: InvoiceKindsStat[];
|
||||||
invoiceLaunchCount: number;
|
invoiceLaunchCount: number;
|
||||||
lastAdditionalTotalAmount: number;
|
lastAdditionalTotalAmount: number;
|
||||||
lastAllTotalAmount: number;
|
lastAllTotalAmount: number;
|
||||||
reimbursementAdditionalTotalAmount: number;
|
reimbursementAdditionalTotalAmount: number;
|
||||||
reimbursementAllTotalAmount: number;
|
reimbursementAllTotalAmount: number;
|
||||||
reimbursementDepartureStats: ReimbursementDepartureStat[];
|
|
||||||
reimbursementDestinationStats: ReimbursementDestinationStat[];
|
|
||||||
reimbursementLaunchCount: number;
|
reimbursementLaunchCount: number;
|
||||||
}
|
reimbursementPlaceStats: ReimbursementPlaceStat[];
|
||||||
|
temporalDepartmentStats: TemporalDepartmentStat[];
|
||||||
export interface DepartmentStat {
|
|
||||||
departmentName: string;
|
|
||||||
reimbursementAmount: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InvoiceKindsStat {
|
export interface InvoiceKindsStat {
|
||||||
|
@ -24,12 +15,21 @@ export interface InvoiceKindsStat {
|
||||||
invoiceLaunchCount: number;
|
invoiceLaunchCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReimbursementDepartureStat {
|
export interface ReimbursementPlaceStat {
|
||||||
placeName: string;
|
departureName: string;
|
||||||
|
destinationName: string;
|
||||||
reimbursementLaunchCount: number;
|
reimbursementLaunchCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReimbursementDestinationStat {
|
export interface TemporalDepartmentStat {
|
||||||
placeName: string;
|
departmentStats: DepartmentStat[];
|
||||||
reimbursementLaunchCount: number;
|
/**
|
||||||
|
* 月份值或日期值
|
||||||
|
*/
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DepartmentStat {
|
||||||
|
departmentId: number;
|
||||||
|
reimbursementAmount: number;
|
||||||
}
|
}
|
|
@ -1,22 +1,45 @@
|
||||||
import type {DatePickerProps, TimePickerProps} from 'antd';
|
import type {DatePickerProps, TimePickerProps} from 'antd';
|
||||||
import {theme, DatePicker, Select, Space, Card, Statistic, Spin} from 'antd';
|
import {theme, DatePicker, Select, Space, Card, Statistic, Spin, Radio} from 'antd';
|
||||||
import {ArrowDownOutlined, ArrowUpOutlined, createFromIconfontCN} from '@ant-design/icons'
|
import {ArrowDownOutlined, ArrowUpOutlined, createFromIconfontCN} from '@ant-design/icons'
|
||||||
import {useEffect, useRef, useState} from "react";
|
import React, {useEffect, useRef, useState} from "react";
|
||||||
import ReactECharts from 'echarts-for-react';
|
import ReactECharts from 'echarts-for-react';
|
||||||
import * as Echarts from 'echarts'
|
import * as Echarts from 'echarts'
|
||||||
import china from '../../assets/mapjson/china.json'
|
import china from '../../assets/mapjson/china.json'
|
||||||
import dayjs, {Dayjs} from "dayjs";
|
import dayjs, {Dayjs} from "dayjs";
|
||||||
|
import {DepartmentStat, ReimbursementPlaceStat, StatResponse} from "../../models/Stat";
|
||||||
|
import {invoiceTypeNameMap} from "../../models/Invoice";
|
||||||
|
import GeoCoordMap from "../../assets/GeoCoordMap";
|
||||||
|
import axiosInstance from "../../utils/axiosInstance";
|
||||||
|
import {Department, Staff} from "../../models/Staff";
|
||||||
|
import {setStaff} from "../../models/store";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
Echarts.registerMap('china', china);
|
Echarts.registerMap('china', china);
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
type PickerType = 'month' | 'year';
|
type StatType = 'month' | 'year';
|
||||||
|
|
||||||
const IconFont = createFromIconfontCN({
|
const IconFont = createFromIconfontCN({
|
||||||
scriptUrl: '//at.alicdn.com/t/c/font_3830502_eyfw75skyu.js',
|
scriptUrl: '//at.alicdn.com/t/c/font_3830502_eyfw75skyu.js',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function TrendStatistic(props: { value: number, type: StatType }) {
|
||||||
|
const {
|
||||||
|
token: {colorSuccess, colorError},
|
||||||
|
} = theme.useToken();
|
||||||
|
return (
|
||||||
|
<Statistic
|
||||||
|
title={props.type === 'month' ? "较上个月" : '较去年'}
|
||||||
|
value={Math.abs(props.value)}
|
||||||
|
precision={2}
|
||||||
|
valueStyle={{color: props.value >= 0 ? colorSuccess : colorError}}
|
||||||
|
prefix={props.value >= 0 ? <ArrowUpOutlined/> : <ArrowDownOutlined/>}
|
||||||
|
suffix="%"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function HorizontalBarChart(props: { title: string, values: number[], labels: string[] }) {
|
function HorizontalBarChart(props: { title: string, values: number[], labels: string[] }) {
|
||||||
return <ReactECharts option={{
|
return <ReactECharts option={{
|
||||||
color: [
|
color: [
|
||||||
|
@ -73,20 +96,64 @@ function HorizontalBarChart(props: { title: string, values: number[], labels: st
|
||||||
}} notMerge={true} lazyUpdate={true}/>
|
}} notMerge={true} lazyUpdate={true}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mMapData =
|
||||||
|
[
|
||||||
|
{from: '青海省', to: '青海省', value: 90},
|
||||||
|
{from: '青海省', to: '安徽省', value: 80},
|
||||||
|
{from: '青海省', to: '甘肃省', value: 70},
|
||||||
|
{from: '青海省', to: '宁夏省', value: 60},
|
||||||
|
{from: '青海省', to: '山西省', value: 50},
|
||||||
|
{from: '青海省', to: '陕西省', value: 40},
|
||||||
|
{from: '青海省', to: '广东省', value: 30},
|
||||||
|
{from: '青海省', to: '重庆省', value: 20},
|
||||||
|
{from: '青海省', to: '西藏省', value: 10}
|
||||||
|
];
|
||||||
|
|
||||||
|
var convertLineData = function (data: { from: string, to: string, value: number }[]) {
|
||||||
|
var res = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
var dataItem = data[i];
|
||||||
|
// @ts-ignore
|
||||||
|
var fromCoord = GeoCoordMap[dataItem.from];
|
||||||
|
// @ts-ignore
|
||||||
|
var toCoord = GeoCoordMap[dataItem.to];
|
||||||
|
|
||||||
|
if (fromCoord && toCoord) {
|
||||||
|
res.push(
|
||||||
|
{
|
||||||
|
fromName: dataItem.from,
|
||||||
|
toName: dataItem.to,
|
||||||
|
coords: [fromCoord, toCoord],
|
||||||
|
value: dataItem.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
function StatView() {
|
function StatView() {
|
||||||
const {
|
const {
|
||||||
token: {colorBgContainer, colorPrimary, colorSuccess},
|
token: {colorBgContainer, colorPrimary, colorSuccess},
|
||||||
} = theme.useToken();
|
} = theme.useToken();
|
||||||
|
|
||||||
const [type, setType] = useState<PickerType>('month');
|
const [type, setType] = useState<StatType>('month');
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
|
const [reimbursementAmount, setReimbursementAmount] = useState(0)
|
||||||
|
const [reimbursementAmountTrend, setReimbursementAmountTrend] = useState(0)
|
||||||
|
const [reimbursementAdditionalAmount, setReimbursementAdditionalAmount] = useState(0)
|
||||||
|
const [reimbursementAdditionalAmountTrend, setReimbursementAdditionalAmountTrend] = useState(0)
|
||||||
const [amounts, setAmounts] = useState([0, 0])
|
const [amounts, setAmounts] = useState([0, 0])
|
||||||
const [invoiceKinds, setInvoiceKinds] = useState<any>([])
|
const [invoiceKinds, setInvoiceKinds] = useState<any>([])
|
||||||
const [departmentPieData, setDepartmentPieData] = useState<any>([])
|
const [departmentPieData, setDepartmentPieData] = useState<any>([])
|
||||||
|
const [mapData, setMapData] = useState<any>([])
|
||||||
const [departureNames, setDepartureNames] = useState<any>([])
|
const [departureNames, setDepartureNames] = useState<any>([])
|
||||||
const [departureValues, setDepartureValues] = useState<any>([])
|
const [departureValues, setDepartureValues] = useState<any>([])
|
||||||
const [destinationNames, setDestinationNames] = useState<any>([])
|
const [destinationNames, setDestinationNames] = useState<any>([])
|
||||||
const [destinationValues, setDestinationValues] = useState<any>([])
|
const [destinationValues, setDestinationValues] = useState<any>([])
|
||||||
|
const [dates, setDates] = useState<any>([])
|
||||||
|
const [departmentSeries, setDepartmentSeries] = useState<any>([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getStatData(dayjs())
|
getStatData(dayjs())
|
||||||
|
@ -95,24 +162,302 @@ function StatView() {
|
||||||
const getStatData = (time: Dayjs | null) => {
|
const getStatData = (time: Dayjs | null) => {
|
||||||
console.log(time)
|
console.log(time)
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
|
||||||
|
axiosInstance({
|
||||||
|
url: 'common/department',
|
||||||
|
method: 'get'
|
||||||
|
}).then(response => {
|
||||||
|
const departments: Department[] = response.data
|
||||||
|
let departmentMap = new Map<number, string>()
|
||||||
|
for (const department of departments)
|
||||||
|
departmentMap.set(department.departmentId, department.departmentName)
|
||||||
|
|
||||||
|
if (time === null)
|
||||||
|
time = dayjs()
|
||||||
|
let dates: string[] = []
|
||||||
|
if (type === 'month')
|
||||||
|
for (let i = 1; i <= time.daysInMonth(); i++) {
|
||||||
|
dates.push(time.date(i).format('M月D日'))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
dates.push(i + '月')
|
||||||
|
}
|
||||||
|
setDates(dates)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setAmounts([120, 43])
|
let statResponse: StatResponse = {
|
||||||
setInvoiceKinds([{value: 1048, name: '增值税发票'},
|
"temporalDepartmentStats": [
|
||||||
{value: 735, name: '火车票'},
|
{
|
||||||
{value: 580, name: '机票行程单'},
|
"value": 4,
|
||||||
{value: 484, name: '通用机打发票'},
|
"departmentStats": [
|
||||||
{value: 300, name: '过路过桥费发票'}])
|
{
|
||||||
setDepartmentPieData([{value: 1048, name: '钝角部'},
|
"departmentId": 1,
|
||||||
{value: 735, name: '投影立体角部'},
|
"reimbursementAmount": 79
|
||||||
{value: 580, name: '财务部'},
|
},
|
||||||
{value: 484, name: '采购部'},
|
{
|
||||||
{value: 300, name: '销售部'}])
|
"departmentId": 2,
|
||||||
setDepartureNames(['北京', '上海', '广州', '深圳', '成都'])
|
"reimbursementAmount": 9
|
||||||
setDepartureValues([100, 80, 70, 60, 50])
|
},
|
||||||
setDestinationNames(['北京', '上海', '广州', '深圳', '成都'])
|
{
|
||||||
setDestinationValues([100, 80, 70, 60, 50])
|
"departmentId": 3,
|
||||||
|
"reimbursementAmount": 29
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 4,
|
||||||
|
"reimbursementAmount": 46
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 5,
|
||||||
|
"reimbursementAmount": 66
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": 3,
|
||||||
|
"departmentStats": [
|
||||||
|
{
|
||||||
|
"departmentId": 1,
|
||||||
|
"reimbursementAmount": 79
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 2,
|
||||||
|
"reimbursementAmount": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 3,
|
||||||
|
"reimbursementAmount": 29
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 4,
|
||||||
|
"reimbursementAmount": 46
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 5,
|
||||||
|
"reimbursementAmount": 66
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": 6,
|
||||||
|
"departmentStats": [
|
||||||
|
{
|
||||||
|
"departmentId": 1,
|
||||||
|
"reimbursementAmount": 79
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 2,
|
||||||
|
"reimbursementAmount": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 3,
|
||||||
|
"reimbursementAmount": 29
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 4,
|
||||||
|
"reimbursementAmount": 46
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 5,
|
||||||
|
"reimbursementAmount": 66
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": 13,
|
||||||
|
"departmentStats": [
|
||||||
|
{
|
||||||
|
"departmentId": 1,
|
||||||
|
"reimbursementAmount": 79
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 2,
|
||||||
|
"reimbursementAmount": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 3,
|
||||||
|
"reimbursementAmount": 29
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 4,
|
||||||
|
"reimbursementAmount": 46
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departmentId": 5,
|
||||||
|
"reimbursementAmount": 66
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reimbursementAllTotalAmount": 79,
|
||||||
|
"reimbursementAdditionalTotalAmount": 25,
|
||||||
|
"lastAllTotalAmount": 7,
|
||||||
|
"lastAdditionalTotalAmount": 19,
|
||||||
|
"reimbursementLaunchCount": 86,
|
||||||
|
"invoiceLaunchCount": 26,
|
||||||
|
"invoiceKindsStats": [
|
||||||
|
{
|
||||||
|
"invoiceKind": 1,
|
||||||
|
"invoiceLaunchCount": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invoiceKind": 2,
|
||||||
|
"invoiceLaunchCount": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invoiceKind": 3,
|
||||||
|
"invoiceLaunchCount": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invoiceKind": 5,
|
||||||
|
"invoiceLaunchCount": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invoiceKind": 6,
|
||||||
|
"invoiceLaunchCount": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invoiceKind": 7,
|
||||||
|
"invoiceLaunchCount": 39
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
"reimbursementPlaceStats": [
|
||||||
|
{
|
||||||
|
"departureName": "青海",
|
||||||
|
"reimbursementLaunchCount": 80,
|
||||||
|
"destinationName": "安徽"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"departureName": "青海",
|
||||||
|
"reimbursementLaunchCount": 70,
|
||||||
|
"destinationName": "甘肃"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
setReimbursementAmount(statResponse.reimbursementAllTotalAmount)
|
||||||
|
setReimbursementAmountTrend(
|
||||||
|
(statResponse.reimbursementAllTotalAmount - statResponse.lastAllTotalAmount) / statResponse.lastAllTotalAmount)
|
||||||
|
setReimbursementAdditionalAmount(statResponse.reimbursementAdditionalTotalAmount)
|
||||||
|
setReimbursementAdditionalAmountTrend(
|
||||||
|
(statResponse.reimbursementAdditionalTotalAmount - statResponse.lastAdditionalTotalAmount) / statResponse.lastAdditionalTotalAmount)
|
||||||
|
|
||||||
|
setAmounts([statResponse.invoiceLaunchCount, statResponse.reimbursementLaunchCount])
|
||||||
|
setInvoiceKinds(statResponse.invoiceKindsStats.map((item) => {
|
||||||
|
return {value: item.invoiceLaunchCount, name: invoiceTypeNameMap.get(item.invoiceKind)}
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
let departmentAmountMap = new Map<number, Map<number, number>>()
|
||||||
|
departmentMap.forEach(function (value, key, map) {
|
||||||
|
departmentAmountMap.set(key, new Map<number, number>())
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const temporalDepartmentStat of statResponse.temporalDepartmentStats) {
|
||||||
|
for (const departmentStat of temporalDepartmentStat.departmentStats) {
|
||||||
|
let valueMap = departmentAmountMap.get(departmentStat.departmentId)
|
||||||
|
if (valueMap) {
|
||||||
|
valueMap.set(temporalDepartmentStat.value, departmentStat.reimbursementAmount)
|
||||||
|
departmentAmountMap.set(departmentStat.departmentId, valueMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data: { value: number, name: string }[] = []
|
||||||
|
let series: any = []
|
||||||
|
|
||||||
|
departmentAmountMap.forEach(function (valueMap, key, map) {
|
||||||
|
let departmentName = departmentMap.get(key)
|
||||||
|
if (!departmentName) return
|
||||||
|
let total = 0
|
||||||
|
valueMap.forEach(function (value, key) {
|
||||||
|
total += value
|
||||||
|
})
|
||||||
|
data.push({value: total, name: departmentName})
|
||||||
|
|
||||||
|
let valueMapArray = Array.from(valueMap);
|
||||||
|
valueMapArray.sort(function (a, b) {
|
||||||
|
return a[0] - b[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
series.push({
|
||||||
|
name: departmentName,
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
areaStyle: {},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: valueMapArray.map(function ([key, value]) {
|
||||||
|
return value
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
setDepartmentPieData(data)
|
||||||
|
setDepartmentSeries(series)
|
||||||
|
|
||||||
|
|
||||||
|
const geoCoordMap = Object.entries(GeoCoordMap)
|
||||||
|
const getCoords = (placeName: string) => {
|
||||||
|
return geoCoordMap.find(([name,]) => name.includes(placeName))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mapDataTemp: { fromName: string, toName: string, coords: any[], value: number }[] = []
|
||||||
|
let departures = new Map<string, number>()
|
||||||
|
let destinations = new Map<string, number>()
|
||||||
|
for (const item of statResponse.reimbursementPlaceStats) {
|
||||||
|
let departureValue = departures.get(item.departureName)
|
||||||
|
if (departureValue)
|
||||||
|
departures.set(item.departureName, departureValue + item.reimbursementLaunchCount)
|
||||||
|
else
|
||||||
|
departures.set(item.departureName, item.reimbursementLaunchCount)
|
||||||
|
|
||||||
|
let destinationValue = departures.get(item.destinationName)
|
||||||
|
if (destinationValue)
|
||||||
|
destinations.set(item.destinationName, destinationValue + item.reimbursementLaunchCount)
|
||||||
|
else
|
||||||
|
destinations.set(item.destinationName, item.reimbursementLaunchCount)
|
||||||
|
|
||||||
|
const fromCoords = getCoords(item.departureName)
|
||||||
|
const toCoords = getCoords(item.destinationName)
|
||||||
|
|
||||||
|
if (fromCoords && toCoords) {
|
||||||
|
mapDataTemp.push({
|
||||||
|
"fromName": fromCoords[0],
|
||||||
|
"toName": toCoords[0],
|
||||||
|
"coords": [fromCoords[1], toCoords[1]],
|
||||||
|
"value": item.reimbursementLaunchCount,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setMapData(mapDataTemp)
|
||||||
|
|
||||||
|
{
|
||||||
|
let placeNames: string[] = []
|
||||||
|
let reimbursementCounts: number[] = []
|
||||||
|
departures.forEach(function (val, key, map) {
|
||||||
|
placeNames.push(key)
|
||||||
|
reimbursementCounts.push(val)
|
||||||
|
})
|
||||||
|
setDepartureNames(placeNames)
|
||||||
|
setDepartureValues(reimbursementCounts)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let placeNames: string[] = []
|
||||||
|
let reimbursementCounts: number[] = []
|
||||||
|
destinations.forEach(function (val, key, map) {
|
||||||
|
placeNames.push(key)
|
||||||
|
reimbursementCounts.push(val)
|
||||||
|
})
|
||||||
|
setDestinationNames(placeNames)
|
||||||
|
setDestinationValues(reimbursementCounts)
|
||||||
|
}
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
}).catch(function (error) {
|
||||||
|
console.log(error)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -144,47 +489,33 @@ function StatView() {
|
||||||
<div>
|
<div>
|
||||||
<div style={{
|
<div style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '30px 30px 0px 30px',
|
padding: '20px 20px 0px 20px',
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
flexWrap: "wrap"
|
flexWrap: "wrap"
|
||||||
}}>
|
}}>
|
||||||
<div style={{flex: 1, flexBasis: 400, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
<div style={{flex: 1, flexBasis: 400, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
||||||
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
||||||
<Statistic title="报销金额" value={1128.45} precision={2}
|
<Statistic title="报销金额" value={reimbursementAmount} precision={2}
|
||||||
prefix={<IconFont type={'icon-renminbi'}/>}/>
|
prefix={<IconFont type={'icon-renminbi'}/>}/>
|
||||||
</Card>
|
</Card>
|
||||||
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
||||||
<Statistic
|
<TrendStatistic type={type} value={reimbursementAmountTrend}/>
|
||||||
title={type === 'month' ? "较上个月" : '较去年'}
|
|
||||||
value={11.28}
|
|
||||||
precision={2}
|
|
||||||
valueStyle={{color: '#3f8600'}}
|
|
||||||
prefix={<ArrowUpOutlined/>}
|
|
||||||
suffix="%"
|
|
||||||
/>
|
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div style={{flex: 1, flexBasis: 400, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
<div style={{flex: 1, flexBasis: 400, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
||||||
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
||||||
<Statistic title="补贴金额" value={1128.45} precision={2}
|
<Statistic title="补贴金额" value={reimbursementAdditionalAmount} precision={2}
|
||||||
prefix={<IconFont type={'icon-renminbi'}/>}/>
|
prefix={<IconFont type={'icon-renminbi'}/>}/>
|
||||||
</Card>
|
</Card>
|
||||||
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
||||||
<Statistic
|
<TrendStatistic type={type} value={reimbursementAdditionalAmountTrend}/>
|
||||||
title={type === 'month' ? "较上个月" : '较去年'}
|
|
||||||
value={11.28}
|
|
||||||
precision={2}
|
|
||||||
valueStyle={{color: '#3f8600'}}
|
|
||||||
prefix={<ArrowUpOutlined/>}
|
|
||||||
suffix="%"
|
|
||||||
/>
|
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '0 30px 0 30px',
|
padding: '0 20px 0 20px',
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
flexWrap: "wrap"
|
flexWrap: "wrap"
|
||||||
|
@ -333,7 +664,7 @@ function StatView() {
|
||||||
|
|
||||||
<div style={{
|
<div style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '0px 30px 0px 30px',
|
padding: '0px 20px 0px 20px',
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
flexWrap: "wrap"
|
flexWrap: "wrap"
|
||||||
|
@ -342,23 +673,38 @@ function StatView() {
|
||||||
<Card style={{flex: 1, flexBasis: 600, margin: 10, minWidth: 0, minHeight: 0}}>
|
<Card style={{flex: 1, flexBasis: 600, margin: 10, minWidth: 0, minHeight: 0}}>
|
||||||
<ReactECharts style={{height: 600}} option={{
|
<ReactECharts style={{height: 600}} option={{
|
||||||
title: {
|
title: {
|
||||||
text: '差旅流向图',
|
text: '差旅去向',
|
||||||
left: 'center',
|
left: 'center',
|
||||||
},
|
},
|
||||||
series: [
|
geo: {
|
||||||
{
|
|
||||||
type: 'map',
|
|
||||||
map: 'china',
|
map: 'china',
|
||||||
emphasis: {
|
emphasis: {
|
||||||
disabled: true
|
disabled: true
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
disabled: true
|
disabled: true
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
areaColor: '#d4e2fd',
|
||||||
|
borderColor: '#8c8c8c'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'lines',
|
||||||
|
zlevel: 2,
|
||||||
|
lineStyle: {
|
||||||
|
normal: {
|
||||||
|
color: '#',
|
||||||
|
width: 3,
|
||||||
|
opacity: 0.2,
|
||||||
|
curveness: .3
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
data: mapData
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}} notMerge={true}
|
}} notMerge={true} lazyUpdate={true}/>
|
||||||
lazyUpdate={true}/>
|
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div style={{flex: 1, flexBasis: 300, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
<div style={{flex: 1, flexBasis: 300, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
||||||
|
@ -371,8 +717,20 @@ function StatView() {
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Card style={{margin: '10px 40px 40px 40px', minWidth: 0, minHeight: 0}}>
|
<Card style={{margin: '10px 30px 30px 30px', minWidth: 0, minHeight: 0}}>
|
||||||
<ReactECharts option={{
|
<ReactECharts option={{
|
||||||
|
color: [
|
||||||
|
'#6395f9',
|
||||||
|
'#d4e2fd',
|
||||||
|
'#73deb3',
|
||||||
|
'#d4f5e8',
|
||||||
|
'#657798',
|
||||||
|
'#d0d6e0',
|
||||||
|
'#7666f9',
|
||||||
|
'#d5d0fd',
|
||||||
|
'#f6c022',
|
||||||
|
'#fcecbd',
|
||||||
|
],
|
||||||
title: {
|
title: {
|
||||||
text: '各部门报销金额',
|
text: '各部门报销金额',
|
||||||
left: 'center'
|
left: 'center'
|
||||||
|
@ -388,7 +746,6 @@ function StatView() {
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
type: 'scroll',
|
type: 'scroll',
|
||||||
data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine'],
|
|
||||||
top: 40
|
top: 40
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
|
@ -402,7 +759,7 @@ function StatView() {
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
data: dates
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
yAxis: [
|
yAxis: [
|
||||||
|
@ -410,65 +767,8 @@ function StatView() {
|
||||||
type: 'value'
|
type: 'value'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
series: [
|
series: departmentSeries
|
||||||
{
|
}} notMerge={true} lazyUpdate={true}/>
|
||||||
name: 'Email',
|
|
||||||
type: 'line',
|
|
||||||
stack: 'Total',
|
|
||||||
areaStyle: {},
|
|
||||||
emphasis: {
|
|
||||||
focus: 'series'
|
|
||||||
},
|
|
||||||
data: [120, 132, 101, 134, 90, 230, 210]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Union Ads',
|
|
||||||
type: 'line',
|
|
||||||
stack: 'Total',
|
|
||||||
areaStyle: {},
|
|
||||||
emphasis: {
|
|
||||||
focus: 'series'
|
|
||||||
},
|
|
||||||
data: [220, 182, 191, 234, 290, 330, 310]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Video Ads',
|
|
||||||
type: 'line',
|
|
||||||
stack: 'Total',
|
|
||||||
areaStyle: {},
|
|
||||||
emphasis: {
|
|
||||||
focus: 'series'
|
|
||||||
},
|
|
||||||
data: [150, 232, 201, 154, 190, 330, 410]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Direct',
|
|
||||||
type: 'line',
|
|
||||||
stack: 'Total',
|
|
||||||
areaStyle: {},
|
|
||||||
emphasis: {
|
|
||||||
focus: 'series'
|
|
||||||
},
|
|
||||||
data: [320, 332, 301, 334, 390, 330, 320]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Search Engine',
|
|
||||||
type: 'line',
|
|
||||||
stack: 'Total',
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'top'
|
|
||||||
},
|
|
||||||
areaStyle: {},
|
|
||||||
emphasis: {
|
|
||||||
focus: 'series'
|
|
||||||
},
|
|
||||||
data: [820, 932, 901, 934, 1290, 1330, 1320]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
notMerge={true}
|
|
||||||
lazyUpdate={true}/>
|
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue