d
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React from "react"
|
import { useState, useEffect } from "react"
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
|
||||||
import { Button } from "../ui/button"
|
import { Button } from "../ui/button"
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
|
||||||
@@ -16,13 +16,59 @@ import {
|
|||||||
CheckCircle,
|
CheckCircle,
|
||||||
Clock,
|
Clock,
|
||||||
MapPin,
|
MapPin,
|
||||||
|
Building2,
|
||||||
|
HardHat,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
|
import { apiGet } from "@/services/api"
|
||||||
|
import { getUserData } from "@/utils/storage"
|
||||||
|
|
||||||
|
// 定义统计数据接口
|
||||||
|
interface StatisticsData {
|
||||||
|
equipmentTotal: number
|
||||||
|
equipmentGrowth: string
|
||||||
|
completedWorkOrders: number
|
||||||
|
workOrdersGrowth: string
|
||||||
|
systemUsers: number
|
||||||
|
usersGrowth: string
|
||||||
|
systemMerchants: number
|
||||||
|
merchantsGrowth: string
|
||||||
|
systemMalls: number | null
|
||||||
|
mallsGrowth: string
|
||||||
|
systemWorkers: number
|
||||||
|
workersGrowth: string
|
||||||
|
totalMerchants: number
|
||||||
|
}
|
||||||
|
|
||||||
export default function StatisticsPage() {
|
export default function StatisticsPage() {
|
||||||
|
const [statisticsData, setStatisticsData] = useState<StatisticsData | null>(null)
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const userData = getUserData()
|
||||||
|
|
||||||
|
// 判断是否是总公司账号(根据实际业务逻辑调整)
|
||||||
|
const isHeadquarters = userData?.role === 'admin' || userData?.roleType === 'headquarters'
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchStatistics()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const fetchStatistics = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const response = await apiGet<{ code: number; msg: string; data: StatisticsData }>('/back/statistics/planTop')
|
||||||
|
if (response.code === 200) {
|
||||||
|
setStatisticsData(response.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取统计数据失败:', error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const stats = {
|
const stats = {
|
||||||
totalEquipment: 1248,
|
totalEquipment: statisticsData?.equipmentTotal || 0,
|
||||||
activeWorkOrders: 23,
|
activeWorkOrders: statisticsData?.completedWorkOrders || 0,
|
||||||
totalUsers: 156,
|
totalUsers: statisticsData?.systemUsers || 0,
|
||||||
lowStock: 8,
|
lowStock: 8,
|
||||||
equipmentStatus: {
|
equipmentStatus: {
|
||||||
normal: 1156,
|
normal: 1156,
|
||||||
@@ -161,21 +207,21 @@ export default function StatisticsPage() {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// 区域设备分布
|
// 区域设备分布(暂未使用)
|
||||||
const regionEquipmentData = [
|
// const regionEquipmentData = [
|
||||||
{ region: "华东区", equipment: 456, workOrders: 89 },
|
// { region: "华东区", equipment: 456, workOrders: 89 },
|
||||||
{ region: "华南区", equipment: 342, workOrders: 67 },
|
// { region: "华南区", equipment: 342, workOrders: 67 },
|
||||||
{ region: "华北区", equipment: 298, workOrders: 52 },
|
// { region: "华北区", equipment: 298, workOrders: 52 },
|
||||||
{ region: "华中区", equipment: 152, workOrders: 34 },
|
// { region: "华中区", equipment: 152, workOrders: 34 },
|
||||||
]
|
// ]
|
||||||
|
|
||||||
// 设备类型分布
|
// 设备类型分布(暂未使用)
|
||||||
const equipmentTypeData = [
|
// const equipmentTypeData = [
|
||||||
{ type: "干粉灭火器", count: 567, percentage: 45.4 },
|
// { type: "干粉灭火器", count: 567, percentage: 45.4 },
|
||||||
{ type: "自动喷淋", count: 234, percentage: 18.8 },
|
// { type: "自动喷淋", count: 234, percentage: 18.8 },
|
||||||
{ type: "烟感器", count: 298, percentage: 23.9 },
|
// { type: "烟感器", count: 298, percentage: 23.9 },
|
||||||
{ type: "消防栓", count: 149, percentage: 11.9 },
|
// { type: "消防栓", count: 149, percentage: 11.9 },
|
||||||
]
|
// ]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
@@ -205,58 +251,112 @@ export default function StatisticsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
|
{/* 1. 所有地区设备总数 */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">设备总数</CardTitle>
|
<CardTitle className="text-sm font-medium">所有地区设备总数</CardTitle>
|
||||||
<Shield className="h-4 w-4 text-blue-600" />
|
<Shield className="h-4 w-4 text-blue-600" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{stats.totalEquipment}</div>
|
<div className="text-2xl font-bold">{loading ? '-' : statisticsData?.equipmentTotal || 0}</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
<TrendingUp className="inline h-3 w-3 mr-1" />
|
<TrendingUp className="inline h-3 w-3 mr-1" />
|
||||||
较上月增长 12%
|
较上月增长 {loading ? '-' : statisticsData?.equipmentGrowth || '0%'}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* 2. 完成工单 */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">活跃工单</CardTitle>
|
<CardTitle className="text-sm font-medium">完成工单</CardTitle>
|
||||||
<Wrench className="h-4 w-4 text-green-600" />
|
<CheckCircle className="h-4 w-4 text-green-600" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{stats.activeWorkOrders}</div>
|
<div className="text-2xl font-bold">{loading ? '-' : statisticsData?.completedWorkOrders || 0}</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
<Clock className="inline h-3 w-3 mr-1" />
|
<TrendingUp className="inline h-3 w-3 mr-1" />
|
||||||
平均处理时间 2.3天
|
较上月增长 {loading ? '-' : statisticsData?.workOrdersGrowth || '0%'}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* 3. 系统用户 */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">系统用户</CardTitle>
|
<CardTitle className="text-sm font-medium">系统用户</CardTitle>
|
||||||
<Users className="h-4 w-4 text-purple-600" />
|
<Users className="h-4 w-4 text-purple-600" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{stats.totalUsers}</div>
|
<div className="text-2xl font-bold">{loading ? '-' : statisticsData?.systemUsers || 0}</div>
|
||||||
<p className="text-xs text-muted-foreground">活跃用户 142 人</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
||||||
<CardTitle className="text-sm font-medium">库存预警</CardTitle>
|
|
||||||
<Package className="h-4 w-4 text-orange-600" />
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="text-2xl font-bold text-orange-600">{stats.lowStock}</div>
|
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
<AlertTriangle className="inline h-3 w-3 mr-1" />
|
<TrendingUp className="inline h-3 w-3 mr-1" />
|
||||||
需要补货
|
较上月增长 {loading ? '-' : statisticsData?.usersGrowth || '0%'}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* 4. 系统商户 */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
|
<CardTitle className="text-sm font-medium">系统商户</CardTitle>
|
||||||
|
<Package className="h-4 w-4 text-orange-600" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="text-2xl font-bold">{loading ? '-' : statisticsData?.systemMerchants || 0}</div>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
<TrendingUp className="inline h-3 w-3 mr-1" />
|
||||||
|
较上月增长 {loading ? '-' : statisticsData?.merchantsGrowth || '0%'}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 5. 系统商场 */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
|
<CardTitle className="text-sm font-medium">系统商场</CardTitle>
|
||||||
|
<Building2 className="h-4 w-4 text-indigo-600" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="text-2xl font-bold">{loading ? '-' : statisticsData?.systemMalls || 0}</div>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
<TrendingUp className="inline h-3 w-3 mr-1" />
|
||||||
|
较上月增长 {loading ? '-' : statisticsData?.mallsGrowth || '0%'}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 6. 系统工人 */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
|
<CardTitle className="text-sm font-medium">系统工人</CardTitle>
|
||||||
|
<HardHat className="h-4 w-4 text-yellow-600" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="text-2xl font-bold">{loading ? '-' : statisticsData?.systemWorkers || 0}</div>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
<TrendingUp className="inline h-3 w-3 mr-1" />
|
||||||
|
较上月增长 {loading ? '-' : statisticsData?.workersGrowth || '0%'}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 7. 总商户 - 仅总公司账号可见 */}
|
||||||
|
{isHeadquarters && (
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
|
<CardTitle className="text-sm font-medium">总商户</CardTitle>
|
||||||
|
<Wrench className="h-4 w-4 text-red-600" />
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="text-2xl font-bold">{loading ? '-' : statisticsData?.totalMerchants || 0}</div>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
<TrendingUp className="inline h-3 w-3 mr-1" />
|
||||||
|
较上月增长 {loading ? '-' : statisticsData?.merchantsGrowth || '0%'}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
|
|||||||
@@ -435,20 +435,22 @@ export default function WorkOrdersPage() {
|
|||||||
<TableHead>类型</TableHead>
|
<TableHead>类型</TableHead>
|
||||||
<TableHead>状态</TableHead>
|
<TableHead>状态</TableHead>
|
||||||
<TableHead>负责人</TableHead>
|
<TableHead>负责人</TableHead>
|
||||||
<TableHead>时间</TableHead>
|
<TableHead>创建时间</TableHead>
|
||||||
|
<TableHead>截至时间</TableHead>
|
||||||
|
<TableHead>完成时间</TableHead>
|
||||||
<TableHead>操作</TableHead>
|
<TableHead>操作</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{loadingWorkOrders ? (
|
{loadingWorkOrders ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={7} className="text-center py-8">
|
<TableCell colSpan={9} className="text-center py-8">
|
||||||
<div className="text-gray-500">加载中...</div>
|
<div className="text-gray-500">加载中...</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : filteredWorkOrders.length === 0 ? (
|
) : filteredWorkOrders.length === 0 ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={7} className="text-center py-8">
|
<TableCell colSpan={9} className="text-center py-8">
|
||||||
<div className="text-gray-500">暂无工单数据</div>
|
<div className="text-gray-500">暂无工单数据</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -485,12 +487,21 @@ export default function WorkOrdersPage() {
|
|||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<div className="space-y-1">
|
<div className="text-sm text-gray-600">{item.createdDate || "-"}</div>
|
||||||
<div className="flex items-center text-sm">
|
</TableCell>
|
||||||
<Calendar className="h-3 w-3 mr-1 text-blue-500" />
|
<TableCell>
|
||||||
<span className="text-blue-600">截止: {item.scheduledDate || "未设置"}</span>
|
<div className="flex items-center text-sm">
|
||||||
</div>
|
<Calendar className="h-3 w-3 mr-1 text-blue-500" />
|
||||||
<div className="text-xs text-gray-500">创建: {item.createdDate}</div>
|
<span className="text-blue-600">{item.scheduledDate || "未设置"}</span>
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="text-sm text-gray-600">
|
||||||
|
{item.completedDate ? (
|
||||||
|
<span className="text-green-600">{item.completedDate}</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-400">-</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
|
|||||||
Reference in New Issue
Block a user