电商交易-交易分析页面优化空数据时的默认展示

This commit is contained in:
郭永超 2025-07-02 11:44:04 +08:00
parent 26551e1d27
commit d14a0b6be2

View File

@ -14,22 +14,14 @@
<div class="app-container-data-left-top">
<div>
<div class="title">
<img
class="title-image"
src="../../assets/images/money.png"
alt=""
/>
<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=""
/>
<img class="title-image" src="../../assets/images/order.png" alt="" />
<div>订单总数()</div>
</div>
<div class="number">{{ topLeftData.orderTotalNum }}</div>
@ -38,22 +30,14 @@
<div class="app-container-data-left-bottom">
<div>
<div class="title">
<img
class="title-image"
src="../../assets/images/views.png"
alt=""
/>
<img class="title-image" src="../../assets/images/views.png" alt="" />
<div>浏览量()</div>
</div>
<div class="number">{{ topLeftData.viewCount }}</div>
</div>
<div>
<div class="title">
<img
class="title-image"
src="../../assets/images/money1.png"
alt=""
/>
<img class="title-image" src="../../assets/images/money1.png" alt="" />
<div>成功退款金额()</div>
</div>
<div class="number">{{ topLeftData.refundSuccessAmout }}</div>
@ -67,30 +51,32 @@
</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" 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"
>
<el-popover title="" :content="item.toolTip" placement="left-start">
<template #reference>
<el-icon color="#c5c5c5" style="float: right;"><QuestionFilled /></el-icon>
<el-icon color="#c5c5c5" style="float: right;">
<QuestionFilled />
</el-icon>
</template>
</el-popover>
</div>
<div class="app-container-block-price">
{{ item.valueStr??'--' }}
{{ item.valueStr ?? '--' }}
<text style="font-size: 12px; color: #999999; margin-left: 5px">
{{ item.unit??'' }}
{{ 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 :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>
@ -100,22 +86,19 @@
<div class="bottom-box-item">
<div class="bottom-box-item-title">商品销量</div>
<div class="bottom-box-item-content" :style="{ height: tableViewportHeight + 'px' }">
<tableComponent
:table-data="tableData"
:columns="columns"
:show-border="false"
:show-pagination="false"
:loading="tableLoading"
>
<tableComponent :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">
<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">
<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>
@ -151,8 +134,10 @@
<!-- -->
<div class="bottom-box-summary" style="line-height: 30px;margin: 0;">
<div class="bottom-box-summary-item">
<img :src="alert" style="width: 30px;height: 30px;" alt="" />
<div class="bottom-box-summary-title" style="display: inline-block;vertical-align: middle;margin-left: 8px;">预警商品</div>
<img :src="alert" style="width: 30px;height: 30px;" alt="" />
<div class="bottom-box-summary-title"
style="display: inline-block;vertical-align: middle;margin-left: 8px;">
预警商品</div>
</div>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
<div class="bottom-box-summary-title">退款订单量</div>
@ -161,24 +146,30 @@
<div class="bottom-box-summary-title">退款金额</div>
</div>
</div>
<div ref="warningGoodsRef" style="overflow-y: auto; height: 150px;" :style="{ height: tableViewportHeight -150 + 'px' }">
<div class="bottom-box-summary" style="line-height: 40px;margin: 0;"
v-for="(item, index) in afterSalesData.warningProductInfos" :key="index">
<div class="bottom-box-summary-item" style="display: flex;">
<img :src="item.goodUrl" style="width: 40px;height: 40px;" alt="" />
<div class="bottom-box-summary-title text-ellipsis" style="flex: 1; vertical-align: top;color: #000;margin-left: 8px;" :title="item.goodName">
{{ item.goodName }}
<div ref="warningGoodsRef" style="overflow-y: auto; height: 150px;"
:style="{ height: tableViewportHeight - 150 + 'px' }">
<div v-if="afterSalesData.warningProductInfos.length == 0" style="color: #909399; font-size: 14px; text-align: center; padding-top: 20px">
暂无数据
</div>
<template v-else>
<div class="bottom-box-summary" style="line-height: 40px;margin: 0;"
v-for="(item, index) in afterSalesData.warningProductInfos" :key="index">
<div class="bottom-box-summary-item" style="display: flex;">
<img :src="item.goodUrl" style="width: 40px;height: 40px;" alt="" />
<div class="bottom-box-summary-title text-ellipsis"
style="flex: 1; vertical-align: top;color: #000;margin-left: 8px;" :title="item.goodName">
{{ item.goodName }}
</div>
</div>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundedOrders }}</div>
</div>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundAmount }}</div>
</div>
</div>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundedOrders }}</div>
</div>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;">
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundAmount }}</div>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
@ -256,7 +247,7 @@ const option = {
extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5); text-align: left;',
formatter: function (params) {
let result = params[0].name + '<br>'; // x"1"
params.forEach((param,index) => {
params.forEach((param, index) => {
// param.color
const colorDot = `<span style="
display:inline-block;
@ -267,13 +258,13 @@ const option = {
background-color:${colorList[index]}">
</span>`;
let unit = "";
if(param.seriesName == '销售总额') {
if (param.seriesName == '销售总额') {
unit = "元";
} else if(param.seriesName == '订单总数') {
} else if (param.seriesName == '订单总数') {
unit = "个";
} else if(param.seriesName == '浏览量') {
} else if (param.seriesName == '浏览量') {
unit = "人次";
} else if(param.seriesName == '成功退款金额') {
} else if (param.seriesName == '成功退款金额') {
unit = "元";
}
result += `${colorDot} ${param.seriesName}: ${param.value} ${unit} <br>`;
@ -559,16 +550,16 @@ const echartsMockData = (count = 7) => {
let obj = Mock.mock({
// x (/)
xData: xzData,
// (500-50002)
[`totalSalesData|${count}`]: ['@float(100, 500, 2, 2)'],
// (1-100)
[`totalOrdersData|${count}`]: ['@integer(10, 100)'],
// (1000-10000)
[`pageViewData|${count}`]: ['@integer(1000, 10000)'],
// 退 (1-1002)
[`refundAmountData|${count}`]: ['@float(10, 100, 2, 2)']
})
@ -582,14 +573,14 @@ const echartsMockData = (count = 7) => {
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
@ -600,26 +591,26 @@ const generateDateArray = (count) => {
let dateRadio = ref(1);
let startDate = ref('');
let endDate = ref('');
const changeDateRadio = (val) => {
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) {
if (val == 1) {
day = 7;
} else if (val == 2) {
} else if (val == 2) {
day = 30;
} else if (val == 3) {
} else if (val == 3) {
day = 365;
}
// echartsMockData(day); //
@ -637,9 +628,9 @@ function generateDateRange(type) {
const endDate = new Date(today);
//
let startDate = new Date(today);
//
switch(type) {
switch (type) {
case 1: //
startDate.setDate(today.getDate() - 6); // 7
break;
@ -653,7 +644,7 @@ function generateDateRange(type) {
//
throw new Error('无效的参数类型请输入1(周)、2(月)或3(年)');
}
// YYYY-MM-DD
const formatDate = (date) => {
const year = date.getFullYear();
@ -661,7 +652,7 @@ function generateDateRange(type) {
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
};
//
return {
startDate: formatDate(startDate),
@ -670,7 +661,7 @@ function generateDateRange(type) {
}
let topLeftData = ref({});
const initTopLeftData = () => {
const initTopLeftData = () => {
topLeftData.value = Object.assign({}, {
salesTotalAmount: 0, //
orderTotalNum: 0, //
@ -772,12 +763,20 @@ const loadbottomLeftData = async () => {
} else {
tableData.value = [];
}
} catch (error) {
} catch (error) {
tableLoading.value = false;
}
};
const afterSalesData = ref({});
const afterSalesData = ref({
totalAfterSalesOrders: 0, //
totalRefundAmount: 0, //退
totalRefundOrders: 0, //
warningProductInfos: [
//
// { goodUrl: tomato.value, goodName: "西", refundedOrders: "25", refundAmount: '129' },
],
});
// -
const loadbottomRightData = async () => {
// console.log('');
@ -829,7 +828,7 @@ const calculateTableHeight = () => {
tableViewportHeight.value = height < 300 ? 300 : height;
};
onMounted(async() => {
onMounted(async () => {
initTopLeftData
await initChart();
changeDateRadio(1);
@ -856,11 +855,13 @@ onBeforeUnmount(() => {
font-size: 18px;
color: #999999;
}
.title-image {
margin-right: 10px;
width: 38px;
height: 38px;
}
.number {
margin-right: 100px;
margin-top: 16px;
@ -868,6 +869,7 @@ onBeforeUnmount(() => {
font-weight: bold;
color: #000000;
}
.app-container-list {
margin-top: 20px;
display: flex;
@ -875,66 +877,84 @@ onBeforeUnmount(() => {
justify-content: space-between;
gap: 20px;
}
.app-container-title {
margin-bottom: 20px;
padding-right: 10px;
font-size: 20px;
font-weight: bold;
}
.app-container-data {
border-radius: 10px;
padding: 20px 10px 20px 20px;
width: 100%;
background-color: #fff;
.app-container-data-left {
width: 500px;
.app-container-data-left-top {
display: flex;
}
.app-container-data-left-bottom {
margin-top: 40px;
display: flex;
}
}
.app-container-data-right {
flex: 1;
}
}
.app-container-block {
flex: 1;
background-color: #fff;
border-radius: 10px;
padding: 10px 10px 10px 14px;
.app-container-block-title {
font-size: 18px;
font-weight: bold;
}
.app-container-block-price {
font-size: 18px;
color: #42b983;
font-weight: bold;
margin: 10px 0;
}
.app-container-block-proportion {
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 */
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%;
@ -942,27 +962,33 @@ onBeforeUnmount(() => {
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%;
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;