@@ -622,6 +622,24 @@ export default [ | |||
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', | |||
}, | |||
], | |||
}, | |||
{ | |||
@@ -0,0 +1,162 @@ | |||
import React, { useState, useEffect } from 'react'; | |||
import { PageContainer } from '@ant-design/pro-layout'; | |||
import { Button, Card, DatePicker, Table, Pagination, Spin, Select } from 'antd'; | |||
import styles from './index.less'; | |||
const { RangePicker } = DatePicker; | |||
import costSalesAPI from "./service"; | |||
import moment from 'moment'; | |||
const columns = [ | |||
{ | |||
title: '门店名称', | |||
dataIndex: 'storeName', | |||
key: 'storeName', | |||
}, | |||
{ | |||
title: '商品名称', | |||
dataIndex: 'goodsName', | |||
key: 'storeName', | |||
}, | |||
{ | |||
title: '销售收入', | |||
dataIndex: 'salesRevenue', | |||
key: 'salesRevenue', | |||
}, | |||
{ | |||
title: '销售成本', | |||
dataIndex: 'costOfSale', | |||
key: 'costOfSale', | |||
}, | |||
{ | |||
title: '销售数量', | |||
dataIndex: 'salesVolumes', | |||
key: 'salesVolumes', | |||
}, | |||
{ | |||
title: '成本率', | |||
dataIndex: 'costRate', | |||
key: 'costRate', | |||
} | |||
]; | |||
const LoadingCard = () => { | |||
return ( | |||
<div className={styles['loading-card']}> | |||
<Spin size="large" /> | |||
</div> | |||
) | |||
} | |||
const children = []; | |||
for (let i = 10; i < 36; i++) { | |||
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>); | |||
} | |||
/** | |||
* 销售成本分析 | |||
* @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 [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 onPageChange = (current, pageSize) => { | |||
setCurrent(current); | |||
setPageSize(pageSize); | |||
} | |||
//查询 | |||
const onQueryOrderReportList = () => { | |||
} | |||
//选择门店 | |||
const handleStoreChange = () => { | |||
} | |||
return ( | |||
<PageContainer> | |||
{showLoading ? <LoadingCard></LoadingCard> : null} | |||
<Card className={styles['data-search-card']}> | |||
<div className={styles['data-search-box']}> | |||
<div className={styles['data-search-left']}> | |||
<Select | |||
showSearch | |||
mode="tags" | |||
size="middle" | |||
allowClear | |||
placeholder="请选择门店" | |||
onChange={handleStoreChange} | |||
filterOption={(input, option) => option.children.toLowerCase().includes(input.toLowerCase())} | |||
style={{ | |||
width: '300px', | |||
marginRight: '50px' | |||
}} | |||
> | |||
{children} | |||
</Select> | |||
<Select | |||
showSearch | |||
mode="tags" | |||
size="middle" | |||
allowClear | |||
placeholder="请选择商品" | |||
onChange={handleStoreChange} | |||
filterOption={(input, option) => option.children.toLowerCase().includes(input.toLowerCase())} | |||
style={{ | |||
width: '300px', | |||
marginRight: '50px' | |||
}} | |||
> | |||
{children} | |||
</Select> | |||
<Select | |||
showSearch | |||
mode="tags" | |||
size="middle" | |||
allowClear | |||
placeholder="请选择商品类别" | |||
onChange={handleStoreChange} | |||
filterOption={(input, option) => option.children.toLowerCase().includes(input.toLowerCase())} | |||
style={{ | |||
width: '300px', | |||
marginRight: '50px' | |||
}} | |||
> | |||
{children} | |||
</Select> | |||
<RangePicker size='middle' 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> | |||
<div className={styles['data-search-btns']}> | |||
<Button className={styles['search-btn-item']}>重置</Button> | |||
<Button className={styles['search-btn-item']} type="primary" onClick={onQueryOrderReportList}>查询</Button> | |||
</div> | |||
</div> | |||
</Card> | |||
<Card className={styles['table-card']}> | |||
<Table dataSource={orderReportList} columns={columns} pagination={false} /> | |||
<div className={styles['table-page']}> | |||
<Pagination current={current} pageSize={pageSize} total={total} onChange={onPageChange} /> | |||
</div> | |||
</Card> | |||
</PageContainer> | |||
) | |||
} |
@@ -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); | |||
} |
@@ -0,0 +1,10 @@ | |||
import { request } from 'umi'; | |||
export default { | |||
getOrderReportList(data) { | |||
return request(`/kitchen/api/report-statistics/order-report`, { | |||
method: 'Post', | |||
data: data, | |||
}); | |||
} | |||
}; |
@@ -0,0 +1,110 @@ | |||
import React, { useState, useEffect } from 'react'; | |||
import { PageContainer } from '@ant-design/pro-layout'; | |||
import { Button, Card, DatePicker, Table, Pagination, Spin, Select } from 'antd'; | |||
import styles from './index.less'; | |||
const { RangePicker } = DatePicker; | |||
import costSalesAPI from "./service"; | |||
import moment from 'moment'; | |||
const columns = [ | |||
{ | |||
title: '门店名称', | |||
dataIndex: 'storeName', | |||
key: 'storeName', | |||
}, | |||
{ | |||
title: '毛利率', | |||
dataIndex: 'grossProfitMargin', | |||
key: 'salesRevenue', | |||
} | |||
]; | |||
const LoadingCard = () => { | |||
return ( | |||
<div className={styles['loading-card']}> | |||
<Spin size="large" /> | |||
</div> | |||
) | |||
} | |||
const children = []; | |||
for (let i = 10; i < 36; i++) { | |||
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>); | |||
} | |||
/** | |||
* 门店销售毛利分析 | |||
* @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 [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 onPageChange = (current, pageSize) => { | |||
setCurrent(current); | |||
setPageSize(pageSize); | |||
} | |||
//查询 | |||
const onQueryOrderReportList = () => { | |||
} | |||
//选择门店 | |||
const handleStoreChange = () => { | |||
} | |||
return ( | |||
<PageContainer> | |||
{showLoading ? <LoadingCard></LoadingCard> : null} | |||
<Card className={styles['data-search-card']}> | |||
<div className={styles['data-search-box']}> | |||
<div className={styles['data-search-left']}> | |||
<Select | |||
mode="tags" | |||
size="middle" | |||
allowClear | |||
placeholder="请选择门店" | |||
onChange={handleStoreChange} | |||
style={{ | |||
width: '300px', | |||
marginRight: '50px' | |||
}} | |||
> | |||
{children} | |||
</Select> | |||
<RangePicker size='middle' 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> | |||
<div className={styles['data-search-btns']}> | |||
<Button className={styles['search-btn-item']}>重置</Button> | |||
<Button className={styles['search-btn-item']} type="primary" onClick={onQueryOrderReportList}>查询</Button> | |||
</div> | |||
</div> | |||
</Card> | |||
<Card className={styles['table-card']}> | |||
<Table dataSource={orderReportList} columns={columns} pagination={false} /> | |||
<div className={styles['table-page']}> | |||
<Pagination current={current} pageSize={pageSize} total={total} onChange={onPageChange} /> | |||
</div> | |||
</Card> | |||
</PageContainer> | |||
) | |||
} |
@@ -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); | |||
} |
@@ -0,0 +1,10 @@ | |||
import { request } from 'umi'; | |||
export default { | |||
getOrderReportList(data) { | |||
return request(`/kitchen/api/report-statistics/order-report`, { | |||
method: 'Post', | |||
data: data, | |||
}); | |||
} | |||
}; |
@@ -0,0 +1,141 @@ | |||
import React, { useState, useEffect } from 'react'; | |||
import { PageContainer } from '@ant-design/pro-layout'; | |||
import { Button, Card, DatePicker, Table, Pagination, Spin, Select } from 'antd'; | |||
import styles from './index.less'; | |||
const { RangePicker } = DatePicker; | |||
import costSalesAPI from "./service"; | |||
import moment from 'moment'; | |||
const columns = [ | |||
{ | |||
title: '门店名称', | |||
dataIndex: 'storeName', | |||
key: 'storeName', | |||
}, | |||
{ | |||
title: '商品名称', | |||
dataIndex: 'goodsName', | |||
key: 'storeName', | |||
}, | |||
{ | |||
title: '毛利率', | |||
dataIndex: 'grossProfitMargin', | |||
key: 'salesRevenue', | |||
} | |||
]; | |||
const LoadingCard = () => { | |||
return ( | |||
<div className={styles['loading-card']}> | |||
<Spin size="large" /> | |||
</div> | |||
) | |||
} | |||
const children = []; | |||
for (let i = 10; i < 36; i++) { | |||
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>); | |||
} | |||
/** | |||
* 销售毛利分析 | |||
* @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 [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 onPageChange = (current, pageSize) => { | |||
setCurrent(current); | |||
setPageSize(pageSize); | |||
} | |||
//查询 | |||
const onQueryOrderReportList = () => { | |||
} | |||
//选择门店 | |||
const handleStoreChange = () => { | |||
} | |||
return ( | |||
<PageContainer> | |||
{showLoading ? <LoadingCard></LoadingCard> : null} | |||
<Card className={styles['data-search-card']}> | |||
<div className={styles['data-search-box']}> | |||
<div className={styles['data-search-left']}> | |||
<Select | |||
mode="tags" | |||
size="middle" | |||
allowClear | |||
placeholder="请选择门店" | |||
onChange={handleStoreChange} | |||
style={{ | |||
width: '300px', | |||
marginRight: '50px' | |||
}} | |||
> | |||
{children} | |||
</Select> | |||
<Select | |||
mode="tags" | |||
size="middle" | |||
allowClear | |||
placeholder="请选择商品" | |||
onChange={handleStoreChange} | |||
style={{ | |||
width: '300px', | |||
marginRight: '50px' | |||
}} | |||
> | |||
{children} | |||
</Select> | |||
<Select | |||
mode="tags" | |||
size="middle" | |||
allowClear | |||
placeholder="请选择商品类别" | |||
onChange={handleStoreChange} | |||
style={{ | |||
width: '300px', | |||
marginRight: '50px' | |||
}} | |||
> | |||
{children} | |||
</Select> | |||
<RangePicker size='middle' 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> | |||
<div className={styles['data-search-btns']}> | |||
<Button className={styles['search-btn-item']}>重置</Button> | |||
<Button className={styles['search-btn-item']} type="primary" onClick={onQueryOrderReportList}>查询</Button> | |||
</div> | |||
</div> | |||
</Card> | |||
<Card className={styles['table-card']}> | |||
<Table dataSource={orderReportList} columns={columns} pagination={false} /> | |||
<div className={styles['table-page']}> | |||
<Pagination current={current} pageSize={pageSize} total={total} onChange={onPageChange} /> | |||
</div> | |||
</Card> | |||
</PageContainer> | |||
) | |||
} |
@@ -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); | |||
} |
@@ -0,0 +1,10 @@ | |||
import { request } from 'umi'; | |||
export default { | |||
getOrderReportList(data) { | |||
return request(`/kitchen/api/report-statistics/order-report`, { | |||
method: 'Post', | |||
data: data, | |||
}); | |||
} | |||
}; |