liqiuying 2 сар өмнө
parent
commit
7de7013192

+ 1 - 1
components/IconCom.tsx

@@ -26,7 +26,7 @@ const IconCom: React.FC<IconComProps> = (props: IconComProps = {}) => {
             {type == "error" && <svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8678" width={width} height={height}><path d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 0.3L512 465.6l-99.3-118.4-66.1-0.3c-4.4 0-8 3.5-8 8 0 1.9 0.7 3.7 1.9 5.2l130.1 155L340.5 670c-1.2 1.5-1.9 3.3-1.9 5.2 0 4.4 3.6 8 8 8l66.1-0.3L512 564.4l99.3 118.4 66 0.3c4.4 0 8-3.5 8-8 0-1.9-0.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z" p-id="8679" fill={fill}></path><path d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" p-id="8680" fill={fill}></path></svg>}
             {type == "error" && <svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8678" width={width} height={height}><path d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 0.3L512 465.6l-99.3-118.4-66.1-0.3c-4.4 0-8 3.5-8 8 0 1.9 0.7 3.7 1.9 5.2l130.1 155L340.5 670c-1.2 1.5-1.9 3.3-1.9 5.2 0 4.4 3.6 8 8 8l66.1-0.3L512 564.4l99.3 118.4 66 0.3c4.4 0 8-3.5 8-8 0-1.9-0.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z" p-id="8679" fill={fill}></path><path d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" p-id="8680" fill={fill}></path></svg>}
             {type == "warn" && <svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8826" width={width} height={height}><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" p-id="8827"></path><path d="M512 336m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" p-id="8828" fill={fill}></path><path d="M536 448h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z" p-id="8829" fill={fill}></path></svg>}
             {type == "warn" && <svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8826" width={width} height={height}><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" p-id="8827"></path><path d="M512 336m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" p-id="8828" fill={fill}></path><path d="M536 448h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z" p-id="8829" fill={fill}></path></svg>}
             {type == "info" && <svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8975" width={width} height={height}><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" p-id="8976" fill={fill}></path><path d="M623.6 316.7C593.6 290.4 554 276 512 276s-81.6 14.5-111.6 40.7C369.2 344 352 380.7 352 420v7.6c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V420c0-44.1 43.1-80 96-80s96 35.9 96 80c0 31.1-22 59.6-56.1 72.7-21.2 8.1-39.2 22.3-52.1 40.9-13.1 19-19.9 41.8-19.9 64.9V620c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-22.7c0-19.7 12.4-37.7 30.9-44.8 59-22.7 97.1-74.7 97.1-132.5 0.1-39.3-17.1-76-48.3-103.3z" p-id="8977" fill={fill}></path><path d="M512 732m-40 0a40 40 0 1 0 80 0 40 40 0 1 0-80 0Z" p-id="8978" fill={fill}></path></svg>}
             {type == "info" && <svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8975" width={width} height={height}><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" p-id="8976" fill={fill}></path><path d="M623.6 316.7C593.6 290.4 554 276 512 276s-81.6 14.5-111.6 40.7C369.2 344 352 380.7 352 420v7.6c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V420c0-44.1 43.1-80 96-80s96 35.9 96 80c0 31.1-22 59.6-56.1 72.7-21.2 8.1-39.2 22.3-52.1 40.9-13.1 19-19.9 41.8-19.9 64.9V620c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-22.7c0-19.7 12.4-37.7 30.9-44.8 59-22.7 97.1-74.7 97.1-132.5 0.1-39.3-17.1-76-48.3-103.3z" p-id="8977" fill={fill}></path><path d="M512 732m-40 0a40 40 0 1 0 80 0 40 40 0 1 0-80 0Z" p-id="8978" fill={fill}></path></svg>}
-
+            {type == "list" && <svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17475" width={width} height={height}><path d="M912 192H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM912 476H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM912 760H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z" p-id="17476" fill={fill}></path><path d="M160 228m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z" p-id="17477" fill={fill}></path><path d="M160 512m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z" p-id="17478" fill={fill}></path><path d="M160 796m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z" p-id="17479" fill={fill}></path></svg>}
         </div>
         </div>
     )
     )
 }
 }

