1.新增批量导入 2.新增财务报表
This commit is contained in:
625
src/views/data/finance.vue
Normal file
625
src/views/data/finance.vue
Normal file
@@ -0,0 +1,625 @@
|
||||
<template>
|
||||
<div class="gyq_container">
|
||||
<div class="row">
|
||||
<div class="between">
|
||||
<el-form :model="queryForm" inline>
|
||||
<el-form-item>
|
||||
<el-date-picker v-model="queryForm.queryDate" type="date" placeholder="选择日期" format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD" :disabled-date="disabledFutureDate" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" :loading="loading" @click="handleQuery">查询</el-button>
|
||||
<el-button @click="handleReset" icon="Refresh" :loading="loading">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form inline>
|
||||
<el-form-item>
|
||||
<el-select v-model="queryForm.platform" placeholder="选择平台" clearable style="width: 150px;">
|
||||
<el-option v-for="item in platformList" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleExport" icon="Download">导出</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-loading="loading">
|
||||
<div class="warp" style="width: 400px;">
|
||||
<div class="card">
|
||||
<div class="header_title">营业额</div>
|
||||
<div class="num" style="color: var(--el-color-primary);">
|
||||
<span class="i">¥</span>
|
||||
{{ multiplyAndFormat(tableData.turnover.turnover || 0) }}
|
||||
</div>
|
||||
<div class="intro">营业额</div>
|
||||
<div class="pay_wrap">
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.turnover.wechat || 0 }}</span>
|
||||
<span class="t">微信支付金额</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.turnover.alipay || 0 }}</span>
|
||||
<span class="t">支付宝支付金额</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.turnover.selfScan || 0 }}</span>
|
||||
<span class="t">主扫收款</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.turnover.cash || 0 }}</span>
|
||||
<span class="t">现金收款</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.turnover.recharge || 0 }}</span>
|
||||
<span class="t">充值</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.turnover.owed || 0 }}</span>
|
||||
<span class="t">挂账</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.turnover.balance || 0 }}</span>
|
||||
<span class="t">余额支付</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="order_info">
|
||||
<div class="order_title">
|
||||
<span class="dot"></span>
|
||||
<span class="t">订单</span>
|
||||
</div>
|
||||
<div class="order_lits">
|
||||
<div class="item">
|
||||
<span class="t">订单金额</span>
|
||||
<span class="n">{{ tableData.order.orderAmount || 0 }}</span>
|
||||
</div>
|
||||
<span class="line">|</span>
|
||||
<div class="item">
|
||||
<span class="t">订单总数</span>
|
||||
<span class="n">{{ tableData.order.orderCount || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="header_title">数据统计</div>
|
||||
<div class="pay_wrap">
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.customerCount || 0 }}</span>
|
||||
<span class="t">就餐人数</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.orderCount || 0 }}</span>
|
||||
<span class="t">订单数</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.tableCount || 0 }}</span>
|
||||
<span class="t">桌台数</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.avgPayAmount || 0 }}</span>
|
||||
<div class="t">客单价
|
||||
<el-tooltip class="box-item" effect="dark" content="实付金额(包含现金支付 包含会员支付 包含挂账)/就餐人数没有具体人数时,默认一桌按照1人计算"
|
||||
placement="top">
|
||||
<el-icon color="#666">
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.turnoverRate || 0 }}%</span>
|
||||
<div class="t">翻台率
|
||||
<el-tooltip class="box-item" effect="dark" content="(订单数-桌台数)/桌台数*100%" placement="top">
|
||||
<el-icon color="#666">
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.profitAmount || 0 }}</span>
|
||||
<div class="t">毛利润
|
||||
<el-tooltip class="box-item" effect="dark" content="(订单实付金额-商品成本)" placement="top">
|
||||
<el-icon color="#666">
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.productCostAmount || 0 }}</span>
|
||||
<span class="t">商品成本</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.profitRate || 0 }}%</span>
|
||||
<div class="t">毛利率
|
||||
<el-tooltip class="box-item" effect="dark" content="(订单实付金额-商品成本)/订单实付金额*100%" placement="top">
|
||||
<el-icon color="#666">
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.netProfitAmount || 0 }}%</span>
|
||||
<span class="t">净利率</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="n">{{ tableData.sts.netProfitRate || 0 }}</span>
|
||||
<span class="t">净利润</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="flex: 1;">
|
||||
<div class="header_title">商家经营数据</div>
|
||||
<div class="content">
|
||||
<div class="card" style="flex: 1;">
|
||||
<div class="num" style="color: var(--el-color-success);">
|
||||
<span class="i">¥</span>
|
||||
{{ multiplyAndFormat(tableData.discount.discountAmount || 0) }}
|
||||
</div>
|
||||
<div class="intro">优惠金额</div>
|
||||
<div class="item_list">
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.discountCount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
优惠笔数
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.newConsumerDiscount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
新客立减
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.freeCashAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
霸王餐
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.fullMinusAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
满减活动
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.couponAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
优惠券
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.memberDiscount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
会员折扣
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.pointsDiscountAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
积分抵扣金额
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.discount.orderDiscount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
订单改价
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="flex: 1;">
|
||||
<div class="num" style="color: var(--el-color-danger);">
|
||||
<span class="i">¥</span>
|
||||
{{ multiplyAndFormat(tableData.refund.refundAmount || 0) }}
|
||||
</div>
|
||||
<div class="intro">退款金额</div>
|
||||
<div class="item_list">
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.refund.onlineRefundAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
线上退款金额
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.refund.cashRefundAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
现金退款金额
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.refund.rechargeRefundAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
充值退款金额
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.refund.onlineRechargeRefundAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
线上充值退款金额
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.refund.cashRechargeRefundAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
现金充值退款金额
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.refund.memberRefundAmount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
会员退款金额
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="flex: 1;">
|
||||
<div class="num" style="color: var(--el-color-warning);">
|
||||
<span class="i">¥</span>
|
||||
{{ multiplyAndFormat(tableData.order.orderAmount || 0) }}
|
||||
</div>
|
||||
<div class="intro">订单金额</div>
|
||||
<div class="item_list">
|
||||
<div class="item">
|
||||
<div class="n">
|
||||
{{ tableData.order.orderCount || 0 }}
|
||||
</div>
|
||||
<div class="label">
|
||||
订单总数
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import dayjs from "dayjs";
|
||||
import { ref, onMounted } from "vue";
|
||||
import OrderApi from "@/api/order/order";
|
||||
import { downloadFile, multiplyAndFormat } from '@/utils'
|
||||
|
||||
const queryForm = ref({
|
||||
queryDate: dayjs().format('YYYY-MM-DD'), // 查询日期 yyyy-MM-dd
|
||||
platform: 'czg',
|
||||
shopId: localStorage.getItem('shopId') || '',
|
||||
mainShopId: ''
|
||||
});
|
||||
|
||||
const platformList = ref([
|
||||
{ value: 'czg', label: '银收客' },
|
||||
{ value: 'MTuan', label: '美团' },
|
||||
{ value: 'CMeMe', label: '菜么么' },
|
||||
{ value: 'KRuYun', label: '客如云' },
|
||||
])
|
||||
|
||||
// 禁用今天以后的日期
|
||||
const disabledFutureDate = (time) => {
|
||||
return dayjs(time).isAfter(dayjs().startOf('day'))
|
||||
}
|
||||
|
||||
// 查询
|
||||
function handleQuery() {
|
||||
getData()
|
||||
}
|
||||
|
||||
// 重置
|
||||
function handleReset() {
|
||||
queryForm.value.queryDate = dayjs().format('YYYY-MM-DD')
|
||||
queryForm.value.platform = 'czg'
|
||||
getData()
|
||||
}
|
||||
|
||||
// 导出
|
||||
async function handleExport() {
|
||||
try {
|
||||
if (!queryForm.value.platform) {
|
||||
ElMessage.error('请选择导出平台')
|
||||
return
|
||||
}
|
||||
const res = await OrderApi.financeExport(queryForm.value)
|
||||
downloadFile(res, '财务报表', 'xlsx')
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
const tableData = ref({
|
||||
turnover: {},
|
||||
order: {},
|
||||
discount: {},
|
||||
refund: {},
|
||||
sts: {}
|
||||
});
|
||||
|
||||
// 查询财务报表
|
||||
async function getData() {
|
||||
try {
|
||||
loading.value = true
|
||||
const res = await OrderApi.financeSts(queryForm.value)
|
||||
tableData.value = res
|
||||
console.log('tableData.value', tableData.value);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 500);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.gyq_container {
|
||||
padding: 14px;
|
||||
|
||||
.gyq_content {
|
||||
padding: 14px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.between {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
|
||||
&.mt14 {
|
||||
margin-top: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.warp {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
|
||||
.header_title {
|
||||
font-size: 16px;
|
||||
color: 333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #F8F8F8;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
padding: 14px;
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
|
||||
.item_list {
|
||||
margin-top: 14px;
|
||||
|
||||
.item {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 14px;
|
||||
|
||||
&:nth-child(odd) {
|
||||
background-color: #F3F7FA;
|
||||
}
|
||||
|
||||
.n {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.num {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.i {
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.pay_wrap {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-column-gap: 0px;
|
||||
grid-row-gap: 14px;
|
||||
background-color: #F8F8F8;
|
||||
padding: 14px;
|
||||
margin-top: 14px;
|
||||
border-radius: 8px;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.n {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.t {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.order_info {
|
||||
border-top: 1px solid #ececec;
|
||||
padding-top: 14px;
|
||||
|
||||
.order_title {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
|
||||
.dot {
|
||||
--size: 12px;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 50%;
|
||||
background-color: var(--el-color-danger);
|
||||
}
|
||||
|
||||
.t {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.order_lits {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
margin-top: 4px;
|
||||
|
||||
.line {
|
||||
color: #ececec;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
|
||||
.t {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.n {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.waterfall {
|
||||
/* 核心属性1:定义瀑布流列数(关键) */
|
||||
column-count: 3;
|
||||
/* 核心属性2:列之间的间距(替代margin,避免卡片间距错乱) */
|
||||
column-gap: 14px;
|
||||
/* 可选:防止卡片内容被列分割(关键!避免卡片跨列断裂) */
|
||||
break-inside: avoid;
|
||||
|
||||
.waterfall-card {
|
||||
/* 必须:适配多列布局,避免卡片宽度溢出 */
|
||||
width: 100%;
|
||||
/* 卡片间距:仅需设置底部外边距(上下间距),左右间距由column-gap控制 */
|
||||
margin-bottom: 14px;
|
||||
padding: 24px;
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
/* 配合break-inside: avoid,强化卡片不可分割 */
|
||||
page-break-inside: avoid;
|
||||
|
||||
.header-title {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.dot {
|
||||
--size: 10px;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.t {
|
||||
font-size: 24px;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
padding-left: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 6px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
padding-left: 24px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user