Files
klp-oa/klp-ui/src/views/wms/order/dashboard.vue
2025-07-30 10:54:11 +08:00

280 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
class="order-analysis-dashboard"
v-loading="loading"
>
<!-- 顶部操作栏刷新和定时刷新设置按钮 -->
<el-row :gutter="20" class="top-row" style="margin-bottom: 0;">
<el-col :span="24" style="display: flex; justify-content: flex-end; align-items: center; margin-bottom: 10px;">
<el-button type="primary" icon="el-icon-refresh" @click="handleRefresh">刷新</el-button>
<el-button icon="el-icon-setting" style="margin-left: 10px;" @click="drawerVisible = true">定时刷新设置</el-button>
</el-col>
</el-row>
<!-- 业绩区 -->
<el-row :gutter="20" class="section-row">
<el-col :span="24">
<div class="section-title">
<h2>业绩区</h2>
<p>产品销售情况销售人员业绩总订单数量</p>
</div>
<PerformanceArea :performance-area="dashboardData.performanceArea" />
</el-col>
</el-row>
<!-- 当前情况区 -->
<el-row :gutter="20" class="section-row">
<el-col :span="24">
<div class="section-title">
<h2>情况区</h2>
<p>订单所需的产品统计根据BOM计算的原料需求原料库存和需求情况</p>
</div>
<CurrentSituationArea :current-situation-area="dashboardData.currentSituationArea" />
</el-col>
</el-row>
<!-- 推荐区 -->
<el-row :gutter="20" class="section-row">
<el-col :span="24">
<div class="section-title">
<h2>推荐区</h2>
<p>订单维度推荐原料维度推荐</p>
</div>
<RecommendationArea :recommendation-area="dashboardData.recommendationArea" />
</el-col>
</el-row>
<!-- 原有图表区域保留兼容性 -->
<el-row :gutter="20" class="section-row">
<el-col :span="24">
<div class="section-title">
<h2>原有图表区域</h2>
<p>兼容原有的图表展示</p>
</div>
</el-col>
</el-row>
<!-- 顶部3 张summary卡片 -->
<el-row :gutter="20" class="top-row">
<el-col :span="24">
<OrderSummary :data-info="orderSummaryData" />
</el-col>
</el-row>
<!-- 第一行图表 -->
<el-row :gutter="20" class="chart-row">
<el-col :span="8">
<OrderCompletion :completion-rate="orderSummaryData.completionRate" />
</el-col>
<el-col :span="8">
<ProductSales :product-sales="productSalesData" />
</el-col>
<el-col :span="8">
<CustomerRegion :customer-data="customerClusterData" />
</el-col>
</el-row>
<!-- 定时刷新设置抽屉 -->
<el-drawer
title="定时刷新设置"
:visible.sync="drawerVisible"
direction="rtl"
size="350px"
>
<el-form label-width="100px">
<el-form-item label="启用定时刷新">
<el-switch v-model="autoRefresh" />
</el-form-item>
<el-form-item label="刷新间隔(秒)">
<el-input-number v-model="refreshInterval" :min="5" :max="3600" :step="1" :disabled="!autoRefresh" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveRefreshSetting">保存</el-button>
<el-button @click="drawerVisible = false">取消</el-button>
</el-form-item>
</el-form>
</el-drawer>
</div>
</template>
<script>
import OrderSummary from './components/OrderSummary.vue'
import OrderCompletion from './components/OrderCompletion.vue'
import ProductSales from './components/ProductSales.vue'
import CustomerRegion from './components/CustomerRegion.vue'
import PerformanceArea from './components/PerformanceArea.vue'
import CurrentSituationArea from './components/CurrentSituationArea.vue'
import RecommendationArea from './components/RecommendationArea.vue'
import { getDashboardData } from '@/api/wms/order'
export default {
name: 'OrderAnalysisDashboard',
components: {
OrderSummary,
OrderCompletion,
ProductSales,
CustomerRegion,
PerformanceArea,
CurrentSituationArea,
RecommendationArea,
},
data() {
return {
// 新的数据结构
dashboardData: {
performanceArea: {},
currentSituationArea: {},
recommendationArea: {}
},
// 原有数据结构(保持兼容性)
orderSummaryData: {
totalOrders: 0,
completedThisMonth: 0,
completionRate: 0
},
productSalesData: [],
customerClusterData: [],
// 新增定时刷新相关数据
drawerVisible: false,
autoRefresh: false,
refreshInterval: 30, // 默认30秒
refreshTimer: null,
loading: false
}
},
created() {
this.fetchAllData()
this.loadRefreshSetting()
this.startAutoRefresh()
},
beforeDestroy() {
this.clearAutoRefresh()
},
methods: {
async fetchAllData() {
this.loading = true
try {
const res = await getDashboardData()
const data = res
// 更新新的数据结构
this.dashboardData = {
performanceArea: data.performanceArea || {},
currentSituationArea: data.currentSituationArea || {},
recommendationArea: data.recommendationArea || {}
}
// 保持原有数据结构的兼容性
this.orderSummaryData = {
totalOrders: data.orderSummary?.totalOrderCount || 0,
completedThisMonth: data.orderSummary?.monthFinishedOrderCount || 0,
completionRate: data.orderSummary?.finishedRate || 0,
...data.orderSummary
}
this.productSalesData = data.productRank || []
this.customerClusterData = data.customerRegion || []
this.materialAnalysisData = {
categories: (data.orderMaterial || []).map(item => item.materialName),
usageFrequency: (data.orderMaterial || []).map(item => item.usedCount),
stockQuantity: (data.orderMaterial || []).map(item => item.stockCount),
purchaseCycle: (data.orderMaterial || []).map(item => item.purchaseCycle)
}
} catch (error) {
console.error('获取数据看板数据失败:', error)
this.$message.error('获取数据失败,请稍后重试')
} finally {
this.loading = false
}
},
handleRefresh() {
this.fetchAllData()
},
// 定时刷新相关
startAutoRefresh() {
this.clearAutoRefresh()
if (this.autoRefresh) {
this.refreshTimer = setInterval(() => {
this.fetchAllData()
}, this.refreshInterval * 1000)
}
},
clearAutoRefresh() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
this.refreshTimer = null
}
},
saveRefreshSetting() {
// 可持久化到localStorage
localStorage.setItem('orderDashboardAutoRefresh', JSON.stringify({
autoRefresh: this.autoRefresh,
refreshInterval: this.refreshInterval
}))
this.drawerVisible = false
this.startAutoRefresh()
},
loadRefreshSetting() {
const setting = localStorage.getItem('orderDashboardAutoRefresh')
if (setting) {
const { autoRefresh, refreshInterval } = JSON.parse(setting)
this.autoRefresh = autoRefresh
this.refreshInterval = refreshInterval
}
}
},
watch: {
autoRefresh(val) {
if (!val) {
this.clearAutoRefresh()
}
},
refreshInterval(val) {
if (this.autoRefresh) {
this.startAutoRefresh()
}
}
}
}
</script>
<style scoped>
.order-analysis-dashboard {
padding: 24px;
background-color: #f7f8fa;
box-sizing: border-box;
}
.section-row {
margin-bottom: 30px;
}
.section-title {
margin-bottom: 20px;
padding: 0 10px;
}
.section-title h2 {
margin: 0 0 8px 0;
font-size: 20px;
font-weight: 600;
color: #303133;
}
.section-title p {
margin: 0;
font-size: 14px;
color: #909399;
}
.top-row,
.chart-row {
margin-bottom: 20px;
}
.chart-row > .el-col {
display: flex;
flex-direction: column;
justify-content: stretch;
}
</style>