电商交易-交易分析页面优化空数据时的默认展示;表格组件增加formatter处理逻辑

This commit is contained in:
郭永超 2025-07-02 14:42:23 +08:00
parent 466cef50a6
commit ef7140e446
2 changed files with 179 additions and 52 deletions

View File

@ -78,6 +78,10 @@
<template v-if="column.slotName" #default="scope"> <template v-if="column.slotName" #default="scope">
<slot :name="column.slotName" :row="scope.row"></slot> <slot :name="column.slotName" :row="scope.row"></slot>
</template> </template>
<!-- 动态处理 formatter -->
<template v-else-if="column.formatter" #default="{ row, colum, $index }">
{{ column.formatter(row, colum, row[column.prop], $index) }}
</template>
</el-table-column> </el-table-column>
</template> </template>
</el-table> </el-table>

View File

@ -1,9 +1,15 @@
<template> <template>
<div class="app-container customer-control"> <div class="app-container customer-control">
<div style="overflow-y: auto;overflow-x: hidden; height: 100%;"> <div style="overflow-y: auto; overflow-x: hidden; height: 100%">
<div class="app-container-data" ref="chartContainer"> <div class="app-container-data" ref="chartContainer">
<div class="app-container-title">运营看板 <div class="app-container-title">
<el-radio-group v-model="dateRadio" @change="changeDateRadio" size="small" style="float: right;"> 运营看板
<el-radio-group
v-model="dateRadio"
@change="changeDateRadio"
size="small"
style="float: right"
>
<el-radio-button label="周" :value="1" /> <el-radio-button label="周" :value="1" />
<el-radio-button label="月" :value="2" /> <el-radio-button label="月" :value="2" />
<el-radio-button label="年" :value="3" /> <el-radio-button label="年" :value="3" />
@ -14,14 +20,22 @@
<div class="app-container-data-left-top"> <div class="app-container-data-left-top">
<div> <div>
<div class="title"> <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>
</div> </div>
<div class="number">{{ topLeftData.salesTotalAmount }}</div> <div class="number">{{ topLeftData.salesTotalAmount }}</div>
</div> </div>
<div> <div>
<div class="title"> <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>
</div> </div>
<div class="number">{{ topLeftData.orderTotalNum }}</div> <div class="number">{{ topLeftData.orderTotalNum }}</div>
@ -30,14 +44,22 @@
<div class="app-container-data-left-bottom"> <div class="app-container-data-left-bottom">
<div> <div>
<div class="title"> <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>
</div> </div>
<div class="number">{{ topLeftData.viewCount }}</div> <div class="number">{{ topLeftData.viewCount }}</div>
</div> </div>
<div> <div>
<div class="title"> <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>
</div> </div>
<div class="number">{{ topLeftData.refundSuccessAmout }}</div> <div class="number">{{ topLeftData.refundSuccessAmout }}</div>
@ -51,32 +73,42 @@
</div> </div>
<!-- 中间模块 --> <!-- 中间模块 -->
<div class="app-container-list" ref="middleRef"> <div class="app-container-list" ref="middleRef">
<div class="app-container-block" v-for="(item, index) in middleData" :key="index"> <div
<div class="app-container-block-title">{{ item.title }} 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> <template #reference>
<el-icon color="#c5c5c5" style="float: right;"> <el-icon color="#c5c5c5" style="float: right">
<QuestionFilled /> <QuestionFilled />
</el-icon> </el-icon>
</template> </template>
</el-popover> </el-popover>
</div> </div>
<div class="app-container-block-price"> <div class="app-container-block-price">
{{ item.valueStr ?? '--' }} {{ item.valueStr ?? "--" }}
<text style="font-size: 12px; color: #999999; margin-left: 5px"> <text style="font-size: 12px; color: #999999; margin-left: 5px">
{{ item.unit ?? '' }} {{ item.unit ?? "" }}
</text> </text>
</div> </div>
<div class="app-container-block-proportion"> <div class="app-container-block-proportion">
{{ item.ratioMethod }} {{ item.ratioMethod }}
<text :style="{ 'font-size': '12px', color: item.ratioStatus == '下降' ? 'red' : 'green' }"> <text
:style="{
'font-size': '12px',
color: item.ratioStatus == '下降' ? 'red' : 'green',
}"
>
<el-icon v-if="item.ratioStatus == '下降'"> <el-icon v-if="item.ratioStatus == '下降'">
<CaretBottom /> <CaretBottom />
</el-icon> </el-icon>
<el-icon v-else> <el-icon v-else>
<CaretTop /> <CaretTop />
</el-icon> </el-icon>
{{ item.ratioValue ?? '' }}% {{ item.ratioValue ?? "" }}%
</text> </text>
</div> </div>
</div> </div>
@ -85,20 +117,38 @@
<div class="bottom-flex-box"> <div class="bottom-flex-box">
<div class="bottom-box-item"> <div class="bottom-box-item">
<div class="bottom-box-item-title">商品销量</div> <div class="bottom-box-item-title">商品销量</div>
<div class="bottom-box-item-content" :style="{ height: tableViewportHeight + 'px' }"> <div
<tableComponent :table-data="tableData" :columns="columns" :show-border="false" :show-pagination="false" class="bottom-box-item-content"
:loading="tableLoading"> :style="{ height: tableViewportHeight + 'px' }"
>
<tableComponent
:table-data="tableData"
:columns="columns"
:show-border="false"
:show-pagination="false"
:loading="tableLoading"
>
<!-- 自定义-排名图片 --> <!-- 自定义-排名图片 -->
<template #ranking="slotProps"> <template #ranking="slotProps">
<div class="table-cell-img-box" style="width: 40px;height: 40px;" v-if="slotProps.row.ranking == 1"> <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="" /> <img :src="img1" class="table-cell-img" alt="" />
</div> </div>
<div class="table-cell-img-box" style="width: 40px;height: 40px;" <div
v-else-if="slotProps.row.ranking == 2"> 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="" /> <img :src="img2" class="table-cell-img" alt="" />
</div> </div>
<div class="table-cell-img-box" style="width: 40px;height: 40px;" <div
v-else-if="slotProps.row.ranking == 3"> 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="" /> <img :src="img3" class="table-cell-img" alt="" />
</div> </div>
<div v-else>{{ slotProps.row.ranking }}</div> <div v-else>{{ slotProps.row.ranking }}</div>
@ -106,8 +156,15 @@
<!-- 自定义-商品图片 --> <!-- 自定义-商品图片 -->
<template #goodUrl="slotProps"> <template #goodUrl="slotProps">
<div class="table-cell-img-box" style="width: 40px;height: 40px;"> <div
<img :src="slotProps.row.goodUrl" class="table-cell-img" alt="" /> class="table-cell-img-box"
style="width: 40px; height: 40px"
>
<img
:src="slotProps.row.goodUrl"
class="table-cell-img"
alt=""
/>
</div> </div>
</template> </template>
</tableComponent> </tableComponent>
@ -117,55 +174,114 @@
<div class="bottom-box-item-title">售后概况</div> <div class="bottom-box-item-title">售后概况</div>
<div class="bottom-box-item-content"> <div class="bottom-box-item-content">
<!-- --> <!-- -->
<div class="bottom-box-summary" style="margin: 20px 0;"> <div class="bottom-box-summary" style="margin: 20px 0">
<div class="bottom-box-summary-item"> <div class="bottom-box-summary-item">
<div class="bottom-box-summary-title">售后订单数量()</div> <div class="bottom-box-summary-title">售后订单数量()</div>
<div class="bottom-box-summary-value">{{ afterSalesData.totalAfterSalesOrders }}</div> <div class="bottom-box-summary-value">
{{ afterSalesData.totalAfterSalesOrders }}
</div>
</div> </div>
<div class="bottom-box-summary-item"> <div class="bottom-box-summary-item">
<div class="bottom-box-summary-title">退货退款金额()</div> <div class="bottom-box-summary-title">退货退款金额()</div>
<div class="bottom-box-summary-value">{{ afterSalesData.totalRefundAmount }}</div> <div class="bottom-box-summary-value">
{{ afterSalesData.totalRefundAmount }}
</div>
</div> </div>
<div class="bottom-box-summary-item"> <div class="bottom-box-summary-item">
<div class="bottom-box-summary-title">退货退款订单数量()</div> <div class="bottom-box-summary-title">退货退款订单数量()</div>
<div class="bottom-box-summary-value">{{ afterSalesData.totalRefundOrders }}</div> <div class="bottom-box-summary-value">
{{ afterSalesData.totalRefundOrders }}
</div>
</div> </div>
</div> </div>
<!-- --> <!-- -->
<div class="bottom-box-summary" style="line-height: 30px;margin: 0;"> <div
class="bottom-box-summary"
style="line-height: 30px; margin: 0"
>
<div class="bottom-box-summary-item"> <div class="bottom-box-summary-item">
<img :src="alert" style="width: 30px;height: 30px;" alt="" /> <img :src="alert" style="width: 30px; height: 30px" alt="" />
<div class="bottom-box-summary-title" <div
style="display: inline-block;vertical-align: middle;margin-left: 8px;"> class="bottom-box-summary-title"
预警商品</div> style="
display: inline-block;
vertical-align: middle;
margin-left: 8px;
"
>
预警商品
</div>
</div> </div>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;"> <div
class="bottom-box-summary-item"
style="width: 120px; flex: none"
>
<div class="bottom-box-summary-title">退款订单量</div> <div class="bottom-box-summary-title">退款订单量</div>
</div> </div>
<div class="bottom-box-summary-item" style="width: 130px;flex: none;"> <div
class="bottom-box-summary-item"
style="width: 130px; flex: none"
>
<div class="bottom-box-summary-title">退款金额</div> <div class="bottom-box-summary-title">退款金额</div>
</div> </div>
</div> </div>
<div ref="warningGoodsRef" style="overflow-y: auto; height: 150px;" <div
:style="{ height: tableViewportHeight - 150 + 'px' }"> ref="warningGoodsRef"
<div v-if="afterSalesData.warningProductInfos.length == 0" style="color: #909399; font-size: 14px; text-align: center; padding-top: 20px"> 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> </div>
<template v-else> <template v-else>
<div class="bottom-box-summary" style="line-height: 40px;margin: 0;" <div
v-for="(item, index) in afterSalesData.warningProductInfos" :key="index"> class="bottom-box-summary"
<div class="bottom-box-summary-item" style="display: flex;"> style="line-height: 40px; margin: 0"
<img :src="item.goodUrl" style="width: 40px;height: 40px;" alt="" /> v-for="(item, index) in afterSalesData.warningProductInfos"
<div class="bottom-box-summary-title text-ellipsis" :key="index"
style="flex: 1; vertical-align: top;color: #000;margin-left: 8px;" :title="item.goodName"> >
<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 }} {{ item.goodName }}
</div> </div>
</div> </div>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;"> <div
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundedOrders }}</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>
<div class="bottom-box-summary-item" style="width: 120px;flex: none;"> <div
<div class="bottom-box-summary-title" style="color: #000;">{{ item.refundAmount }}</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> </div>
</template> </template>
@ -679,7 +795,10 @@ const loadTopLeftData = async () => {
queryType: dateRadio.value, queryType: dateRadio.value,
}); });
if (response.code == 200) { if (response.code == 200) {
topLeftData.value = response.data; topLeftData.value.salesTotalAmount = response.data.salesTotalAmount ?? 0;
topLeftData.value.orderTotalNum = response.data.orderTotalNum ?? 0;
topLeftData.value.viewCount = response.data.viewCount ?? 0;
topLeftData.value.refundSuccessAmout = response.data.refundSuccessAmout ?? 0;
} else { } else {
initTopLeftData(); initTopLeftData();
} }
@ -739,8 +858,8 @@ const columns = ref([
{ prop: "ranking", label: "排名", slotName: "ranking", width: 66 }, { prop: "ranking", label: "排名", slotName: "ranking", width: 66 },
{ prop: "goodUrl", label: "商品图片", slotName: "goodUrl", width: 80, align: "left" }, { prop: "goodUrl", label: "商品图片", slotName: "goodUrl", width: 80, align: "left" },
{ prop: "goodName", label: "商品名称", width: "auto", align: "left" }, { prop: "goodName", label: "商品名称", width: "auto", align: "left" },
{ prop: "stockToUseRatio", label: "存销比", width: 70, align: "left" }, { prop: "stockToUseRatio", label: "存销比", width: 70, align: "left", formatter: (row) => `${row.stockToUseRatio ?? 0}%` },
{ prop: "salesAmount", label: "销售金额", width: 100, align: "left" }, { prop: "salesAmount", label: "销售金额", width: 100, align: "left", formatter: (row) => `${row.salesAmount ?? 0}` },
]); ]);
// - // -
const loadbottomLeftData = async () => { const loadbottomLeftData = async () => {
@ -801,7 +920,11 @@ const loadbottomRightData = async () => {
queryType: dateRadio.value, queryType: dateRadio.value,
}); });
if (response.code == 200) { if (response.code == 200) {
afterSalesData.value = response.data; afterSalesData.value.totalAfterSalesOrders = response.data.totalAfterSalesOrders ?? 0;
afterSalesData.value.totalRefundAmount = response.data.totalRefundAmount ?? 0;
afterSalesData.value.totalAfterSalesOrders = response.data.totalAfterSalesOrders ?? 0;
afterSalesData.value.warningProductInfos = response.data.warningProductInfos ?? [];
console.log(afterSalesData.value);
} }
} catch (error) { } } catch (error) { }
}; };