Files
shanxia2.0/miniprogram/pages/db/dashboard/index.vue
T

150 lines
4.5 KiB
Vue

<template>
<view class="db-page">
<view class="db-header" :style="safeAreaStyle">
<view class="db-header__nav">
<view class="db-header__left">
<text class="db-header__back" @click="goWorkbench">←</text>
<text class="db-header__title">仪表盘</text>
</view>
<view /><!-- 胶囊占位 -->
</view>
</view>
<view class="db-menu-grid">
<view class="db-menu-item" @click="go(PAGE_PATHS.dbPlansList)">
<view class="db-menu-icon">📋</view>
<view class="db-menu-label">计划管理</view>
</view>
<view class="db-menu-item" @click="go(PAGE_PATHS.dbInventoryList)">
<view class="db-menu-icon">📦</view>
<view class="db-menu-label">出入库管理</view>
</view>
<view class="db-menu-item" @click="go(PAGE_PATHS.dbWeighingList)">
<view class="db-menu-icon">⚖️</view>
<view class="db-menu-label">地磅单管理</view>
</view>
</view>
<view class="db-stat-grid">
<view class="db-stat-card">
<view class="db-stat-title">今日入库</view>
<view class="db-stat-value">
{{ inboundCount }}<text class="db-stat-suffix">车</text>
</view>
</view>
<view class="db-stat-card">
<view class="db-stat-title">今日出库</view>
<view class="db-stat-value">
{{ outboundCount }}<text class="db-stat-suffix">车</text>
</view>
</view>
</view>
<view v-for="block in chartBlocks" :key="block.title" class="db-chart-block">
<view class="db-chart-title">{{ block.title }}</view>
<view v-if="!block.rows.length" class="db-empty" style="padding: 16px">暂无数据</view>
<view v-for="row in block.rows" :key="row.label" class="db-bar-row">
<view class="db-bar-label">{{ row.label }}</view>
<view class="db-bar-track">
<view class="db-bar-planned" :style="{ width: barPct(row.planned, block.max) }" />
<view class="db-bar-actual" :style="{ width: barPct(row.actual, block.max) }" />
</view>
<view class="db-bar-meta">计划 {{ fmt(row.planned) }} · 实绩 {{ fmt(row.actual) }}</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useUserStore } from '@/stores/user'
import { PAGE_PATHS } from '@/config/api'
import { dashboardApi } from '@/pages/db/api/db'
import { getSafeAreaStyle } from '@/utils/safeArea'
const safeAreaStyle = getSafeAreaStyle()
const userStore = useUserStore()
const inboundByCargo = ref([])
const outboundByCargo = ref([])
const inboundByPartner = ref([])
const outboundByPartner = ref([])
const inboundCount = computed(() => {
const set = new Set()
inboundByCargo.value.forEach((i) => {
if (Number(i.planned) > 0) set.add(i.label)
})
return set.size
})
const outboundCount = computed(() => {
const set = new Set()
outboundByCargo.value.forEach((i) => {
if (Number(i.planned) > 0) set.add(i.label)
})
return set.size
})
const chartBlocks = computed(() => [
pack('今日入库量(按货物,t)', inboundByCargo.value),
pack('今日出库量(按货物,t)', outboundByCargo.value),
pack('今日入库量(按往来单位+货物,t)', inboundByPartner.value),
pack('今日出库量(按往来单位+货物,t)', outboundByPartner.value)
])
function pack(title, rows) {
const list = Array.isArray(rows) ? rows : []
const max = Math.max(1, ...list.map((r) => Math.max(Number(r.planned) || 0, Number(r.actual) || 0)))
return { title, rows: list, max }
}
function barPct(v, max) {
const n = Number(v) || 0
return `${Math.min(100, (n / max) * 100)}%`
}
function fmt(v) {
const n = Number(v)
return Number.isFinite(n) ? n.toFixed(2) : '0'
}
function goWorkbench() {
uni.reLaunch({ url: PAGE_PATHS.workbench })
}
function go(url) {
uni.navigateTo({ url })
}
async function load() {
try {
const [a, b, c, d] = await Promise.all([
dashboardApi.getInboundByCargo(),
dashboardApi.getOutboundByCargo(),
dashboardApi.getInboundByPartnerCargo(),
dashboardApi.getOutboundByPartnerCargo()
])
inboundByCargo.value = a || []
outboundByCargo.value = b || []
inboundByPartner.value = c || []
outboundByPartner.value = d || []
} catch (e) {
console.error(e)
}
}
onMounted(load)
onShow(() => {
userStore.checkLoginStatus()
if (!userStore.isLoggedIn) {
uni.reLaunch({ url: PAGE_PATHS.login })
}
})
</script>
<style lang="scss">
@import '@/styles/db-theme.scss';
</style>