diff --git a/config/routes.js b/config/routes.js
index 4fec1eb..a5c011c 100644
--- a/config/routes.js
+++ b/config/routes.js
@@ -586,6 +586,60 @@ export default [
component: './order/exOrder',
access: 'k31',
},
+ {
+ name: '营销报表',
+ path: '/order/order-market-report',
+ component: './order/order-market-report',
+ access: 'k31',
+ },
+ {
+ name: '订单报表',
+ path: '/order/order-report',
+ 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',
+ component: './order/order-revenue-statement',
+ access: 'k31',
+ },
+ {
+ name: '产品报表',
+ path: '/order/order-product-report',
+ component: './order/order-product-report',
+ access: 'k31',
+ },
+ {
+ name: '会员报表',
+ path: '/order/order-member-statement',
+ component: './order/order-member-statement',
+ access: 'k31',
+ },
+ {
+ name: '销售成本分析',
+ path: '/order/cost-of-sales',
+ component: './order/cost-of-sales',
+ access: 'k31',
+ },
+ {
+ name: '销售毛利分析',
+ path: '/order/sales-gross-profit',
+ component: './order/sales-gross-profit',
+ access: 'k31',
+ },
+ {
+ name: '门店销售毛利分析',
+ path: '/order/gross-profit-store-sales',
+ component: './order/gross-profit-store-sales',
+ access: 'k31',
+ },
],
},
{
diff --git a/src/pages/order/cost-of-sales/index.jsx b/src/pages/order/cost-of-sales/index.jsx
new file mode 100644
index 0000000..f815970
--- /dev/null
+++ b/src/pages/order/cost-of-sales/index.jsx
@@ -0,0 +1,245 @@
+import React, { useState, useEffect } from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Button, Card, DatePicker, Table, Pagination, Spin, Select, message } from 'antd';
+import styles from './index.less';
+const { RangePicker } = DatePicker;
+import costSalesAPI from "./service";
+import moment from 'moment';
+
+const columns = [
+ {
+ title: '门店名称',
+ dataIndex: 'storeId',
+ key: 'storeId',
+ },
+ {
+ title: '商品名称',
+ dataIndex: 'goodsId',
+ key: 'goodsId',
+ },
+ {
+ title: '销售收入',
+ dataIndex: 'salesPrice',
+ key: 'salesPrice',
+ },
+ {
+ title: '销售成本',
+ dataIndex: 'costPrice',
+ key: 'costPrice',
+ },
+ {
+ title: '销售数量',
+ dataIndex: 'salesNum',
+ key: 'salesNum',
+ },
+ {
+ title: '成本率',
+ dataIndex: 'costRate',
+ key: 'costRate',
+ }
+];
+
+const LoadingCard = () => {
+ return (
+
+
+
+ )
+}
+
+/**
+ * 销售成本分析
+ * @returns
+ */
+export default function Index() {
+
+ //订单报表列表
+ const [costSalesData, setCostSalesData] = useState([]);
+ const [current, setCurrent] = useState(1);
+ const [pageSize, setPageSize] = useState(10);
+ const [total, setTotal] = useState(0);
+ const [showLoading, setShowLoading] = useState(false);
+ const [timeRange, setTimeRange] = useState([
+ 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')),
+ ]); //日期选择器
+ //门店
+ const [storeIdArray, setStoreIdArray] = useState([]);
+ const [storeSelect, setStoreSelect] = useState([]);
+ //商品
+ const [goodsIdArray, setGoodsIdArray] = useState([]);
+ const [goodsIdSelect, setGoodsIdSelect] = useState([]);
+ //商品类型
+ const [goodsTypeArray, setGoodsTypeArray] = useState([]);
+ const [goodsTypeSelect, setGoodsTypeSelect] = useState([]);
+
+ //页码变化
+ const onPageChange = (current, pageSize) => {
+ setCurrent(current);
+ setPageSize(pageSize);
+ }
+
+ //查询
+ const onQueryReportSalescost = async () => {
+ const jsonData = {
+ "storeId": storeIdArray,
+ "goodsId": goodsIdArray,
+ "goodsTypeId": goodsTypeArray,
+ "begintime": timeRange[0],
+ "endtime": timeRange[1],
+ current,
+ pageSize
+ }
+ setShowLoading(true);
+ const response = await costSalesAPI.getReportSalescost({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setCostSalesData(response.data.data);
+ } else {
+ message.error(response.errors || '获取销售成本失败');
+ }
+ }
+
+ /**
+ * 查询店铺列表
+ */
+ const onQueryStoreList = async () => {
+ setShowLoading(true);
+ const response = await costSalesAPI.gettree({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ const storeList = [];
+ response.data.forEach(item => {
+ if (item.type === 2 || item.type === 3) {
+ storeList.push(item)
+ }
+ })
+ setStoreSelect(storeList);
+ } else {
+ message.error('查询店铺列表失败');
+ }
+ }
+
+ //查询商品列表
+ const onQueryGoodsList = async () => {
+ setShowLoading(true);
+ const response = await costSalesAPI.goodsList({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setGoodsIdSelect(response.data);
+ } else {
+ message.error('查询商品列表失败');
+ }
+ }
+
+ //查询商品分类类型列表
+ const onQueryGoodsType = async () => {
+ setShowLoading(true);
+ const response = await costSalesAPI.goodsTypeList({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setGoodsTypeSelect(response.data);
+ } else {
+ message.error('查询商品分类列表失败');
+ }
+ }
+
+ useEffect(() => {
+ onQueryReportSalescost();
+ onQueryStoreList();
+ onQueryGoodsList();
+ onQueryGoodsType();
+ }, []);
+
+ 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);
+ }} />
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/pages/order/cost-of-sales/index.less b/src/pages/order/cost-of-sales/index.less
new file mode 100644
index 0000000..c33fc6a
--- /dev/null
+++ b/src/pages/order/cost-of-sales/index.less
@@ -0,0 +1,36 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.data-search-box {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.search-btn-item {
+ margin-left: 20px;
+}
+
+.table-page {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ height: 50px;
+}
+
+// 加载中
+.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);
+}
\ No newline at end of file
diff --git a/src/pages/order/cost-of-sales/service.js b/src/pages/order/cost-of-sales/service.js
new file mode 100644
index 0000000..bb2fdb4
--- /dev/null
+++ b/src/pages/order/cost-of-sales/service.js
@@ -0,0 +1,40 @@
+import { request } from 'umi';
+
+export default {
+ getReportSalescost(data) {
+ return request(`/kitchen/api/report/salescost`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+ /**
+ * 查询商品信息
+ */
+ goodsList(data) {
+ return request(`/kitchen/api/goodes/list`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+ /**
+ * 查询商品类型
+ */
+ goodsTypeList(data) {
+ return request(`/kitchen/api/goodstype/list`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+
+ /**
+ * 查询门店列表
+ */
+ gettree(params) {
+ return request('/kitchen/api/sysOrg/tree', {
+ data: {
+ ...params,
+ },
+ });
+ }
+
+};
diff --git a/src/pages/order/gross-profit-store-sales/index.jsx b/src/pages/order/gross-profit-store-sales/index.jsx
new file mode 100644
index 0000000..5d5b1f7
--- /dev/null
+++ b/src/pages/order/gross-profit-store-sales/index.jsx
@@ -0,0 +1,149 @@
+import React, { useState, useEffect } from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Button, Card, DatePicker, Table, Pagination, Spin, Select, message } from 'antd';
+import styles from './index.less';
+const { RangePicker } = DatePicker;
+import costSalesAPI from "./service";
+import moment from 'moment';
+
+const columns = [
+ {
+ title: '门店名称',
+ dataIndex: 'storeId',
+ key: 'storeId',
+ },
+ {
+ title: '毛利率',
+ dataIndex: 'marginRatio',
+ key: 'marginRatio',
+ }
+];
+
+const LoadingCard = () => {
+ return (
+
+
+
+ )
+}
+
+/**
+ * 门店销售毛利分析
+ * @returns
+ */
+export default function Index() {
+
+ //订单报表列表
+ const [costSalesData, setCostSalesData] = useState([]);
+ const [current, setCurrent] = useState(1);
+ const [pageSize, setPageSize] = useState(10);
+ const [total, setTotal] = useState(0);
+ const [showLoading, setShowLoading] = useState(false);
+ const [timeRange, setTimeRange] = useState([
+ 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')),
+ ]); //日期选择器
+ //门店
+ const [storeIdArray, setStoreIdArray] = useState([]);
+ const [storeSelect, setStoreSelect] = useState([]);
+
+ //页码变化
+ const onPageChange = (current, pageSize) => {
+ setCurrent(current);
+ setPageSize(pageSize);
+ }
+
+ //查询
+ const onQueryReportSalescost = async () => {
+ const jsonData = {
+ "storeId": storeIdArray,
+ "begintime": timeRange[0],
+ "endtime": timeRange[1],
+ current,
+ pageSize
+ }
+ setShowLoading(true);
+ const response = await costSalesAPI.getReportOrgsalesmargin({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setCostSalesData(response.data.data);
+ } else {
+ message.error(response.errors || '获取销售成本失败');
+ }
+ }
+
+ /**
+ * 查询店铺列表
+ */
+ const onQueryStoreList = async () => {
+ setShowLoading(true);
+ const response = await costSalesAPI.gettree({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ const storeList = [];
+ response.data.forEach(item => {
+ if (item.type === 2 || item.type === 3) {
+ storeList.push(item)
+ }
+ })
+ setStoreSelect(storeList);
+ } else {
+ message.error('查询店铺列表失败');
+ }
+ }
+
+ useEffect(() => {
+ onQueryReportSalescost();
+ onQueryStoreList();
+ }, []);
+
+ 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);
+ }} />
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/pages/order/gross-profit-store-sales/index.less b/src/pages/order/gross-profit-store-sales/index.less
new file mode 100644
index 0000000..c33fc6a
--- /dev/null
+++ b/src/pages/order/gross-profit-store-sales/index.less
@@ -0,0 +1,36 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.data-search-box {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.search-btn-item {
+ margin-left: 20px;
+}
+
+.table-page {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ height: 50px;
+}
+
+// 加载中
+.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);
+}
\ No newline at end of file
diff --git a/src/pages/order/gross-profit-store-sales/service.js b/src/pages/order/gross-profit-store-sales/service.js
new file mode 100644
index 0000000..d25abba
--- /dev/null
+++ b/src/pages/order/gross-profit-store-sales/service.js
@@ -0,0 +1,21 @@
+import { request } from 'umi';
+
+export default {
+ getReportOrgsalesmargin(data) {
+ return request(`/kitchen/api/report/orgsalesmargin`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+
+ /**
+ * 查询门店列表
+ */
+ gettree(params) {
+ return request('/kitchen/api/sysOrg/tree', {
+ data: {
+ ...params,
+ },
+ });
+ }
+};
diff --git a/src/pages/order/order-market-report/index.jsx b/src/pages/order/order-market-report/index.jsx
new file mode 100644
index 0000000..b9403b5
--- /dev/null
+++ b/src/pages/order/order-market-report/index.jsx
@@ -0,0 +1,591 @@
+import React, { useEffect, useState } from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { DownloadOutlined } from '@ant-design/icons';
+import { Button, Table, Card, DatePicker, message, Pagination, Spin, TreeSelect } from 'antd';
+import styles from './index.less';
+import moment from 'moment';
+import marketAPI from "./service";
+import ExportJsonExcel from "js-export-excel"
+
+const { TreeNode } = TreeSelect;
+const { RangePicker } = DatePicker;
+const columns = [
+ {
+ title: '时间',
+ dataIndex: 'date',
+ key: 'date',
+ width: 170,
+ align: 'center',
+ fixed: 'left'
+ },
+ {
+ title: '店铺',
+ dataIndex: 'shopName',
+ key: 'shopName',
+ width: 170,
+ align: 'center',
+ fixed: 'left',
+ filters: [
+ {
+ text: '四川黑菠萝科技',
+ value: '四川黑菠萝科技',
+ },
+ {
+ text: '四川白菠萝科技',
+ value: '四川白菠萝科技',
+ }
+ ],
+ onFilter: (value, record) => record.shopName.indexOf(value) === 0,
+ },
+ {
+ title: '营收',
+ dataIndex: 'revenue',
+ key: 'revenue',
+ children: [
+ {
+ title: '营业额',
+ dataIndex: 'turnover',
+ key: 'turnover',
+ children: [
+ {
+ title: '流水',
+ dataIndex: 'revenueFlow',
+ key: 'revenueFlow',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '实收',
+ dataIndex: 'paidAmount',
+ key: 'paidAmount',
+ width: 100,
+ align: 'center',
+ },
+ ]
+ },
+ {
+ title: '优惠明细',
+ dataIndex: 'discountDetails',
+ key: 'discountDetails',
+ children: [
+ {
+ title: '会员价',
+ dataIndex: 'discountMember',
+ key: 'discountMember',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '优惠券',
+ dataIndex: 'discountCoupon',
+ key: 'discountCoupon',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '活动',
+ dataIndex: 'discountActivity',
+ key: 'discountActivity',
+ width: 100,
+ align: 'center',
+ }
+ ]
+ },
+ ]
+ },
+ {
+ title: '分类营收',
+ dataIndex: 'classifiedRevenue',
+ key: 'classifiedRevenue',
+ children: [
+ {
+ title: '外卖营业额',
+ dataIndex: 'takeOutTurnover',
+ key: 'takeOutTurnover',
+ children: [
+ {
+ title: '外卖营收',
+ dataIndex: 'takeOutRevenue',
+ key: 'takeOutRevenue',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '美团外卖',
+ dataIndex: 'meituanTakeout',
+ key: 'meituanTakeout',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '饿了么外卖',
+ dataIndex: 'hungryTakeOut',
+ key: 'hungryTakeOut',
+ width: 100,
+ align: 'center',
+ },
+ ]
+ },
+ {
+ title: '食堂营收',
+ dataIndex: 'canteenRevenue',
+ key: 'canteenRevenue',
+ children: [
+ {
+ title: '堂食流水',
+ dataIndex: 'freshWaterInTheHall',
+ key: 'freshWaterInTheHall',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '堂食实收',
+ dataIndex: 'paidInFood',
+ key: 'paidInFood',
+ width: 100,
+ align: 'center',
+ }
+ ]
+ },
+ {
+ title: '第三方平台营收',
+ dataIndex: 'thirdPartyPlatformRevenue',
+ key: 'thirdPartyPlatformRevenue',
+ children: [
+ {
+ title: '大众点评',
+ dataIndex: 'publicComments',
+ key: 'publicComments',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '口碑',
+ dataIndex: 'wordOfMouth',
+ key: 'wordOfMouth',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '抖音',
+ dataIndex: 'tiktok',
+ key: 'tiktok',
+ width: 100,
+ align: 'center',
+ }
+ ]
+ },
+ ]
+ },
+ {
+ title: '堂食单价',
+ dataIndex: 'unitPriceCanteenFood',
+ key: 'unitPriceCanteenFood',
+ children: [
+ {
+ title: '客单价',
+ dataIndex: 'customerUnitPrice',
+ key: 'customerUnitPrice',
+ children: [
+ {
+ title: '流水单价',
+ dataIndex: 'customerRevenueFlow',
+ key: 'customerRevenueFlow',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '实收单价',
+ dataIndex: 'customerPaidAmount',
+ key: 'customerPaidAmount',
+ width: 100,
+ align: 'center',
+ }
+ ]
+ },
+ {
+ title: '单单价',
+ dataIndex: 'singleUnitPrice',
+ key: 'singleUnitPrice',
+ children: [
+ {
+ title: '流水单价',
+ dataIndex: 'orderRevenueFlow',
+ key: 'orderRevenueFlow',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '实收单价',
+ dataIndex: 'orderPaidAmount',
+ key: 'orderPaidAmount',
+ width: 100,
+ align: 'center',
+ }
+ ]
+ },
+ ]
+ },
+ {
+ title: '交易笔数',
+ dataIndex: 'numberOfTransactions',
+ key: 'numberOfTransactions',
+ children: [
+ {
+ title: '现金',
+ dataIndex: 'sourceCashCount',
+ key: 'sourceCashCount',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '微信支付',
+ dataIndex: 'sourceWeChatCount',
+ key: 'sourceWeChatCount',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '大众点评',
+ dataIndex: 'numPublicComments',
+ key: 'numPublicComments',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '口碑',
+ dataIndex: 'numWordOfMouth',
+ key: 'numWordOfMouth',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '抖音',
+ dataIndex: 'numTiktok',
+ key: 'numTiktok',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '美团外卖',
+ dataIndex: 'numMeituanTakeout',
+ key: 'numMeituanTakeout',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '饿了么外卖',
+ dataIndex: 'numHungryTakeOut',
+ key: 'numHungryTakeOut',
+ width: 100,
+ align: 'center',
+ },
+ ]
+ },
+ {
+ title: '收入构成',
+ dataIndex: 'revenueComposition',
+ key: 'revenueComposition',
+ children: [
+ {
+ title: '收入来源',
+ dataIndex: 'sourceOfIncome',
+ key: 'sourceOfIncome',
+ children: [
+ {
+ title: '会员',
+ dataIndex: 'memberIncomeMoney',
+ key: 'memberIncomeMoney',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '非会员',
+ dataIndex: 'nonMemberIncomeMoney',
+ key: 'nonMemberIncomeMoney',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '外卖',
+ dataIndex: 'incomeTakeOut',
+ key: 'incomeTakeOut',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '团购',
+ dataIndex: 'incomeGroupPurchase',
+ key: 'incomeGroupPurchase',
+ width: 100,
+ align: 'center',
+ },
+ ]
+ },
+ {
+ title: '收入结构',
+ dataIndex: 'revenueStructure',
+ key: 'revenueStructure',
+ children: [
+ {
+ title: '微信支付',
+ dataIndex: 'sourceWeChatMoney',
+ key: 'sourceWeChatMoney',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '现金支付',
+ dataIndex: 'sourceCashMoney',
+ key: 'sourceCashMoney',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '大众点评',
+ dataIndex: 'incomePublicComments',
+ key: 'incomePublicComments',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '口碑',
+ dataIndex: 'incomeWordOfMouth',
+ key: 'incomeWordOfMouth',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '抖音',
+ dataIndex: 'incomeTiktok',
+ key: 'incomeTiktok',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '美团外卖',
+ dataIndex: 'incomeMeituan',
+ key: 'incomeMeituan',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '饿了么外卖',
+ dataIndex: 'incomeHungry',
+ key: 'incomeHungry',
+ width: 100,
+ align: 'center',
+ },
+ ]
+ },
+ ]
+ }
+]
+
+const LoadingCard = () => {
+ return (
+
+
+
+ )
+}
+
+/**
+ * 营销报表
+ * @returns
+ */
+export default function Index() {
+
+ const [data, setData] = useState([]);
+ const [current, setCurrent] = useState(1);
+ const [pageSize, setPageSize] = useState(10);
+ const [total, setTotal] = useState(0);
+ const [orgTree, setOrgTree] = useState([]);
+ const [showLoading, setShowLoading] = useState(false);
+ const [timeRange, setTimeRange] = useState([
+ 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')),
+ ]); //日期选择器
+ const [currentOrg, setCurrentOrg] = useState('');
+
+ useEffect(() => {
+ queryMarketReport();
+ }, [current, pageSize, timeRange]);
+
+ useEffect(() => {
+ onGetOrgTree();
+ }, []);
+
+ //计算总计
+ const calcTotal = () => {
+ const originData = JSON.parse(JSON.stringify(data));
+ const totalData = {}
+ data.forEach(dataObj => {
+ Object.keys(dataObj).forEach(key => {
+ if (key === 'date') {
+ totalData.date = '合计';
+ } else if (key == 'shopName') {
+ totalData.shopName = '';
+ } else if (typeof dataObj[key] === 'number') {
+ if (totalData[key] && typeof totalData[key] === 'number') {
+ totalData[key] += dataObj[key];
+ } else {
+ totalData[key] = 0;
+ totalData[key] += dataObj[key];
+ }
+ } else {
+ totalData[key] = '暂无统计'
+ }
+ });
+ });
+ originData.push(totalData);
+ setData(originData);
+ }
+
+ const queryMarketReport = async () => {
+ const jsonData = {
+ startTime: timeRange[0],
+ endTime: timeRange[1],
+ current: current,
+ pageSize: pageSize
+ }
+ currentOrg.key && (jsonData.shopId = currentOrg.key);
+ setShowLoading(true);
+ const response = await marketAPI.getMarketReportList(jsonData);
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setData(response.data.data);
+ setTotal(response.data.total);
+ } else {
+ message.error(response.errors || '获取营销报表失败');
+ }
+ }
+
+ //页码变化
+ const onPageChange = (current, pageSize) => {
+ setCurrent(current);
+ setPageSize(pageSize);
+ }
+
+ //下载Excel
+ const onDownloadExcel = async () => {
+ const jsonData = {
+ startTime: timeRange[0],
+ endTime: timeRange[1],
+ }
+ currentOrg.key && (jsonData.shopId = currentOrg.key);
+ setShowLoading(true);
+ const response = await marketAPI.marketingReportExport(jsonData);
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ let option = {}; //option代表的就是excel文件
+ const date = new Date();
+ const excelName = "营销报表-" + date.toLocaleString().replaceAll('\/', '-');
+ option.fileName = excelName; //excel文件名称
+ const sheetHeader = [];
+ Object.keys(response.data[0]).forEach(item => {
+ sheetHeader.push(item);
+ });
+ console.log('sheetHeader', sheetHeader);
+ option.datas = [
+ {
+ sheetData: response.data, //excel文件中的数据源
+ sheetName: excelName, //excel文件中sheet页名称
+ sheetFilter: sheetHeader, //excel文件中需显示的列数据
+ sheetHeader: ['ID', '时间', '店铺名称', '店铺ID', '营收流水',
+ '实际营收', '会员折扣', '优惠券折扣', '活动折扣','客单价-流水单价', '客单价-实收单价',
+ '单单价-总流水', '单单价-总实收',
+ '现金-交易笔数', '现金收入', '微信-交易笔数', '微信收入', '会员收入', '非会员收入'
+ ] //excel文件中每列的表头名称
+ }
+ ]
+ let toExcel = new ExportJsonExcel(option); //生成excel文件
+ toExcel.saveExcel();
+ } else {
+ message.error(response.errors || '导出失败');
+ }
+ }
+
+ //获取组织树
+ 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;
+ }
+ }
+ });
+ }
+
+ 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);
+ }} />
+ {
+ if (node.type === 2 || node === 3) {
+ setCurrentOrg(node);
+ } else {
+ setCurrentOrg("");
+ }
+ }}
+ placeholder="请选择组织架构"
+ treeDefaultExpandAll
+ />
+
+
+
+ } size='middle' onClick={onDownloadExcel}>
+ 下载
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/pages/order/order-market-report/index.less b/src/pages/order/order-market-report/index.less
new file mode 100644
index 0000000..ed50ea4
--- /dev/null
+++ b/src/pages/order/order-market-report/index.less
@@ -0,0 +1,41 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.data-search-box {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.search-btn-item {
+ margin-left: 20px;
+}
+
+.table-page {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ height: 50px;
+}
+
+.data-search-left {
+ display: flex;
+ align-items: center;
+}
+
+// 加载中
+.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);
+}
\ No newline at end of file
diff --git a/src/pages/order/order-market-report/service.js b/src/pages/order/order-market-report/service.js
new file mode 100644
index 0000000..7820383
--- /dev/null
+++ b/src/pages/order/order-market-report/service.js
@@ -0,0 +1,26 @@
+import { request } from 'umi';
+
+export default {
+ //获取分页数据
+ getMarketReportList(data) {
+ return request(`/kitchen/api/report-statistics/marketing-report`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+
+ //获取组织架构
+ getOrgTree() {
+ return request(`/kitchen/api/report-statistics/org-tree`, {
+ method: 'GET',
+ });
+ },
+
+ //下载报表
+ marketingReportExport(data) {
+ return request(`/kitchen/api/report-statistics/marketing-report-export`, {
+ method: 'Post',
+ data: data,
+ });
+ }
+};
diff --git a/src/pages/order/order-member-statement/index.jsx b/src/pages/order/order-member-statement/index.jsx
new file mode 100644
index 0000000..8c62138
--- /dev/null
+++ b/src/pages/order/order-member-statement/index.jsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Button, Card, DatePicker } from 'antd';
+import styles from './index.less';
+const { RangePicker } = DatePicker;
+/**
+ * 会员报表
+ * @returns
+ */
+export default function Index() {
+
+ return (
+
+
+
+
+
+ 会员报表
+
+
+ )
+}
diff --git a/src/pages/order/order-member-statement/index.less b/src/pages/order/order-member-statement/index.less
new file mode 100644
index 0000000..74d0c92
--- /dev/null
+++ b/src/pages/order/order-member-statement/index.less
@@ -0,0 +1,16 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.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/index.jsx b/src/pages/order/order-product-report/index.jsx
new file mode 100644
index 0000000..253aa3b
--- /dev/null
+++ b/src/pages/order/order-product-report/index.jsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Button, Card, DatePicker } from 'antd';
+import styles from './index.less';
+const { RangePicker } = DatePicker;
+/**
+ * 产品报表
+ * @returns
+ */
+export default function Index() {
+
+ return (
+
+
+
+
+
+ 产品报表
+
+
+ )
+}
diff --git a/src/pages/order/order-product-report/index.less b/src/pages/order/order-product-report/index.less
new file mode 100644
index 0000000..74d0c92
--- /dev/null
+++ b/src/pages/order/order-product-report/index.less
@@ -0,0 +1,16 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.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-report-detail/index.jsx b/src/pages/order/order-report-detail/index.jsx
new file mode 100644
index 0000000..e3df461
--- /dev/null
+++ b/src/pages/order/order-report-detail/index.jsx
@@ -0,0 +1,245 @@
+import React, { useState, useEffect } from 'react';
+import { Button, Card, Image, Timeline, message, Tag } from 'antd';
+import styles from './index.less';
+import { ExclamationCircleOutlined, UserOutlined, RedEnvelopeOutlined, WhatsAppOutlined } from '@ant-design/icons';
+import { history } from 'umi';
+import orderReportAPI from "./service";
+import { PageContainer } from '@ant-design/pro-layout';
+
+const orderNumber = history.location.query.orderNumber;
+
+/**
+ * 订单详情
+ * @returns
+ */
+export default function Index() {
+
+ const [orderInfo, setOrderInfo] = useState({
+ memberInfo: {}, //用户信息
+ goodsInfo: [], //商品信息
+ informationRefundInfo: [], //售后信息
+ discountInfo: [] //优惠信息
+ });
+
+ const [orderStatus, setOrderStatus] = useState({
+ isTrue: true
+ });
+
+ const onQueryOrderDetail = async () => {
+ if (orderNumber) {
+ const response = await orderReportAPI.getOrderReporByNumber(orderNumber);
+ if (response.statusCode === 200) {
+ setOrderInfo(response.data);
+ orderIsNormal(response.data);
+ } else {
+ message.error(response.errors || '订单详情获取失败');
+ }
+ }
+ }
+
+ const orderIsNormal = (order) => {
+ let isNormal = {
+ isTrue: true,
+ msg: '正常订单'
+ };
+ if (!(order.payMoneyEx === '正常')) {
+ isNormal.isTrue = false;
+ isNormal.msg = '订单支付金额异常';
+ }
+ else if (!(order.payOrderTimeEx === '正常')) {
+ isNormal.isTrue = false;
+ isNormal.msg = '订单支付时间异常';
+ }
+ else if (!(order.payOrderEx === '正常')) {
+ isNormal.isTrue = false;
+ isNormal.msg = '订单支付异常';
+ }
+ else if (!(order.refundMoneyEx === '正常' || order.refundMoneyEx === '' || order.refundMoneyEx === null)) {
+ isNormal.isTrue = false;
+ isNormal.msg = '订单退款金额异常';
+ }
+ else if (!(order.refundOrderTimeEx === '正常' || order.refundOrderTimeEx === '' || order.refundOrderTimeEx === null)) {
+ isNormal.isTrue = false;
+ isNormal.msg = '订单退款时间异常';
+ }
+ else if (!(order.refundOrderEx === '正常' || order.refundOrderEx === '' || order.refundOrderEx === null)) {
+ isNormal.isTrue = false;
+ isNormal.msg = '订单退款异常';
+ }
+ console.log('isNormal', isNormal);
+ setOrderStatus(isNormal);
+ }
+
+ useEffect(() => {
+ onQueryOrderDetail();
+ }, []);
+
+ return (
+
+
+ {/* 用户基本信息 */}
+
+
+
+ #{orderInfo.sortId}
+
+
+ {
+ orderStatus.isTrue ?
正常订单
:
{orderStatus.msg}
+ }
+
+
+ {orderInfo.createdAt}
+
+
+
+
+
+
+
+
+ {orderInfo.memberInfo.memberName || '系统用户'}
+
+
+ #门店新客
+ #门店会员
+
+
+
+
+
+ 为保证服务体验,您在拨打或接听隐私号电话时,可能被录音
+
+
+
+ 顾客电话
+
+
+ {orderInfo.memberInfo.phone || '暂无电话'}
+
+
+
+
+ 优惠信息
+
+
+ {
+ orderInfo.discountInfo?.map(discountItem => {
+ return (
+
+ {discountItem.type === 1 ? } color="#f50">{discountItem.name}:{discountItem.value} : null}
+ {discountItem.type === 2 ? } color="#87d068">{discountItem.name}:{discountItem.value} : null}
+ {discountItem.type === 3 ? } color="#108ee9">{discountItem.name}:{discountItem.value} : null}
+
+ )
+ })
+ }
+
+
+
+
+ {/* 订单数据 */}
+
+
+ 订单信息
+
+
+
订单编号
+
{orderInfo.orderNumber}
+
+
+
+
下单时间
+
{orderInfo.createdAt}
+
+
+
+
+ {/* 商品信息 */}
+
+
+ 商品信息
+
+
+ {
+ orderInfo.goodsInfo.map(item => {
+ return (
+
+
+
+
+
+ {item.goodsName || '暂无名称'}
+
+
+ ¥{item.memberPrice}
+
+
+ x{item.count}份
+
+
+ )
+ })
+ }
+
+ {/* 小计 */}
+
+
小计
+
+
优惠金额
+
¥{orderInfo.discountMoney}
+
+
+
支付金额
+
¥{orderInfo.orderRealMoney}
+
+
+
+ {/* 售后信息 */}
+
+
+ 售后信息
+
+
+ {
+ orderInfo.informationRefundInfo.length > 0 ?
+ orderInfo.informationRefundInfo.map(item => {
+ return (
+
+
+ {item.createdAt} {item.refundDesc}
+
+
+ )
+ })
+ :
+
+ 暂无售后信息
+
+ }
+
+
+
+
+
+ )
+}
diff --git a/src/pages/order/order-report-detail/index.less b/src/pages/order/order-report-detail/index.less
new file mode 100644
index 0000000..6768071
--- /dev/null
+++ b/src/pages/order/order-report-detail/index.less
@@ -0,0 +1,201 @@
+.order-detail-container {
+ display: flex;
+ justify-content: space-between;
+ flex-wrap: wrap;
+}
+
+.order-head {
+ display: flex;
+ align-items: center;
+ position: relative;
+ height: 50px;
+ margin-bottom: 10px;
+}
+
+.order-head::before {
+ position: absolute;
+ content: '';
+ width: 0;
+ height: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ left: 50px;
+ border-top: 20px solid transparent;
+ border-bottom: 20px solid transparent;
+ border-left: 20px solid rgb(88, 91, 110);
+}
+
+.order-number {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: absolute;
+ width: 70px;
+ height: 40px;
+ left: -20px;
+ top: 50%;
+ transform: translateY(-50%);
+ background-color: rgb(88, 91, 110);
+ color: #FFF;
+ font-size: 26px;
+}
+
+.order-status-true {
+ font-size: 14px;
+ padding: 5px 20px;
+ background-color: #2db7f5;
+ color: #FFF;
+}
+
+.order-status-false {
+ font-size: 14px;
+ padding: 5px 20px;
+ background-color: #F84352;
+ color: #FFF;
+}
+
+.order-cook-state {
+ font-size: 22px;
+ margin-left: 100px;
+ margin-right: 20px;
+}
+
+.order-cook-date {
+ font-size: 16px;
+ color: rgb(246, 152, 38);
+}
+
+// 用户信息
+.member-info {
+ display: flex;
+}
+
+.member-info-img {
+ margin-right: 20px;
+}
+
+.member-info-row {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.member-info-head {
+ font-size: 22px;
+ margin-right: 10px;
+}
+
+.member-info-label {
+ font-size: 16px;
+ color: #999;
+}
+
+.member-info-label span {
+ margin-right: 10px;
+}
+
+.member-info-privacy {
+ margin: 10px 0;
+ font-size: 16px;
+ color: rgb(88, 91, 110);
+}
+
+.member-info-privacy span {
+ margin-left: 10px;
+}
+
+.member-info-prefix {
+ font-size: 16px;
+ color: rgb(88, 91, 110);
+ margin-right: 10px;
+}
+
+.member-info-suffix {
+ font-size: 16px;
+ color: #222;
+}
+
+// 备餐状态
+.prepare-meals {
+ margin-top: 20px;
+ font-size: 16px;
+ color: #222;
+}
+
+.prepare-meals-title {
+ font-weight: 700;
+}
+
+
+
+// 商品信息
+.goods-card {
+ // margin-top: 20px;
+}
+
+.goods-title {
+ font-size: 22px;
+ font-weight: 700;
+ margin-bottom: 10px;
+}
+
+.goods-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+ font-size: 16px;
+ color: #222;
+}
+
+// 小计
+.goods-calc {
+ padding-top: 10px;
+ border-top: 1px dashed #dedede;
+ font-size: 16px;
+}
+
+.goods-calc-title {
+ font-size: 16px;
+ font-weight: 700;
+}
+
+.goods-calc-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 16px;
+}
+
+.goods-calc-pay .goods-calc-sufix {
+ color: #F84352;
+}
+
+// 订单信息
+.sale-after-line {
+ font-size: 16px;
+}
+
+@media screen and (min-width: 1200px) {
+ .order-head-card,
+ .goods-card,
+ .order-base-card,
+ .sale-after-card {
+ padding: 20px;
+ background-color: #FFF;
+ width: 49.5%;
+ box-sizing: border-box;
+ }
+}
+
+@media screen and (max-width: 1200px) {
+ .order-head-card,
+ .goods-card,
+ .order-base-card,
+ .sale-after-card {
+ padding: 20px;
+ background-color: #FFF;
+ width: 100%;
+ box-sizing: border-box;
+ }
+}
\ No newline at end of file
diff --git a/src/pages/order/order-report-detail/service.js b/src/pages/order/order-report-detail/service.js
new file mode 100644
index 0000000..bc9b448
--- /dev/null
+++ b/src/pages/order/order-report-detail/service.js
@@ -0,0 +1,9 @@
+import { request } from 'umi';
+
+export default {
+ getOrderReporByNumber(orderNumber) {
+ return request(`/kitchen/api/report-statistics/order-info-report/${orderNumber}`, {
+ method: 'GET',
+ });
+ }
+};
diff --git a/src/pages/order/order-report/index.jsx b/src/pages/order/order-report/index.jsx
new file mode 100644
index 0000000..d58951b
--- /dev/null
+++ b/src/pages/order/order-report/index.jsx
@@ -0,0 +1,299 @@
+import React, { useState, useEffect } from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Button, Card, DatePicker, Table, message, Pagination, Space, Tag, Spin, TreeSelect } from 'antd';
+import styles from './index.less';
+const { RangePicker } = DatePicker;
+import orderReportAPI from "./service";
+import moment from 'moment';
+import { history } from "umi";
+import { CheckCircleOutlined, CloseCircleOutlined, DownloadOutlined } from '@ant-design/icons';
+import ExportJsonExcel from "js-export-excel"
+
+const columns = [
+ {
+ title: '交易单号',
+ dataIndex: 'transactionId',
+ key: 'transactionId',
+ },
+ {
+ title: '店铺名称',
+ dataIndex: 'shopName',
+ key: 'shopName',
+ },
+ {
+ title: '原价(¥)',
+ dataIndex: 'orderOriginalMoney',
+ key: 'orderOriginalMoney',
+ },
+ {
+ title: '优惠(¥)',
+ dataIndex: 'discountMoney',
+ key: 'discountMoney',
+ },
+ {
+ title: '实际支付(¥)',
+ dataIndex: 'orderRealMoney',
+ key: 'orderRealMoney',
+ },
+ {
+ title: '创建时间',
+ dataIndex: 'createdAt',
+ key: 'createdAt',
+ },
+ {
+ title: '订单状态',
+ key: 'orderStatus',
+ render: (record) => {
+ let isNormal = true;
+ if (!(record.payMoneyEx === '正常' &&
+ record.payOrderTimeEx === '正常' &&
+ record.payOrderEx === '正常')
+ ) {
+ isNormal = false;
+ }
+ if (!(record.refundMoneyEx === '正常' || record.refundMoneyEx === '' || record.refundMoneyEx === null)) {
+ isNormal = false;
+ }
+ if (!(record.refundOrderTimeEx === '正常' || record.refundOrderTimeEx === '' || record.refundOrderTimeEx === null)) {
+ isNormal = false;
+ }
+ if (!(record.refundOrderEx === '正常' || record.refundOrderEx === '' || record.refundOrderEx === null)) {
+ isNormal = false;
+ }
+ return (
+ <>
+ {
+ isNormal ? } color="success">
+ 正常
+
+ :
+ } color="error">
+ 异常
+
+ }
+ >
+ )
+ },
+ },
+ {
+ title: '售后信息',
+ key: 'orderStatus',
+ render: (record) => {
+ return (
+ <>
+ {
+ record.isRefund ?
+ 有
+
+ :
+
+ 无
+
+ }
+ >
+ )
+ },
+ },
+ {
+ title: '操作',
+ key: 'action',
+ render: (_, record) => (
+
+ {
+ history.push({
+ pathname: '/order/order-report/order-report-detail',
+ query: {
+ orderNumber: record.orderNumber
+ }
+ });
+ }}>详情
+
+ ),
+ },
+];
+
+const LoadingCard = () => {
+ return (
+
+
+
+ )
+}
+
+/**
+ * 订单报表
+ * @returns
+ */
+export default function Index() {
+
+ //订单报表列表
+ const [orderReportList, setOrderReportList] = useState([]);
+ const [current, setCurrent] = useState(1);
+ const [pageSize, setPageSize] = useState(10);
+ const [total, setTotal] = useState(0);
+ const [showLoading, setShowLoading] = useState(false);
+ const [currentOrg, setCurrentOrg] = useState('');
+ const [orgTree, setOrgTree] = useState([]);
+
+
+ const [timeRange, setTimeRange] = useState([
+ 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')),
+ ]); //日期选择器
+
+ useEffect(() => {
+ onQueryOrderReportList();
+ }, [current, pageSize]);
+
+
+ useEffect(() => {
+ onGetOrgTree();
+ }, []);
+
+
+ //获取订单列表
+ const onQueryOrderReportList = async () => {
+ const jsonData = {
+ startTime: timeRange[0],
+ endTime: timeRange[1],
+ current,
+ pageSize
+ }
+ currentOrg.key && (jsonData.shopId = currentOrg.key);
+ setShowLoading(true);
+ const response = await orderReportAPI.getOrderReportList(jsonData);
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setOrderReportList(response.data.data);
+ setTotal(response.data.total)
+ } else {
+ message.error(response.errors || '获取订单报表列表失败');
+ }
+ }
+
+ //页码变化
+ const onPageChange = (current, pageSize) => {
+ setCurrent(current);
+ setPageSize(pageSize);
+ }
+
+ //获取组织树
+ const onGetOrgTree = async () => {
+ setShowLoading(true);
+ const response = await orderReportAPI.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;
+ }
+ }
+ });
+ }
+
+ //下载Excel
+ const onDownloadExcel = async () => {
+ const jsonData = {
+ startTime: timeRange[0],
+ endTime: timeRange[1],
+ }
+ currentOrg.key && (jsonData.shopId = currentOrg.key);
+ setShowLoading(true);
+ const response = await orderReportAPI.orderReportExport(jsonData);
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ let option = {}; //option代表的就是excel文件
+ const date = new Date();
+ const excelName = "订单报表-" + date.toLocaleString().replaceAll('\/', '-');
+ option.fileName = excelName; //excel文件名称
+ const sheetHeader = [];
+ Object.keys(response.data[0]).forEach(item => {
+ sheetHeader.push(item);
+ });
+ option.datas = [
+ {
+ sheetData: response.data, //excel文件中的数据源
+ sheetName: excelName, //excel文件中sheet页名称
+ sheetFilter: sheetHeader, //excel文件中需显示的列数据
+ sheetHeader: ['ID', '取餐号', '用户Id', '优惠合集', '订单号(本系统)',
+ '交易号', '店铺ID', '店铺名字', '商品总价', '优惠金额', '实付金额',
+ '创建时间', '支付金额异常',
+ '订单支付时间异常', '订单异常', '售后金额异常', '售后时间异常', '售后订单异常'
+ ] //excel文件中每列的表头名称
+ }
+ ]
+ let toExcel = new ExportJsonExcel(option); //生成excel文件
+ toExcel.saveExcel();
+ } else {
+ message.error(response.errors || '导出失败');
+ }
+ }
+
+ 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);
+ }} />
+ {
+ console.log('node>>>', node);
+ if (node.type === 2 || node === 3) {
+ setCurrentOrg(node);
+ } else {
+ setCurrentOrg("");
+ }
+ }}
+ placeholder="请选择组织架构"
+ treeDefaultExpandAll
+ />
+
+
+ } size='middle' onClick={onDownloadExcel}>
+ 下载
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/pages/order/order-report/index.less b/src/pages/order/order-report/index.less
new file mode 100644
index 0000000..c33fc6a
--- /dev/null
+++ b/src/pages/order/order-report/index.less
@@ -0,0 +1,36 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.data-search-box {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.search-btn-item {
+ margin-left: 20px;
+}
+
+.table-page {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ height: 50px;
+}
+
+// 加载中
+.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);
+}
\ No newline at end of file
diff --git a/src/pages/order/order-report/service.js b/src/pages/order/order-report/service.js
new file mode 100644
index 0000000..777cde2
--- /dev/null
+++ b/src/pages/order/order-report/service.js
@@ -0,0 +1,25 @@
+import { request } from 'umi';
+
+export default {
+ getOrderReportList(data) {
+ return request(`/kitchen/api/report-statistics/order-report`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+
+ //获取组织架构
+ getOrgTree() {
+ return request(`/kitchen/api/report-statistics/org-tree`, {
+ method: 'GET',
+ });
+ },
+
+ //下载报表
+ orderReportExport(data) {
+ return request(`/kitchen/api/report-statistics/order-report-export`, {
+ method: 'Post',
+ data: data,
+ });
+ }
+};
diff --git a/src/pages/order/order-revenue-statement/index.jsx b/src/pages/order/order-revenue-statement/index.jsx
new file mode 100644
index 0000000..c2e0ebd
--- /dev/null
+++ b/src/pages/order/order-revenue-statement/index.jsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Button, Card, DatePicker } from 'antd';
+import styles from './index.less';
+const { RangePicker } = DatePicker;
+/**
+ * 营收报表
+ * @returns
+ */
+export default function Index() {
+
+ return (
+
+
+
+
+
+ 营收报表
+
+
+ )
+}
diff --git a/src/pages/order/order-revenue-statement/index.less b/src/pages/order/order-revenue-statement/index.less
new file mode 100644
index 0000000..74d0c92
--- /dev/null
+++ b/src/pages/order/order-revenue-statement/index.less
@@ -0,0 +1,16 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.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/sales-gross-profit/index.jsx b/src/pages/order/sales-gross-profit/index.jsx
new file mode 100644
index 0000000..6ef8a2a
--- /dev/null
+++ b/src/pages/order/sales-gross-profit/index.jsx
@@ -0,0 +1,229 @@
+import React, { useState, useEffect } from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Button, Card, DatePicker, Table, Pagination, Spin, Select, message } from 'antd';
+import styles from './index.less';
+const { RangePicker } = DatePicker;
+import costSalesAPI from "./service";
+import moment from 'moment';
+
+const columns = [
+ {
+ title: '门店名称',
+ dataIndex: 'storeId',
+ key: 'storeId',
+ },
+ {
+ title: '商品名称',
+ dataIndex: 'goodsId',
+ key: 'goodsId',
+ },
+ {
+ title: '毛利率',
+ dataIndex: 'marginRatio',
+ key: 'marginRatio',
+ }
+];
+
+const LoadingCard = () => {
+ return (
+
+
+
+ )
+}
+
+/**
+ * 销售毛利分析
+ * @returns
+ */
+export default function Index() {
+
+ //订单报表列表
+ const [costSalesData, setCostSalesData] = useState([]);
+ const [current, setCurrent] = useState(1);
+ const [pageSize, setPageSize] = useState(10);
+ const [total, setTotal] = useState(0);
+ const [showLoading, setShowLoading] = useState(false);
+ const [timeRange, setTimeRange] = useState([
+ 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')),
+ ]); //日期选择器
+ //门店
+ const [storeIdArray, setStoreIdArray] = useState([]);
+ const [storeSelect, setStoreSelect] = useState([]);
+ //商品
+ const [goodsIdArray, setGoodsIdArray] = useState([]);
+ const [goodsIdSelect, setGoodsIdSelect] = useState([]);
+ //商品类型
+ const [goodsTypeArray, setGoodsTypeArray] = useState([]);
+ const [goodsTypeSelect, setGoodsTypeSelect] = useState([]);
+
+ //页码变化
+ const onPageChange = (current, pageSize) => {
+ setCurrent(current);
+ setPageSize(pageSize);
+ }
+
+ //查询
+ const onQueryReportSalescost = async () => {
+ const jsonData = {
+ "storeId": storeIdArray,
+ "goodsId": goodsIdArray,
+ "goodsTypeId": goodsTypeArray,
+ "begintime": timeRange[0],
+ "endtime": timeRange[1],
+ current,
+ pageSize
+ }
+ setShowLoading(true);
+ const response = await costSalesAPI.getReportSalesmargin({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setCostSalesData(response.data.data);
+ } else {
+ message.error(response.errors || '获取销售成本失败');
+ }
+ }
+
+ /**
+ * 查询店铺列表
+ */
+ const onQueryStoreList = async () => {
+ setShowLoading(true);
+ const response = await costSalesAPI.gettree({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ const storeList = [];
+ response.data.forEach(item => {
+ if (item.type === 2 || item.type === 3) {
+ storeList.push(item)
+ }
+ })
+ setStoreSelect(storeList);
+ } else {
+ message.error('查询店铺列表失败');
+ }
+ }
+
+ //查询商品列表
+ const onQueryGoodsList = async () => {
+ setShowLoading(true);
+ const response = await costSalesAPI.goodsList({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setGoodsIdSelect(response.data);
+ } else {
+ message.error('查询商品列表失败');
+ }
+ }
+
+ //查询商品分类类型列表
+ const onQueryGoodsType = async () => {
+ setShowLoading(true);
+ const response = await costSalesAPI.goodsTypeList({});
+ setShowLoading(false);
+ if (response.statusCode === 200) {
+ setGoodsTypeSelect(response.data);
+ } else {
+ message.error('查询商品分类列表失败');
+ }
+ }
+
+ useEffect(() => {
+ onQueryReportSalescost();
+ onQueryStoreList();
+ onQueryGoodsList();
+ onQueryGoodsType();
+ }, []);
+ 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);
+ }} />
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/pages/order/sales-gross-profit/index.less b/src/pages/order/sales-gross-profit/index.less
new file mode 100644
index 0000000..c33fc6a
--- /dev/null
+++ b/src/pages/order/sales-gross-profit/index.less
@@ -0,0 +1,36 @@
+.data-search-card {
+ margin-bottom: 20px;
+}
+
+.data-search-box {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.search-btn-item {
+ margin-left: 20px;
+}
+
+.table-page {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ height: 50px;
+}
+
+// 加载中
+.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);
+}
\ No newline at end of file
diff --git a/src/pages/order/sales-gross-profit/service.js b/src/pages/order/sales-gross-profit/service.js
new file mode 100644
index 0000000..7537b2e
--- /dev/null
+++ b/src/pages/order/sales-gross-profit/service.js
@@ -0,0 +1,39 @@
+import { request } from 'umi';
+
+export default {
+ getReportSalesmargin(data) {
+ return request(`/kitchen/api/report/salesmargin`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+ /**
+ * 查询商品信息
+ */
+ goodsList(data) {
+ return request(`/kitchen/api/goodes/list`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+ /**
+ * 查询商品类型
+ */
+ goodsTypeList(data) {
+ return request(`/kitchen/api/goodstype/list`, {
+ method: 'Post',
+ data: data,
+ });
+ },
+
+ /**
+ * 查询门店列表
+ */
+ gettree(params) {
+ return request('/kitchen/api/sysOrg/tree', {
+ data: {
+ ...params,
+ },
+ });
+ }
+};