feat: 增加 ERP 订单自动化抓取自定义工具及相关开发文档
This commit is contained in:
@@ -2,6 +2,7 @@ import { type AgentConfig, PageAgentCore } from '@page-agent/core'
|
||||
|
||||
import { RemotePageController } from './RemotePageController'
|
||||
import { TabsController } from './TabsController'
|
||||
import { scrapeErpOrdersTool } from './customTools'
|
||||
import SYSTEM_PROMPT from './system_prompt.md?raw'
|
||||
import { createTabTools } from './tabTools'
|
||||
|
||||
@@ -26,7 +27,12 @@ export class MultiPageAgent extends PageAgentCore {
|
||||
// multi page controller
|
||||
const tabsController = new TabsController()
|
||||
const pageController = new RemotePageController(tabsController)
|
||||
const customTools = createTabTools(tabsController)
|
||||
|
||||
// 注册内置工具以及我们自定义的 ERP 抓取工具
|
||||
const customTools = {
|
||||
...createTabTools(tabsController),
|
||||
scrape_erp_orders: scrapeErpOrdersTool,
|
||||
}
|
||||
|
||||
// system prompt - auto-detect language if not specified
|
||||
const language = config.language ?? detectLanguage()
|
||||
|
||||
64
packages/extension/src/agent/customTools.ts
Normal file
64
packages/extension/src/agent/customTools.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { tool } from '@page-agent/core'
|
||||
import * as z from 'zod/v4'
|
||||
|
||||
export const scrapeErpOrdersTool = tool({
|
||||
description:
|
||||
'当到达 ERP 订单列表或查询列表的第一页时,调用此工具。该工具会自动接管浏览器,静默抓取所有分页表格数据。',
|
||||
inputSchema: z.object({}),
|
||||
execute: async function (input, { signal }) {
|
||||
console.log('🚀 大模型已切断,原生爬虫代码接管...')
|
||||
|
||||
// 获取当前正在被 Agent 控制的标签页 ID
|
||||
const tabId = (this.pageController as any).currentTabId
|
||||
if (!tabId) {
|
||||
return '❌ 错误:没有找到激活的标签页,无法执行抓取。'
|
||||
}
|
||||
|
||||
try {
|
||||
// 在 Chrome 插件中,不能使用 executeJavascript,必须使用 Chrome 原生的 scripting API 注入代码
|
||||
const results = await chrome.scripting.executeScript({
|
||||
target: { tabId: tabId },
|
||||
func: async () => {
|
||||
// --- 以下代码将原封不动地在金蝶/AntDesign的网页环境内部执行 ---
|
||||
let allData: any[] = []
|
||||
let pageCount = 1
|
||||
while (true) {
|
||||
const rows = document.querySelectorAll('tr.ant-table-row')
|
||||
const pageData = Array.from(rows).map((row) => {
|
||||
const cells = row.querySelectorAll('td')
|
||||
return {
|
||||
ruleName: cells[1] ? (cells[1] as HTMLElement).innerText.trim() : '',
|
||||
desc: cells[2] ? (cells[2] as HTMLElement).innerText.trim() : '',
|
||||
}
|
||||
})
|
||||
|
||||
allData = allData.concat(pageData)
|
||||
|
||||
const nextLi = document.querySelector('li.ant-pagination-next')
|
||||
if (!nextLi || nextLi.classList.contains('ant-pagination-disabled')) {
|
||||
return allData // 把数据回传
|
||||
}
|
||||
|
||||
const nextBtn = nextLi.querySelector('button')
|
||||
if (nextBtn) nextBtn.click()
|
||||
else (nextLi as HTMLElement).click()
|
||||
|
||||
pageCount++
|
||||
await new Promise((r) => setTimeout(r, 1500))
|
||||
}
|
||||
// --- 网页内部代码结束 ---
|
||||
},
|
||||
})
|
||||
|
||||
// 提取网页返回的数据
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const extractedOrders = (results && results[0] ? results[0].result : []) as any
|
||||
console.log('✅ 成功拿到了网页返回的全部数据:', extractedOrders)
|
||||
|
||||
return `成功抓取了所有 ${extractedOrders?.length || 0} 条订单数据,并已打印到后台控制台日志中。`
|
||||
} catch (error) {
|
||||
console.error('执行脚本失败:', error)
|
||||
return `❌ 抓取失败: ${error}`
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -45,7 +45,7 @@ export default defineConfig({
|
||||
name: '__MSG_extName__',
|
||||
description: '__MSG_extDescription__',
|
||||
homepage_url: 'https://alibaba.github.io/page-agent/',
|
||||
permissions: ['tabs', 'tabGroups', 'sidePanel', 'storage'],
|
||||
permissions: ['tabs', 'tabGroups', 'sidePanel', 'storage', 'scripting'],
|
||||
host_permissions: ['<all_urls>'],
|
||||
icons: {
|
||||
64: 'assets/page-agent-64.png',
|
||||
|
||||
Reference in New Issue
Block a user