内容管理提交
This commit is contained in:
commit
36f9dc0169
43
src/api/trade/dataBoard.js
Normal file
43
src/api/trade/dataBoard.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
|
|
||||||
|
// 获取顶部左侧数据(运营看板)
|
||||||
|
export function getAstsTransTotals(data) {
|
||||||
|
return request({
|
||||||
|
url: "/tairui-transettle/astsInfo/getAstsTransTotals",
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//获取顶部右侧数据(线形图)
|
||||||
|
export function getEchartsData(data) {
|
||||||
|
return request({
|
||||||
|
url: "/tairui-transettle/astsInfo/getSalesChartData",
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//获取中间数据(统计数据)
|
||||||
|
export function getMidleInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: "/tairui-transettle/astsInfo/getLeftMidQueryInfo",
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 获取厎部左侧数据(产品销量)
|
||||||
|
export function getGoodsSalesInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: "/tairui-transettle/astsInfo/getGoodsSalesInfo",
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取厎部右侧数据(售后概况)
|
||||||
|
export function getAfterSalesData(data) {
|
||||||
|
return request({
|
||||||
|
url: "/tairui-transettle/astsInfo/getAfterSalesData",
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
@ -237,6 +237,7 @@
|
|||||||
.table-cell-img-box {
|
.table-cell-img-box {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
|
text-align: center;
|
||||||
overflow: hidden; /* 隐藏超出部分 */
|
overflow: hidden; /* 隐藏超出部分 */
|
||||||
display: flex; /* 使用 Flex 布局居中 */
|
display: flex; /* 使用 Flex 布局居中 */
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -304,3 +305,11 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 溢出隐藏
|
||||||
|
.text-ellipsis {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="custom-table-container">
|
<div class="custom-table-container">
|
||||||
<div class="custom-table-tool">
|
<div class="custom-table-tool" v-if="showPagination">
|
||||||
<el-form :inline="true" class="demo-form-inline" :label-width="'auto'">
|
<el-form :inline="true" class="demo-form-inline" :label-width="'auto'">
|
||||||
<el-form-item label="每页显示" style="margin-bottom: 10px">
|
<el-form-item label="每页显示" style="margin-bottom: 10px">
|
||||||
<el-select
|
<el-select
|
||||||
|
@ -317,7 +317,7 @@ export const constantRoutes = [
|
|||||||
name: 'dataBoard',
|
name: 'dataBoard',
|
||||||
hidden: false,
|
hidden: false,
|
||||||
meta: {
|
meta: {
|
||||||
title: "电商数据看板",
|
title: "交易分析",
|
||||||
icon: "",
|
icon: "",
|
||||||
noCache: false,
|
noCache: false,
|
||||||
link: null,
|
link: null,
|
||||||
|
@ -149,7 +149,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-for="(item, index) in formInline.attribute" :key="index" class="attr-row">
|
<div v-for="(item, index) in formInline.attribute" :key="index" class="attr-row">
|
||||||
<div class="attr-input">{{ item.name }}</div>
|
<div class="attr-input">{{ item.name }}</div>
|
||||||
<el-input v-model="item.value" class="attr-input" />
|
<el-input v-model="item.value" class="attr-input" placeholder="请输入属性内容"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -197,6 +197,9 @@
|
|||||||
<myUploadImage v-model="formInline.detailUrl" :isShowSubscript="false"></myUploadImage>
|
<myUploadImage v-model="formInline.detailUrl" :isShowSubscript="false"></myUploadImage>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="商品描述" prop="describeContent">
|
||||||
|
<el-input v-model="formInline.describeContent" style="width: 400px;" :rows="2" type="textarea" clearable placeholder="请输入商品描述" />
|
||||||
|
</el-form-item>
|
||||||
<!-- 商品视频 -->
|
<!-- 商品视频 -->
|
||||||
<el-form-item label="商品视频" prop="videoUrl">
|
<el-form-item label="商品视频" prop="videoUrl">
|
||||||
<div>
|
<div>
|
||||||
@ -280,6 +283,7 @@ const formInline = reactive({
|
|||||||
]
|
]
|
||||||
}, //优惠折扣
|
}, //优惠折扣
|
||||||
detailUrl: "",
|
detailUrl: "",
|
||||||
|
describeContent: "",
|
||||||
brandId: "",
|
brandId: "",
|
||||||
traceCode: "",
|
traceCode: "",
|
||||||
videoUrl: "",
|
videoUrl: "",
|
||||||
|
@ -145,7 +145,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-for="(item, index) in formInline.attribute" :key="index" class="attr-row">
|
<div v-for="(item, index) in formInline.attribute" :key="index" class="attr-row">
|
||||||
<div class="attr-input">{{ item.name }}</div>
|
<div class="attr-input">{{ item.name }}</div>
|
||||||
<el-input v-model="item.value" class="attr-input" />
|
<el-input v-model="item.value" class="attr-input" placeholder="请输入属性内容" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -194,6 +194,9 @@
|
|||||||
<myUploadImage v-model="formInline.detailUrl" :isShowSubscript="false"></myUploadImage>
|
<myUploadImage v-model="formInline.detailUrl" :isShowSubscript="false"></myUploadImage>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="商品描述" prop="describeContent">
|
||||||
|
<el-input v-model="formInline.describeContent" style="width: 400px;" :rows="2" type="textarea" clearable placeholder="请输入商品描述" />
|
||||||
|
</el-form-item>
|
||||||
<!-- 商品视频 -->
|
<!-- 商品视频 -->
|
||||||
<el-form-item label="商品视频" prop="videoUrl">
|
<el-form-item label="商品视频" prop="videoUrl">
|
||||||
<div>
|
<div>
|
||||||
@ -280,6 +283,7 @@ const formInline = reactive({
|
|||||||
]
|
]
|
||||||
}, //优惠折扣
|
}, //优惠折扣
|
||||||
detailUrl: "",
|
detailUrl: "",
|
||||||
|
describeContent: "",
|
||||||
brandId: "",
|
brandId: "",
|
||||||
traceCode: "",
|
traceCode: "",
|
||||||
videoUrl: "",
|
videoUrl: "",
|
||||||
|
@ -150,7 +150,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-for="(item, index) in formInline.attribute" :key="index" class="attr-row">
|
<div v-for="(item, index) in formInline.attribute" :key="index" class="attr-row">
|
||||||
<div class="attr-input">{{ item.name }}</div>
|
<div class="attr-input">{{ item.name }}</div>
|
||||||
<el-input v-model="item.value" class="attr-input" />
|
<el-input v-model="item.value" class="attr-input" placeholder="请输入属性内容" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -200,6 +200,9 @@
|
|||||||
<img v-for="(item, index) in formInline.detailUrl.split(',')" :key="index" style="width: 100px;margin-right: 5px;" :src="item" alt="">
|
<img v-for="(item, index) in formInline.detailUrl.split(',')" :key="index" style="width: 100px;margin-right: 5px;" :src="item" alt="">
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="商品描述" prop="describeContent">
|
||||||
|
<el-input v-model="formInline.describeContent" style="width: 400px;" :rows="2" type="textarea" clearable placeholder="请输入商品描述" />
|
||||||
|
</el-form-item>
|
||||||
<!-- 商品视频 -->
|
<!-- 商品视频 -->
|
||||||
<el-form-item label="商品视频" prop="videoUrl" v-if="formInline.videoUrl">
|
<el-form-item label="商品视频" prop="videoUrl" v-if="formInline.videoUrl">
|
||||||
<div>
|
<div>
|
||||||
@ -288,6 +291,7 @@ const formInline = reactive({
|
|||||||
]
|
]
|
||||||
}, //优惠折扣
|
}, //优惠折扣
|
||||||
detailUrl: "",
|
detailUrl: "",
|
||||||
|
describeContent: "",
|
||||||
brandId: "",
|
brandId: "",
|
||||||
traceCode: "",
|
traceCode: "",
|
||||||
videoUrl: "",
|
videoUrl: "",
|
||||||
|
@ -1,144 +1,215 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container customer-control">
|
||||||
<div class="app-container-data">
|
<div style="overflow-y: auto;overflow-x: hidden; height: 100%;">
|
||||||
<div class="app-container-title">运营看板</div>
|
<div class="app-container-data" ref="chartContainer">
|
||||||
<div style="display: flex">
|
<div class="app-container-title">运营看板
|
||||||
<div class="app-container-data-left">
|
<el-radio-group v-model="dateRadio" @change="changeDateRadio" size="small" style="float: right;">
|
||||||
<div class="app-container-data-left-top">
|
<el-radio-button label="周" :value="1" />
|
||||||
<div>
|
<el-radio-button label="月" :value="2" />
|
||||||
<div class="title">
|
<el-radio-button label="年" :value="3" />
|
||||||
<img
|
</el-radio-group>
|
||||||
class="title-image"
|
</div>
|
||||||
src="../../assets/images/money.png"
|
<div style="display: flex">
|
||||||
alt=""
|
<div class="app-container-data-left">
|
||||||
/>
|
<div class="app-container-data-left-top">
|
||||||
<div>销售总额(元)</div>
|
<div>
|
||||||
|
<div class="title">
|
||||||
|
<img
|
||||||
|
class="title-image"
|
||||||
|
src="../../assets/images/money.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div>销售总额(元)</div>
|
||||||
|
</div>
|
||||||
|
<div class="number">{{ topLeftData.salesTotalAmount }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="title">
|
||||||
|
<img
|
||||||
|
class="title-image"
|
||||||
|
src="../../assets/images/order.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div>订单总数(单)</div>
|
||||||
|
</div>
|
||||||
|
<div class="number">{{ topLeftData.orderTotalNum }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="number">4,541.00</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="app-container-data-left-bottom">
|
||||||
<div class="title">
|
<div>
|
||||||
<img
|
<div class="title">
|
||||||
class="title-image"
|
<img
|
||||||
src="../../assets/images/order.png"
|
class="title-image"
|
||||||
alt=""
|
src="../../assets/images/views.png"
|
||||||
/>
|
alt=""
|
||||||
<div>订单总数(单)</div>
|
/>
|
||||||
|
<div>浏览量(次)</div>
|
||||||
|
</div>
|
||||||
|
<div class="number">{{ topLeftData.viewCount }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="title">
|
||||||
|
<img
|
||||||
|
class="title-image"
|
||||||
|
src="../../assets/images/money1.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div>成功退款金额(元)</div>
|
||||||
|
</div>
|
||||||
|
<div class="number">{{ topLeftData.refundSuccessAmout }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="number">45</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-container-data-left-bottom">
|
<div class="app-container-data-right">
|
||||||
<div>
|
<div ref="chartRef" style="width: 100%; height: 200px"></div>
|
||||||
<div class="title">
|
|
||||||
<img
|
|
||||||
class="title-image"
|
|
||||||
src="../../assets/images/views.png"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
<div>浏览量(次)</div>
|
|
||||||
</div>
|
|
||||||
<div class="number">61,151</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="title">
|
|
||||||
<img
|
|
||||||
class="title-image"
|
|
||||||
src="../../assets/images/money1.png"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
<div>成功退款金额(元)</div>
|
|
||||||
</div>
|
|
||||||
<div class="number">541.00</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-container-data-right">
|
</div>
|
||||||
<div ref="chartRef" style="width: 100%; height: 200px"></div>
|
<!-- 中间模块 -->
|
||||||
|
<div class="app-container-list" ref="middleRef">
|
||||||
|
<div class="app-container-block" v-for="(item,index) in middleData" :key="index">
|
||||||
|
<div class="app-container-block-title">{{ item.title }}
|
||||||
|
<el-popover
|
||||||
|
title=""
|
||||||
|
:content="item.toolTip"
|
||||||
|
placement="left-start"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-icon color="#c5c5c5" style="float: right;"><QuestionFilled /></el-icon>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
<div class="app-container-block-price">
|
||||||
|
{{ item.valueStr??'--' }}
|
||||||
|
<text style="font-size: 12px; color: #999999; margin-left: 5px">
|
||||||
|
{{ item.unit??'' }}
|
||||||
|
</text>
|
||||||
|
</div>
|
||||||
|
<div class="app-container-block-proportion">
|
||||||
|
{{ item.ratioMethod }}:
|
||||||
|
<text :style="{'font-size': '12px',color: item.ratioStatus == '下降'?'red' : 'green'}">
|
||||||
|
<el-icon v-if="item.ratioStatus == '下降'"><CaretBottom /></el-icon>
|
||||||
|
<el-icon v-else><CaretTop /></el-icon>
|
||||||
|
{{ item.ratioValue??'' }}%
|
||||||
|
</text>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<!-- 底部模块 -->
|
||||||
<div class="app-container-list">
|
<div class="bottom-flex-box">
|
||||||
<div class="app-container-block">
|
<div class="bottom-box-item">
|
||||||
<div class="app-container-block-title">销售总额</div>
|
<div class="bottom-box-item-title">商品销量</div>
|
||||||
<div class="app-container-block-price">
|
<div class="bottom-box-item-content" :style="{ height: tableViewportHeight + 'px' }">
|
||||||
15698<text style="font-size: 10px; color: #999999; margin-left: 10px"
|
<tableComponent
|
||||||
>元</text
|
:table-data="tableData"
|
||||||
>
|
:columns="columns"
|
||||||
|
:show-border="false"
|
||||||
|
:show-pagination="false"
|
||||||
|
:loading="tableLoading"
|
||||||
|
>
|
||||||
|
<!-- 自定义-排名图片 -->
|
||||||
|
<template #ranking="slotProps">
|
||||||
|
<div class="table-cell-img-box" style="width: 40px;height: 40px;" v-if="slotProps.row.ranking == 1">
|
||||||
|
<img :src="img1" class="table-cell-img" alt="" />
|
||||||
|
</div>
|
||||||
|
<div class="table-cell-img-box" style="width: 40px;height: 40px;" v-else-if="slotProps.row.ranking == 2">
|
||||||
|
<img :src="img2" class="table-cell-img" alt="" />
|
||||||
|
</div>
|
||||||
|
<div class="table-cell-img-box" style="width: 40px;height: 40px;" v-else-if="slotProps.row.ranking == 3">
|
||||||
|
<img :src="img3" class="table-cell-img" alt="" />
|
||||||
|
</div>
|
||||||
|
<div v-else>{{ slotProps.row.ranking }}</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 自定义-商品图片 -->
|
||||||
|
<template #goodUrl="slotProps">
|
||||||
|
<div class="table-cell-img-box" style="width: 40px;height: 40px;">
|
||||||
|
<img :src="slotProps.row.goodUrl" class="table-cell-img" alt="" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</tableComponent>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-container-block-proportion">
|
<div class="bottom-box-item">
|
||||||
环比:<text style="color: red; font-size: 12px">↓2.6%</text>
|
<div class="bottom-box-item-title">售后概况</div>
|
||||||
</div>
|
<div class="bottom-box-item-content">
|
||||||
</div>
|
<!-- 上 -->
|
||||||
<div class="app-container-block">
|
<div class="bottom-box-summary" style="margin: 20px 0;">
|
||||||
<div class="app-container-block-title">订单总数</div>
|
<div class="bottom-box-summary-item">
|
||||||
<div class="app-container-block-price">
|
<div class="bottom-box-summary-title">售后订单数量(单)</div>
|
||||||
52<text style="font-size: 10px; color: #999999; margin-left: 10px"
|
<div class="bottom-box-summary-value">{{ afterSalesData.totalAfterSalesOrders }}</div>
|
||||||
>单</text
|
</div>
|
||||||
>
|
<div class="bottom-box-summary-item">
|
||||||
</div>
|
<div class="bottom-box-summary-title">退货退款金额(元)</div>
|
||||||
<div class="app-container-block-proportion">
|
<div class="bottom-box-summary-value">{{ afterSalesData.totalRefundAmount }}</div>
|
||||||
环比:<text style="color: red; font-size: 12px">↓2.6%</text>
|
</div>
|
||||||
</div>
|
<div class="bottom-box-summary-item">
|
||||||
</div>
|
<div class="bottom-box-summary-title">退货退款订单数量(单)</div>
|
||||||
<div class="app-container-block">
|
<div class="bottom-box-summary-value">{{ afterSalesData.totalRefundOrders }}</div>
|
||||||
<div class="app-container-block-title">支付转化率</div>
|
</div>
|
||||||
<div class="app-container-block-price">
|
</div>
|
||||||
16.56<text style="font-size: 10px; color: #999999; margin-left: 10px"
|
<!-- 下 -->
|
||||||
>%</text
|
<div class="bottom-box-summary" style="line-height: 30px;margin: 0;">
|
||||||
>
|
<div class="bottom-box-summary-item">
|
||||||
</div>
|
<img :src="alert" style="width: 30px;height: 30px;" alt="" />
|
||||||
<div class="app-container-block-proportion">
|
<div class="bottom-box-summary-title" style="display: inline-block;vertical-align: middle;margin-left: 8px;">预警商品</div>
|
||||||
环比:<text style="color: red; font-size: 12px">↓2.6%</text>
|
</div>
|
||||||
</div>
|
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
|
||||||
</div>
|
<div class="bottom-box-summary-title">退款订单量</div>
|
||||||
<div class="app-container-block">
|
</div>
|
||||||
<div class="app-container-block-title">客单价</div>
|
<div class="bottom-box-summary-item" style="width: 130px;flex: none;">
|
||||||
<div class="app-container-block-price">
|
<div class="bottom-box-summary-title">退款金额</div>
|
||||||
12.33<text style="font-size: 10px; color: #999999; margin-left: 10px"
|
</div>
|
||||||
>元</text
|
</div>
|
||||||
>
|
<div ref="warningGoodsRef" style="overflow-y: auto; height: 150px;" :style="{ height: tableViewportHeight -150 + 'px' }">
|
||||||
</div>
|
<div class="bottom-box-summary" style="line-height: 40px;margin: 0;"
|
||||||
<div class="app-container-block-proportion">
|
v-for="(item, index) in afterSalesData.warningProductInfos" :key="index">
|
||||||
环比:<text style="color: red; font-size: 12px">↓2.6%</text>
|
<div class="bottom-box-summary-item" style="display: flex;">
|
||||||
</div>
|
<img :src="item.goodUrl" style="width: 40px;height: 40px;" alt="" />
|
||||||
</div>
|
<div class="bottom-box-summary-title text-ellipsis" style="flex: 1; vertical-align: top;color: #000;margin-left: 8px;" :title="item.goodName">
|
||||||
<div class="app-container-block">
|
{{ item.goodName }}
|
||||||
<div class="app-container-block-title">成功退款金额</div>
|
</div>
|
||||||
<div class="app-container-block-price">
|
</div>
|
||||||
152.5<text style="font-size: 10px; color: #999999; margin-left: 10px"
|
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
|
||||||
>元</text
|
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundedOrders }}单</div>
|
||||||
>
|
</div>
|
||||||
</div>
|
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
|
||||||
<div class="app-container-block-proportion">
|
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundAmount }}元</div>
|
||||||
环比:<text style="color: red; font-size: 12px">↓2.6%</text>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-container-block">
|
|
||||||
<div class="app-container-block-title">浏览量</div>
|
</div>
|
||||||
<div class="app-container-block-price">
|
|
||||||
156988<text style="font-size: 10px; color: #999999; margin-left: 10px"
|
|
||||||
>次</text
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="app-container-block-proportion">
|
|
||||||
环比:<text style="color: red; font-size: 12px">↓2.6%</text>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref, onBeforeUnmount } from "vue";
|
||||||
|
import Mock from "mockjs";
|
||||||
|
import tableComponent from "@/components/tableComponent.vue";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
|
import { getAstsTransTotals, getEchartsData, getMidleInfo, getGoodsSalesInfo, getAfterSalesData } from "@/api/trade/dataBoard";
|
||||||
|
|
||||||
|
import img1 from "@/assets/images/first.png";
|
||||||
|
import img2 from "@/assets/images/second.png";
|
||||||
|
import img3 from "@/assets/images/third.png";
|
||||||
|
import alert from "@/assets/images/alert.png";
|
||||||
|
let tomato = ref("http://gov-cloud.oss-cn-chengdu.aliyuncs.com/backend/a866613495ed4678957a4440b8d3776c.png");
|
||||||
|
|
||||||
// 图表 DOM 引用
|
// 图表 DOM 引用
|
||||||
const chartRef = ref(null);
|
const chartRef = ref(null);
|
||||||
// ECharts 实例
|
// ECharts 实例
|
||||||
let chartInstance = null;
|
let chartInstance = null;
|
||||||
// 颜色列表
|
// 颜色列表
|
||||||
const colorList = ['#3685FE', '#FFD500', '#25BF82'];
|
const colorList = ['#3685FE', '#FFD500', '#25BF82', '#FF7F00'];
|
||||||
// x轴数据
|
// x轴数据
|
||||||
const xData = ['1月', '2月', '3月', '4月', '5月', '6月', '7月'];
|
const xData = ref([]);
|
||||||
|
const totalSalesData = ref([]); //销售总额数据
|
||||||
|
const totalOrdersData = ref([]); //订单总数数据
|
||||||
|
const pageViewData = ref([]); //浏览量数据
|
||||||
|
const refundAmountData = ref([]); //成功退款金额数据
|
||||||
|
|
||||||
// 图表配置
|
// 图表配置
|
||||||
const option = {
|
const option = {
|
||||||
@ -150,12 +221,12 @@ const option = {
|
|||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
},
|
},
|
||||||
left: 'center',
|
left: 'center',
|
||||||
top: '5%',
|
top: '0%',
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
icon: 'circle',
|
icon: 'circle',
|
||||||
top: '0',
|
top: '0',
|
||||||
right: '5%',
|
right: '30%',
|
||||||
itemWidth: 6,
|
itemWidth: 6,
|
||||||
itemGap: 20,
|
itemGap: 20,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
@ -169,8 +240,8 @@ const option = {
|
|||||||
show: true,
|
show: true,
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
color: '#556677',
|
color: '#556677',
|
||||||
borderColor: 'rgba(0,0,0,0)',
|
borderColor: 'rgba(0,0,0)',
|
||||||
shadowColor: 'rgba(0,0,0,0)',
|
shadowColor: 'rgba(0,0,0,0.3)',
|
||||||
shadowOffsetY: 0,
|
shadowOffsetY: 0,
|
||||||
},
|
},
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
@ -185,7 +256,7 @@ const option = {
|
|||||||
extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5); text-align: left;',
|
extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5); text-align: left;',
|
||||||
formatter: function (params) {
|
formatter: function (params) {
|
||||||
let result = params[0].name + '<br>'; // x轴值(如"1月")
|
let result = params[0].name + '<br>'; // x轴值(如"1月")
|
||||||
params.forEach((param) => {
|
params.forEach((param,index) => {
|
||||||
// 获取系列颜色(param.color)
|
// 获取系列颜色(param.color)
|
||||||
const colorDot = `<span style="
|
const colorDot = `<span style="
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
@ -193,20 +264,33 @@ const option = {
|
|||||||
border-radius:50%;
|
border-radius:50%;
|
||||||
width:10px;
|
width:10px;
|
||||||
height:10px;
|
height:10px;
|
||||||
background-color:${param.color}">
|
background-color:${colorList[index]}">
|
||||||
</span>`;
|
</span>`;
|
||||||
result += `${colorDot} ${param.seriesName}: ${param.value}${param.seriesName === '茎秆高度' ? 'cm' : param.seriesName === '叶片温度' ? '℃' : 'mm'} <br>`;
|
let unit = "";
|
||||||
|
if(param.seriesName == '销售总额') {
|
||||||
|
unit = "元";
|
||||||
|
} else if(param.seriesName == '订单总数') {
|
||||||
|
unit = "个";
|
||||||
|
} else if(param.seriesName == '浏览量') {
|
||||||
|
unit = "人次";
|
||||||
|
} else if(param.seriesName == '成功退款金额') {
|
||||||
|
unit = "元";
|
||||||
|
}
|
||||||
|
result += `${colorDot} ${param.seriesName}: ${param.value} ${unit} <br>`;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: '20%',
|
top: '20%',
|
||||||
|
left: 26,
|
||||||
|
right: 26,
|
||||||
|
bottom: 40, // 底部留白给图例
|
||||||
},
|
},
|
||||||
xAxis: [
|
xAxis: [
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: xData,
|
data: xData.value,
|
||||||
axisLine: {
|
axisLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: 'rgba(107,107,107,0.37)',
|
color: 'rgba(107,107,107,0.37)',
|
||||||
@ -346,7 +430,7 @@ const option = {
|
|||||||
{
|
{
|
||||||
name: '销售总额',
|
name: '销售总额',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: [514.14, 468.18, 988.35, 1204.84, 954.16, 651.24, ],
|
data: totalSalesData.value,
|
||||||
symbolSize: 1,
|
symbolSize: 1,
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
@ -354,7 +438,7 @@ const option = {
|
|||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 3,
|
width: 3,
|
||||||
color: '#25BF82',
|
color: '#3685FE',
|
||||||
shadowColor: 'rgba(158,135,255, 0.3)',
|
shadowColor: 'rgba(158,135,255, 0.3)',
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
shadowOffsetY: 20,
|
shadowOffsetY: 20,
|
||||||
@ -367,36 +451,36 @@ const option = {
|
|||||||
{
|
{
|
||||||
name: '订单总数',
|
name: '订单总数',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: [4, 18, 29, 33, 18, 10, 28],
|
data: totalOrdersData.value,
|
||||||
symbolSize: 1,
|
symbolSize: 1,
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
yAxisIndex: 1,
|
yAxisIndex: 1,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 5,
|
width: 3,
|
||||||
color: '#FFD500',
|
color: '#FFD500',
|
||||||
shadowColor: 'rgba(115,221,255, 0.3)',
|
shadowColor: 'rgba(115,221,255, 0.3)',
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
shadowOffsetY: 20,
|
shadowOffsetY: 20,
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: colorList[2],
|
color: colorList[1],
|
||||||
borderColor: colorList[2],
|
borderColor: colorList[1],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '浏览量',
|
name: '浏览量',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: [1589, 2648, 5289, 4289, 9654, 6487, 5968],
|
data: pageViewData.value,
|
||||||
symbolSize: 1,
|
symbolSize: 1,
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
yAxisIndex: 2,
|
yAxisIndex: 2,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 5,
|
width: 3,
|
||||||
color: '#3685FE',
|
color: '#25BF82',
|
||||||
shadowColor: 'rgba(115,221,255, 0.3)',
|
shadowColor: 'rgba(115,221,255, 0.3)',
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
shadowOffsetY: 20,
|
shadowOffsetY: 20,
|
||||||
@ -409,22 +493,22 @@ const option = {
|
|||||||
{
|
{
|
||||||
name: '成功退款金额',
|
name: '成功退款金额',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: [62.44, 14.15, 17.48, 25.18, 21.91, 10.02, 2.25],
|
data: refundAmountData.value,
|
||||||
symbolSize: 1,
|
symbolSize: 1,
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
yAxisIndex: 3,
|
yAxisIndex: 3,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 5,
|
width: 3,
|
||||||
color: '#3685FE',
|
color: '#FF7F00',
|
||||||
shadowColor: 'rgba(115,221,255, 0.3)',
|
shadowColor: 'rgba(115,221,255, 0.3)',
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
shadowOffsetY: 20,
|
shadowOffsetY: 20,
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: colorList[2],
|
color: colorList[3],
|
||||||
borderColor: colorList[2],
|
borderColor: colorList[3],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -442,6 +526,317 @@ const initChart = () => {
|
|||||||
window.addEventListener('resize', resizeChart);
|
window.addEventListener('resize', resizeChart);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 调整图表大小
|
||||||
|
const resizeChart = () => {
|
||||||
|
if (chartInstance) {
|
||||||
|
chartInstance.resize();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 加载数据-图表模块
|
||||||
|
const loadEchartsData = async () => {
|
||||||
|
try {
|
||||||
|
let response = await getEchartsData({
|
||||||
|
queryStartTime: startDate.value + " 00:00:00",
|
||||||
|
queryEndTime: endDate.value + " 23:59:59",
|
||||||
|
queryType: dateRadio.value,
|
||||||
|
});
|
||||||
|
if (response.code == 200) {
|
||||||
|
option.xAxis[0].data = response.data?.xdata ?? generateDateArray(7);
|
||||||
|
option.series[0].data = response.data?.totalSalesData;
|
||||||
|
option.series[1].data = response.data?.totalOrdersData;
|
||||||
|
option.series[2].data = response.data?.pageViewData;
|
||||||
|
option.series[3].data = response.data?.refundAmountData;
|
||||||
|
chartInstance.setOption(option);
|
||||||
|
} else {
|
||||||
|
echartsMockData(7);
|
||||||
|
}
|
||||||
|
} catch (error) { }
|
||||||
|
};
|
||||||
|
const echartsMockData = (count = 7) => {
|
||||||
|
// console.log("右上角图表数据更新");
|
||||||
|
const xzData = generateDateArray(count);
|
||||||
|
let obj = Mock.mock({
|
||||||
|
// x轴数据 (日期/月份)
|
||||||
|
xData: xzData,
|
||||||
|
|
||||||
|
// 总销售额 (500-5000之间的浮点数,保留2位小数)
|
||||||
|
[`totalSalesData|${count}`]: ['@float(100, 500, 2, 2)'],
|
||||||
|
|
||||||
|
// 总订单数 (1-100之间的整数)
|
||||||
|
[`totalOrdersData|${count}`]: ['@integer(10, 100)'],
|
||||||
|
|
||||||
|
// 页面浏览量 (1000-10000之间的整数)
|
||||||
|
[`pageViewData|${count}`]: ['@integer(1000, 10000)'],
|
||||||
|
|
||||||
|
// 退款金额 (1-100之间的浮点数,保留2位小数)
|
||||||
|
[`refundAmountData|${count}`]: ['@float(10, 100, 2, 2)']
|
||||||
|
})
|
||||||
|
option.xAxis[0].data = obj.xData;
|
||||||
|
option.series[0].data = obj.totalSalesData;
|
||||||
|
option.series[1].data = obj.totalOrdersData;
|
||||||
|
option.series[2].data = obj.pageViewData;
|
||||||
|
option.series[3].data = obj.refundAmountData;
|
||||||
|
chartInstance.setOption(option);
|
||||||
|
};
|
||||||
|
const generateDateArray = (count) => {
|
||||||
|
const result = []
|
||||||
|
const today = new Date()
|
||||||
|
|
||||||
|
for (let i = count - 1; i >= 0; i--) {
|
||||||
|
const date = new Date(today)
|
||||||
|
date.setDate(date.getDate() - i)
|
||||||
|
|
||||||
|
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||||
|
const day = date.getDate().toString().padStart(2, '0')
|
||||||
|
|
||||||
|
result.push(`${month}-${day}`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 切换日期按钮
|
||||||
|
let dateRadio = ref(1);
|
||||||
|
let startDate = ref('');
|
||||||
|
let endDate = ref('');
|
||||||
|
const changeDateRadio = (val) => {
|
||||||
|
// val 1 按周 2 按月 3 按年
|
||||||
|
let date = generateDateRange(val);
|
||||||
|
startDate.value = date.startDate;
|
||||||
|
endDate.value = date.endDate;
|
||||||
|
|
||||||
|
// 调用各个模块的方法更新数据
|
||||||
|
loadTopLeftData();
|
||||||
|
loadEchartsData(); //真实图表数据
|
||||||
|
loadMiddleData();
|
||||||
|
loadbottomLeftData();
|
||||||
|
loadbottomRightData();
|
||||||
|
|
||||||
|
// 测试图表数据-----------
|
||||||
|
let day = 7;
|
||||||
|
if (val == 1) {
|
||||||
|
day = 7;
|
||||||
|
} else if (val == 2) {
|
||||||
|
day = 30;
|
||||||
|
} else if (val == 3) {
|
||||||
|
day = 365;
|
||||||
|
}
|
||||||
|
// echartsMockData(day); //模拟图表数据
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据给定的时间范围类型,生成相应的日期范围
|
||||||
|
* @param {number} type - 日期范围类型:1:按周 2:按月 3:按年
|
||||||
|
* @returns {Object} 包含开始日期和结束日期的对象,格式为YYYY-MM-DD
|
||||||
|
*/
|
||||||
|
function generateDateRange(type) {
|
||||||
|
// 获取今天的日期
|
||||||
|
const today = new Date();
|
||||||
|
// 结束日期为今天的日期
|
||||||
|
const endDate = new Date(today);
|
||||||
|
// 初始化开始日期为今天的日期
|
||||||
|
let startDate = new Date(today);
|
||||||
|
|
||||||
|
// 根据不同类型计算开始日期
|
||||||
|
switch(type) {
|
||||||
|
case 1: // 周
|
||||||
|
startDate.setDate(today.getDate() - 6); // 7天包括今天
|
||||||
|
break;
|
||||||
|
case 2: // 月
|
||||||
|
startDate.setDate(today.getDate() - 29); // 30天包括今天
|
||||||
|
break;
|
||||||
|
case 3: // 年
|
||||||
|
startDate.setDate(today.getDate() - 364); // 365天包括今天
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 抛出异常,提示参数类型无效
|
||||||
|
throw new Error('无效的参数类型,请输入1(周)、2(月)或3(年)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期为YYYY-MM-DD
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 返回计算出的日期范围
|
||||||
|
return {
|
||||||
|
startDate: formatDate(startDate),
|
||||||
|
endDate: formatDate(endDate)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let topLeftData = ref({});
|
||||||
|
const initTopLeftData = () => {
|
||||||
|
topLeftData.value = Object.assign({}, {
|
||||||
|
salesTotalAmount: 0, //销售总额
|
||||||
|
orderTotalNum: 0, //订单总数
|
||||||
|
viewCount: 0, //浏览量
|
||||||
|
refundSuccessAmout: 0, //成功退款金额
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 加载数据-顶部左侧模块
|
||||||
|
const loadTopLeftData = async () => {
|
||||||
|
// console.log('左上角数据更新');
|
||||||
|
try {
|
||||||
|
let response = await getAstsTransTotals({
|
||||||
|
queryStartTime: startDate.value + " 00:00:00",
|
||||||
|
queryEndTime: endDate.value + " 23:59:59",
|
||||||
|
queryType: dateRadio.value,
|
||||||
|
});
|
||||||
|
if (response.code == 200) {
|
||||||
|
topLeftData.value = response.data;
|
||||||
|
} else {
|
||||||
|
initTopLeftData();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
initTopLeftData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 中间模块
|
||||||
|
const middleData = ref([]);
|
||||||
|
const generateMockData = () => {
|
||||||
|
return Mock.mock({
|
||||||
|
"list|5": [
|
||||||
|
{ // 中间模块数据
|
||||||
|
"id|+1": 10000,
|
||||||
|
title: '@pick(["买家数量", "支付转化率", "客单价", "退款率", "加购数量"])', //标题
|
||||||
|
value: "@float(10, 200, 2, 2)", //数值
|
||||||
|
unit: '@pick(["人", "%", "元", "%", "次"])', //单位
|
||||||
|
toolTip: '@pick(["购买商品人数统计", "支付转化率 = 完成支付的订单数量 + 访问网站的用户数量 x 100%", "客单价是指每一位顾客平均购买商品金额", "退款率 = (退款订单数量 + 总订单数量) x 100%", "用户将商品加入购物车次数"])', //描述提示
|
||||||
|
ratioMethod: '@pick(["环比", "同比"])', //比率方式
|
||||||
|
ratioStatus: '@pick(["上升", "下降"])', //比率状态, 后台看存储的是汉字还是数字
|
||||||
|
ratioValue: '@float(10, 20, 1, 1)' + '%', //比率值
|
||||||
|
|
||||||
|
// 底部左侧数据
|
||||||
|
"ranking|+1": 1, //排名
|
||||||
|
goodUrl: tomato.value, //商品图片地址
|
||||||
|
goodName: "@cname", //商品信息
|
||||||
|
stockToUseRatio: "@float(10, 200, 2, 2)" + "%", //存销比
|
||||||
|
salesAmount: "@integer(1000, 20000)" + "元", //销售金额
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).list;
|
||||||
|
};
|
||||||
|
// 加载数据-中间模块
|
||||||
|
const loadMiddleData = async () => {
|
||||||
|
// console.log('中间数据更新');
|
||||||
|
// middleData.value = generateMockData();
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = await getMidleInfo({
|
||||||
|
queryStartTime: startDate.value + " 00:00:00",
|
||||||
|
queryEndTime: endDate.value + " 23:59:59",
|
||||||
|
queryType: dateRadio.value,
|
||||||
|
});
|
||||||
|
if (response.code == 200) {
|
||||||
|
middleData.value = response.data;
|
||||||
|
} else {
|
||||||
|
middleData.value = [];
|
||||||
|
}
|
||||||
|
} catch (error) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 底部左侧模块
|
||||||
|
const tableData = ref([]);
|
||||||
|
let tableLoading = ref(false);
|
||||||
|
const columns = ref([
|
||||||
|
{ prop: "ranking", label: "排名", slotName: "ranking", width: 66 },
|
||||||
|
{ prop: "goodUrl", label: "商品图片", slotName: "goodUrl", width: 80, align: "left" },
|
||||||
|
{ prop: "goodName", label: "商品名称", width: "auto", align: "left" },
|
||||||
|
{ prop: "stockToUseRatio", label: "存销比", width: 70, align: "left" },
|
||||||
|
{ prop: "salesAmount", label: "销售金额", width: 100, align: "left" },
|
||||||
|
]);
|
||||||
|
// 加载数据-底部左侧模块
|
||||||
|
const loadbottomLeftData = async () => {
|
||||||
|
// console.log('左下角数据更新');
|
||||||
|
// tableLoading.value = true;
|
||||||
|
// tableData.value = generateMockData();
|
||||||
|
// tableLoading.value = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
tableLoading.value = true;
|
||||||
|
let response = await getGoodsSalesInfo({
|
||||||
|
queryStartTime: startDate.value + " 00:00:00",
|
||||||
|
queryEndTime: endDate.value + " 23:59:59",
|
||||||
|
queryType: dateRadio.value,
|
||||||
|
orderByType: 0 // 0: 按照销售金额排序 2: 按照销售数量排序
|
||||||
|
});
|
||||||
|
tableLoading.value = false;
|
||||||
|
if (response.code == 200) {
|
||||||
|
tableData.value = response.data;
|
||||||
|
} else {
|
||||||
|
tableData.value = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
tableLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const afterSalesData = ref({});
|
||||||
|
// 加载数据-底部右侧模块
|
||||||
|
const loadbottomRightData = async () => {
|
||||||
|
// console.log('右下角数据更新');
|
||||||
|
// afterSalesData.value = {
|
||||||
|
// totalAfterSalesOrders: 1128,
|
||||||
|
// totalRefundAmount: 265,
|
||||||
|
// totalRefundOrders: 129,
|
||||||
|
// warningProductInfos: [
|
||||||
|
// { goodUrl: tomato.value, goodName: "耿马西红柿耿马西红柿耿马西红柿耿马西红柿耿马西红柿", refundedOrders: "25单", refundAmount: '129元' },
|
||||||
|
// { goodUrl: tomato.value, goodName: "耿马西红柿", refundedOrders: "36单", refundAmount: '265元' },
|
||||||
|
// { goodUrl: tomato.value, goodName: "耿马西红柿", refundedOrders: "51单", refundAmount: '146元' },
|
||||||
|
// { goodUrl: tomato.value, goodName: "耿马西红柿耿马西红柿耿马西红柿耿马西红柿耿马西红柿", refundedOrders: "25单", refundAmount: '239元' },
|
||||||
|
// { goodUrl: tomato.value, goodName: "耿马西红柿", refundedOrders: "36单", refundAmount: '365元' },
|
||||||
|
// { goodUrl: tomato.value, goodName: "耿马西红柿", refundedOrders: "51单", refundAmount: '198元' },
|
||||||
|
// ],
|
||||||
|
// };
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = await getAfterSalesData({
|
||||||
|
queryStartTime: startDate.value + " 00:00:00",
|
||||||
|
queryEndTime: endDate.value + " 23:59:59",
|
||||||
|
queryType: dateRadio.value,
|
||||||
|
});
|
||||||
|
if (response.code == 200) {
|
||||||
|
afterSalesData.value = response.data;
|
||||||
|
}
|
||||||
|
} catch (error) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const chartContainer = ref(null);
|
||||||
|
const middleRef = ref(null);
|
||||||
|
const warningGoodsRef = ref(null);
|
||||||
|
const tableViewportHeight = ref(0);
|
||||||
|
// 精确计算可用高度
|
||||||
|
const calculateTableHeight = () => {
|
||||||
|
// 获取窗口总高度
|
||||||
|
const windowHeight = window.innerHeight;
|
||||||
|
|
||||||
|
// 获取各组件高度
|
||||||
|
const chartContainerHeight = chartContainer.value?.offsetHeight || 0;
|
||||||
|
const middleRefHeight = middleRef.value?.offsetHeight || 0;
|
||||||
|
|
||||||
|
// 计算容器内边距补偿(根据实际样式调整)
|
||||||
|
const paddingCompensation = 306;
|
||||||
|
|
||||||
|
// 最终计算
|
||||||
|
const height = windowHeight - chartContainerHeight - middleRefHeight - paddingCompensation;
|
||||||
|
tableViewportHeight.value = height < 300 ? 300 : height;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async() => {
|
||||||
|
initTopLeftData
|
||||||
|
await initChart();
|
||||||
|
changeDateRadio(1);
|
||||||
|
await nextTick();
|
||||||
|
calculateTableHeight();
|
||||||
|
window.addEventListener("resize", calculateTableHeight);
|
||||||
|
});
|
||||||
// 组件卸载前销毁图表
|
// 组件卸载前销毁图表
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
if (chartInstance) {
|
if (chartInstance) {
|
||||||
@ -449,15 +844,7 @@ onBeforeUnmount(() => {
|
|||||||
chartInstance.dispose();
|
chartInstance.dispose();
|
||||||
chartInstance = null;
|
chartInstance = null;
|
||||||
}
|
}
|
||||||
});
|
window.removeEventListener('resize', calculateTableHeight);
|
||||||
// 调整图表大小
|
|
||||||
const resizeChart = () => {
|
|
||||||
if (chartInstance) {
|
|
||||||
chartInstance.resize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
onMounted(() => {
|
|
||||||
initChart();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -465,7 +852,7 @@ onMounted(() => {
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: 50px;
|
margin-right: 20px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
}
|
}
|
||||||
@ -476,7 +863,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
.number {
|
.number {
|
||||||
margin-right: 100px;
|
margin-right: 100px;
|
||||||
margin-top: 20px;
|
margin-top: 16px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
@ -485,38 +872,39 @@ onMounted(() => {
|
|||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: space-between;
|
||||||
|
gap: 20px;
|
||||||
}
|
}
|
||||||
.app-container-title {
|
.app-container-title {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
padding-right: 10px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.app-container-data {
|
.app-container-data {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 20px;
|
padding: 20px 10px 20px 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
.app-container-data-left {
|
.app-container-data-left {
|
||||||
width: 40%;
|
width: 500px;
|
||||||
.app-container-data-left-top {
|
.app-container-data-left-top {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.app-container-data-left-bottom {
|
.app-container-data-left-bottom {
|
||||||
margin-top: 50px;
|
margin-top: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.app-container-data-right {
|
.app-container-data-right {
|
||||||
width: 60%;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.app-container-block {
|
.app-container-block {
|
||||||
width: 250px;
|
flex: 1;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px 10px 10px 14px;
|
||||||
margin-left: 26px;
|
|
||||||
.app-container-block-title {
|
.app-container-block-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@ -529,6 +917,59 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
.app-container-block-proportion {
|
.app-container-block-proportion {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
.el-icon {
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.el-popper.tooltip-box-item) {
|
||||||
|
max-width: 200px; /* 限制最大宽度 */
|
||||||
|
word-break: break-word; /* 长单词或URL换行 */
|
||||||
|
white-space: normal !important; /* 覆盖默认的 nowrap */
|
||||||
|
}
|
||||||
|
.tooltip-box-item {
|
||||||
|
width: 200px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bottom-flex-box {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 20px;
|
||||||
|
.bottom-box-item {
|
||||||
|
flex: 1;
|
||||||
|
width: 50%;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 20px 20px 0px 20px;
|
||||||
|
}
|
||||||
|
.bottom-box-item-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.bottom-box-item-content {
|
||||||
|
height: 300px;
|
||||||
|
min-height: 300px;
|
||||||
|
.bottom-box-summary {
|
||||||
|
display: flex;
|
||||||
|
margin: 10px 0;
|
||||||
|
gap: 20px;
|
||||||
|
width: 100%;
|
||||||
|
.bottom-box-summary-item {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
.bottom-box-summary-title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #999;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.bottom-box-summary-value {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user