feat: 存储了
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import BackButton from '@/components/BackButton';
|
||||
import { useSimpleBack } from '@/hooks/useBackNavigation';
|
||||
import { ChevronLeft, Smartphone, Battery, Wifi, MessageCircle, Users, Settings, History, RefreshCw, Loader2 } from 'lucide-react';
|
||||
import { devicesApi, fetchDeviceDetail, fetchDeviceRelatedAccounts, fetchDeviceHandleLogs, updateDeviceTaskConfig } from '@/api/devices';
|
||||
import { useToast } from '@/components/ui/toast';
|
||||
@@ -52,7 +55,7 @@ interface HandleLog {
|
||||
|
||||
export default function DeviceDetail() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { goBack } = useSimpleBack('/devices');
|
||||
const { toast } = useToast();
|
||||
const [device, setDevice] = useState<Device | null>(null);
|
||||
const [activeTab, setActiveTab] = useState("info");
|
||||
@@ -442,13 +445,11 @@ export default function DeviceDetail() {
|
||||
<div className="text-sm text-gray-500 text-center">
|
||||
无法加载ID为 "{id}" 的设备信息,请检查设备是否存在。
|
||||
</div>
|
||||
<button
|
||||
onClick={() => navigate(-1)}
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center gap-2 transition-colors"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
返回上一页
|
||||
</button>
|
||||
<BackButton
|
||||
variant="button"
|
||||
text="返回上一页"
|
||||
onBack={goBack}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -457,22 +458,15 @@ export default function DeviceDetail() {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
{/* 固定header */}
|
||||
<header className="fixed top-0 left-0 right-0 z-20 bg-white border-b border-gray-200">
|
||||
<div className="flex items-center justify-between px-4 py-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<button
|
||||
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
onClick={() => navigate(-1)}
|
||||
>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</button>
|
||||
<h1 className="text-lg font-semibold">设备详情</h1>
|
||||
</div>
|
||||
<PageHeader
|
||||
title="设备详情"
|
||||
defaultBackPath="/devices"
|
||||
rightContent={
|
||||
<button className="p-2 hover:bg-gray-100 rounded-lg transition-colors">
|
||||
<Settings className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* 内容区域 */}
|
||||
<div className="pt-16 pb-20">
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ChevronLeft, Plus, Search, RefreshCw, QrCode, Smartphone, Loader2, AlertTriangle, Trash2, X } from 'lucide-react';
|
||||
import { Plus, Search, RefreshCw, QrCode, Smartphone, Loader2, AlertTriangle, Trash2, X } from 'lucide-react';
|
||||
import { devicesApi } from '@/api';
|
||||
import { useToast } from '@/components/ui/toast';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
|
||||
// 设备接口
|
||||
interface Device {
|
||||
@@ -375,18 +376,11 @@ export default function Devices() {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
{/* 固定header */}
|
||||
<header className="fixed top-0 left-0 right-0 z-20 bg-white border-b border-gray-200">
|
||||
<div className="flex items-center justify-between px-4 py-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<button
|
||||
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
onClick={() => navigate(-1)}
|
||||
>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</button>
|
||||
<h1 className="text-lg font-semibold">设备管理</h1>
|
||||
</div>
|
||||
{/* 页面Header */}
|
||||
<PageHeader
|
||||
title="设备管理"
|
||||
defaultBackPath="/"
|
||||
rightContent={
|
||||
<button
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center gap-2 transition-colors"
|
||||
onClick={handleOpenAddDeviceModal}
|
||||
@@ -394,8 +388,8 @@ export default function Devices() {
|
||||
<Plus className="h-4 w-4" />
|
||||
添加设备
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* 内容区域 */}
|
||||
<div className="pt-16 pb-20">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Plus, Calendar } from 'lucide-react';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
|
||||
interface Plan {
|
||||
id: string;
|
||||
@@ -98,11 +99,10 @@ export default function Plans() {
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<h1 className="text-xl font-semibold">获客计划</h1>
|
||||
</div>
|
||||
</header>
|
||||
<PageHeader
|
||||
title="获客计划"
|
||||
showBack={false}
|
||||
/>
|
||||
<div className="flex justify-center items-center h-40">
|
||||
<div className="text-gray-500">加载中...</div>
|
||||
</div>
|
||||
@@ -113,11 +113,10 @@ export default function Plans() {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<h1 className="text-xl font-semibold">获客计划</h1>
|
||||
</div>
|
||||
</header>
|
||||
<PageHeader
|
||||
title="获客计划"
|
||||
showBack={false}
|
||||
/>
|
||||
<div className="text-red-500 text-center py-8">{error}</div>
|
||||
</div>
|
||||
);
|
||||
@@ -125,9 +124,10 @@ export default function Plans() {
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<h1 className="text-xl font-semibold">获客计划</h1>
|
||||
<PageHeader
|
||||
title="获客计划"
|
||||
showBack={false}
|
||||
rightContent={
|
||||
<button
|
||||
onClick={() => navigate('/scenarios/new')}
|
||||
className="flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm"
|
||||
@@ -135,8 +135,8 @@ export default function Plans() {
|
||||
<Plus className="h-4 w-4 mr-1" />
|
||||
新建计划
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="p-4">
|
||||
{plans.length === 0 ? (
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { ArrowLeft, Plus, Users, TrendingUp, Calendar } from 'lucide-react';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import { useSimpleBack } from '@/hooks/useBackNavigation';
|
||||
import { Plus, Users, TrendingUp, Calendar } from 'lucide-react';
|
||||
|
||||
interface Plan {
|
||||
id: string;
|
||||
@@ -26,6 +28,7 @@ interface ScenarioData {
|
||||
export default function ScenarioDetail() {
|
||||
const { scenarioId } = useParams<{ scenarioId: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { goBack } = useSimpleBack('/scenarios');
|
||||
const [scenario, setScenario] = useState<ScenarioData | null>(null);
|
||||
const [plans, setPlans] = useState<Plan[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -166,20 +169,10 @@ export default function ScenarioDetail() {
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<div className="flex items-center">
|
||||
<button
|
||||
onClick={() => navigate(-1)}
|
||||
className="mr-3 p-1 hover:bg-gray-100 rounded"
|
||||
>
|
||||
<ArrowLeft className="h-5 w-5" />
|
||||
</button>
|
||||
<div className="flex items-center">
|
||||
<img src={scenario.image} alt={scenario.name} className="w-8 h-8 mr-3 rounded" />
|
||||
<h1 className="text-xl font-semibold">{scenario.name}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<PageHeader
|
||||
title={scenario.name}
|
||||
defaultBackPath="/scenarios"
|
||||
rightContent={
|
||||
<button
|
||||
onClick={() => navigate(`/scenarios/new?scenario=${scenarioId}`)}
|
||||
className="flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm"
|
||||
@@ -187,8 +180,8 @@ export default function ScenarioDetail() {
|
||||
<Plus className="h-4 w-4 mr-1" />
|
||||
新建计划
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="p-4">
|
||||
{/* 场景描述 */}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Plus, TrendingUp } from 'lucide-react';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
|
||||
interface Scenario {
|
||||
id: string;
|
||||
@@ -107,11 +108,10 @@ export default function Scenarios() {
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<h1 className="text-xl font-semibold">场景获客</h1>
|
||||
</div>
|
||||
</header>
|
||||
<PageHeader
|
||||
title="场景获客"
|
||||
showBack={false}
|
||||
/>
|
||||
<div className="flex justify-center items-center h-40">
|
||||
<div className="text-gray-500">加载中...</div>
|
||||
</div>
|
||||
@@ -122,11 +122,10 @@ export default function Scenarios() {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<h1 className="text-xl font-semibold">场景获客</h1>
|
||||
</div>
|
||||
</header>
|
||||
<PageHeader
|
||||
title="场景获客"
|
||||
showBack={false}
|
||||
/>
|
||||
<div className="text-red-500 text-center py-8">{error}</div>
|
||||
</div>
|
||||
);
|
||||
@@ -134,9 +133,10 @@ export default function Scenarios() {
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<h1 className="text-xl font-semibold">场景获客</h1>
|
||||
<PageHeader
|
||||
title="场景获客"
|
||||
showBack={false}
|
||||
rightContent={
|
||||
<button
|
||||
onClick={() => navigate('/scenarios/new')}
|
||||
className="flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm"
|
||||
@@ -144,8 +144,8 @@ export default function Scenarios() {
|
||||
<Plus className="h-4 w-4 mr-1" />
|
||||
新建计划
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="p-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import {
|
||||
ChevronLeft,
|
||||
ChevronLeft,
|
||||
Smartphone,
|
||||
Users,
|
||||
Star,
|
||||
@@ -407,17 +408,10 @@ export default function WechatAccountDetail() {
|
||||
return (
|
||||
<div className="flex-1 bg-gradient-to-b from-blue-50 to-white min-h-screen overflow-x-hidden">
|
||||
{/* 固定header */}
|
||||
<header className="fixed top-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-b border-gray-200 shadow-sm">
|
||||
<div className="flex items-center p-4">
|
||||
<button
|
||||
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
onClick={handleBack}
|
||||
>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</button>
|
||||
<h1 className="ml-2 text-lg font-medium">账号详情</h1>
|
||||
</div>
|
||||
</header>
|
||||
<PageHeader
|
||||
title="账号详情"
|
||||
defaultBackPath="/wechat-accounts"
|
||||
/>
|
||||
|
||||
{/* 内容区域 - 添加顶部内边距避免被固定header遮挡 */}
|
||||
<div className="pt-20 p-4 space-y-4">
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ChevronLeft, Search, RefreshCw, ArrowRightLeft, AlertCircle, Loader2 } from 'lucide-react';
|
||||
import { Search, RefreshCw, ArrowRightLeft, AlertCircle, Loader2 } from 'lucide-react';
|
||||
import { fetchWechatAccountList, transformWechatAccount } from '@/api/wechat-accounts';
|
||||
import { useToast } from '@/components/ui/toast';
|
||||
import { useWechatAccount } from '@/contexts/WechatAccountContext';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
|
||||
interface WechatAccount {
|
||||
id: string;
|
||||
@@ -150,24 +151,16 @@ export default function WechatAccounts() {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
{/* 固定header */}
|
||||
<header className="fixed top-0 left-0 right-0 z-20 bg-white border-b border-gray-200">
|
||||
<div className="flex items-center px-4 py-3">
|
||||
<button
|
||||
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
onClick={() => navigate(-1)}
|
||||
>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</button>
|
||||
<h1 className="ml-2 text-lg font-semibold">微信号</h1>
|
||||
</div>
|
||||
</header>
|
||||
<PageHeader
|
||||
title="微信号"
|
||||
defaultBackPath="/"
|
||||
/>
|
||||
|
||||
{/* 内容区域 */}
|
||||
<div className="pt-16 pb-20">
|
||||
<div className="pt-14 pb-20">
|
||||
<div className="p-4">
|
||||
{/* 搜索和操作栏 */}
|
||||
<div className="bg-white p-4 rounded-xl shadow-sm border border-gray-100 mb-4">
|
||||
<div className="bg-white p-4 rounded-xl shadow-sm border border-gray-100 mb-4 ">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="relative flex-1">
|
||||
<Search className="w-4 h-4 absolute left-3 top-3 text-gray-400" />
|
||||
|
||||
Reference in New Issue
Block a user