@ -1,144 +1,215 @@
< template >
< div class = "app-container" >
< div class = "app-container-data" >
< div class = "app-container-title" > 运营看板 < / div >
< div style = "display: flex" >
< div class = "app-container-data-left" >
< div class = "app-container-data-left-top" >
< div >
< div class = "title" >
< img
class = "title-image"
src = "../../assets/images/money.png"
alt = ""
/ >
< div > 销售总额 ( 元 ) < / div >
< div class = "app-container customer-control" >
< div style = "overflow-y: auto;overflow-x: hidden; height: 100%;" >
< div class = "app-container-data" ref = "chartContainer" >
< div class = "app-container-title" > 运营看板
< el-radio-group v-model = "dateRadio" @change="changeDateRadio" size="small" style="float: right;" >
< el-radio-button label = "周" :value = "1" / >
< el-radio-button label = "月" :value = "2" / >
< el-radio-button label = "年" :value = "3" / >
< / el-radio-group >
< / div >
< div style = "display: flex" >
< div class = "app-container-data-left" >
< div class = "app-container-data-left-top" >
< 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 class = "number" > 4 , 541.00 < / div >
< / div >
< div >
< div class = "title" >
< img
class = "title-image"
src = "../../assets/images/order.png"
alt = ""
/ >
< div > 订单总数 ( 单 ) < / div >
< div class = "app-container-data-left-bottom" >
< div >
< div class = "title" >
< 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 = ""
/ >
< div > 成功退款金额 ( 元 ) < / div >
< / div >
< div class = "number" > { { topLeftData . refundSuccessAmout } } < / div >
< / div >
< div class = "number" > 45 < / div >
< / div >
< / div >
< div class = "app-container-data-left-bottom" >
< 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 class = "app-container-data-right" >
< div ref = "chartRef" style = "width: 100%; height: 200px" > < / div >
< / div >
< / div >
< div class = "app-container-data-right" >
< div ref = "chartRef" style = "width: 100%; height: 200px" > < / div >
< / 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 class = "app-container-list" >
< div class = "app-container-block" >
< div class = "app-container-block-title" > 销售总额 < / div >
< div class = "app-container-block-price" >
15698 < text style = "font-size: 10px; color: #999999; margin-left: 10px"
> 元 < / t e x t
>
<!-- 底部模块 -- >
< div class = "bottom-flex-box" >
< 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"
>
<!-- 自定义 - 排名图片 -- >
< 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 class = "app-container-block-proportion" >
环比 : < text style = "color: red; font-size: 12px" > ↓ 2.6 % < / text >
< / div >
< / div >
< div class = "app-container-block" >
< div class = "app-container-block-title" > 订单总数 < / div >
< div class = "app-container-block-price" >
52 < text style = "font-size: 10px; color: #999999; margin-left: 10px"
> 单 < / t e x t
>
< / div >
< div class = "app-container-block-proportion" >
环比 : < text style = "color: red; font-size: 12px" > ↓ 2.6 % < / text >
< / div >
< / div >
< div class = "app-container-block" >
< div class = "app-container-block-title" > 支付转化率 < / div >
< div class = "app-container-block-price" >
16.56 < text style = "font-size: 10px; color: #999999; margin-left: 10px"
> % < / t e x t
>
< / div >
< div class = "app-container-block-proportion" >
环比 : < text style = "color: red; font-size: 12px" > ↓ 2.6 % < / text >
< / div >
< / div >
< div class = "app-container-block" >
< div class = "app-container-block-title" > 客单价 < / div >
< div class = "app-container-block-price" >
12.33 < text style = "font-size: 10px; color: #999999; margin-left: 10px"
> 元 < / t e x t
>
< / div >
< div class = "app-container-block-proportion" >
环比 : < text style = "color: red; font-size: 12px" > ↓ 2.6 % < / text >
< / div >
< / div >
< div class = "app-container-block" >
< div class = "app-container-block-title" > 成功退款金额 < / div >
< div class = "app-container-block-price" >
152.5 < text style = "font-size: 10px; color: #999999; margin-left: 10px"
> 元 < / t e x t
>
< / div >
< div class = "app-container-block-proportion" >
环比 : < text style = "color: red; font-size: 12px" > ↓ 2.6 % < / text >
< / div >
< / div >
< div class = "app-container-block" >
< div class = "app-container-block-title" > 浏览量 < / div >
< div class = "app-container-block-price" >
156988 < text style = "font-size: 10px; color: #999999; margin-left: 10px"
> 次 < / t e x t
>
< / div >
< div class = "app-container-block-proportion" >
环比 : < text style = "color: red; font-size: 12px" > ↓ 2.6 % < / text >
< div class = "bottom-box-item" >
< div class = "bottom-box-item-title" > 售后概况 < / div >
< div class = "bottom-box-item-content" >
<!-- 上 -- >
< div class = "bottom-box-summary" style = "margin: 20px 0;" >
< div class = "bottom-box-summary-item" >
< div class = "bottom-box-summary-title" > 售后订单数量 ( 单 ) < / div >
< div class = "bottom-box-summary-value" > { { afterSalesData . totalAfterSalesOrders } } < / div >
< / div >
< div class = "bottom-box-summary-item" >
< div class = "bottom-box-summary-title" > 退货退款金额 ( 元 ) < / div >
< div class = "bottom-box-summary-value" > { { afterSalesData . totalRefundAmount } } < / div >
< / div >
< div class = "bottom-box-summary-item" >
< div class = "bottom-box-summary-title" > 退货退款订单数量 ( 单 ) < / div >
< div class = "bottom-box-summary-value" > { { afterSalesData . totalRefundOrders } } < / div >
< / div >
< / div >
<!-- 下 -- >
< 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 >
< / div >
< div class = "bottom-box-summary-item" style = "width: 120px;flex: none;" >
< div class = "bottom-box-summary-title" > 退款订单量 < / div >
< / div >
< div class = "bottom-box-summary-item" style = "width: 130px;flex: none;" >
< 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 >
< / 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 >
< / div >
< / div >
< / div >
< / div >
< / div >
< / template >
< 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 { 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" ) ;
/ / 图 表 D O M 引 用
const chartRef = ref ( null ) ;
/ / E C h a r t s 实 例
let chartInstance = null ;
/ / 颜 色 列 表
const colorList = [ '#3685FE' , '#FFD500' , '#25BF82' ] ;
const colorList = [ '#3685FE' , '#FFD500' , '#25BF82' , '#FF7F00' ];
/ / 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 = {
@ -150,12 +221,12 @@ const option = {
fontWeight : 400 ,
} ,
left : 'center' ,
top : ' 5 %',
top : ' 0 %',
} ,
legend : {
icon : 'circle' ,
top : '0' ,
right : ' 5 %',
right : ' 30 %',
itemWidth : 6 ,
itemGap : 20 ,
textStyle : {
@ -169,8 +240,8 @@ const option = {
show : true ,
backgroundColor : '#fff' ,
color : '#556677' ,
borderColor : 'rgba(0,0,0 ,0 )',
shadowColor : 'rgba(0,0,0,0 )',
borderColor : 'rgba(0,0,0 )',
shadowColor : 'rgba(0,0,0,0 .3 )',
shadowOffsetY : 0 ,
} ,
lineStyle : {
@ -185,7 +256,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 ) => {
params . forEach ( ( param ,index ) => {
/ / 获 取 系 列 颜 色 ( p a r a m . c o l o r )
const colorDot = ` <span style="
display : inline - block ;
@ -193,20 +264,33 @@ const option = {
border - radius : 50 % ;
width : 10 px ;
height : 10 px ;
background - color : $ { param. color } " >
background - color : $ { colorList[ index ] } " >
< / 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 ;
} ,
} ,
grid : {
top : '20%' ,
left : 26 ,
right : 26 ,
bottom : 40 , / / 底 部 留 白 给 图 例
} ,
xAxis : [
{
type : 'category' ,
data : xData ,
data : xData .value ,
axisLine : {
lineStyle : {
color : 'rgba(107,107,107,0.37)' ,
@ -346,7 +430,7 @@ const option = {
{
name : '销售总额' ,
type : 'line' ,
data : [ 514.14 , 468.18 , 988.35 , 1204.84 , 954.16 , 651.24 , ] ,
data : totalSalesData . value ,
symbolSize : 1 ,
symbol : 'circle' ,
smooth : true ,
@ -354,7 +438,7 @@ const option = {
showSymbol : false ,
lineStyle : {
width : 3 ,
color : '# 25BF82 ',
color : '# 3685FE ',
shadowColor : 'rgba(158,135,255, 0.3)' ,
shadowBlur : 10 ,
shadowOffsetY : 20 ,
@ -367,36 +451,36 @@ const option = {
{
name : '订单总数' ,
type : 'line' ,
data : [ 4 , 18 , 29 , 33 , 18 , 10 , 28 ] ,
data : totalOrdersData . value ,
symbolSize : 1 ,
symbol : 'circle' ,
smooth : true ,
yAxisIndex : 1 ,
showSymbol : false ,
lineStyle : {
width : 5 ,
width : 3 ,
color : '#FFD500' ,
shadowColor : 'rgba(115,221,255, 0.3)' ,
shadowBlur : 10 ,
shadowOffsetY : 20 ,
} ,
itemStyle : {
color : colorList [ 2 ] ,
borderColor : colorList [ 2 ] ,
color : colorList [ 1 ] ,
borderColor : colorList [ 1 ] ,
} ,
} ,
{
name : '浏览量' ,
type : 'line' ,
data : [ 1589 , 2648 , 5289 , 4289 , 9654 , 6487 , 5968 ] ,
data : pageViewData . value ,
symbolSize : 1 ,
symbol : 'circle' ,
smooth : true ,
yAxisIndex : 2 ,
showSymbol : false ,
lineStyle : {
width : 5 ,
color : '# 3685FE ',
width : 3 ,
color : '# 25BF82 ',
shadowColor : 'rgba(115,221,255, 0.3)' ,
shadowBlur : 10 ,
shadowOffsetY : 20 ,
@ -409,22 +493,22 @@ const option = {
{
name : '成功退款金额' ,
type : 'line' ,
data : [ 62.44 , 14.15 , 17.48 , 25.18 , 21.91 , 10.02 , 2.25 ] ,
data : refundAmountData . value ,
symbolSize : 1 ,
symbol : 'circle' ,
smooth : true ,
yAxisIndex : 3 ,
showSymbol : false ,
lineStyle : {
width : 5 ,
color : '# 3685FE ',
width : 3 ,
color : '# FF7F00 ',
shadowColor : 'rgba(115,221,255, 0.3)' ,
shadowBlur : 10 ,
shadowOffsetY : 20 ,
} ,
itemStyle : {
color : colorList [ 2 ] ,
borderColor : colorList [ 2 ] ,
color : colorList [ 3 ] ,
borderColor : colorList [ 3 ] ,
} ,
} ,
] ,
@ -442,6 +526,317 @@ const initChart = () => {
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 ) => {
/ / c o n s o l e . l o g ( " 右 上 角 图 表 数 据 更 新 " ) ;
const xzData = generateDateArray ( count ) ;
let obj = Mock . mock ( {
/ / x 轴 数 据 ( 日 期 / 月 份 )
xData : xzData ,
/ / 总 销 售 额 ( 5 0 0 - 5 0 0 0 之 间 的 浮 点 数 , 保 留 2 位 小 数 )
[ ` totalSalesData| ${ count } ` ] : [ '@float(100, 500, 2, 2)' ] ,
/ / 总 订 单 数 ( 1 - 1 0 0 之 间 的 整 数 )
[ ` totalOrdersData| ${ count } ` ] : [ '@integer(10, 100)' ] ,
/ / 页 面 浏 览 量 ( 1 0 0 0 - 1 0 0 0 0 之 间 的 整 数 )
[ ` pageViewData| ${ count } ` ] : [ '@integer(1000, 10000)' ] ,
/ / 退 款 金 额 ( 1 - 1 0 0 之 间 的 浮 点 数 , 保 留 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 ) => {
/ / v a l 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 ;
}
/ / e c h a r t s M o c k D a t a ( d a y ) ; / / 模 拟 图 表 数 据
} ;
/ * *
* 根据给定的时间范围类型 , 生成相应的日期范围
* @ 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 ) ; / / 3 0 天 包 括 今 天
break ;
case 3 : / / 年
startDate . setDate ( today . getDate ( ) - 364 ) ; / / 3 6 5 天 包 括 今 天
break ;
default :
/ / 抛 出 异 常 , 提 示 参 数 类 型 无 效
throw new Error ( '无效的参数类型, 请输入1(周)、2(月)或3(年)' ) ;
}
/ / 格 式 化 日 期 为 Y Y Y Y - M M - D D
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 ( ) => {
/ / c o n s o l e . l o g ( ' 左 上 角 数 据 更 新 ' ) ;
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 ( ) => {
/ / c o n s o l e . l o g ( ' 中 间 数 据 更 新 ' ) ;
/ / m i d d l e D a t a . v a l u e = g e n e r a t e M o c k D a t a ( ) ;
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 ( ) => {
/ / c o n s o l e . l o g ( ' 左 下 角 数 据 更 新 ' ) ;
/ / t a b l e L o a d i n g . v a l u e = t r u e ;
/ / t a b l e D a t a . v a l u e = g e n e r a t e M o c k D a t a ( ) ;
/ / t a b l e L o a d i n g . v a l u e = f a l s e ;
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 ( ) => {
/ / c o n s o l e . l o g ( ' 右 下 角 数 据 更 新 ' ) ;
/ / a f t e r S a l e s D a t a . v a l u e = {
/ / t o t a l A f t e r S a l e s O r d e r s : 1 1 2 8 ,
/ / t o t a l R e f u n d A m o u n t : 2 6 5 ,
/ / t o t a l R e f u n d O r d e r s : 1 2 9 ,
/ / w a r n i n g P r o d u c t I n f o s : [
/ / { g o o d U r l : t o m a t o . v a l u e , g o o d N a m e : " 耿 马 西 红 柿 耿 马 西 红 柿 耿 马 西 红 柿 耿 马 西 红 柿 耿 马 西 红 柿 " , r e f u n d e d O r d e r s : " 2 5 单 " , r e f u n d A m o u n t : ' 1 2 9 元 ' } ,
/ / { g o o d U r l : t o m a t o . v a l u e , g o o d N a m e : " 耿 马 西 红 柿 " , r e f u n d e d O r d e r s : " 3 6 单 " , r e f u n d A m o u n t : ' 2 6 5 元 ' } ,
/ / { g o o d U r l : t o m a t o . v a l u e , g o o d N a m e : " 耿 马 西 红 柿 " , r e f u n d e d O r d e r s : " 5 1 单 " , r e f u n d A m o u n t : ' 1 4 6 元 ' } ,
/ / { g o o d U r l : t o m a t o . v a l u e , g o o d N a m e : " 耿 马 西 红 柿 耿 马 西 红 柿 耿 马 西 红 柿 耿 马 西 红 柿 耿 马 西 红 柿 " , r e f u n d e d O r d e r s : " 2 5 单 " , r e f u n d A m o u n t : ' 2 3 9 元 ' } ,
/ / { g o o d U r l : t o m a t o . v a l u e , g o o d N a m e : " 耿 马 西 红 柿 " , r e f u n d e d O r d e r s : " 3 6 单 " , r e f u n d A m o u n t : ' 3 6 5 元 ' } ,
/ / { g o o d U r l : t o m a t o . v a l u e , g o o d N a m e : " 耿 马 西 红 柿 " , r e f u n d e d O r d e r s : " 5 1 单 " , r e f u n d A m o u n t : ' 1 9 8 元 ' } ,
/ / ] ,
/ / } ;
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 ( ( ) => {
if ( chartInstance ) {
@ -449,15 +844,7 @@ onBeforeUnmount(() => {
chartInstance . dispose ( ) ;
chartInstance = null ;
}
} ) ;
/ / 调 整 图 表 大 小
const resizeChart = ( ) => {
if ( chartInstance ) {
chartInstance . resize ( ) ;
}
} ;
onMounted ( ( ) => {
initChart ( ) ;
window . removeEventListener ( 'resize' , calculateTableHeight ) ;
} ) ;
< / script >
< style lang = "scss" scoped >
@ -465,7 +852,7 @@ onMounted(() => {
width : 200 px ;
display : flex ;
align - items : center ;
margin - right : 5 0px ;
margin - right : 2 0px ;
font - size : 18 px ;
color : # 999999 ;
}
@ -476,7 +863,7 @@ onMounted(() => {
}
. number {
margin - right : 100 px ;
margin - top : 20 px ;
margin - top : 16 px ;
font - size : 18 px ;
font - weight : bold ;
color : # 000000 ;
@ -485,38 +872,39 @@ onMounted(() => {
margin - top : 20 px ;
display : flex ;
align - items : center ;
justify - content : flex - start ;
justify - content : space - between ;
gap : 20 px ;
}
. app - container - title {
margin - bottom : 20 px ;
padding - right : 10 px ;
font - size : 20 px ;
font - weight : bold ;
}
. app - container - data {
border - radius : 10 px ;
padding : 20 px ;
padding : 20 px 10 px 20 px 20 px ;
width : 100 % ;
background - color : # fff ;
. app - container - data - left {
width : 40% ;
width : 500px ;
. app - container - data - left - top {
display : flex ;
}
. app - container - data - left - bottom {
margin - top : 5 0px ;
margin - top : 4 0px ;
display : flex ;
}
}
. app - container - data - right {
width: 60 % ;
flex: 1 ;
}
}
. app - container - block {
width: 250 px ;
flex: 1 ;
background - color : # fff ;
border - radius : 10 px ;
padding : 10 px ;
margin - left : 26 px ;
padding : 10 px 10 px 10 px 14 px ;
. app - container - block - title {
font - size : 18 px ;
font - weight : bold ;
@ -529,6 +917,59 @@ onMounted(() => {
}
. app - container - block - proportion {
font - size : 12 px ;
. el - icon {
vertical - align : text - top ;
}
}
: deep ( . el - popper . tooltip - box - item ) {
max - width : 200 px ; /* 限制最大宽度 */
word - break : break - word ; /* 长单词或URL换行 */
white - space : normal ! important ; /* 覆盖默认的 nowrap */
}
. tooltip - box - item {
width : 200 px ! important ;
}
}
. bottom - flex - box {
margin - top : 20 px ;
display : flex ;
justify - content : space - between ;
gap : 20 px ;
. bottom - box - item {
flex : 1 ;
width : 50 % ;
background - color : # fff ;
border - radius : 10 px ;
padding : 20 px 20 px 0 px 20 px ;
}
. bottom - box - item - title {
font - size : 18 px ;
font - weight : bold ;
}
. bottom - box - item - content {
height : 300 px ;
min - height : 300 px ;
. bottom - box - summary {
display : flex ;
margin : 10 px 0 ;
gap : 20 px ;
width : 100 % ;
. bottom - box - summary - item {
flex : 1 ;
min - width : 0 ;
overflow : hidden ;
. bottom - box - summary - title {
font - size : 16 px ;
color : # 999 ;
margin - bottom : 16 px ;
}
. bottom - box - summary - value {
font - size : 20 px ;
color : # 000 ;
font - weight : bold ;
}
}
}
}
}
< / style >