完成统计页,待后端上线
parent
b30fbc9fb9
commit
eac61bc7ba
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,13 @@
|
|||
export interface StatResponse {
|
||||
/**
|
||||
* 当yearly=true时,此处会返回12项,对应12个月;否则按日返回
|
||||
*/
|
||||
departmentStats: Array<DepartmentStat[]>;
|
||||
invoiceKindsStats: InvoiceKindsStat[];
|
||||
invoiceLaunchCount: number;
|
||||
lastAdditionalTotalAmount: number;
|
||||
lastAllTotalAmount: number;
|
||||
reimbursementAdditionalTotalAmount: number;
|
||||
reimbursementAllTotalAmount: number;
|
||||
reimbursementDepartureStats: ReimbursementDepartureStat[];
|
||||
reimbursementDestinationStats: ReimbursementDestinationStat[];
|
||||
reimbursementLaunchCount: number;
|
||||
}
|
||||
|
||||
export interface DepartmentStat {
|
||||
departmentName: string;
|
||||
reimbursementAmount: string;
|
||||
reimbursementPlaceStats: ReimbursementPlaceStat[];
|
||||
temporalDepartmentStats: TemporalDepartmentStat[];
|
||||
}
|
||||
|
||||
export interface InvoiceKindsStat {
|
||||
|
@ -24,12 +15,21 @@ export interface InvoiceKindsStat {
|
|||
invoiceLaunchCount: number;
|
||||
}
|
||||
|
||||
export interface ReimbursementDepartureStat {
|
||||
placeName: string;
|
||||
export interface ReimbursementPlaceStat {
|
||||
departureName: string;
|
||||
destinationName: string;
|
||||
reimbursementLaunchCount: number;
|
||||
}
|
||||
|
||||
export interface ReimbursementDestinationStat {
|
||||
placeName: string;
|
||||
reimbursementLaunchCount: number;
|
||||
export interface TemporalDepartmentStat {
|
||||
departmentStats: DepartmentStat[];
|
||||
/**
|
||||
* 月份值或日期值
|
||||
*/
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface DepartmentStat {
|
||||
departmentId: number;
|
||||
reimbursementAmount: number;
|
||||
}
|
|
@ -1,22 +1,45 @@
|
|||
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 {useEffect, useRef, useState} from "react";
|
||||
import React, {useEffect, useRef, useState} from "react";
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import * as Echarts from 'echarts'
|
||||
import china from '../../assets/mapjson/china.json'
|
||||
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
|
||||
Echarts.registerMap('china', china);
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
type PickerType = 'month' | 'year';
|
||||
type StatType = 'month' | 'year';
|
||||
|
||||
const IconFont = createFromIconfontCN({
|
||||
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[] }) {
|
||||
return <ReactECharts option={{
|
||||
color: [
|
||||
|
@ -73,20 +96,64 @@ function HorizontalBarChart(props: { title: string, values: number[], labels: st
|
|||
}} 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() {
|
||||
const {
|
||||
token: {colorBgContainer, colorPrimary, colorSuccess},
|
||||
} = theme.useToken();
|
||||
|
||||
const [type, setType] = useState<PickerType>('month');
|
||||
const [type, setType] = useState<StatType>('month');
|
||||
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 [invoiceKinds, setInvoiceKinds] = useState<any>([])
|
||||
const [departmentPieData, setDepartmentPieData] = useState<any>([])
|
||||
const [mapData, setMapData] = useState<any>([])
|
||||
const [departureNames, setDepartureNames] = useState<any>([])
|
||||
const [departureValues, setDepartureValues] = useState<any>([])
|
||||
const [destinationNames, setDestinationNames] = useState<any>([])
|
||||
const [destinationValues, setDestinationValues] = useState<any>([])
|
||||
const [dates, setDates] = useState<any>([])
|
||||
const [departmentSeries, setDepartmentSeries] = useState<any>([])
|
||||
|
||||
useEffect(() => {
|
||||
getStatData(dayjs())
|
||||
|
@ -95,24 +162,302 @@ function StatView() {
|
|||
const getStatData = (time: Dayjs | null) => {
|
||||
console.log(time)
|
||||
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(() => {
|
||||
setAmounts([120, 43])
|
||||
setInvoiceKinds([{value: 1048, name: '增值税发票'},
|
||||
{value: 735, name: '火车票'},
|
||||
{value: 580, name: '机票行程单'},
|
||||
{value: 484, name: '通用机打发票'},
|
||||
{value: 300, name: '过路过桥费发票'}])
|
||||
setDepartmentPieData([{value: 1048, name: '钝角部'},
|
||||
{value: 735, name: '投影立体角部'},
|
||||
{value: 580, name: '财务部'},
|
||||
{value: 484, name: '采购部'},
|
||||
{value: 300, name: '销售部'}])
|
||||
setDepartureNames(['北京', '上海', '广州', '深圳', '成都'])
|
||||
setDepartureValues([100, 80, 70, 60, 50])
|
||||
setDestinationNames(['北京', '上海', '广州', '深圳', '成都'])
|
||||
setDestinationValues([100, 80, 70, 60, 50])
|
||||
let statResponse: StatResponse = {
|
||||
"temporalDepartmentStats": [
|
||||
{
|
||||
"value": 4,
|
||||
"departmentStats": [
|
||||
{
|
||||
"departmentId": 1,
|
||||
"reimbursementAmount": 79
|
||||
},
|
||||
{
|
||||
"departmentId": 2,
|
||||
"reimbursementAmount": 9
|
||||
},
|
||||
{
|
||||
"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)
|
||||
}, 1000);
|
||||
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -138,53 +483,39 @@ function StatView() {
|
|||
</Space>
|
||||
</div>
|
||||
{loading ?
|
||||
<div style={{flex: 1,display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<div style={{flex: 1, display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Spin size="large"/>
|
||||
</div> :
|
||||
<div>
|
||||
<div style={{
|
||||
width: '100%',
|
||||
padding: '30px 30px 0px 30px',
|
||||
padding: '20px 20px 0px 20px',
|
||||
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}}>
|
||||
<Statistic title="报销金额" value={1128.45} precision={2}
|
||||
<Statistic title="报销金额" value={reimbursementAmount} precision={2}
|
||||
prefix={<IconFont type={'icon-renminbi'}/>}/>
|
||||
</Card>
|
||||
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
||||
<Statistic
|
||||
title={type === 'month' ? "较上个月" : '较去年'}
|
||||
value={11.28}
|
||||
precision={2}
|
||||
valueStyle={{color: '#3f8600'}}
|
||||
prefix={<ArrowUpOutlined/>}
|
||||
suffix="%"
|
||||
/>
|
||||
<TrendStatistic type={type} value={reimbursementAmountTrend}/>
|
||||
</Card>
|
||||
</div>
|
||||
<div style={{flex: 1, flexBasis: 400, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
||||
<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'}/>}/>
|
||||
</Card>
|
||||
<Card style={{flex: 1, flexBasis: 200, margin: 10}}>
|
||||
<Statistic
|
||||
title={type === 'month' ? "较上个月" : '较去年'}
|
||||
value={11.28}
|
||||
precision={2}
|
||||
valueStyle={{color: '#3f8600'}}
|
||||
prefix={<ArrowUpOutlined/>}
|
||||
suffix="%"
|
||||
/>
|
||||
<TrendStatistic type={type} value={reimbursementAdditionalAmountTrend}/>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{
|
||||
width: '100%',
|
||||
padding: '0 30px 0 30px',
|
||||
padding: '0 20px 0 20px',
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap"
|
||||
|
@ -333,7 +664,7 @@ function StatView() {
|
|||
|
||||
<div style={{
|
||||
width: '100%',
|
||||
padding: '0px 30px 0px 30px',
|
||||
padding: '0px 20px 0px 20px',
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap"
|
||||
|
@ -342,23 +673,38 @@ function StatView() {
|
|||
<Card style={{flex: 1, flexBasis: 600, margin: 10, minWidth: 0, minHeight: 0}}>
|
||||
<ReactECharts style={{height: 600}} option={{
|
||||
title: {
|
||||
text: '差旅流向图',
|
||||
text: '差旅去向',
|
||||
left: 'center',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'map',
|
||||
geo: {
|
||||
map: 'china',
|
||||
emphasis: {
|
||||
disabled: true
|
||||
},
|
||||
select: {
|
||||
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}
|
||||
lazyUpdate={true}/>
|
||||
}} notMerge={true} lazyUpdate={true}/>
|
||||
</Card>
|
||||
</div>
|
||||
<div style={{flex: 1, flexBasis: 300, display: "flex", flexDirection: "row", flexWrap: "wrap"}}>
|
||||
|
@ -371,8 +717,20 @@ function StatView() {
|
|||
</Card>
|
||||
</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={{
|
||||
color: [
|
||||
'#6395f9',
|
||||
'#d4e2fd',
|
||||
'#73deb3',
|
||||
'#d4f5e8',
|
||||
'#657798',
|
||||
'#d0d6e0',
|
||||
'#7666f9',
|
||||
'#d5d0fd',
|
||||
'#f6c022',
|
||||
'#fcecbd',
|
||||
],
|
||||
title: {
|
||||
text: '各部门报销金额',
|
||||
left: 'center'
|
||||
|
@ -388,7 +746,6 @@ function StatView() {
|
|||
},
|
||||
legend: {
|
||||
type: 'scroll',
|
||||
data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine'],
|
||||
top: 40
|
||||
},
|
||||
grid: {
|
||||
|
@ -402,7 +759,7 @@ function StatView() {
|
|||
{
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
||||
data: dates
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
|
@ -410,65 +767,8 @@ function StatView() {
|
|||
type: 'value'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
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}/>
|
||||
series: departmentSeries
|
||||
}} notMerge={true} lazyUpdate={true}/>
|
||||
</Card>
|
||||
</div>
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue