From 5d0c3ebc783a0b2af3c4dff9629c275fe9a7e207 Mon Sep 17 00:00:00 2001
From: yangwenhua <1289978696@qq.com>
Date: Tue, 5 Jul 2022 17:42:30 +0800
Subject: [PATCH 1/7] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BC=9A=E5=91=98?=
=?UTF-8?q?=E5=9B=BE=E8=A1=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package.json | 1 +
.../order/order-member-statement/index.jsx | 313 +++++++++++++++++-
.../order/order-member-statement/index.less | 85 ++++-
.../order/order-member-statement/service.js | 18 +
4 files changed, 401 insertions(+), 16 deletions(-)
create mode 100644 src/pages/order/order-member-statement/service.js
diff --git a/package.json b/package.json
index 883d2d0..23ce52f 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
"braft-editor": "^2.3.9",
"classnames": "^2.2.6",
"cos-js-sdk-v5": "^1.3.5",
+ "echarts": "^5.3.3",
"js-export-excel": "^1.1.4",
"linq": "^4.0.0",
"lodash": "^4.17.11",
diff --git a/src/pages/order/order-member-statement/index.jsx b/src/pages/order/order-member-statement/index.jsx
index 8c62138..a4ed26e 100644
--- a/src/pages/order/order-member-statement/index.jsx
+++ b/src/pages/order/order-member-statement/index.jsx
@@ -1,28 +1,317 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
-import { Button, Card, DatePicker } from 'antd';
+import { Button, Card, DatePicker, Col, Row, TreeSelect, Spin, message } from 'antd';
import styles from './index.less';
+import moment from 'moment';
+import marketAPI from "./service";
+import * as echarts from 'echarts';
const { RangePicker } = DatePicker;
+
/**
* 会员报表
* @returns
*/
export default function Index() {
+ //日期选择下标:0:今天、1:昨天、2:近7天、3、近30天
+ const [searchDayIndex, setSearchDayIndex] = useState(0);
+ //日期选择器
+ const [timeRange, setTimeRange] = useState([
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59'))
+ ]);
+ const [orgTree, setOrgTree] = useState([]);
+ const [showLoading, setShowLoading] = useState(false);
+ const [currentOrg, setCurrentOrg] = useState("");
+
+ //会员图表
+ const [memberReport, setMemberReport] = useState({
+ userCount: 0,
+ newAddUser: [],
+ repurChase: []
+ });
+
+ //新增会员图表实例
+ let newMemberObj = null;
+ //复购图表实例
+ let repurChaseObj = null;
+
+ //切换时间
+ const onChangeTime = (dayIndex) => {
+ setSearchDayIndex(dayIndex);
+ let tempDate = [];
+ switch (dayIndex) {
+ case 0:
+ tempDate = [
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59'))
+ ]
+ break;
+ case 1:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000)).format('YYYY-MM-DD 23:59:59'))
+ ]
+ break;
+ case 2:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000 * 7)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59')),
+ ]
+ break;
+ case 3:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000 * 30)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59')),
+ ]
+ break;
+ }
+ setTimeRange(tempDate);
+ }
+
+ //获取组织树
+ const onGetOrgTree = async () => {
+ setShowLoading(true);
+ const response = await marketAPI.getOrgTree();
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ const originTree = response.data;
+ onSetOrgTreeStatus(originTree);
+ setOrgTree(originTree);
+ } else {
+ message.error(response.errors || '获取组织树出错');
+ }
+ }
+
+ //设置组织树不可选择状态
+ const onSetOrgTreeStatus = (originTree) => {
+ originTree.forEach(treeItem => {
+ if (treeItem.children && treeItem.children.length > 0) {
+ onSetOrgTreeStatus(treeItem.children);
+ } else {
+ if (treeItem.type === 2 || treeItem.type === 3) {
+ treeItem.disabled = false;
+ } else {
+ treeItem.disabled = true;
+ }
+ }
+ });
+ }
+
+ const LoadingCard = () => {
+ return (
+
+
+
+ )
+ }
+
+ //初始化会员报表数据
+ const initMemberReport = async () => {
+ const jsonData = {
+ "startTime": timeRange[0],
+ "endTime": timeRange[1]
+ }
+ setShowLoading(true);
+ const response = await marketAPI.getMemberReport(jsonData);
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setMemberReport(response.data);
+ } else {
+ message.error(response.errors || '获取会员报表失败');
+ }
+ }
+
+
+ //初始化新增会员图表
+ const initNewMemberCharts = () => {
+ const chartDom = document.getElementById('new-member');
+ if (!newMemberObj) {
+ newMemberObj = echarts.init(chartDom);
+ }
+ const xAxisData = [];
+ const seriesData = [];
+ memberReport.newAddUser.forEach(item => {
+ const date = new Date(item.userKey);
+ xAxisData.push(date.toLocaleString());
+ seriesData.push(item.userValue);
+ });
+ const option = {
+ title: {
+ text: '新增会员'
+ },
+ xAxis: {
+ type: 'category',
+ data: xAxisData
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ data: seriesData,
+ type: 'bar'
+ }
+ ]
+ };
+ newMemberObj.setOption(option);
+ }
+
+ //复购次数图表
+ const initRepurChaseCharts = () => {
+ const chartDom = document.getElementById('repur-chase');
+ if (!repurChaseObj) {
+ repurChaseObj = echarts.init(chartDom);
+ }
+ const xAxisData = [];
+ const seriesData = [];
+ memberReport.repurChase.forEach(item => {
+ xAxisData.push(item.userKey);
+ seriesData.push(item.userValue);
+ });
+ const option = {
+ title: {
+ text: '复购次数'
+ },
+ xAxis: {
+ type: 'category',
+ data: xAxisData
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ data: seriesData,
+ type: 'line',
+ smooth: true
+ }
+ ]
+ };
+ repurChaseObj.setOption(option);
+ }
+
+ //重置
+ const onResetSearch = () => {
+ setCurrentOrg("");
+ }
+
+ useEffect(() => {
+ onGetOrgTree();
+ initMemberReport();
+ }, []);
+
+ useEffect(() => {
+ initNewMemberCharts();
+ initRepurChaseCharts();
+ window.onresize = () => {
+ if (newMemberObj && repurChaseObj) {
+ newMemberObj.resize();
+ repurChaseObj.resize();
+ }
+ }
+ }, [memberReport]);
+
return (
+ {showLoading ? : null}
-
-
-
- 会员报表
+
+
+ {
+ let tempDate = [
+ moment(moment(new Date(dateStrings[0])).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(dateStrings[1])).format('YYYY-MM-DD 23:59:59')),
+ ]
+ setTimeRange(tempDate);
+ }} />
+
+
+ onChangeTime(0)}>
+ 今天
+
+ onChangeTime(1)}>
+ 昨天
+
+ onChangeTime(2)}>
+ 近7天
+
+ onChangeTime(3)}>
+ 近30天
+
+
+
+ {
+ if (node.type === 2 || node === 3) {
+ setCurrentOrg(node);
+ } else {
+ setCurrentOrg("");
+ }
+ }}
+ placeholder="请选择组织架构"
+ treeDefaultExpandAll
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 会员总量
+
+
+ {memberReport.userCount}
+
+
+
+
+ 新增会员
+
+
+ {memberReport.newAddUser.length}
+
+
+
+
+ 复购数量
+
+
+ {memberReport.repurChase.length}
+
+
+
+
+
+
+ {/* 新增会员图表 */}
+
+
+
+
+
+
+
+ {/* 复购次数图表 */}
+
+
+
+
)
}
diff --git a/src/pages/order/order-member-statement/index.less b/src/pages/order/order-member-statement/index.less
index 74d0c92..5b5dbc1 100644
--- a/src/pages/order/order-member-statement/index.less
+++ b/src/pages/order/order-member-statement/index.less
@@ -2,15 +2,92 @@
margin-bottom: 20px;
}
-.data-search-box {
+.data-search-row {
+ margin-bottom: 10px;
+}
+
+.data-search-item {
display: flex;
align-items: center;
- justify-content: space-between;
+ margin-bottom: 10px;
+}
+
+.data-search-prefix {
+ margin-right: 10px;
+ font-size: 18px;
}
.search-btn-item {
- margin-left: 20px;
+ margin-right: 20px;
+}
+
+.data-search-day {
+ padding: 5px 20px;
+ border: 1px solid #dedede;
+ cursor: pointer;
+}
+
+.data-search-day:nth-child(1), .data-search-day:nth-child(2), .data-search-day:nth-child(3) {
+ border-right: none;
+}
+
+.search-day-selected {
+ border: 1px solid #FA541C !important;
+ color: #FA541C;
+}
+
+.data-search-sufixx {
+ width: 100%;
+}
+
+// 加载中
+.loading-card {
+ position: fixed;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100vw;
+ height: 100vh;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 999;
+ background-color: rgba(0, 0, 0, 0.5);
+}
+
+.member-card-box {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 5px;
+}
+
+.member-card-prefix {
+ font-size: 20px;
+ font-weight: 700;
+ color: #999;
+ font-family: '楷体';
+}
+
+.member-card-sufixx {
+ font-size: 22px;
+}
+
+.new-member {
+ width: 100%;
+ height: 250px;
+}
+
+.repur-chase {
+ width: 100%;
+ height: 250px;
+}
+
+.member-card {
+ height: 300px;
}
-.table-card {
+.member-row-common {
+ margin-bottom: 10px;
}
\ No newline at end of file
diff --git a/src/pages/order/order-member-statement/service.js b/src/pages/order/order-member-statement/service.js
new file mode 100644
index 0000000..063d1c6
--- /dev/null
+++ b/src/pages/order/order-member-statement/service.js
@@ -0,0 +1,18 @@
+import { request } from 'umi';
+
+export default {
+ //获取组织架构
+ getOrgTree() {
+ return request(`/kitchen/api/report-statistics/org-tree`, {
+ method: 'GET',
+ });
+ },
+
+ //获取会员报表
+ getMemberReport(data) {
+ return request(`/kitchen/api/report-statistics/user-report`, {
+ method: 'POST',
+ data
+ });
+ }
+};
From 3e900b86f98b2de0081136e649aeb24b4f52de90 Mon Sep 17 00:00:00 2001
From: yangwenhua <1289978696@qq.com>
Date: Tue, 5 Jul 2022 18:13:45 +0800
Subject: [PATCH 2/7] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9B=BE=E8=A1=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../order/order-member-statement/index.jsx | 29 +++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/src/pages/order/order-member-statement/index.jsx b/src/pages/order/order-member-statement/index.jsx
index a4ed26e..631a9cf 100644
--- a/src/pages/order/order-member-statement/index.jsx
+++ b/src/pages/order/order-member-statement/index.jsx
@@ -30,6 +30,10 @@ export default function Index() {
newAddUser: [],
repurChase: []
});
+ //新增会员数
+ const [newMemberNum, setNewMemberNum] = useState(0);
+ //复购次数
+ const [repurChaseNum, setRepurChaseNum] = useState(0);
//新增会员图表实例
let newMemberObj = null;
@@ -116,6 +120,16 @@ export default function Index() {
const response = await marketAPI.getMemberReport(jsonData);
setShowLoading(false);
if (response.statusCode === 200) {
+ let sumNewMember = 0;
+ let sumRepurChase = 0;
+ response.data.newAddUser.forEach(item => {
+ sumNewMember += item.userValue
+ });
+ response.data.repurChase.forEach(item => {
+ sumRepurChase += item.userValue
+ });
+ setNewMemberNum(sumNewMember);
+ setRepurChaseNum(sumRepurChase);
setMemberReport(response.data);
} else {
message.error(response.errors || '获取会员报表失败');
@@ -133,7 +147,7 @@ export default function Index() {
const seriesData = [];
memberReport.newAddUser.forEach(item => {
const date = new Date(item.userKey);
- xAxisData.push(date.toLocaleString());
+ xAxisData.push(date.toLocaleDateString());
seriesData.push(item.userValue);
});
const option = {
@@ -173,6 +187,15 @@ export default function Index() {
title: {
text: '复购次数'
},
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ label: {
+ show: true,
+ formatter: '复购{value}次'
+ }
+ }
+ },
xAxis: {
type: 'category',
data: xAxisData
@@ -284,7 +307,7 @@ export default function Index() {
新增会员
- {memberReport.newAddUser.length}
+ {newMemberNum}
@@ -292,7 +315,7 @@ export default function Index() {
复购数量
- {memberReport.repurChase.length}
+ {repurChaseNum}
From 95746e5bb51e7ef30e3f122304db1835b45d1a92 Mon Sep 17 00:00:00 2001
From: yangwenhua <1289978696@qq.com>
Date: Wed, 6 Jul 2022 09:36:47 +0800
Subject: [PATCH 3/7] =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/pages/order/order-member-statement/index.jsx | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/pages/order/order-member-statement/index.jsx b/src/pages/order/order-member-statement/index.jsx
index 631a9cf..dfe1e84 100644
--- a/src/pages/order/order-member-statement/index.jsx
+++ b/src/pages/order/order-member-statement/index.jsx
@@ -240,7 +240,7 @@ export default function Index() {
{showLoading ? : null}
-
+
{
let tempDate = [
moment(moment(new Date(dateStrings[0])).format('YYYY-MM-DD 00:00:00')),
@@ -249,7 +249,7 @@ export default function Index() {
setTimeRange(tempDate);
}} />
-
+
onChangeTime(0)}>
今天
@@ -263,7 +263,7 @@ export default function Index() {
近30天
-
+
- {/* 新增会员图表 */}
-
+ {/* 复购次数图表 */}
+
+
- {/* 复购次数图表 */}
-
+ {/* 新增会员图表 */}
+
From 877034b863c7b755dec7bada5fa5451f70047bad Mon Sep 17 00:00:00 2001
From: yangwenhua <1289978696@qq.com>
Date: Wed, 6 Jul 2022 11:54:00 +0800
Subject: [PATCH 4/7] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=A1=E4=BB=B6?=
=?UTF-8?q?=E6=9F=A5=E8=AF=A2=E7=BB=84=E4=BB=B6=E3=80=81=E4=BC=9A=E5=91=98?=
=?UTF-8?q?=E6=8A=A5=E8=A1=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/ConditionQuery/index.jsx | 79 ++++++
src/components/ConditionQuery/index.less | 93 +++++++
.../order/order-member-statement/index.jsx | 94 ++-----
.../order/order-product-report/index.jsx | 261 +++++++++++++++++-
.../order/order-product-report/index.less | 18 +-
.../order/order-product-report/service.js | 18 ++
6 files changed, 468 insertions(+), 95 deletions(-)
create mode 100644 src/components/ConditionQuery/index.jsx
create mode 100644 src/components/ConditionQuery/index.less
create mode 100644 src/pages/order/order-product-report/service.js
diff --git a/src/components/ConditionQuery/index.jsx b/src/components/ConditionQuery/index.jsx
new file mode 100644
index 0000000..7535263
--- /dev/null
+++ b/src/components/ConditionQuery/index.jsx
@@ -0,0 +1,79 @@
+import React, { useEffect } from 'react';
+import { Button, Card, DatePicker, Col, Row, TreeSelect, Spin } from 'antd';
+import styles from './index.less';
+import moment from 'moment';
+const { RangePicker } = DatePicker;
+
+/**
+ * 条件查询通用头部
+ * @returns
+ */
+export default function Index(props) {
+
+ const LoadingCard = () => {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+ {props.showLoading ?
: null}
+
+
+
+ {
+ let tempDate = [
+ moment(moment(new Date(dateStrings[0])).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(dateStrings[1])).format('YYYY-MM-DD 23:59:59')),
+ ]
+ props.onTimePickerChange(tempDate);
+ }} />
+
+
+ props.onChangeTimeIndex(0)}>
+ 今天
+
+ props.onChangeTimeIndex(1)}>
+ 昨天
+
+ props.onChangeTimeIndex(2)}>
+ 近7天
+
+ props.onChangeTimeIndex(3)}>
+ 近30天
+
+
+
+ {
+ if (node.type === 2 || node === 3) {
+ props.onCurrentOrgChange(node);
+ } else {
+ props.onCurrentOrgChange("");
+ }
+ }}
+ placeholder="请选择组织架构"
+ treeDefaultExpandAll
+ />
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/ConditionQuery/index.less b/src/components/ConditionQuery/index.less
new file mode 100644
index 0000000..5b5dbc1
--- /dev/null
+++ b/src/components/ConditionQuery/index.less
@@ -0,0 +1,93 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.data-search-row {
+ margin-bottom: 10px;
+}
+
+.data-search-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 10px;
+}
+
+.data-search-prefix {
+ margin-right: 10px;
+ font-size: 18px;
+}
+
+.search-btn-item {
+ margin-right: 20px;
+}
+
+.data-search-day {
+ padding: 5px 20px;
+ border: 1px solid #dedede;
+ cursor: pointer;
+}
+
+.data-search-day:nth-child(1), .data-search-day:nth-child(2), .data-search-day:nth-child(3) {
+ border-right: none;
+}
+
+.search-day-selected {
+ border: 1px solid #FA541C !important;
+ color: #FA541C;
+}
+
+.data-search-sufixx {
+ width: 100%;
+}
+
+// 加载中
+.loading-card {
+ position: fixed;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100vw;
+ height: 100vh;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 999;
+ background-color: rgba(0, 0, 0, 0.5);
+}
+
+.member-card-box {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 5px;
+}
+
+.member-card-prefix {
+ font-size: 20px;
+ font-weight: 700;
+ color: #999;
+ font-family: '楷体';
+}
+
+.member-card-sufixx {
+ font-size: 22px;
+}
+
+.new-member {
+ width: 100%;
+ height: 250px;
+}
+
+.repur-chase {
+ width: 100%;
+ height: 250px;
+}
+
+.member-card {
+ height: 300px;
+}
+
+.member-row-common {
+ margin-bottom: 10px;
+}
\ No newline at end of file
diff --git a/src/pages/order/order-member-statement/index.jsx b/src/pages/order/order-member-statement/index.jsx
index dfe1e84..38f1763 100644
--- a/src/pages/order/order-member-statement/index.jsx
+++ b/src/pages/order/order-member-statement/index.jsx
@@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
-import { Button, Card, DatePicker, Col, Row, TreeSelect, Spin, message } from 'antd';
+import { Card, Col, Row, message } from 'antd';
+import ConditionQuery from "../../../components/ConditionQuery";
import styles from './index.less';
import moment from 'moment';
import marketAPI from "./service";
import * as echarts from 'echarts';
-const { RangePicker } = DatePicker;
/**
* 会员报表
@@ -41,7 +41,7 @@ export default function Index() {
let repurChaseObj = null;
//切换时间
- const onChangeTime = (dayIndex) => {
+ const onChangeTimeIndex = (dayIndex) => {
setSearchDayIndex(dayIndex);
let tempDate = [];
switch (dayIndex) {
@@ -102,17 +102,12 @@ export default function Index() {
});
}
- const LoadingCard = () => {
- return (
-
-
-
- )
- }
-
//初始化会员报表数据
const initMemberReport = async () => {
const jsonData = {
+ "shopIds": [
+ currentOrg.key
+ ],
"startTime": timeRange[0],
"endTime": timeRange[1]
}
@@ -219,6 +214,16 @@ export default function Index() {
setCurrentOrg("");
}
+ //子组件切换组织架构
+ const onCurrentOrgChange = (curOrg) => {
+ setCurrentOrg(curOrg)
+ }
+
+ //子组件时间改变
+ const onTimePickerChange = (nowTimeRange) => {
+ setTimeRange(nowTimeRange);
+ }
+
useEffect(() => {
onGetOrgTree();
initMemberReport();
@@ -237,60 +242,19 @@ export default function Index() {
return (
- {showLoading ? : null}
-
-
-
- {
- let tempDate = [
- moment(moment(new Date(dateStrings[0])).format('YYYY-MM-DD 00:00:00')),
- moment(moment(new Date(dateStrings[1])).format('YYYY-MM-DD 23:59:59')),
- ]
- setTimeRange(tempDate);
- }} />
-
-
- onChangeTime(0)}>
- 今天
-
- onChangeTime(1)}>
- 昨天
-
- onChangeTime(2)}>
- 近7天
-
- onChangeTime(3)}>
- 近30天
-
-
-
- {
- if (node.type === 2 || node === 3) {
- setCurrentOrg(node);
- } else {
- setCurrentOrg("");
- }
- }}
- placeholder="请选择组织架构"
- treeDefaultExpandAll
- />
-
-
-
-
-
-
-
-
-
+
+
diff --git a/src/pages/order/order-product-report/index.jsx b/src/pages/order/order-product-report/index.jsx
index 253aa3b..3fd206f 100644
--- a/src/pages/order/order-product-report/index.jsx
+++ b/src/pages/order/order-product-report/index.jsx
@@ -1,28 +1,259 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
-import { Button, Card, DatePicker } from 'antd';
+import { Card, Col, Row, message } from 'antd';
+import ConditionQuery from "../../../components/ConditionQuery";
+import * as echarts from 'echarts';
+import moment from 'moment';
import styles from './index.less';
-const { RangePicker } = DatePicker;
+import productAPI from "./service";
/**
* 产品报表
* @returns
*/
export default function Index() {
+ //日期选择下标:0:今天、1:昨天、2:近7天、3、近30天
+ const [searchDayIndex, setSearchDayIndex] = useState(0);
+ //日期选择器
+ const [timeRange, setTimeRange] = useState([
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59'))
+ ]);
+ //组织树
+ const [orgTree, setOrgTree] = useState([]);
+ //加载中
+ const [showLoading, setShowLoading] = useState(false);
+ //当前选中门店
+ const [currentOrg, setCurrentOrg] = useState("");
+ //产品Top
+ const [topGoods, setTopGoods] = useState([]);
+
+ //热销商品折线图实例
+ let topGoodsLine = null;
+ //热销商品柱状图实例
+ let topGoodsBar = null;
+
+ //切换时间
+ const onChangeTimeIndex = (dayIndex) => {
+ setSearchDayIndex(dayIndex);
+ let tempDate = [];
+ switch (dayIndex) {
+ case 0:
+ tempDate = [
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59'))
+ ]
+ break;
+ case 1:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000)).format('YYYY-MM-DD 23:59:59'))
+ ]
+ break;
+ case 2:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000 * 7)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59')),
+ ]
+ break;
+ case 3:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000 * 30)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59')),
+ ]
+ break;
+ }
+ setTimeRange(tempDate);
+ }
+
+ //获取组织树
+ const onGetOrgTree = async () => {
+ setShowLoading(true);
+ const response = await productAPI.getOrgTree();
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ const originTree = response.data;
+ onSetOrgTreeStatus(originTree);
+ setOrgTree(originTree);
+ } else {
+ message.error(response.errors || '获取组织树出错');
+ }
+ }
+
+ //设置组织树不可选择状态
+ const onSetOrgTreeStatus = (originTree) => {
+ originTree.forEach(treeItem => {
+ if (treeItem.children && treeItem.children.length > 0) {
+ onSetOrgTreeStatus(treeItem.children);
+ } else {
+ if (treeItem.type === 2 || treeItem.type === 3) {
+ treeItem.disabled = false;
+ } else {
+ treeItem.disabled = true;
+ }
+ }
+ });
+ }
+
+ //重置
+ const onResetSearch = () => {
+ setCurrentOrg("");
+ }
+
+ //子组件切换组织架构
+ const onCurrentOrgChange = (curOrg) => {
+ setCurrentOrg(curOrg)
+ }
+
+ //子组件时间改变
+ const onTimePickerChange = (nowTimeRange) => {
+ setTimeRange(nowTimeRange);
+ }
+
+ //获取热销产品数据
+ const onGetTopGoods = async () => {
+ const jsonData = {
+ "top": 10,
+ "shopIds": [
+ currentOrg.key
+ ],
+ "startTime": timeRange[0],
+ "endTime": timeRange[1]
+ }
+ setShowLoading(true);
+ const response = await productAPI.getProductEcharts(jsonData);
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setTopGoods(response.data.topGoods);
+ } else {
+ message.error(response.errors || '获取热销产品数据出错')
+ }
+ }
+
+ //初始化热销商品柱状图
+ const initHotTopGoods = () => {
+ const chartDom = document.getElementById('top-goods');
+ topGoodsBar = echarts.init(chartDom);
+ const xData = [];
+ const seriesData = [];
+ topGoods.forEach(item => {
+ xData.push(item.name);
+ seriesData.push(item.count);
+ });
+ const option = {
+ title: {
+ show: true,
+ text: '热销商品'
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ label: {
+ show: true,
+ formatter: '热销商品'
+ }
+ }
+ },
+ xAxis: {
+ type: 'category',
+ data: xData
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ data: seriesData,
+ type: 'bar',
+ showBackground: true,
+ backgroundStyle: {
+ color: 'rgba(180, 180, 180, 0.2)'
+ }
+ }
+ ]
+ };
+ option && topGoodsBar.setOption(option);
+ }
+
+ //初始化热销商品折线图
+ const initHotTopLine = () => {
+ const chartDom = document.getElementById('top-goods-line');
+ topGoodsLine = echarts.init(chartDom);
+ const option = {
+ title: {
+ show: true,
+ text: '热销商品'
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ label: {
+ show: true,
+ formatter: '热销商品'
+ }
+ }
+ },
+ xAxis: {
+ type: 'category',
+ data: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00']
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ data: [150, 230, 224, 218, 135, 147, 260],
+ type: 'line'
+ }
+ ]
+ };
+ option && topGoodsLine.setOption(option);
+ }
+
+ useEffect(() => {
+ onGetOrgTree();
+ onGetTopGoods();
+ }, []);
+
+ useEffect(() => {
+ initHotTopGoods();
+ initHotTopLine();
+ window.onresize = () => {
+ if (topGoodsLine && topGoodsBar) {
+ topGoodsLine.resize();
+ topGoodsBar.resize();
+ }
+ }
+ }, [topGoods]);
+
+
return (
-
-
-
-
- 产品报表
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
diff --git a/src/pages/order/order-product-report/index.less b/src/pages/order/order-product-report/index.less
index 74d0c92..37f49a0 100644
--- a/src/pages/order/order-product-report/index.less
+++ b/src/pages/order/order-product-report/index.less
@@ -1,16 +1,4 @@
-.data-search-card {
- margin-bottom: 20px;
+.top-goods , .top-goods-line{
+ width: 100%;
+ height: 300px;
}
-
-.data-search-box {
- display: flex;
- align-items: center;
- justify-content: space-between;
-}
-
-.search-btn-item {
- margin-left: 20px;
-}
-
-.table-card {
-}
\ No newline at end of file
diff --git a/src/pages/order/order-product-report/service.js b/src/pages/order/order-product-report/service.js
new file mode 100644
index 0000000..33db2fd
--- /dev/null
+++ b/src/pages/order/order-product-report/service.js
@@ -0,0 +1,18 @@
+import { request } from 'umi';
+
+export default {
+ //获取组织架构
+ getOrgTree() {
+ return request(`/kitchen/api/report-statistics/org-tree`, {
+ method: 'GET',
+ });
+ },
+
+ //获取产品报表
+ getProductEcharts(data) {
+ return request(`/kitchen/api/report-statistics/productc`, {
+ method: 'POST',
+ data
+ });
+ }
+};
From 29585760b56476e38ff739d3d71020746c03b6a8 Mon Sep 17 00:00:00 2001
From: yangwenhua <1289978696@qq.com>
Date: Wed, 6 Jul 2022 13:34:33 +0800
Subject: [PATCH 5/7] =?UTF-8?q?=E5=8F=96=E6=B6=88=E8=AE=A2=E5=8D=95?=
=?UTF-8?q?=E6=8A=A5=E8=A1=A8=E8=AF=A6=E6=83=85=E8=B7=AF=E7=94=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/app.jsx | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/app.jsx b/src/app.jsx
index 8ca8868..656335a 100644
--- a/src/app.jsx
+++ b/src/app.jsx
@@ -582,12 +582,6 @@ export async function getInitialState() {
component: './order/order-report',
access: 'k31',
},
- {
- name: '订单报表详情',
- path: '/order/order-report/order-report-detail',
- component: './order/order-report-detail',
- access: 'k31',
- },
{
name: '营收报表',
path: '/order/order-revenue-statement',
From b5e61e63e08c0d41212e2b06a57a6e4f30fb7575 Mon Sep 17 00:00:00 2001
From: yangwenhua <1289978696@qq.com>
Date: Wed, 6 Jul 2022 14:14:18 +0800
Subject: [PATCH 6/7] =?UTF-8?q?=E9=97=A8=E5=BA=97ID=E8=BD=AC=E5=90=8D?=
=?UTF-8?q?=E5=AD=97=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/pages/order/cost-of-sales/index.jsx | 24 +++++++++++++++----
.../order/gross-profit-store-sales/index.jsx | 19 ++++++++++++---
src/pages/order/sales-gross-profit/index.jsx | 19 ++++++++++++---
3 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/src/pages/order/cost-of-sales/index.jsx b/src/pages/order/cost-of-sales/index.jsx
index bcfce3c..e7ba857 100644
--- a/src/pages/order/cost-of-sales/index.jsx
+++ b/src/pages/order/cost-of-sales/index.jsx
@@ -33,6 +33,7 @@ export default function Index() {
//门店
const [storeIdArray, setStoreIdArray] = useState("");
const [storeSelect, setStoreSelect] = useState([]);
+ const [storeList, setStoreList] = useState([]);
//商品
const [goodsIdArray, setGoodsIdArray] = useState([]);
const [goodsIdSelect, setGoodsIdSelect] = useState([]);
@@ -52,9 +53,9 @@ export default function Index() {
dataIndex: 'storeId',
key: 'storeId',
render: (text) => {
- const findGoods = storeSelect.find(item => item.id === text);
+ const findGoods = storeList.find(item => item.key === text);
if (findGoods) {
- return {findGoods.name}
+ return {findGoods.title}
} else {
return 暂无门店名称
}
@@ -123,10 +124,11 @@ export default function Index() {
*/
const onQueryStoreList = async () => {
setShowLoading(true);
- const response = await costSalesAPI.gettree({});
+ const response = await costSalesAPI.gettree();
setShowLoading(false);
if (response.statusCode === 200) {
setStoreSelect(response.data);
+ setStoreList(treeArrayToFlat(response.data));
} else {
message.error('查询店铺列表失败');
}
@@ -135,7 +137,7 @@ export default function Index() {
//查询商品列表
const onQueryGoodsList = async () => {
setShowLoading(true);
- const response = await costSalesAPI.goodsList({});
+ const response = await costSalesAPI.goodsList();
setShowLoading(false);
if (response.statusCode === 200) {
setGoodsIdSelect(response.data);
@@ -147,7 +149,7 @@ export default function Index() {
//查询商品分类类型列表
const onQueryGoodsType = async () => {
setShowLoading(true);
- const response = await costSalesAPI.goodsTypeList({});
+ const response = await costSalesAPI.goodsTypeList();
setShowLoading(false);
if (response.statusCode === 200) {
setGoodsTypeSelect(response.data);
@@ -167,6 +169,18 @@ export default function Index() {
]);
}
+ //树形数据扁平化
+ const treeArrayToFlat = (tree, arr = []) => {
+ tree.forEach(item => {
+ const { children, ...props } = item;
+ arr.push(props);
+ if (children && children.length > 0) {
+ treeArrayToFlat(children, arr);
+ }
+ });
+ return arr;
+ }
+
useEffect(() => {
onQueryReportSalescost();
onQueryStoreList();
diff --git a/src/pages/order/gross-profit-store-sales/index.jsx b/src/pages/order/gross-profit-store-sales/index.jsx
index 2797e12..7ced9be 100644
--- a/src/pages/order/gross-profit-store-sales/index.jsx
+++ b/src/pages/order/gross-profit-store-sales/index.jsx
@@ -35,6 +35,7 @@ export default function Index() {
//门店
const [storeIdArray, setStoreIdArray] = useState([]);
const [storeSelect, setStoreSelect] = useState([]);
+ const [storeList, setStoreList] = useState([]);
const columns = [
{
@@ -42,13 +43,12 @@ export default function Index() {
dataIndex: 'storeId',
key: 'storeId',
render: (text) => {
- const findGoods = storeSelect.find(item => item.id === text);
+ const findGoods = storeList.find(item => item.key === text);
if (findGoods) {
- return {findGoods.name}
+ return {findGoods.title}
} else {
return 暂无门店名称
}
-
},
},
{
@@ -92,6 +92,7 @@ export default function Index() {
setShowLoading(false);
if (response.statusCode === 200) {
setStoreSelect(response.data);
+ setStoreList(treeArrayToFlat(response.data));
} else {
message.error('查询店铺列表失败');
}
@@ -106,6 +107,18 @@ export default function Index() {
]);
}
+ //树形数据扁平化
+ const treeArrayToFlat = (tree, arr = []) => {
+ tree.forEach(item => {
+ const { children, ...props } = item;
+ arr.push(props);
+ if (children && children.length > 0) {
+ treeArrayToFlat(children, arr);
+ }
+ });
+ return arr;
+ }
+
useEffect(() => {
onQueryReportSalescost();
onQueryStoreList();
diff --git a/src/pages/order/sales-gross-profit/index.jsx b/src/pages/order/sales-gross-profit/index.jsx
index 4eb682b..42c9305 100644
--- a/src/pages/order/sales-gross-profit/index.jsx
+++ b/src/pages/order/sales-gross-profit/index.jsx
@@ -33,6 +33,7 @@ export default function Index() {
//门店
const [storeIdArray, setStoreIdArray] = useState("");
const [storeSelect, setStoreSelect] = useState([]);
+ const [storeList, setStoreList] = useState([]);
//商品
const [goodsIdArray, setGoodsIdArray] = useState([]);
const [goodsIdSelect, setGoodsIdSelect] = useState([]);
@@ -46,13 +47,12 @@ export default function Index() {
dataIndex: 'storeId',
key: 'storeId',
render: (text) => {
- const findGoods = storeSelect.find(item => item.id === text);
+ const findGoods = storeList.find(item => item.key === text);
if (findGoods) {
- return {findGoods.name}
+ return {findGoods.title}
} else {
return 暂无门店名称
}
-
},
},
{
@@ -112,6 +112,7 @@ export default function Index() {
setShowLoading(false);
if (response.statusCode === 200) {
setStoreSelect(response.data);
+ setStoreList(treeArrayToFlat(response.data));
} else {
message.error('查询店铺列表失败');
}
@@ -152,6 +153,18 @@ export default function Index() {
]);
}
+ //树形数据扁平化
+ const treeArrayToFlat = (tree, arr = []) => {
+ tree.forEach(item => {
+ const { children, ...props } = item;
+ arr.push(props);
+ if (children && children.length > 0) {
+ treeArrayToFlat(children, arr);
+ }
+ });
+ return arr;
+ }
+
useEffect(() => {
onQueryReportSalescost();
onQueryStoreList();
From 0e56c696152c4d5891490793b0ac5291e7e8d1cc Mon Sep 17 00:00:00 2001
From: yangwenhua <1289978696@qq.com>
Date: Thu, 7 Jul 2022 10:35:19 +0800
Subject: [PATCH 7/7] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=90=A5=E9=94=80?=
=?UTF-8?q?=E6=8A=A5=E8=A1=A8=E3=80=81=E4=BC=98=E5=8C=96=E4=BC=9A=E5=91=98?=
=?UTF-8?q?=E3=80=81=E4=BA=A7=E5=93=81=E6=8A=A5=E8=A1=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
config/routes.js | 4 +-
src/app.jsx | 4 +-
src/pages/order/order-market-report/index.jsx | 2 +-
.../order/order-member-statement/index.jsx | 13 +
.../order/order-product-report/index.jsx | 10 +
.../order/order-revenue-statement/index.jsx | 289 +++++++++++++++++-
.../order/order-revenue-statement/index.less | 4 +-
.../order/order-revenue-statement/service.js | 17 ++
8 files changed, 321 insertions(+), 22 deletions(-)
create mode 100644 src/pages/order/order-revenue-statement/service.js
diff --git a/config/routes.js b/config/routes.js
index a5c011c..64dac7e 100644
--- a/config/routes.js
+++ b/config/routes.js
@@ -587,7 +587,7 @@ export default [
access: 'k31',
},
{
- name: '营销报表',
+ name: '营收报表',
path: '/order/order-market-report',
component: './order/order-market-report',
access: 'k31',
@@ -605,7 +605,7 @@ export default [
access: 'k31',
},
{
- name: '营收报表',
+ name: '营销报表',
path: '/order/order-revenue-statement',
component: './order/order-revenue-statement',
access: 'k31',
diff --git a/src/app.jsx b/src/app.jsx
index 656335a..5855dc4 100644
--- a/src/app.jsx
+++ b/src/app.jsx
@@ -571,7 +571,7 @@ export async function getInitialState() {
access: 'k32',
},
{
- name: '营销报表',
+ name: '营收报表',
path: '/order/order-market-report',
component: './order/order-market-report',
access: 'k31',
@@ -583,7 +583,7 @@ export async function getInitialState() {
access: 'k31',
},
{
- name: '营收报表',
+ name: '营销报表',
path: '/order/order-revenue-statement',
component: './order/order-revenue-statement',
access: 'k31',
diff --git a/src/pages/order/order-market-report/index.jsx b/src/pages/order/order-market-report/index.jsx
index b9403b5..ea52c2a 100644
--- a/src/pages/order/order-market-report/index.jsx
+++ b/src/pages/order/order-market-report/index.jsx
@@ -391,7 +391,7 @@ const LoadingCard = () => {
}
/**
- * 营销报表
+ * 营收报表
* @returns
*/
export default function Index() {
diff --git a/src/pages/order/order-member-statement/index.jsx b/src/pages/order/order-member-statement/index.jsx
index 38f1763..c0ca33d 100644
--- a/src/pages/order/order-member-statement/index.jsx
+++ b/src/pages/order/order-member-statement/index.jsx
@@ -149,6 +149,14 @@ export default function Index() {
title: {
text: '新增会员'
},
+ tooltip: {
+ trigger: 'axis'
+ },
+ toolbox: {
+ feature: {
+ saveAsImage: {}
+ }
+ },
xAxis: {
type: 'category',
data: xAxisData
@@ -191,6 +199,11 @@ export default function Index() {
}
}
},
+ toolbox: {
+ feature: {
+ saveAsImage: {}
+ }
+ },
xAxis: {
type: 'category',
data: xAxisData
diff --git a/src/pages/order/order-product-report/index.jsx b/src/pages/order/order-product-report/index.jsx
index 3fd206f..17a3110 100644
--- a/src/pages/order/order-product-report/index.jsx
+++ b/src/pages/order/order-product-report/index.jsx
@@ -154,6 +154,11 @@ export default function Index() {
}
}
},
+ toolbox: {
+ feature: {
+ saveAsImage: {}
+ }
+ },
xAxis: {
type: 'category',
data: xData
@@ -184,6 +189,11 @@ export default function Index() {
show: true,
text: '热销商品'
},
+ toolbox: {
+ feature: {
+ saveAsImage: {}
+ }
+ },
tooltip: {
trigger: 'axis',
axisPointer: {
diff --git a/src/pages/order/order-revenue-statement/index.jsx b/src/pages/order/order-revenue-statement/index.jsx
index c2e0ebd..1d325ba 100644
--- a/src/pages/order/order-revenue-statement/index.jsx
+++ b/src/pages/order/order-revenue-statement/index.jsx
@@ -1,28 +1,285 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
-import { Button, Card, DatePicker } from 'antd';
+import { Card, Col, Row, message } from 'antd';
+import ConditionQuery from "../../../components/ConditionQuery";
+import * as echarts from 'echarts';
+import moment from 'moment';
import styles from './index.less';
-const { RangePicker } = DatePicker;
+import reportAPI from "./service";
/**
- * 营收报表
+ * 营销报表
* @returns
*/
export default function Index() {
+ //日期选择下标:0:今天、1:昨天、2:近7天、3、近30天
+ const [searchDayIndex, setSearchDayIndex] = useState(0);
+ //日期选择器
+ const [timeRange, setTimeRange] = useState([
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59'))
+ ]);
+ //组织树
+ const [orgTree, setOrgTree] = useState([]);
+ //加载中
+ const [showLoading, setShowLoading] = useState(false);
+ //当前选中门店
+ const [currentOrg, setCurrentOrg] = useState("");
+ //营销活动
+ const [reportActivity, setReportActivity] = useState([]);
+ //营销优惠券
+ const [reportCoupon, setReportCoupon] = useState([]);
+
+ //活动报表图表实例
+ let activityEcharts = null;
+ //优惠券报表图表实例
+ let couponEcharts = null;
+
+ //切换时间
+ const onChangeTimeIndex = (dayIndex) => {
+ setSearchDayIndex(dayIndex);
+ let tempDate = [];
+ switch (dayIndex) {
+ case 0:
+ tempDate = [
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59'))
+ ]
+ break;
+ case 1:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000)).format('YYYY-MM-DD 23:59:59'))
+ ]
+ break;
+ case 2:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000 * 7)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59')),
+ ]
+ break;
+ case 3:
+ tempDate = [
+ moment(moment(new Date(Date.now() - 24 * 60 * 60 * 1000 * 30)).format('YYYY-MM-DD 00:00:00')),
+ moment(moment(new Date(Date.now())).format('YYYY-MM-DD 23:59:59')),
+ ]
+ break;
+ }
+ setTimeRange(tempDate);
+ }
+
+ //获取组织树
+ const onGetOrgTree = async () => {
+ setShowLoading(true);
+ const response = await reportAPI.getOrgTree();
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ const originTree = response.data;
+ onSetOrgTreeStatus(originTree);
+ setOrgTree(originTree);
+ } else {
+ message.error(response.errors || '获取组织树出错');
+ }
+ }
+
+ //设置组织树不可选择状态
+ const onSetOrgTreeStatus = (originTree) => {
+ originTree.forEach(treeItem => {
+ if (treeItem.children && treeItem.children.length > 0) {
+ onSetOrgTreeStatus(treeItem.children);
+ } else {
+ if (treeItem.type === 2 || treeItem.type === 3) {
+ treeItem.disabled = false;
+ } else {
+ treeItem.disabled = true;
+ }
+ }
+ });
+ }
+
+ //重置
+ const onResetSearch = () => {
+ setCurrentOrg("");
+ }
+
+ //子组件切换组织架构
+ const onCurrentOrgChange = (curOrg) => {
+ setCurrentOrg(curOrg)
+ }
+
+ //子组件时间改变
+ const onTimePickerChange = (nowTimeRange) => {
+ setTimeRange(nowTimeRange);
+ }
+
+ //获取营销报表列表
+ const onQueryMarketing = async () => {
+ setShowLoading(true);
+ const response = await reportAPI.getReportStatisticsMarketing();
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setReportActivity(response.data.activity);
+ setReportCoupon(response.data.coupon);
+ } else {
+ message.error(response.errors || '获取营销报表列表出错');
+ }
+ }
+
+ //生成营销报表活动信息柱状图
+ const initActivityEcharts = () => {
+ const chartDom = document.getElementById('activity-echarts');
+ activityEcharts = echarts.init(chartDom);
+ const xAxisData = [];
+ const seriesData = [];
+ reportActivity.forEach(item => {
+ xAxisData.push(item.activityName);
+ seriesData.push(item.numberParticipants);
+ });
+ const option = {
+ title: {
+ text: '活动报表'
+ },
+ tooltip: {
+ trigger: 'axis'
+ },
+ toolbox: {
+ feature: {
+ saveAsImage: {}
+ }
+ },
+ xAxis: {
+ type: 'category',
+ data: xAxisData
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ data: seriesData,
+ type: 'bar',
+ showBackground: true,
+ backgroundStyle: {
+ color: 'rgba(180, 180, 180, 0.2)'
+ }
+ }
+ ]
+ };
+
+ option && activityEcharts.setOption(option);
+ }
+
+ //生成优惠券报表折线图
+ const initCouponEcharts = () => {
+ const chartDom = document.getElementById('coupon-ehcarts');
+ couponEcharts = echarts.init(chartDom);
+ const xAxisData = [];
+ const seriesPreferentialAmount = [];
+ const seriesSend = [];
+ const seriesGet = [];
+ reportCoupon.forEach(item => {
+ xAxisData.push(item.couponName);
+ seriesPreferentialAmount.push(item.preferentialAmount);
+ seriesSend.push(item.send);
+ seriesGet.push(item.get);
+ });
+ const option = {
+ title: {
+ text: '优惠券报表'
+ },
+ tooltip: {
+ trigger: 'axis'
+ },
+ legend: {
+ data: ['优惠金额', '发放数量', '领取数量']
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ toolbox: {
+ feature: {
+ saveAsImage: {}
+ }
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: xAxisData
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ name: '优惠金额',
+ type: 'line',
+ stack: 'Total',
+ data: seriesPreferentialAmount
+ },
+ {
+ name: '发放数量',
+ type: 'line',
+ stack: 'Total',
+ data: seriesSend
+ },
+ {
+ name: '领取数量',
+ type: 'line',
+ stack: 'Total',
+ data: seriesGet
+ }
+ ]
+ };
+ option && couponEcharts.setOption(option);
+ }
+
+ useEffect(() => {
+ onGetOrgTree();
+ onQueryMarketing();
+ }, []);
+
+ useEffect(() => {
+ initActivityEcharts();
+ initCouponEcharts();
+ window.onresize = () => {
+ if (activityEcharts && couponEcharts) {
+ activityEcharts.resize();
+ couponEcharts.resize();
+ }
+ }
+ }, [reportActivity, reportCoupon]);
+
+
return (
-
-
-
-
- 营收报表
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
diff --git a/src/pages/order/order-revenue-statement/index.less b/src/pages/order/order-revenue-statement/index.less
index 74d0c92..1fcef07 100644
--- a/src/pages/order/order-revenue-statement/index.less
+++ b/src/pages/order/order-revenue-statement/index.less
@@ -12,5 +12,7 @@
margin-left: 20px;
}
-.table-card {
+.activity-echarts, .coupon-ehcarts {
+ width: 100%;
+ height: 300px;
}
\ No newline at end of file
diff --git a/src/pages/order/order-revenue-statement/service.js b/src/pages/order/order-revenue-statement/service.js
new file mode 100644
index 0000000..a079fa0
--- /dev/null
+++ b/src/pages/order/order-revenue-statement/service.js
@@ -0,0 +1,17 @@
+import { request } from 'umi';
+
+export default {
+ //获取组织架构
+ getOrgTree() {
+ return request(`/kitchen/api/report-statistics/org-tree`, {
+ method: 'GET',
+ });
+ },
+
+ //获取营销报表
+ getReportStatisticsMarketing() {
+ return request(`/kitchen/api/report-statistics/marketing`, {
+ method: 'POST',
+ });
+ }
+};