feat: 本次提交更新内容如下

更新
This commit is contained in:
笔记本里的永平
2025-07-21 09:55:37 +08:00
parent 5122a0965a
commit f6f9e45198
7 changed files with 398 additions and 264 deletions

View File

@@ -1,21 +1,30 @@
import React, { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Bell, Smartphone, Users, Activity, MessageSquare, TrendingUp } from 'lucide-react';
import Chart from 'chart.js/auto';
import Layout from '@/components/Layout';
import BottomNav from '@/components/BottomNav';
import UnifiedHeader, { HeaderPresets } from '@/components/UnifiedHeader';
import { Card } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress';
import '@/components/Layout.css';
import React, { useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import {
Bell,
Smartphone,
Users,
Activity,
MessageSquare,
TrendingUp,
} from "lucide-react";
import Chart from "chart.js/auto";
import Layout from "@/components/Layout";
import BottomNav from "@/components/BottomNav";
import UnifiedHeader, { HeaderPresets } from "@/components/UnifiedHeader";
import { Card } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import "@/components/Layout.css";
// API接口定义
const API_BASE_URL = process.env.REACT_APP_API_BASE_URL || "https://ckbapi.quwanzhi.com";
const API_BASE_URL =
process.env.REACT_APP_API_BASE_URL || "https://ckbapi.quwanzhi.com";
// 统一的API请求客户端
async function apiRequest<T>(url: string): Promise<T> {
try {
const token = typeof window !== "undefined" ? localStorage.getItem("token") : null;
const token =
typeof window !== "undefined" ? localStorage.getItem("token") : null;
const headers: Record<string, string> = {
"Content-Type": "application/json",
Accept: "application/json",
@@ -99,7 +108,7 @@ export default function Home() {
growth: 12,
},
{
id: "xiaohongshu",
id: "xiaohongshu",
name: "小红书获客",
icon: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-yvnMxpoBUzcvEkr8DfvHgPHEo1kmQ3.png",
color: "bg-red-100 text-red-600",
@@ -135,7 +144,7 @@ export default function Home() {
},
{
title: "群发任务",
value: "8",
value: "8",
icon: <Users className="h-4 w-4" />,
color: "text-orange-600",
path: "/workspace/group-push",
@@ -180,10 +189,11 @@ export default function Home() {
// 尝试请求API数据
try {
// 并行请求多个接口
const [deviceStatsResult, wechatStatsResult] = await Promise.allSettled([
apiRequest(`${API_BASE_URL}/v1/dashboard/device-stats`),
apiRequest(`${API_BASE_URL}/v1/dashboard/wechat-stats`),
]);
const [deviceStatsResult, wechatStatsResult] =
await Promise.allSettled([
apiRequest(`${API_BASE_URL}/v1/dashboard/device-stats`),
apiRequest(`${API_BASE_URL}/v1/dashboard/wechat-stats`),
]);
const newStats = {
totalDevices: 0,
@@ -213,7 +223,9 @@ export default function Home() {
setStats(newStats);
} catch (apiError) {
console.warn("API请求失败使用默认数据:", apiError);
setApiError(apiError instanceof Error ? apiError.message : "API连接失败");
setApiError(
apiError instanceof Error ? apiError.message : "API连接失败"
);
// 使用默认数据
setStats({
@@ -247,11 +259,11 @@ export default function Home() {
}, []); // 移除stats依赖
const handleDevicesClick = () => {
navigate('/profile/devices');
navigate("/profile/devices");
};
const handleWechatClick = () => {
navigate('/wechat-accounts');
navigate("/wechat-accounts");
};
// 使用Chart.js创建图表
@@ -263,7 +275,7 @@ export default function Home() {
}
const ctx = chartRef.current.getContext("2d");
// 添加null检查
if (!ctx) return;
@@ -391,9 +403,12 @@ export default function Home() {
<div className="flex flex-col">
<span className="text-xs text-gray-500 mb-1"></span>
<div className="flex items-center justify-between">
<span className="text-lg font-bold text-blue-600">{stats.totalDevices}</span>
<span className="text-lg font-bold text-blue-600">
{stats.totalDevices}
</span>
<Smartphone className="w-5 h-5 text-blue-600" />
</div>
<div className="h-2"></div>
</div>
</Card>
</div>
@@ -402,22 +417,31 @@ export default function Home() {
<div className="flex flex-col">
<span className="text-xs text-gray-500 mb-1"></span>
<div className="flex items-center justify-between">
<span className="text-lg font-bold text-blue-600">{stats.totalWechatAccounts}</span>
<span className="text-lg font-bold text-blue-600">
{stats.totalWechatAccounts}
</span>
<Users className="w-5 h-5 text-blue-600" />
</div>
</div>
<div className="h-2"></div>
</Card>
</div>
<Card className="p-3 bg-white">
<div className="flex flex-col">
<span className="text-xs text-gray-500 mb-1">线</span>
<div className="flex items-center justify-between mb-1">
<span className="text-lg font-bold text-blue-600">{stats.onlineWechatAccounts}</span>
<span className="text-lg font-bold text-blue-600">
{stats.onlineWechatAccounts}
</span>
<Activity className="w-5 h-5 text-blue-600" />
</div>
<Progress
value={
stats.totalWechatAccounts > 0 ? (stats.onlineWechatAccounts / stats.totalWechatAccounts) * 100 : 0
stats.totalWechatAccounts > 0
? (stats.onlineWechatAccounts /
stats.totalWechatAccounts) *
100
: 0
}
className="h-1"
/>
@@ -435,16 +459,30 @@ export default function Home() {
.sort((a, b) => b.value - a.value)
.slice(0, 4) // 只显示前4个
.map((scenario) => (
<div
<div
key={scenario.id}
className="block flex-1 cursor-pointer"
onClick={() => navigate(`/scenarios/${scenario.id}?name=${encodeURIComponent(scenario.name)}`)}
onClick={() =>
navigate(
`/scenarios/${scenario.id}?name=${encodeURIComponent(
scenario.name
)}`
)
}
>
<div className="flex flex-col items-center text-center space-y-1">
<div className={`w-10 h-10 rounded-full ${scenario.color} flex items-center justify-center`}>
<img src={scenario.icon || "/placeholder.svg"} alt={scenario.name} className="w-5 h-5" />
<div
className={`w-10 h-10 rounded-full ${scenario.color} flex items-center justify-center`}
>
<img
src={scenario.icon || "/placeholder.svg"}
alt={scenario.name}
className="w-5 h-5"
/>
</div>
<div className="text-sm font-medium">
{scenario.value}
</div>
<div className="text-sm font-medium">{scenario.value}</div>
<div className="text-xs text-gray-500 whitespace-nowrap overflow-hidden text-ellipsis w-full">
{scenario.name}
</div>
@@ -466,7 +504,9 @@ export default function Home() {
className="flex items-center space-x-3 p-3 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition-colors"
onClick={() => stat.path && navigate(stat.path)}
>
<div className={`p-2 rounded-full bg-white ${stat.color}`}>{stat.icon}</div>
<div className={`p-2 rounded-full bg-white ${stat.color}`}>
{stat.icon}
</div>
<div>
<div className="text-lg font-semibold">{stat.value}</div>
<div className="text-xs text-gray-500">{stat.title}</div>
@@ -487,4 +527,4 @@ export default function Home() {
</div>
</Layout>
);
}
}