diff --git a/Cunkebao/api/devices.ts b/Cunkebao/api/devices.ts index 8f13f92c..eb240e23 100644 --- a/Cunkebao/api/devices.ts +++ b/Cunkebao/api/devices.ts @@ -45,8 +45,8 @@ export const fetchDeviceHandleLogs = async (id: string | number, page: number = // 更新设备任务配置 export const updateDeviceTaskConfig = async ( - id: string | number, config: { + deviceId: string | number; autoAddFriend?: boolean; autoReply?: boolean; momentsSync?: boolean; @@ -54,7 +54,6 @@ export const updateDeviceTaskConfig = async ( } ): Promise> => { return api.post>(`/v1/devices/task-config`, { - id, ...config }); }; diff --git a/Cunkebao/app/devices/page.tsx b/Cunkebao/app/devices/page.tsx index 2aa2e5ab..6a8eaa96 100644 --- a/Cunkebao/app/devices/page.tsx +++ b/Cunkebao/app/devices/page.tsx @@ -47,6 +47,20 @@ export default function DevicesPage() { const [isLoadingQRCode, setIsLoadingQRCode] = useState(false) const [isSubmittingImei, setIsSubmittingImei] = useState(false) const [activeTab, setActiveTab] = useState("scan") + const [pollingStatus, setPollingStatus] = useState<{ + isPolling: boolean; + message: string; + messageType: 'default' | 'success' | 'error'; + showAnimation: boolean; + }>({ + isPolling: false, + message: '', + messageType: 'default', + showAnimation: false + }); + + // 添加轮询定时器引用 + const pollingTimerRef = useRef(null); const devicesPerPage = 20 // 每页显示20条记录 @@ -315,12 +329,127 @@ export default function DevicesPage() { } } - // 打开添加设备模态框时获取二维码 + // 清理轮询函数 + const cleanupPolling = useCallback(() => { + if (pollingTimerRef.current) { + clearTimeout(pollingTimerRef.current); + pollingTimerRef.current = null; + } + setPollingStatus({ + isPolling: false, + message: '', + messageType: 'default', + showAnimation: false + }); + }, []); + + // 轮询检测设备添加状态 + const startPolling = useCallback(() => { + let pollCount = 0; + const maxPolls = 60; + const pollInterval = 1000; // 1秒 + const initialDelay = 5000; // 5秒后开始轮询 + + // 初始提示 + setPollingStatus({ + isPolling: false, + message: '请扫描二维码添加设备,5秒后将开始检测添加结果', + messageType: 'default', + showAnimation: false + }); + + const poll = async () => { + try { + const accountId = localStorage.getItem('s2_accountId'); + if (!accountId) { + setPollingStatus({ + isPolling: false, + message: '未获取到用户信息,请重新登录', + messageType: 'error', + showAnimation: false + }); + return; + } + + const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/devices/add-results?accountId=${accountId}`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + + const data = await response.json(); + + if (data.code === 200 && data.data) { + if (data.data.added) { + setPollingStatus({ + isPolling: false, + message: '设备添加成功。关闭后可继续', + messageType: 'success', + showAnimation: false + }); + setQrCodeImage('/broken-qr.png'); // 显示损坏的二维码 + cleanupPolling(); + return; + } + } + + pollCount++; + if (pollCount >= maxPolls) { + setPollingStatus({ + isPolling: false, + message: '未检测到设备添加,请关闭后重试', + messageType: 'error', + showAnimation: false + }); + cleanupPolling(); + return; + } + + pollingTimerRef.current = setTimeout(poll, pollInterval); + } catch (error) { + setPollingStatus({ + isPolling: false, + message: '检测过程中发生错误,请重试', + messageType: 'error', + showAnimation: false + }); + cleanupPolling(); + } + }; + + // 5秒后开始轮询 + pollingTimerRef.current = setTimeout(() => { + setPollingStatus({ + isPolling: true, + message: '正在检测添加结果', + messageType: 'default', + showAnimation: true + }); + poll(); + }, initialDelay); + }, [cleanupPolling]); + + // 修改打开添加设备模态框的处理函数 const handleOpenAddDeviceModal = () => { - setIsAddDeviceOpen(true) - setDeviceImei("") - setDeviceName("") - fetchDeviceQRCode() + setIsAddDeviceOpen(true); + setDeviceImei(""); + setDeviceName(""); + setQrCodeImage(""); + setPollingStatus({ + isPolling: false, + message: '', + messageType: 'default', + showAnimation: false + }); + fetchDeviceQRCode(); + startPolling(); + } + + // 修改关闭模态框的处理函数 + const handleCloseAddDeviceModal = () => { + cleanupPolling(); + setIsAddDeviceOpen(false); } // 通过IMEI添加设备 @@ -484,7 +613,10 @@ export default function DevicesPage() { try { const s2_accountId = localStorage.getItem('s2_accountId'); if (!s2_accountId) { - toast.error('未获取到用户信息,请重新登录'); + toast({ + title: '未获取到用户信息,请重新登录', + variant: 'destructive', + }); return; } @@ -503,16 +635,25 @@ export default function DevicesPage() { const data = await response.json(); if (data.code === 200) { - toast.success('添加设备成功'); + toast({ + title: '添加设备成功', + variant: 'default', + }); setIsAddDeviceOpen(false); // 刷新设备列表 loadDevices(1, true); } else { - toast.error(data.msg || '添加设备失败'); + toast({ + title: data.msg || '添加设备失败', + variant: 'destructive', + }); } } catch (error) { console.error('添加设备失败:', error); - toast.error('添加设备失败,请稍后重试'); + toast({ + title: '添加设备失败,请稍后重试', + variant: 'destructive', + }); } }; @@ -651,8 +792,12 @@ export default function DevicesPage() { - {/* 添加设备对话框 */} - + {/* 修改添加设备对话框 */} + { + if (!open) { + handleCloseAddDeviceModal(); + } + }}> 添加设备 @@ -671,7 +816,24 @@ export default function DevicesPage() { */} -
+
+ {/* 悬浮提示区域,上移50% */} +
+
+ {pollingStatus.isPolling || pollingStatus.showAnimation ? ( + <> + 正在检测添加结果 +
+
+
+
+
+ + ) : ( + 5秒后将开始检测添加结果 + )} +
+
{isLoadingQRCode ? (
@@ -719,7 +881,7 @@ export default function DevicesPage() { type="button" onClick={fetchDeviceQRCode} disabled={isLoadingQRCode} - className="w-48" + className="w-48 mt-8" > {isLoadingQRCode ? ( <> @@ -776,6 +938,28 @@ export default function DevicesPage() {
+ + {/* 在二维码显示区域下方添加状态提示 */} +
+ {pollingStatus.message && ( +
+

+ {pollingStatus.message} +

+ {pollingStatus.showAnimation && ( +
+
+
+
+
+ )} +
+ )} +
) } diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index 309a6dfd..744fdba2 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -10,6 +10,7 @@ Route::group('v1/', function () { // 设备管理相关 Route::group('devices', function () { + Route::get('add-results', 'app\cunkebao\controller\device\GetAddResultedDevicesController@index'); // 更新设备任务配置 Route::get(':id/related-accounts', 'app\cunkebao\controller\device\GetRelatedAccountsV1Controller@index'); // 设备关联微信账号路由 Route::get(':id/handle-logs', 'app\cunkebao\controller\device\GetDeviceHandleLogsV1Controller@index'); // 获取设备操作记录 Route::get('', 'app\cunkebao\controller\device\GetDeviceListV1Controller@index'); // 获取设备列表 @@ -18,7 +19,6 @@ Route::group('v1/', function () { Route::put('refresh', 'app\cunkebao\controller\device\RefreshDeviceDetailV1Controller@index'); // 刷新设备状态 Route::delete(':id', 'app\cunkebao\controller\Device@delete'); // 删除设备 Route::post('task-config', 'app\cunkebao\controller\device\UpdateDeviceTaskConfigV1Controller@index'); - Route::get('add-results', 'app\cunkebao\controller\device\GetAddResultedDevicesController@index'); // 更新设备任务配置 }); // 设备微信相关