2025-06-14 10:30:10 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="pageBox">
|
|
|
|
|
|
<div class="searchBox">
|
|
|
|
|
|
<div class="row row1">
|
|
|
|
|
|
<span class="span">商品名称:</span>
|
|
|
|
|
|
<div class="right"><el-input v-model="filter.title" class="wid100" clearable></el-input></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="row row1">
|
|
|
|
|
|
<span class="span">规格编码:</span>
|
|
|
|
|
|
<div class="right"><el-input v-model="filter.sku_code" class="wid100" clearable></el-input></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="row row1">
|
|
|
|
|
|
<span class="span">商品品牌:</span>
|
|
|
|
|
|
<div class="right">
|
|
|
|
|
|
<el-select v-model="filter.brand_id" placeholder="请选择" clearable class="wid100">
|
|
|
|
|
|
<el-option v-for="it in brandList" :key="it.id" :label="it.name" :value="it.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="row row1">
|
|
|
|
|
|
<span class="span">赠品:</span>
|
|
|
|
|
|
<div class="right">
|
|
|
|
|
|
<el-select v-model="filter.gift" placeholder="请选择" :clearable="false" class="wid100">
|
|
|
|
|
|
<el-option label="全部" value="all" />
|
|
|
|
|
|
<el-option label="否" :value="0" />
|
|
|
|
|
|
<el-option label="是" :value="1" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="row">
|
|
|
|
|
|
<span class="span">时间区间:</span>
|
|
|
|
|
|
<div class="right">
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="rangeTime"
|
|
|
|
|
|
type="daterange"
|
|
|
|
|
|
range-separator="至"
|
|
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
|
|
value-format="YYYY-MM-DD"
|
|
|
|
|
|
format="YYYY-MM-DD"
|
|
|
|
|
|
style="width: 250px;">
|
|
|
|
|
|
</el-date-picker>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="row">
|
|
|
|
|
|
<span class="span"></span>
|
|
|
|
|
|
<el-button type="primary" @click="handleSearch"><el-icon><Search /></el-icon> 筛选</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<el-card shadow="never">
|
|
|
|
|
|
<el-table :data="statisticsList" style="width: 100%" border v-loading="loading" @sort-change="sortChange"
|
|
|
|
|
|
:default-sort="{
|
|
|
|
|
|
prop: 'number,order_num,seven_day_avg_number,stock_wait,three_day_avg_number,three_day_stock_wait,thirty_day_number,actual_inventory,total_profit',
|
|
|
|
|
|
}">
|
|
|
|
|
|
<el-table-column prop="date" label="日期" align="center" />
|
|
|
|
|
|
<el-table-column prop="type" label="商品信息" width="220">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<div class="goodInfo" v-if="scope.row.goods_sku">
|
|
|
|
|
|
<div class="imgBox" v-if="scope.row.goods_sku.goods && scope.row.goods_sku.goods.images">
|
|
|
|
|
|
<el-image v-for="(it, i) in scope.row.goods_sku.goods.images" :key="i" :z-index="9999"
|
|
|
|
|
|
:src="it" :hide-on-click-modal="true" :preview-src-list="[scope.row.goods_sku.goods.images]"
|
|
|
|
|
|
fit="cover" :preview-teleported="true" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="tit">{{ scope.row.goods_sku.goods.title }}({{ scope.row.goods_sku.title }})</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="number" label="销量" align="center" sortable="custom" />
|
|
|
|
|
|
<el-table-column prop="order_num" label="单数" align="center" sortable="custom" />
|
|
|
|
|
|
<el-table-column prop="seven_day_avg_number" label="7天日销" align="center" sortable="custom" />
|
|
|
|
|
|
<el-table-column prop="stock_wait" label="7天周转天数" align="center" sortable="custom" />
|
|
|
|
|
|
<el-table-column prop="three_day_avg_number" label="3天日销" align="center" sortable="custom" />
|
|
|
|
|
|
<el-table-column prop="three_day_stock_wait" label="3天周转天数" align="center" sortable="custom" />
|
|
|
|
|
|
<el-table-column prop="thirty_day_number" label="近30天销量" align="center" sortable="custom" />
|
|
|
|
|
|
<el-table-column prop="actual_inventory" label="总库存" align="center" sortable="custom">
|
|
|
|
|
|
<template #header>
|
|
|
|
|
|
<span style="margin-right: 5px;">总库存</span>
|
|
|
|
|
|
<span>
|
|
|
|
|
|
<el-tooltip placement="top" :hide-after="0" :show-after="200">
|
|
|
|
|
|
<template #content>总库存包含未锁定和锁定库存,括号里为锁定库存</template>
|
|
|
|
|
|
<el-icon size="18"><QuestionFilled /></el-icon>
|
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<div v-if="scope.row.goods_sku">{{ scope.row.goods_sku.actual_inventory }}({{ scope.row.goods_sku.lock_in_stock }})</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="refund_amount" label="退款金额" align="center" />
|
|
|
|
|
|
<el-table-column prop="red_refund_amount" label="红包退款有责金额" align="center" />
|
|
|
|
|
|
<el-table-column prop="total_profit" label="总利润" align="center" />
|
|
|
|
|
|
<el-table-column label="数据" align="center" width="180">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-button type="primary" circle @click="handleAnalysis(scope.row.sku_code)" title="店铺数据"><el-icon><Shop /></el-icon></el-button>
|
|
|
|
|
|
<el-button type="primary" circle :loading="scope.row.loading" @click="trendCharts(scope.row)" title="趋势图"><el-icon><TrendCharts /></el-icon></el-button>
|
|
|
|
|
|
<el-button type="primary" circle @click="orderCharts(scope.row)" title="订单商品销量趋势"><el-icon><List /></el-icon></el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
<div class="page-pagination">
|
|
|
|
|
|
<el-pagination
|
|
|
|
|
|
:current-page="page"
|
|
|
|
|
|
background
|
|
|
|
|
|
layout="prev, pager, next, sizes, total"
|
|
|
|
|
|
:total="total"
|
|
|
|
|
|
:page-sizes="[10, 50, 100]"
|
|
|
|
|
|
:page-size="pageSize"
|
|
|
|
|
|
@size-change="handleSizeChange"
|
|
|
|
|
|
@current-change="handleCurrentChange"></el-pagination>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
<el-dialog v-model="showDialog" width="1000px" title="店铺数据">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
|
|
|
|
<span>时间:</span>
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="pickTime"
|
|
|
|
|
|
type="daterange"
|
|
|
|
|
|
range-separator="至"
|
|
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
|
|
value-format="YYYY-MM-DD"
|
|
|
|
|
|
format="YYYY-MM-DD"
|
|
|
|
|
|
style="width: 250px;"
|
|
|
|
|
|
:clearable="false"
|
|
|
|
|
|
@change="getDialogList()">
|
|
|
|
|
|
</el-date-picker>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="tabBox">
|
|
|
|
|
|
<el-table :data="dialogList" style="width: 100%" border v-loading="opa_loading">
|
|
|
|
|
|
<el-table-column label="排名" width="70" align="center">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<span>{{ scope.$index + 1 }}</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="mx_shop_name" label="店铺" align="center" />
|
|
|
|
|
|
<el-table-column prop="date" label="日期" align="center" />
|
|
|
|
|
|
<el-table-column prop="number" label="销量" align="center" />
|
|
|
|
|
|
<el-table-column prop="order_num" label="单数" align="center" />
|
|
|
|
|
|
<el-table-column prop="avg_number" label="日销量" align="center" />
|
|
|
|
|
|
<el-table-column prop="total_price" label="支付金额" align="center" />
|
|
|
|
|
|
<el-table-column prop="refund_amount" label="退款金额" align="center" />
|
|
|
|
|
|
<el-table-column prop="total_profit" label="利润" align="center" />
|
|
|
|
|
|
<el-table-column label="趋势图" align="center" width="80">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-button type="primary" circle @click="getDataLine(scope.row)" :loading="scope.row.loading"><el-icon><TrendCharts /></el-icon></el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<el-dialog v-model="showChart" width="900px" title="趋势图分析">
|
|
|
|
|
|
<el-form label-width="110px">
|
|
|
|
|
|
<el-form-item label="时间:">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="chartTime"
|
|
|
|
|
|
type="daterange"
|
|
|
|
|
|
range-separator="至"
|
|
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
|
|
value-format="YYYY-MM-DD"
|
|
|
|
|
|
format="YYYY-MM-DD"
|
|
|
|
|
|
style="width: 250px;"
|
|
|
|
|
|
:clearable="false"
|
|
|
|
|
|
@change="changeTime0()">
|
|
|
|
|
|
</el-date-picker>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
<div id="lineChart" style="width: 100%;height:500px;" v-loading="loading1"></div>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<el-dialog v-model="showTrend" width="900px" title="趋势图分析">
|
|
|
|
|
|
<el-form label-width="110px" :inline="true">
|
|
|
|
|
|
<el-form-item label="时间:">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="trendTime"
|
|
|
|
|
|
type="daterange"
|
|
|
|
|
|
range-separator="至"
|
|
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
|
|
value-format="YYYY-MM-DD"
|
|
|
|
|
|
format="YYYY-MM-DD"
|
|
|
|
|
|
style="width: 250px;"
|
|
|
|
|
|
:clearable="false"
|
|
|
|
|
|
@change="changeTime()">
|
|
|
|
|
|
</el-date-picker>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="总计:"><span style="color: #f00;">{{ sumDaily }}</span></el-form-item>
|
2025-06-18 10:08:52 +08:00
|
|
|
|
<el-form-item label="平均值:"><span style="color: #f00;">{{ avg }}</span></el-form-item>
|
2025-06-14 10:30:10 +08:00
|
|
|
|
</el-form>
|
|
|
|
|
|
<div id="trendChart" style="width: 100%;height:500px;" v-loading="loading1"></div>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<el-dialog v-model="showOrderTrend" width="900px" title="订单商品销量趋势">
|
|
|
|
|
|
<el-form label-width="80px" :inline="true">
|
|
|
|
|
|
<el-form-item label="店铺:">
|
|
|
|
|
|
<el-select v-model="from_shop_ids" @change="changeOrderTime()" placeholder="请选择" clearable filterable multiple collapse-tags style="width: 200px;">
|
|
|
|
|
|
<el-option v-for="it in shopsList" :key="it.id" :label="it.name" :value="it.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="时间:">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="orderTrendTime"
|
|
|
|
|
|
type="datetimerange"
|
|
|
|
|
|
range-separator="至"
|
|
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
|
style="width: 340px;"
|
|
|
|
|
|
:clearable="false"
|
|
|
|
|
|
@change="changeOrderTime()">
|
|
|
|
|
|
</el-date-picker>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="粒度:">
|
|
|
|
|
|
<el-radio-group v-model="grain_size" size="mini" @change="changeOrderTime()">
|
|
|
|
|
|
<el-radio-button label="60分钟" :value="60" />
|
|
|
|
|
|
<el-radio-button label="30分钟" :value="30" />
|
|
|
|
|
|
<el-radio-button label="15分钟" :value="15" />
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
<div id="orderChart" style="width: 100%;height:500px;" v-loading="loading1"></div>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import { onMounted, reactive, toRefs } from "vue"
|
|
|
|
|
|
import { get } from "@/api/request"
|
|
|
|
|
|
import { Search, Shop, TrendCharts, QuestionFilled, List } from '@element-plus/icons'
|
|
|
|
|
|
import * as echarts from 'echarts'
|
|
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
components: {
|
|
|
|
|
|
Search, Shop, TrendCharts, QuestionFilled, List
|
|
|
|
|
|
},
|
|
|
|
|
|
setup() {
|
|
|
|
|
|
const data = reactive({
|
|
|
|
|
|
filter: {
|
|
|
|
|
|
title: '',
|
|
|
|
|
|
gift: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
rangeTime: [],
|
|
|
|
|
|
statisticsList: [],
|
|
|
|
|
|
page: 1,
|
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
|
total: 0,
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
opaType: '',
|
|
|
|
|
|
showDialog: false,
|
|
|
|
|
|
opa_loading: false,
|
|
|
|
|
|
itemId: 0,
|
|
|
|
|
|
from_shop_id: 0,
|
|
|
|
|
|
dialogList: [],
|
|
|
|
|
|
pickTime: [],
|
|
|
|
|
|
loading1: false,
|
|
|
|
|
|
dataLineX: [],
|
|
|
|
|
|
dataLineY: [],
|
|
|
|
|
|
showChart: false,
|
|
|
|
|
|
brandList: [],
|
|
|
|
|
|
ascOrDesc: 'desc',
|
|
|
|
|
|
sort: 'number',
|
|
|
|
|
|
showTrend: false,
|
|
|
|
|
|
sumDaily: 0,
|
2025-06-18 10:08:52 +08:00
|
|
|
|
avg: 0,
|
2025-06-14 10:30:10 +08:00
|
|
|
|
trendTime: [],
|
|
|
|
|
|
chartTime: [],
|
|
|
|
|
|
showOrderTrend: false,
|
|
|
|
|
|
orderTrendTime: [],
|
|
|
|
|
|
from_shop_ids: [],
|
|
|
|
|
|
shopsList: [],
|
|
|
|
|
|
grain_size: 60,
|
|
|
|
|
|
dataLineY2: []
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
function handleSearch() {
|
|
|
|
|
|
data.page = 1
|
|
|
|
|
|
fetchData()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getShopsList() {
|
|
|
|
|
|
get(`/api/mxShops`).then((res) => {
|
|
|
|
|
|
data.shopsList = res.data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const fetchData = () => {
|
|
|
|
|
|
data.loading = true
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
...data.filter,
|
|
|
|
|
|
page: data.page,
|
|
|
|
|
|
pageSize: data.pageSize,
|
|
|
|
|
|
start_date: data.rangeTime ? data.rangeTime[0] : '',
|
|
|
|
|
|
end_date: data.rangeTime ? data.rangeTime[1] : '',
|
|
|
|
|
|
direction: data.ascOrDesc,
|
|
|
|
|
|
order_by_column: data.sort
|
|
|
|
|
|
}
|
|
|
|
|
|
params.brand_id = data.filter.brand_id || 0
|
|
|
|
|
|
get(`/api/orderItemDailyReport`, params).then((res) => {
|
|
|
|
|
|
data.statisticsList = res.data
|
|
|
|
|
|
data.total = res.meta.total
|
|
|
|
|
|
data.loading = false
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
data.loading = false
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleCurrentChange(e) {
|
|
|
|
|
|
data.page = e
|
|
|
|
|
|
fetchData()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleSizeChange(e) {
|
|
|
|
|
|
data.page = 1
|
|
|
|
|
|
data.pageSize = e
|
|
|
|
|
|
fetchData()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleAnalysis(sku_code) {
|
|
|
|
|
|
let end = dayjs().format('YYYY-MM-DD')
|
|
|
|
|
|
let start = dayjs().subtract(30, 'day').format('YYYY-MM-DD')
|
|
|
|
|
|
data.pickTime = [end, end]
|
|
|
|
|
|
data.itemId = sku_code
|
|
|
|
|
|
getDialogList()
|
|
|
|
|
|
data.showDialog = true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const getDialogList = () => {
|
|
|
|
|
|
data.opa_loading = true
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
sku_code: data.itemId,
|
|
|
|
|
|
start_date: data.pickTime ? data.pickTime[0] : '',
|
|
|
|
|
|
end_date: data.pickTime ? data.pickTime[1] : ''
|
|
|
|
|
|
}
|
|
|
|
|
|
get(`/api/mxShopDailyReport`, params).then((res) => {
|
|
|
|
|
|
data.dialogList = res.data
|
|
|
|
|
|
data.opa_loading = false
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
data.opa_loading = false
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const getDataLine = (row) => {
|
|
|
|
|
|
row.loading = true
|
|
|
|
|
|
data.loading1 = true
|
|
|
|
|
|
let end = dayjs().format('YYYY-MM-DD')
|
|
|
|
|
|
let start = dayjs().subtract(30, 'day').format('YYYY-MM-DD')
|
|
|
|
|
|
data.chartTime = [start, end]
|
|
|
|
|
|
data.from_shop_id = row.from_shop_id
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
from_shop_id: row.from_shop_id,
|
|
|
|
|
|
sku_code: data.itemId,
|
|
|
|
|
|
start_date: data.chartTime ? data.chartTime[0] : '',
|
|
|
|
|
|
end_date: data.chartTime ? data.chartTime[1] : ''
|
|
|
|
|
|
}
|
|
|
|
|
|
get(`/api/mxShopTendency`, params).then((res) => {
|
|
|
|
|
|
data.dataLineX = []
|
|
|
|
|
|
data.dataLineY = []
|
|
|
|
|
|
res.data.forEach((item) => {
|
|
|
|
|
|
data.dataLineX.push(item.date)
|
|
|
|
|
|
data.dataLineY.push(item.number)
|
|
|
|
|
|
})
|
|
|
|
|
|
data.showChart = true
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
getTrendChart('lineChart')
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
}, 500)
|
|
|
|
|
|
row.loading = false
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
row.loading = false
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function changeTime0() {
|
|
|
|
|
|
data.loading1 = true
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
from_shop_id: data.from_shop_id,
|
|
|
|
|
|
sku_code: data.itemId,
|
|
|
|
|
|
start_date: data.chartTime ? data.chartTime[0] : '',
|
|
|
|
|
|
end_date: data.chartTime ? data.chartTime[1] : ''
|
|
|
|
|
|
}
|
|
|
|
|
|
get(`/api/mxShopTendency`, params).then((res) => {
|
|
|
|
|
|
data.dataLineX = []
|
|
|
|
|
|
data.dataLineY = []
|
|
|
|
|
|
res.data.forEach((item) => {
|
|
|
|
|
|
data.dataLineX.push(item.date)
|
|
|
|
|
|
data.dataLineY.push(item.number)
|
|
|
|
|
|
})
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
getTrendChart('lineChart')
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
}, 500)
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
data.loading = false
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getTrendChart(id, val = 0) {
|
|
|
|
|
|
let myChart = echarts.init(document.getElementById(id))
|
|
|
|
|
|
let option = {
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
trigger: 'axis'
|
|
|
|
|
|
},
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
data: ['销量']
|
|
|
|
|
|
},
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
type: 'category',
|
|
|
|
|
|
data: data.dataLineX
|
|
|
|
|
|
},
|
|
|
|
|
|
yAxis: {},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '销量',
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
smooth: true,
|
|
|
|
|
|
data: data.dataLineY
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
if(val == 2) {
|
|
|
|
|
|
option.legend.data.push('累计销量')
|
|
|
|
|
|
option.series.push({
|
|
|
|
|
|
name: '累计销量',
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
smooth: true,
|
|
|
|
|
|
data: data.dataLineY2
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
myChart.setOption(option)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function trendCharts(row) {
|
|
|
|
|
|
data.itemId = row.sku_code
|
|
|
|
|
|
row.loading = true
|
|
|
|
|
|
data.loading1 = true
|
|
|
|
|
|
let end = dayjs().format('YYYY-MM-DD')
|
|
|
|
|
|
let start = dayjs().subtract(30, 'day').format('YYYY-MM-DD')
|
|
|
|
|
|
data.trendTime = [start, end]
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
sku_code: row.sku_code,
|
|
|
|
|
|
start_date: data.trendTime ? data.trendTime[0] : '',
|
|
|
|
|
|
end_date: data.trendTime ? data.trendTime[1] : ''
|
|
|
|
|
|
}
|
|
|
|
|
|
get(`/api/orderItemDailyTendency`, params).then((res) => {
|
|
|
|
|
|
data.dataLineX = []
|
|
|
|
|
|
data.dataLineY = []
|
|
|
|
|
|
res.data.forEach((item) => {
|
|
|
|
|
|
data.dataLineX.push(item.date)
|
|
|
|
|
|
data.dataLineY.push(item.number)
|
|
|
|
|
|
})
|
2025-06-18 10:08:52 +08:00
|
|
|
|
data.avg = res.avg
|
2025-06-14 10:30:10 +08:00
|
|
|
|
data.sumDaily = res.sum
|
|
|
|
|
|
data.showTrend = true
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
getTrendChart('trendChart')
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
}, 500)
|
|
|
|
|
|
row.loading = false
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
row.loading = false
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function changeTime() {
|
|
|
|
|
|
data.loading1 = true
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
sku_code: data.itemId,
|
|
|
|
|
|
start_date: data.trendTime ? data.trendTime[0] : '',
|
|
|
|
|
|
end_date: data.trendTime ? data.trendTime[1] : ''
|
|
|
|
|
|
}
|
|
|
|
|
|
get(`/api/orderItemDailyTendency`, params).then((res) => {
|
|
|
|
|
|
data.dataLineX = []
|
|
|
|
|
|
data.dataLineY = []
|
|
|
|
|
|
res.data.forEach((item) => {
|
|
|
|
|
|
data.dataLineX.push(item.date)
|
|
|
|
|
|
data.dataLineY.push(item.number)
|
|
|
|
|
|
})
|
|
|
|
|
|
data.sumDaily = res.sum
|
2025-06-20 11:10:09 +08:00
|
|
|
|
data.avg = res.avg
|
2025-06-14 10:30:10 +08:00
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
getTrendChart('trendChart')
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
}, 500)
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getBrandList() {
|
|
|
|
|
|
get(`/api/all/brands`).then((res) => {
|
|
|
|
|
|
data.brandList = res.data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function sortChange({ prop, order }) {
|
|
|
|
|
|
console.log(prop, order)
|
|
|
|
|
|
let arr = prop.split('.')
|
|
|
|
|
|
let length = arr.length
|
|
|
|
|
|
data.ascOrDesc = order == 'ascending' ? 'asc' : 'desc'
|
|
|
|
|
|
data.sort = arr[length - 1]
|
|
|
|
|
|
fetchData()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function orderCharts(row) {
|
|
|
|
|
|
data.from_shop_ids = []
|
|
|
|
|
|
data.itemId = row.sku_code
|
|
|
|
|
|
data.grain_size = 60
|
|
|
|
|
|
let end = dayjs().format('YYYY-MM-DD HH:mm:ss')
|
|
|
|
|
|
let start = dayjs().format('YYYY-MM-DD') + ' 00:00:00'
|
|
|
|
|
|
data.orderTrendTime = [start, end]
|
|
|
|
|
|
data.showOrderTrend = true
|
|
|
|
|
|
getOrderCharts()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function changeOrderTime() {
|
|
|
|
|
|
getOrderCharts()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getOrderCharts() {
|
|
|
|
|
|
data.loading1 = true
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
sku_code: data.itemId,
|
|
|
|
|
|
from_shop_ids: data.from_shop_ids,
|
|
|
|
|
|
start_time: data.orderTrendTime ? data.orderTrendTime[0] : '',
|
|
|
|
|
|
end_time: data.orderTrendTime ? data.orderTrendTime[1] : '',
|
|
|
|
|
|
minute: data.grain_size
|
|
|
|
|
|
}
|
|
|
|
|
|
get(`/api/orderItemTendency`, params).then((res) => {
|
|
|
|
|
|
data.dataLineX = []
|
|
|
|
|
|
data.dataLineY = []
|
|
|
|
|
|
data.dataLineY2 = []
|
|
|
|
|
|
res.data.forEach((item) => {
|
|
|
|
|
|
data.dataLineX.push(item.time_period)
|
|
|
|
|
|
data.dataLineY.push(item.total_number)
|
|
|
|
|
|
data.dataLineY2.push(item.total)
|
|
|
|
|
|
})
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
getTrendChart('orderChart', 2)
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
}, 500)
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
data.loading1 = false
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
fetchData()
|
|
|
|
|
|
getBrandList()
|
|
|
|
|
|
getShopsList()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
...toRefs(data),
|
|
|
|
|
|
handleSearch,
|
|
|
|
|
|
handleCurrentChange,
|
|
|
|
|
|
handleSizeChange,
|
|
|
|
|
|
fetchData,
|
|
|
|
|
|
handleAnalysis,
|
|
|
|
|
|
getDataLine,
|
|
|
|
|
|
getBrandList,
|
|
|
|
|
|
getDialogList,
|
|
|
|
|
|
sortChange,
|
|
|
|
|
|
trendCharts,
|
|
|
|
|
|
changeTime,
|
|
|
|
|
|
changeTime0,
|
|
|
|
|
|
orderCharts,
|
|
|
|
|
|
getOrderCharts,
|
|
|
|
|
|
changeOrderTime,
|
|
|
|
|
|
getShopsList
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.searchBox{
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
padding: 15px 0 0 0;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
.row{
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
width: auto;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
margin-right: 15px;
|
|
|
|
|
|
&.row1{
|
|
|
|
|
|
width: 300px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.span{
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
width: 80px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
.right{
|
|
|
|
|
|
width: calc(100% - 80px);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.imgBox{
|
|
|
|
|
|
.el-image{
|
|
|
|
|
|
width: 60px;
|
|
|
|
|
|
height: 60px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.skuBox{
|
|
|
|
|
|
border: 1px solid #e5e5e5;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
padding: 15px 0;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
background-color: #f3f3f3;
|
|
|
|
|
|
.tit{
|
|
|
|
|
|
padding-left: 40px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|