+ 17 - 12
entrypoints/content.ts

@@ -1,12 +1,13 @@
+import { OptionScript } from "./content_script/OptionScript";
 export default defineContentScript({
 export default defineContentScript({
   matches: ["<all_urls>"],
   matches: ["<all_urls>"],
-  
+
   main() {
   main() {
     // 辅助函数:提取背景图片URL
     // 辅助函数:提取背景图片URL
     const extractBackgroundUrl = (element: Element): string | null => {
     const extractBackgroundUrl = (element: Element): string | null => {
       const computedStyle = window.getComputedStyle(element);
       const computedStyle = window.getComputedStyle(element);
       const backgroundImage = computedStyle.backgroundImage;
       const backgroundImage = computedStyle.backgroundImage;
-      
+
       if (backgroundImage && backgroundImage !== 'none' && backgroundImage.includes('url')) {
       if (backgroundImage && backgroundImage !== 'none' && backgroundImage.includes('url')) {
         // 处理包含转义字符的URL
         // 处理包含转义字符的URL
         const urlMatch = backgroundImage.match(/url\(["']?(.*?)["']?\)/);
         const urlMatch = backgroundImage.match(/url\(["']?(.*?)["']?\)/);
@@ -18,26 +19,26 @@ export default defineContentScript({
           return textarea.value;
           return textarea.value;
         }
         }
       }
       }
-      
+
       return null;
       return null;
     };
     };
-    
+
     // 监听来自popup的消息
     // 监听来自popup的消息
     browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
     browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
       if (request.action === "getTbodyData") {
       if (request.action === "getTbodyData") {
         // 获取所有tbody中的数据,包括背景图片
         // 获取所有tbody中的数据,包括背景图片
         const tables = Array.from(document.querySelectorAll('table')).map((table, tableIndex) => {
         const tables = Array.from(document.querySelectorAll('table')).map((table, tableIndex) => {
           const tbodies = Array.from(table.querySelectorAll('tbody'));
           const tbodies = Array.from(table.querySelectorAll('tbody'));
-          
+
           return tbodies.map(tbody => {
           return tbodies.map(tbody => {
             const rows = Array.from(tbody.querySelectorAll('tr'));
             const rows = Array.from(tbody.querySelectorAll('tr'));
-            
+
             return rows.map((row, rowIndex) => {
             return rows.map((row, rowIndex) => {
               const cells = Array.from(row.querySelectorAll('td, th'));
               const cells = Array.from(row.querySelectorAll('td, th'));
               return cells.map((cell, cellIndex) => {
               return cells.map((cell, cellIndex) => {
                 // 获取单元格文本内容
                 // 获取单元格文本内容
                 const textContent = cell.textContent?.trim() || '';
                 const textContent = cell.textContent?.trim() || '';
-                
+
                 // 查找单元格内所有带有背景图片的div元素
                 // 查找单元格内所有带有背景图片的div元素
                 const divsWithBackground = Array.from(cell.querySelectorAll('div[style*="background-image"]'))
                 const divsWithBackground = Array.from(cell.querySelectorAll('div[style*="background-image"]'))
                   .map((div, divIndex) => {
                   .map((div, divIndex) => {
@@ -52,7 +53,7 @@ export default defineContentScript({
                     return null;
                     return null;
                   })
                   })
                   .filter(item => item !== null);
                   .filter(item => item !== null);
-                
+
                 // 如果找到带背景图片的div,返回包含这些信息的对象
                 // 如果找到带背景图片的div,返回包含这些信息的对象
                 if (divsWithBackground.length > 0) {
                 if (divsWithBackground.length > 0) {
                   return {
                   return {
@@ -60,7 +61,7 @@ export default defineContentScript({
                     backgroundImages: divsWithBackground
                     backgroundImages: divsWithBackground
                   };
                   };
                 }
                 }
-                
+
                 // 检查单元格本身是否有背景图片
                 // 检查单元格本身是否有背景图片
                 const cellBackgroundUrl = extractBackgroundUrl(cell);
                 const cellBackgroundUrl = extractBackgroundUrl(cell);
                 if (cellBackgroundUrl) {
                 if (cellBackgroundUrl) {
@@ -69,19 +70,23 @@ export default defineContentScript({
                     cellBackgroundUrl: cellBackgroundUrl
                     cellBackgroundUrl: cellBackgroundUrl
                   };
                   };
                 }
                 }
-                
+
                 // 否则返回文本内容
                 // 否则返回文本内容
                 return textContent;
                 return textContent;
               });
               });
             });
             });
           }).flat();
           }).flat();
         }).flat();
         }).flat();
-        
+
         // 过滤掉空表格
         // 过滤掉空表格
         const nonEmptyTables = tables.filter(table => table.length > 0);
         const nonEmptyTables = tables.filter(table => table.length > 0);
-        
+
         sendResponse({ tables: nonEmptyTables });
         sendResponse({ tables: nonEmptyTables });
       }
       }
+      // 模拟用户重复性操作
+      if (request.action === "autoSendMessages") {
+        OptionScript(request, sender, sendResponse)
+      }
     });
     });
   }
   }
 });
 });

+ 89 - 0
entrypoints/content_script/OptionScript.ts

@@ -0,0 +1,89 @@
+export const OptionScript = (
+    request: any,
+    sender: any,
+    sendResponse: (response?: any) => void
+) => {
+    // 自动发送消息的函数
+    const autoSendMessages = async (
+        messages: string[],
+        inputSelector: string,
+        buttonSelector: string
+    ) => {
+        const results = [];
+
+        // 逐条发送消息
+        for (const message of messages) {
+            // 点开弹窗
+            // 获取输入框和按钮
+            // 点击按钮搜索
+            // 获取搜索结果
+            // 搜索结果发送
+            // 结果返回
+            
+            // 查找输入框和发送按钮
+            const inputElement = document.querySelector(inputSelector) as
+                | HTMLInputElement
+                | HTMLTextAreaElement
+                | null;
+            const sendButton = document.querySelector(
+                buttonSelector
+            ) as HTMLElement | null;
+            console.log(sendButton, "sendButton", message);
+
+            if (!inputElement || !sendButton) {
+                throw new Error("找不到输入框或发送按钮");
+            }
+            try {
+                // 设置输入框的值
+                inputElement.value = message;
+
+                // 触发输入事件(有些网站需要)
+                const inputEvent = new Event("input", { bubbles: true });
+                inputElement.dispatchEvent(inputEvent);
+
+                // 触发change事件(有些网站需要)
+                const changeEvent = new Event("change", { bubbles: true });
+                inputElement.dispatchEvent(changeEvent);
+
+
+                // 点击发送按钮
+                sendButton.click();
+
+                // 记录发送的消息
+                results.push({ message, status: "sent", timestamp: Date.now() });
+
+                // 没有按顺序发送,输入框需存在值后按钮才会启用,设置disabled无效
+                // 结束标识
+
+
+                // 等待一段时间再发送下一条消息(可根据需要调整)
+                await new Promise((resolve) => setTimeout(resolve, 10000));
+            } catch (error) {
+                results.push({
+                    message,
+                    status: "error",
+                    error: error instanceof Error ? error.message : "未知错误",
+                    timestamp: Date.now(),
+                });
+            }
+        }
+
+        return results;
+    };
+    console.log("OptionScript");
+    autoSendMessages(
+        request.messages ||
+        Array.from({ length: 10 }, (_, i) => (i + 1).toString()),
+        request.inputSelector,
+        request.buttonSelector
+    )
+        .then((results) => {
+            sendResponse({ success: true, results });
+        })
+        .catch((error) => {
+            sendResponse({ success: false, error: error.message });
+        });
+
+    // 异步响应,需要返回 true
+    return true;
+};

+ 36 - 19
entrypoints/popup/App.tsx

@@ -2,7 +2,7 @@
 import { useState, useEffect } from 'react';
 import { useState, useEffect } from 'react';
 import { HashRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
 import { HashRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
 import { Link, useNavigate } from 'react-router-dom';
 import { Link, useNavigate } from 'react-router-dom';
-import { Button } from '@alifd/next';
+import { Button, Dropdown, Menu } from '@alifd/next';
 import './App.css';
 import './App.css';
 import '../../assets/tailwind.css'
 import '../../assets/tailwind.css'
 import '@alifd/next/dist/next.css';
 import '@alifd/next/dist/next.css';
@@ -10,6 +10,8 @@ import '@alifd/next/dist/next.min.css';
 import Login from './pages/Login'
 import Login from './pages/Login'
 import DesignPic from './pages/DesignPic';
 import DesignPic from './pages/DesignPic';
 import { useLoading } from '@/components/LoadingContext';
 import { useLoading } from '@/components/LoadingContext';
+import AutoOptions from './pages/AutoOptions';
+import IconCom from '@/components/IconCom';
 
 
 // 创建一个保护路由组件
 // 创建一个保护路由组件
 function ProtectedRoute({ children }: { children: React.ReactNode }) {
 function ProtectedRoute({ children }: { children: React.ReactNode }) {
@@ -26,6 +28,17 @@ function Navigation({ onLogout, userinfo }: { onLogout: () => void, userinfo: an
     navigate('/login');
     navigate('/login');
   };
   };
 
 
+  const menu = (
+    <Menu>
+      <Menu.Item>
+        <Link to="/" className="text-blue-500 hover:underline">定制信息</Link>
+      </Menu.Item>
+      <Menu.Item>
+        <Link to="/autoOptions" className="text-blue-500 hover:underline">自动发送</Link>
+      </Menu.Item>
+    </Menu>
+  );
+
   return (
   return (
     <div className="flex gap-4 items-center justify-between">
     <div className="flex gap-4 items-center justify-between">
       <div className='font-bold'>{userinfo && userinfo.nickname ? <div>
       <div className='font-bold'>{userinfo && userinfo.nickname ? <div>
@@ -33,7 +46,16 @@ function Navigation({ onLogout, userinfo }: { onLogout: () => void, userinfo: an
         <span>账户: {userinfo.nickname}</span>
         <span>账户: {userinfo.nickname}</span>
       </div> : <>未获取到用户信息</>}</div>
       </div> : <>未获取到用户信息</>}</div>
       <nav className="flex gap-4 items-center">
       <nav className="flex gap-4 items-center">
-        {/* <Link to="/" className="text-blue-500 hover:underline">首页</Link> */}
+        {/* <div>
+          <Dropdown
+            trigger={<Button style={{ width: 30, padding: 3 }}><IconCom type='list' /></Button>}
+            onVisibleChange={console.log}
+            triggerType={['hover']}
+            afterOpen={() => console.log('after open')}
+          >
+            {menu}
+          </Dropdown>
+        </div> */}
         <Button
         <Button
           type="normal" warning
           type="normal" warning
           onClick={handleLogout}
           onClick={handleLogout}
@@ -87,29 +109,24 @@ function App() {
   };
   };
 
 
   return (
   return (
-      <Router>
-        {/* 只在登录后显示导航栏 */}
-        {isLoggedIn && <Navigation onLogout={handleLogout} userinfo={userinfo} />}
+    <Router>
+      {/* 只在登录后显示导航栏 */}
+      {isLoggedIn && <Navigation onLogout={handleLogout} userinfo={userinfo} />}
 
 
-        <Routes>
-          <Route path="/login" element={<Login setIsLoggedIn={setIsLoggedIn} />} />
-          <Route path="/" element={
-            <ProtectedRoute>
-              <DesignPic />
-            </ProtectedRoute>
-          } />
-          {/* <Route path="/about" element={
+      <Routes>
+        <Route path="/login" element={<Login setIsLoggedIn={setIsLoggedIn} />} />
+        <Route path="/" element={
           <ProtectedRoute>
           <ProtectedRoute>
-            <About />
+            <DesignPic />
           </ProtectedRoute>
           </ProtectedRoute>
         } />
         } />
-        <Route path="/home" element={
+        <Route path="/autoOptions" element={
           <ProtectedRoute>
           <ProtectedRoute>
-            <Home />
+            <AutoOptions />
           </ProtectedRoute>
           </ProtectedRoute>
-        } /> */}
-        </Routes>
-      </Router>
+        } />
+      </Routes>
+    </Router>
   );
   );
 }
 }
 
 

+ 202 - 0
entrypoints/popup/pages/AutoOptions.tsx

@@ -0,0 +1,202 @@
+import React, { useState } from 'react';
+
+// 定义输入框信息类型
+interface InputInfo {
+    id: string;
+    name: string;
+    type: string;
+    value: string;
+    placeholder: string;
+}
+
+// 定义自动发送消息的配置
+interface AutoSendConfig {
+    inputSelector: string;
+    buttonSelector: string;
+    messages: string[];
+}
+
+export default function AutoOptions() {
+    const [inputs, setInputs] = useState<InputInfo[]>([]);
+    const [showInputs, setShowInputs] = useState(false);
+    const [autoSendConfig, setAutoSendConfig] = useState<AutoSendConfig>({
+        inputSelector: '.semi-input-textarea',  // 设置默认输入框选择器
+        buttonSelector: '#flow-end-msg-send',   // 设置默认按钮选择器
+        messages: Array.from({ length: 10 }, (_, i) => {
+            const num = i + 1;
+            return num === 1 ? ['0', num.toString()] : [`0${num - 1}`, num.toString()];
+        }).flat() // 生成 ["0", "1", "01", "2", "02", "3", ..., "09", "10"]
+    });
+    const [isAutoSending, setIsAutoSending] = useState(false);
+    const [autoSendResults, setAutoSendResults] = useState<any[]>([]);
+
+    // 自动发送消息
+    const autoSendMessages = async () => {
+        setIsAutoSending(true);
+        setAutoSendResults([]);
+
+        try {
+            const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
+
+            if (tab.id) {
+                const response = await browser.tabs.sendMessage(tab.id, {
+                    action: "autoSendMessages",
+                    ...autoSendConfig
+                });
+
+                if (response.success) {
+                    setAutoSendResults(response.results);
+                } else {
+                    console.error('自动发送消息失败:', response.error);
+                }
+            }
+        } catch (error) {
+            console.error('自动发送消息出错:', error);
+        } finally {
+            setIsAutoSending(false);
+        }
+    };
+
+    // 更新自动发送配置
+    const updateAutoSendConfig = (field: keyof AutoSendConfig, value: string | string[]) => {
+        setAutoSendConfig(prev => ({
+            ...prev,
+            [field]: value
+        }));
+    };
+
+    return (
+        <>
+            <div>
+                <h1>页面分析工具</h1>
+
+                {/* 自动发送消息配置区域 */}
+                <div style={{ marginTop: '20px', padding: '10px', border: '1px solid #ccc', borderRadius: '4px' }}>
+                    <h2>自动发送消息</h2>
+                    <div style={{ marginBottom: '10px' }}>
+                        <label>
+                            输入框选择器:
+                            <input
+                                type="text"
+                                value={autoSendConfig.inputSelector}
+                                onChange={(e) => updateAutoSendConfig('inputSelector', e.target.value)}
+                                placeholder="例如: #message-input 或 .input-class"
+                                style={{ width: '100%', padding: '5px', marginTop: '5px' }}
+                            />
+                        </label>
+                    </div>
+                    <div style={{ marginBottom: '10px' }}>
+                        <label>
+                            发送按钮选择器:
+                            <input
+                                type="text"
+                                value={autoSendConfig.buttonSelector}
+                                onChange={(e) => updateAutoSendConfig('buttonSelector', e.target.value)}
+                                placeholder="例如: #send-button 或 .send-btn"
+                                style={{ width: '100%', padding: '5px', marginTop: '5px' }}
+                            />
+                        </label>
+                    </div>
+                    <div style={{ marginBottom: '10px' }}>
+                        <label>
+                            消息列表 (每行一条):
+                            <textarea
+                                value={autoSendConfig.messages.join('\n')}
+                                onChange={(e) => updateAutoSendConfig('messages', e.target.value.split('\n').filter(msg => msg.trim()))}
+                                placeholder="每行输入一条消息"
+                                rows={5}
+                                style={{ width: '100%', padding: '5px', marginTop: '5px' }}
+                            />
+                        </label>
+                    </div>
+                    <button
+                        onClick={autoSendMessages}
+                        disabled={isAutoSending || !autoSendConfig.inputSelector || !autoSendConfig.buttonSelector}
+                        style={{
+                            padding: '8px 16px',
+                            backgroundColor: isAutoSending ? '#6c757d' : '#28a745',
+                            color: 'white',
+                            border: 'none',
+                            borderRadius: '4px',
+                            cursor: isAutoSending ? 'not-allowed' : 'pointer'
+                        }}
+                    >
+                        {isAutoSending ? '发送中...' : '开始自动发送'}
+                    </button>
+
+                    {/* 显示发送结果 */}
+                    {autoSendResults.length > 0 && (
+                        <div style={{ marginTop: '10px' }}>
+                            <h3>发送结果:</h3>
+                            <div style={{ maxHeight: '200px', overflowY: 'auto' }}>
+                                {autoSendResults.map((result, index) => (
+                                    <div
+                                        key={index}
+                                        style={{
+                                            padding: '5px',
+                                            marginBottom: '5px',
+                                            backgroundColor: result.status === 'sent' ? '#d4edda' : '#f8d7da',
+                                            borderRadius: '3px'
+                                        }}
+                                    >
+                                        <span>[{new Date(result.timestamp).toLocaleTimeString()}] </span>
+                                        <span>消息: {result.message} - </span>
+                                        <span style={{ fontWeight: 'bold' }}>
+                                            {result.status === 'sent' ? '已发送' : '发送失败'}
+                                        </span>
+                                        {result.error && <span> (错误: {result.error})</span>}
+                                    </div>
+                                ))}
+                            </div>
+                        </div>
+                    )}
+                </div>
+
+                {showInputs && (
+                    <div style={{ marginTop: '20px' }}>
+                        <h2>页面输入框 ({inputs.length} 个):</h2>
+                        {inputs.length > 0 ? (
+                            <div style={{ maxHeight: '300px', overflowY: 'auto' }}>
+                                {inputs.map((input, index) => (
+                                    <div
+                                        key={index}
+                                        style={{
+                                            padding: '10px',
+                                            border: '1px solid #eee',
+                                            marginBottom: '10px',
+                                            borderRadius: '4px'
+                                        }}
+                                    >
+                                        <div><strong>ID:</strong> {input.id || '无'}</div>
+                                        <div><strong>Name:</strong> {input.name || '无'}</div>
+                                        <div><strong>Type:</strong> {input.type}</div>
+                                        <div><strong>Placeholder:</strong> {input.placeholder || '无'}</div>
+                                        <div><strong>Value:</strong> {input.value || '无'}</div>
+                                    </div>
+                                ))}
+                            </div>
+                        ) : (
+                            <p>未找到输入框元素</p>
+                        )}
+                        <button
+                            onClick={() => setShowInputs(false)}
+                            style={{
+                                padding: '8px 16px',
+                                backgroundColor: '#6c757d',
+                                color: 'white',
+                                border: 'none',
+                                borderRadius: '4px',
+                                cursor: 'pointer'
+                            }}
+                        >
+                            隐藏输入框信息
+                        </button>
+                    </div>
+                )}
+            </div>
+        </>
+    );
+}
+
+
+