|
|
@@ -1,7 +1,12 @@ |
|
|
|
import React, { useEffect, useState } from 'react'; |
|
|
|
import { PageContainer } from '@ant-design/pro-layout'; |
|
|
|
import { Button, Table, Card, DatePicker } from 'antd'; |
|
|
|
import { DownloadOutlined } from '@ant-design/icons'; |
|
|
|
import { Button, Table, Card, DatePicker, message, Pagination } from 'antd'; |
|
|
|
import styles from './index.less'; |
|
|
|
import moment from 'moment'; |
|
|
|
import marketAPI from "./service"; |
|
|
|
|
|
|
|
import ExportJsonExcel from "js-export-excel" |
|
|
|
|
|
|
|
const { RangePicker } = DatePicker; |
|
|
|
const columns = [ |
|
|
@@ -15,8 +20,8 @@ const columns = [ |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '店铺', |
|
|
|
dataIndex: 'storeName', |
|
|
|
key: 'storeName', |
|
|
|
dataIndex: 'shopName', |
|
|
|
key: 'shopName', |
|
|
|
width: 170, |
|
|
|
align: 'center', |
|
|
|
fixed: 'left', |
|
|
@@ -30,7 +35,7 @@ const columns = [ |
|
|
|
value: '四川白菠萝科技', |
|
|
|
} |
|
|
|
], |
|
|
|
onFilter: (value, record) => record.storeName.indexOf(value) === 0, |
|
|
|
onFilter: (value, record) => record.shopName.indexOf(value) === 0, |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '营收', |
|
|
@@ -44,15 +49,15 @@ const columns = [ |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
title: '流水', |
|
|
|
dataIndex: 'flowingWater', |
|
|
|
key: 'flowingWater', |
|
|
|
dataIndex: 'revenueFlow', |
|
|
|
key: 'revenueFlow', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '实收', |
|
|
|
dataIndex: 'netReceipts', |
|
|
|
key: 'netReceipts', |
|
|
|
dataIndex: 'paidAmount', |
|
|
|
key: 'paidAmount', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
@@ -65,22 +70,22 @@ const columns = [ |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
title: '会员价', |
|
|
|
dataIndex: 'membershipPrice', |
|
|
|
key: 'membershipPrice', |
|
|
|
dataIndex: 'discountMember', |
|
|
|
key: 'discountMember', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '优惠券', |
|
|
|
dataIndex: 'coupon', |
|
|
|
key: 'coupon', |
|
|
|
dataIndex: 'discountCoupon', |
|
|
|
key: 'discountCoupon', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '活动', |
|
|
|
dataIndex: 'activity', |
|
|
|
key: 'activity', |
|
|
|
dataIndex: 'discountActivity', |
|
|
|
key: 'discountActivity', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
} |
|
|
@@ -184,15 +189,15 @@ const columns = [ |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
title: '流水单价', |
|
|
|
dataIndex: 'unitPriceOfWater', |
|
|
|
key: 'unitPriceOfWater', |
|
|
|
dataIndex: 'customerRevenueFlow', |
|
|
|
key: 'customerRevenueFlow', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '实收单价', |
|
|
|
dataIndex: 'paidInUnitPrice', |
|
|
|
key: 'paidInUnitPrice', |
|
|
|
dataIndex: 'customerPaidAmount', |
|
|
|
key: 'customerPaidAmount', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
} |
|
|
@@ -205,15 +210,15 @@ const columns = [ |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
title: '流水单价', |
|
|
|
dataIndex: 'singleUnitPriceOfWater', |
|
|
|
key: 'singleUnitPriceOfWater', |
|
|
|
dataIndex: 'orderRevenueFlow', |
|
|
|
key: 'orderRevenueFlow', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '实收单价', |
|
|
|
dataIndex: 'singlePaidInUnitPrice', |
|
|
|
key: 'singlePaidInUnitPrice', |
|
|
|
dataIndex: 'orderPaidAmount', |
|
|
|
key: 'orderPaidAmount', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
} |
|
|
@@ -228,15 +233,15 @@ const columns = [ |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
title: '现金', |
|
|
|
dataIndex: 'numCash', |
|
|
|
key: 'numCash', |
|
|
|
dataIndex: 'sourceCashCount', |
|
|
|
key: 'sourceCashCount', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '微信支付', |
|
|
|
dataIndex: 'numWechatPayment', |
|
|
|
key: 'numWechatPayment', |
|
|
|
dataIndex: 'sourceWeChatCount', |
|
|
|
key: 'sourceWeChatCount', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
@@ -289,15 +294,15 @@ const columns = [ |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
title: '会员', |
|
|
|
dataIndex: 'incomeMember', |
|
|
|
key: 'incomeMember', |
|
|
|
dataIndex: 'memberIncomeMoney', |
|
|
|
key: 'memberIncomeMoney', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '非会员', |
|
|
|
dataIndex: 'incomeNonMember', |
|
|
|
key: 'incomeNonMember', |
|
|
|
dataIndex: 'nonMemberIncomeMoney', |
|
|
|
key: 'nonMemberIncomeMoney', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
@@ -324,15 +329,15 @@ const columns = [ |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
title: '微信支付', |
|
|
|
dataIndex: 'incomeWechatPay', |
|
|
|
key: 'incomeWechatPay', |
|
|
|
dataIndex: 'sourceWeChatMoney', |
|
|
|
key: 'sourceWeChatMoney', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '现金支付', |
|
|
|
dataIndex: 'incomeCashPay', |
|
|
|
key: 'incomeCashPay', |
|
|
|
dataIndex: 'sourceCashMoney', |
|
|
|
key: 'sourceCashMoney', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
@@ -383,91 +388,25 @@ const columns = [ |
|
|
|
*/ |
|
|
|
export default function Index() { |
|
|
|
|
|
|
|
const [data, setData] = useState([ |
|
|
|
{ |
|
|
|
date: '2022-6-22 14:01:53', |
|
|
|
storeName: '四川黑菠萝科技', |
|
|
|
flowingWater: 10010, |
|
|
|
netReceipts: 8848, |
|
|
|
membershipPrice: 6000, |
|
|
|
coupon: 2848, |
|
|
|
activity: 998, |
|
|
|
takeOutRevenue: 10086, |
|
|
|
meituanTakeout: 5500, |
|
|
|
hungryTakeOut: 5600, |
|
|
|
freshWaterInTheHall: 10010, |
|
|
|
paidInFood: 10010, |
|
|
|
publicComments: 8000, |
|
|
|
wordOfMouth: 1000, |
|
|
|
tiktok: 2000, |
|
|
|
unitPriceOfWater: 68, |
|
|
|
paidInUnitPrice: 70, |
|
|
|
singleUnitPriceOfWater: 99, |
|
|
|
singlePaidInUnitPrice: 88, |
|
|
|
numCash: 10, |
|
|
|
numWechatPayment: 100, |
|
|
|
numPublicComments: 99, |
|
|
|
numWordOfMouth: 88, |
|
|
|
numTiktok: 77, |
|
|
|
numMeituanTakeout: 66, |
|
|
|
numHungryTakeOut: 55, |
|
|
|
incomeMember: 50, |
|
|
|
incomeNonMember: 50, |
|
|
|
incomeTakeOut: 70, |
|
|
|
incomeGroupPurchase: 90, |
|
|
|
incomeWechatPay: 10, |
|
|
|
incomeCashPay: 30, |
|
|
|
incomePublicComments: 20, |
|
|
|
incomeWordOfMouth: 50, |
|
|
|
incomeTiktok: 30, |
|
|
|
incomeMeituan: 80, |
|
|
|
incomeHungry: 100 |
|
|
|
}, |
|
|
|
{ |
|
|
|
date: '2022-6-22 15:58:43', |
|
|
|
storeName: '四川白菠萝科技', |
|
|
|
flowingWater: 10010, |
|
|
|
netReceipts: 8848, |
|
|
|
membershipPrice: 6000, |
|
|
|
coupon: 2848, |
|
|
|
activity: 998, |
|
|
|
takeOutRevenue: 10086, |
|
|
|
meituanTakeout: 5500, |
|
|
|
hungryTakeOut: 5600, |
|
|
|
freshWaterInTheHall: 10010, |
|
|
|
paidInFood: 10010, |
|
|
|
publicComments: 8000, |
|
|
|
wordOfMouth: 1000, |
|
|
|
tiktok: 2000, |
|
|
|
unitPriceOfWater: 68, |
|
|
|
paidInUnitPrice: 70, |
|
|
|
singleUnitPriceOfWater: 99, |
|
|
|
singlePaidInUnitPrice: 88, |
|
|
|
numCash: 10, |
|
|
|
numWechatPayment: 100, |
|
|
|
numPublicComments: 99, |
|
|
|
numWordOfMouth: 88, |
|
|
|
numTiktok: 77, |
|
|
|
numMeituanTakeout: 66, |
|
|
|
numHungryTakeOut: 55, |
|
|
|
incomeMember: 50, |
|
|
|
incomeNonMember: 50, |
|
|
|
incomeTakeOut: 70, |
|
|
|
incomeGroupPurchase: 90, |
|
|
|
incomeWechatPay: 10, |
|
|
|
incomeCashPay: 30, |
|
|
|
incomePublicComments: 20, |
|
|
|
incomeWordOfMouth: 50, |
|
|
|
incomeTiktok: 30, |
|
|
|
incomeMeituan: 80, |
|
|
|
incomeHungry: 100 |
|
|
|
} |
|
|
|
]) |
|
|
|
const [data, setData] = useState([]); |
|
|
|
const [current, setCurrent] = useState(1); |
|
|
|
const [pageSize, setPageSize] = useState(10); |
|
|
|
const [total, setTotal] = useState(0); |
|
|
|
|
|
|
|
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(() => { |
|
|
|
calcTotal(); |
|
|
|
}, []); |
|
|
|
queryMarketReport(); |
|
|
|
}, [current, pageSize, timeRange]); |
|
|
|
|
|
|
|
// useEffect(() => { |
|
|
|
// calcTotal(); |
|
|
|
// }, [data]); |
|
|
|
|
|
|
|
//计算总计 |
|
|
|
const calcTotal = () => { |
|
|
|
const originData = JSON.parse(JSON.stringify(data)); |
|
|
|
const totalData = {} |
|
|
@@ -475,8 +414,8 @@ export default function Index() { |
|
|
|
Object.keys(dataObj).forEach(key => { |
|
|
|
if (key === 'date') { |
|
|
|
totalData.date = '合计'; |
|
|
|
} else if (key == 'storeName') { |
|
|
|
totalData.storeName = ''; |
|
|
|
} else if (key == 'shopName') { |
|
|
|
totalData.shopName = ''; |
|
|
|
} else if (typeof dataObj[key] === 'number') { |
|
|
|
if (totalData[key] && typeof totalData[key] === 'number') { |
|
|
|
totalData[key] += dataObj[key]; |
|
|
@@ -490,24 +429,82 @@ export default function Index() { |
|
|
|
}); |
|
|
|
}); |
|
|
|
originData.push(totalData); |
|
|
|
console.log('originData', originData); |
|
|
|
setData(originData); |
|
|
|
} |
|
|
|
|
|
|
|
const queryMarketReport = async () => { |
|
|
|
const jsonData = { |
|
|
|
current: current, |
|
|
|
pageSize: pageSize |
|
|
|
} |
|
|
|
const response = await marketAPI.getMarketReportList(jsonData); |
|
|
|
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 = () => { |
|
|
|
let option = {}; //option代表的就是excel文件 |
|
|
|
const date = new Date(); |
|
|
|
const excelName = "营销报表-" + date.toLocaleString().replaceAll('\/', '-'); |
|
|
|
option.fileName = excelName; //excel文件名称 |
|
|
|
const sheetHeader = []; |
|
|
|
Object.keys(data[0]).forEach(item => { |
|
|
|
sheetHeader.push(item); |
|
|
|
}); |
|
|
|
console.log('sheetHeader', sheetHeader); |
|
|
|
option.datas = [ |
|
|
|
{ |
|
|
|
sheetData: data, //excel文件中的数据源 |
|
|
|
sheetName: excelName, //excel文件中sheet页名称 |
|
|
|
sheetFilter: sheetHeader, //excel文件中需显示的列数据 |
|
|
|
sheetHeader: ['ID', '时间', '店铺名称', '店铺ID', '营收流水', |
|
|
|
'实际营收', '会员价', '优惠券', '活动折扣', '营收流水', |
|
|
|
'营收流水', '客单价-流水单价', '客单价-实收单价', '单单价-总流水', '单单价-总实收', |
|
|
|
'现金-交易笔数', '现金收入', '微信-交易笔数', '微信收入', '会员收入', '非会员收入' |
|
|
|
] //excel文件中每列的表头名称 |
|
|
|
} |
|
|
|
] |
|
|
|
let toExcel = new ExportJsonExcel(option); //生成excel文件 |
|
|
|
toExcel.saveExcel(); |
|
|
|
} |
|
|
|
|
|
|
|
return ( |
|
|
|
<PageContainer> |
|
|
|
<Card className={styles['data-search-card']}> |
|
|
|
<div className={styles['data-search-box']}> |
|
|
|
<RangePicker /> |
|
|
|
<RangePicker className={styles['my-range-picker']} value={timeRange} onChange={(date, dateStrings) => { |
|
|
|
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); |
|
|
|
}} /> |
|
|
|
<div className={styles['data-search-btns']}> |
|
|
|
<Button type="primary" icon={<DownloadOutlined />} size='middle' onClick={onDownloadExcel}> |
|
|
|
下载 |
|
|
|
</Button> |
|
|
|
<Button className={styles['search-btn-item']}>重置</Button> |
|
|
|
<Button className={styles['search-btn-item']} type="primary">查询</Button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</Card> |
|
|
|
<Card className={styles['table-card']}> |
|
|
|
<Table dataSource={data} columns={columns} bordered={true} sticky={true} scroll={{ x: 1000 }}> |
|
|
|
<Table dataSource={data} columns={columns} bordered={true} sticky={true} scroll={{ x: 1000 }} pagination={false}> |
|
|
|
</Table> |
|
|
|
<div className={styles['table-page']}> |
|
|
|
<Pagination current={current} pageSize={pageSize} total={total} onChange={onPageChange} /> |
|
|
|
</div> |
|
|
|
</Card> |
|
|
|
</PageContainer> |
|
|
|
) |
|
|
|