diff --git a/src/assets/images/icon-rank-1.png b/src/assets/images/icon-rank-1.png new file mode 100644 index 0000000..d66c925 Binary files /dev/null and b/src/assets/images/icon-rank-1.png differ diff --git a/src/assets/images/icon-rank-2.png b/src/assets/images/icon-rank-2.png new file mode 100644 index 0000000..feaf502 Binary files /dev/null and b/src/assets/images/icon-rank-2.png differ diff --git a/src/assets/images/icon-rank-3.png b/src/assets/images/icon-rank-3.png new file mode 100644 index 0000000..0010751 Binary files /dev/null and b/src/assets/images/icon-rank-3.png differ diff --git a/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/echarts.config.js b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/echarts.config.js new file mode 100644 index 0000000..8816fe0 --- /dev/null +++ b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/echarts.config.js @@ -0,0 +1,76 @@ +const colorList = ['#3AA9FF', '#F997DF'] +import utils from "@/config/utils" + +export default { + pieChartOption: { + title: { + show: true, + text: '', + bottom: 0, + x: 'center', + textStyle: { + color: '#fff' + }, + textAlign: 'left' + }, + color: colorList, + tooltip: { + trigger: 'item', + formatter: (params) => { + return ` + <div> + ${params.marker} + ${params.name}: + + ${utils.parseFormatNum(params?.value || 0)} + </div> + ` + } + }, + legend: { + top: '5%', + left: 'center', + itemHeight: 6, + itemGap: 20, + textStyle: { + color: '#fff' + } + }, + series: [ + { + name: '', + type: 'pie', + center: ["50%", "52%"], + radius: ['60%', '70%'], + avoidLabelOverlap: true, + label: { + normal: { + show: false, + position: 'center', + formatter: '{title|{b}}\n\r\n\r{percent|{d}}%', + textStyle: { + color: '#fff' + }, + rich: { + title: { + fontSize: 18 + }, + percent: { + fontSize: 20, + fontWeight: 700 + } + } + }, + emphasis: { + show: true + } + }, + labelLine: { + show: false + }, + data: [ + ] + } + ] + }, +} \ No newline at end of file diff --git a/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.jsx b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.jsx index 2fc39d7..afab685 100644 --- a/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.jsx +++ b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.jsx @@ -1,30 +1,161 @@ -import React, { useEffect } from 'react' +import React, { useEffect, useState, useRef } from 'react' +import ajax from "@/services" +import { Tabs } from 'antd' +import ReactEcharts from "echarts-for-react"; +import EchartsConfig from './echarts.config' +import utils from "@/config/utils" import './index.scss' const Overview = function(props) { const { - yisaData + formData } = props + const [yisaData, setYisaData] = useState({}) + const [activeTab, setActiveTab] = useState('parkRank') + const [moneyPieChartOption, setMoneyPieChartOption] = useState({...EchartsConfig.pieChartOption}) + const [itemPieChartOption, setItemPieChartOption] = useState({...EchartsConfig.pieChartOption}) + + const ajaxGetData = () => { + ajax.getIncomeOverviewData({...formData}).then(res => { + if (res.status == 20000) { + setYisaData({...res.data}) + } + }) + } + + const initMoneyPieChart = (data, unit) => { + let total = 0 + data.map((item) => { + total += item.value + }) + setMoneyPieChartOption({ + ...moneyPieChartOption, + title: { + ...moneyPieChartOption.title, + text: `总金额:${utils.parseFormatNum(total)}(${unit})` + }, + tooltip: { + ...moneyPieChartOption.tooltip, + formatter: (params) => { + return ` + <div> + ${params.marker} + ${params.name}: + + ${utils.parseFormatNum(params?.value || 0)} + ${unit} + </div> + ` + } + }, + series: [ + { + ...moneyPieChartOption.series[0], + data: data + } + ] + }) + } + + const initItemPieChart = (data, unit) => { + let total = 0 + data.map((item) => { + total += item.value + }) + setItemPieChartOption({ + ...itemPieChartOption, + title: { + ...itemPieChartOption.title, + text: `总订单数:${utils.parseFormatNum(total)}(${unit})` + }, + tooltip: { + ...itemPieChartOption.tooltip, + formatter: (params) => { + return ` + <div> + ${params.marker} + ${params.name}: + + ${utils.parseFormatNum(params?.value || 0)} + ${unit} + </div> + ` + } + }, + series: [ + { + ...itemPieChartOption.series[0], + data: data + } + ] + }) + } + useEffect(() => { - console.log(yisaData) + ajaxGetData() }, []) + useEffect(() => { + if (yisaData.amount) { + initMoneyPieChart(yisaData.amount, '元') + } + if (yisaData.items) { + initItemPieChart(yisaData.items, '个') + } + }, [yisaData]) + return ( <div className="overview-container"> <div className="overview-top"> <div className="overview-item"> <div className="overview-item-title">欠费金额占比图</div> - <div className="overview-item-content" id="moneyPieChart"></div> + <div className="overview-item-content" id="moneyPieChart"> + <ReactEcharts + option={moneyPieChartOption} + style={{ overflow: "hidden" }} + /> + </div> </div> <div className="overview-item"> <div className="overview-item-title">欠费条数占比图</div> - <div className="overview-item-content" id="itemPieChart"></div> + <div className="overview-item-content" id="itemPieChart"> + <ReactEcharts + option={itemPieChartOption} + style={{ overflow: "hidden" }} + /> + </div> </div> <div className="overview-item"> <div className="overview-item-title">排行榜</div> - <div className="overview-item-content"></div> + <div className="overview-item-content"> + <div className="item-tabs-container"> + <Tabs + defaultActiveKey={activeTab} + onChange={(v) => setActiveTab(v)} + items={[ + { label: '欠费车场', key: 'parkRank' }, + { label: '欠费车牌', key: 'plateRank' } + ]} + /> + </div> + <div className="item-tab-content"> + { + yisaData[activeTab] && yisaData[activeTab].map((item, index) => ( + <div className="rank-item" key={index}> + <div className="rank-left"> + <div className="rank-no">{index+1 > 3 ? (index+1) : ''}</div> + <div className="rank-label">{item.name}</div> + </div> + <div className="rank-right"> + <div className="rank-value">{utils.parseFormatNum(item.value || 0)}</div> + </div> + </div> + )) + } + </div> + </div> </div> </div> <div className="overview-bottom"> diff --git a/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.scss b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.scss index 454dc4b..4bafed3 100644 --- a/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.scss +++ b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/Overview/index.scss @@ -1,3 +1,5 @@ +@import "@/assets/css/mixin.scss"; + .overview-container { display: flex; flex-direction: column; @@ -39,6 +41,67 @@ &:last-child { margin-right: 0; } + .overview-item-content { + height: 100%; + display: flex; + flex-direction: column; + .item-tab-content { + flex: 1; + margin-top: 10px; + display: flex; + flex-direction: column; + user-select: none; + padding-right: 10px; + overflow-y: hidden; + &:hover { + overflow-y: auto; + @include scrollBar(var(--color-user-list-bg), #3B97FF); + } + .rank-item { + display: flex; + justify-content: space-between; + align-items: center; + height: 30px; + margin-bottom: 5px; + font-size: 16px; + .rank-left { + display: flex; + font-weight: 700; + .rank-no { + width: 25px; + height: 25px; + margin: 0 5px; + margin-right: 10px; + text-align: center; + } + } + &:nth-child(1) { + .rank-no { + background: url('@/assets/images/icon-rank-1.png') no-repeat 100% 100%; + background-size: 100% 100%; + } + } + &:nth-child(2) { + .rank-no { + background: url('@/assets/images/icon-rank-2.png') no-repeat 100% 100%; + background-size: 100% 100%; + } + } + &:nth-child(3) { + .rank-no { + background: url('@/assets/images/icon-rank-3.png') no-repeat 100% 100%; + background-size: 100% 100%; + } + } + } + } + } + .item-tabs-container { + margin-top: 10px; + .ant-tabs-tab { + padding-bottom: 5px; + } + } } } .overview-bottom { diff --git a/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/loadable.jsx b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/loadable.jsx index c8b3458..24e9a8b 100644 --- a/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/loadable.jsx +++ b/src/pages/DataAnalysisPrediction/ParkingIncomeAly/ArrearageAly/loadable.jsx @@ -132,13 +132,13 @@ function ArrearageAly(props) { </div> <div className="parking-wrapper"> { - activeTab == 1 ? <Overview yisaData={formData}/> : null + activeTab == 1 ? <Overview formData={formData}/> : null } { - activeTab == 2 ? <ParkArrear yisaData={formData}/> : null + activeTab == 2 ? <ParkArrear formData={formData}/> : null } { - activeTab == 3 ? <PlateArrear yisaData={formData}/> : null + activeTab == 3 ? <PlateArrear formData={formData}/> : null } </div> </div> diff --git a/src/services/DataAnalysisPrediction/ParkingIncomeAly/index.js b/src/services/DataAnalysisPrediction/ParkingIncomeAly/index.js new file mode 100644 index 0000000..44b1833 --- /dev/null +++ b/src/services/DataAnalysisPrediction/ParkingIncomeAly/index.js @@ -0,0 +1,11 @@ +import ajax from "@/config/ajax" + +export default { + getIncomeOverviewData: function(data) { + return ajax({ + url: '/api/dataAnalysis/overview', + type: 'post', + data + }) + } +} diff --git a/src/services/DataAnalysisPrediction/index.js b/src/services/DataAnalysisPrediction/index.js index e6b55bb..503de14 100644 --- a/src/services/DataAnalysisPrediction/index.js +++ b/src/services/DataAnalysisPrediction/index.js @@ -1,4 +1,6 @@ import ParkingBusinessAly from "./ParkingBusinessAly"; +import ParkingIncomeAly from "./ParkingIncomeAly"; export default { - ...ParkingBusinessAly + ...ParkingBusinessAly, + ...ParkingIncomeAly };