feat: 调整脚本功能
This commit is contained in:
@@ -220,8 +220,8 @@
|
||||
#### 3.5 添加脚本模板和默认脚本
|
||||
- **内容**:
|
||||
- 提供常用模板(点击元素、输入文本、等待页面加载)
|
||||
- 预置参考图中的示例脚本(change model、pause、pause resume 等)作为 `.mjs` 文件放置到 `electron/scripts/seed/` 目录
|
||||
- 应用首次启动或检测到 `electron/scripts/` 为空时,将 seed 目录下的示例脚本复制/同步到主目录,并注册到元数据索引
|
||||
- 预置参考图中的示例脚本(change model、pause、pause resume 等)作为 `.mjs` 文件放置到 `electron/scripts/` 目录
|
||||
- 应用首次启动或检测到 `electron/scripts/` 为空时,直接将 `electron/scripts/` 目录下的 `.mjs` 示例脚本注册到元数据索引
|
||||
- 用户通过面板删除默认脚本时,直接删除对应的 `.mjs` 文件及索引条目
|
||||
- **依赖**:script-store-service
|
||||
- **预估工时**:3 小时
|
||||
@@ -235,7 +235,7 @@
|
||||
- 录制功能至少能生成可运行的 Playwright 代码并正确落盘
|
||||
- 面板中的"测试"或"运行"按钮能直接执行 `electron/scripts/` 目录下的真实脚本文件
|
||||
- 脚本执行输出完整呈现在日志面板
|
||||
- 默认脚本从 `electron/scripts/seed/` 同步后可正常加载和运行
|
||||
- 默认脚本从 `electron/scripts/` 同步后可正常加载和运行
|
||||
|
||||
---
|
||||
|
||||
@@ -414,13 +414,9 @@
|
||||
electron/
|
||||
└── scripts/
|
||||
├── scripts.meta.json # 脚本元数据索引(名称、启用状态、渠道等)
|
||||
├── change-model.mjs # 默认示例脚本(由 seed/ 自动同步)
|
||||
├── change-model.mjs # 默认示例脚本(自动同步)
|
||||
├── pause.mjs
|
||||
├── pause-resume.mjs
|
||||
└── seed/ # 预置种子脚本目录(应用自带,只读模板源)
|
||||
├── change-model.mjs
|
||||
├── pause.mjs
|
||||
└── pause-resume.mjs
|
||||
└── pause-resume.mjs
|
||||
|
||||
src/
|
||||
├── common/
|
||||
|
||||
@@ -1488,7 +1488,6 @@ class executeScriptService extends events.EventEmitter {
|
||||
}
|
||||
}
|
||||
const META_FILENAME = "scripts.meta.json";
|
||||
const SEED_DIR = "seed";
|
||||
function getScriptsDir$1() {
|
||||
return electron.app.isPackaged ? path.join(__dirname, "scripts") : path.join(process.cwd(), "electron/scripts");
|
||||
}
|
||||
@@ -1541,18 +1540,14 @@ function seedScripts() {
|
||||
if (fs.existsSync(metaPath)) {
|
||||
return;
|
||||
}
|
||||
const seedDir = path.join(scriptsDir, SEED_DIR);
|
||||
if (!fs.existsSync(seedDir)) {
|
||||
log.info("[script-store-service] Seed directory does not exist, skipping seed.");
|
||||
if (!fs.existsSync(scriptsDir)) {
|
||||
log.info("[script-store-service] Scripts directory does not exist, skipping seed.");
|
||||
return;
|
||||
}
|
||||
const meta = { scripts: [] };
|
||||
const seedFiles = fs.readdirSync(seedDir).filter((f) => f.endsWith(".mjs"));
|
||||
for (const file of seedFiles) {
|
||||
const seedPath = path.join(seedDir, file);
|
||||
const destPath = path.join(scriptsDir, file);
|
||||
const scriptFiles = fs.readdirSync(scriptsDir).filter((f) => f.endsWith(".mjs"));
|
||||
for (const file of scriptFiles) {
|
||||
try {
|
||||
fs.copyFileSync(seedPath, destPath);
|
||||
const name = file.replace(/\.mjs$/, "");
|
||||
const now = (/* @__PURE__ */ new Date()).toISOString();
|
||||
meta.scripts.push({
|
||||
@@ -1566,7 +1561,7 @@ function seedScripts() {
|
||||
updatedAt: now
|
||||
});
|
||||
} catch (err) {
|
||||
log.warn("[script-store-service] Failed to copy seed file", file, err);
|
||||
log.warn("[script-store-service] Failed to seed script", file, err);
|
||||
}
|
||||
}
|
||||
writeMeta(meta);
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import { chromium } from 'playwright';
|
||||
import { preparePage, safeDisconnectBrowser } from './common/tabs.js';
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
|
||||
const { page } = await preparePage(browser, {
|
||||
targetUrl: 'about:blank',
|
||||
});
|
||||
|
||||
// Example: navigate and click an element
|
||||
// await page.goto('https://example.com');
|
||||
// await page.click('text=Change Model');
|
||||
|
||||
console.log('Change model script executed');
|
||||
|
||||
await safeDisconnectBrowser(browser);
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,18 +0,0 @@
|
||||
import { chromium } from 'playwright';
|
||||
import { preparePage, safeDisconnectBrowser } from './common/tabs.js';
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
|
||||
const { page } = await preparePage(browser, {
|
||||
targetUrl: 'about:blank',
|
||||
});
|
||||
|
||||
// Example: fill a form and submit
|
||||
// await page.fill('input[name="username"]', 'test');
|
||||
// await page.click('button[type="submit"]');
|
||||
|
||||
console.log('Pause resume script executed');
|
||||
|
||||
await safeDisconnectBrowser(browser);
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,18 +0,0 @@
|
||||
import { chromium } from 'playwright';
|
||||
import { preparePage, safeDisconnectBrowser } from './common/tabs.js';
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
|
||||
const { page } = await preparePage(browser, {
|
||||
targetUrl: 'about:blank',
|
||||
});
|
||||
|
||||
// Example: wait for a specific element or timeout
|
||||
// await page.waitForSelector('[data-testid="status-paused"]');
|
||||
// await page.waitForTimeout(2000);
|
||||
|
||||
console.log('Pause script executed');
|
||||
|
||||
await safeDisconnectBrowser(browser);
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,34 +1,54 @@
|
||||
{
|
||||
"scripts": [
|
||||
{
|
||||
"id": "seed-change-model",
|
||||
"name": "change-model",
|
||||
"description": "",
|
||||
"filename": "change-model.mjs",
|
||||
"id": "script-dy-hot-spring-trace",
|
||||
"name": "抖音温泉房态追踪",
|
||||
"description": "抖音生活服务平台温泉房型房态自动化追踪脚本",
|
||||
"filename": "dy_hot_spring_trace.js",
|
||||
"enabled": true,
|
||||
"channel": "common",
|
||||
"createdAt": "2026-04-12T05:27:08.543Z",
|
||||
"updatedAt": "2026-04-12T05:27:08.543Z"
|
||||
"channel": "douyin",
|
||||
"createdAt": "2026-04-09T19:29:52.000Z",
|
||||
"updatedAt": "2026-04-09T19:29:52.000Z"
|
||||
},
|
||||
{
|
||||
"id": "seed-pause-resume",
|
||||
"name": "pause-resume",
|
||||
"description": "",
|
||||
"filename": "pause-resume.mjs",
|
||||
"id": "script-dy-hotel-trace",
|
||||
"name": "抖音酒店房态追踪",
|
||||
"description": "抖音生活服务平台酒店房型房态自动化追踪脚本",
|
||||
"filename": "dy_hotel_trace.js",
|
||||
"enabled": true,
|
||||
"channel": "common",
|
||||
"createdAt": "2026-04-12T05:27:08.544Z",
|
||||
"updatedAt": "2026-04-12T05:27:08.544Z"
|
||||
"channel": "douyin",
|
||||
"createdAt": "2026-04-09T19:29:52.000Z",
|
||||
"updatedAt": "2026-04-09T19:29:52.000Z"
|
||||
},
|
||||
{
|
||||
"id": "seed-pause",
|
||||
"name": "pause",
|
||||
"description": "",
|
||||
"filename": "pause.mjs",
|
||||
"id": "script-fg-trace",
|
||||
"name": "飞猪房态追踪",
|
||||
"description": "飞猪平台房型房态自动化追踪脚本",
|
||||
"filename": "fg_trace.js",
|
||||
"enabled": true,
|
||||
"channel": "common",
|
||||
"createdAt": "2026-04-12T05:27:08.544Z",
|
||||
"updatedAt": "2026-04-12T05:27:08.544Z"
|
||||
"channel": "fliggy",
|
||||
"createdAt": "2026-04-09T19:35:34.000Z",
|
||||
"updatedAt": "2026-04-09T19:35:34.000Z"
|
||||
},
|
||||
{
|
||||
"id": "script-mt-trace",
|
||||
"name": "美团房态追踪",
|
||||
"description": "美团平台房型房态自动化追踪脚本",
|
||||
"filename": "mt_trace.js",
|
||||
"enabled": true,
|
||||
"channel": "meituan",
|
||||
"createdAt": "2026-04-09T19:29:52.000Z",
|
||||
"updatedAt": "2026-04-09T19:29:52.000Z"
|
||||
},
|
||||
{
|
||||
"id": "script-open-all-channel",
|
||||
"name": "打开所有渠道",
|
||||
"description": "一键打开所有配置渠道页面的通用脚本",
|
||||
"filename": "open_all_channel.js",
|
||||
"enabled": true,
|
||||
"channel": "",
|
||||
"createdAt": "2026-04-09T19:29:52.000Z",
|
||||
"updatedAt": "2026-04-09T19:29:52.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { chromium } from 'playwright';
|
||||
import { preparePage, safeDisconnectBrowser } from './common/tabs.js';
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
|
||||
const { page } = await preparePage(browser, {
|
||||
targetUrl: 'about:blank',
|
||||
});
|
||||
|
||||
// Example: navigate and click an element
|
||||
// await page.goto('https://example.com');
|
||||
// await page.click('text=Change Model');
|
||||
|
||||
console.log('Change model script executed');
|
||||
|
||||
await safeDisconnectBrowser(browser);
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,18 +0,0 @@
|
||||
import { chromium } from 'playwright';
|
||||
import { preparePage, safeDisconnectBrowser } from './common/tabs.js';
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
|
||||
const { page } = await preparePage(browser, {
|
||||
targetUrl: 'about:blank',
|
||||
});
|
||||
|
||||
// Example: fill a form and submit
|
||||
// await page.fill('input[name="username"]', 'test');
|
||||
// await page.click('button[type="submit"]');
|
||||
|
||||
console.log('Pause resume script executed');
|
||||
|
||||
await safeDisconnectBrowser(browser);
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,18 +0,0 @@
|
||||
import { chromium } from 'playwright';
|
||||
import { preparePage, safeDisconnectBrowser } from './common/tabs.js';
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
|
||||
const { page } = await preparePage(browser, {
|
||||
targetUrl: 'about:blank',
|
||||
});
|
||||
|
||||
// Example: wait for a specific element or timeout
|
||||
// await page.waitForSelector('[data-testid="status-paused"]');
|
||||
// await page.waitForTimeout(2000);
|
||||
|
||||
console.log('Pause script executed');
|
||||
|
||||
await safeDisconnectBrowser(browser);
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -10,7 +10,6 @@ import type {
|
||||
} from '@lib/script-types';
|
||||
|
||||
const META_FILENAME = 'scripts.meta.json';
|
||||
const SEED_DIR = 'seed';
|
||||
|
||||
function getScriptsDir(): string {
|
||||
return app.isPackaged
|
||||
@@ -79,20 +78,16 @@ function seedScripts(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const seedDir = path.join(scriptsDir, SEED_DIR);
|
||||
if (!fs.existsSync(seedDir)) {
|
||||
log.info('[script-store-service] Seed directory does not exist, skipping seed.');
|
||||
if (!fs.existsSync(scriptsDir)) {
|
||||
log.info('[script-store-service] Scripts directory does not exist, skipping seed.');
|
||||
return;
|
||||
}
|
||||
|
||||
const meta: ScriptsMeta = { scripts: [] };
|
||||
const seedFiles = fs.readdirSync(seedDir).filter((f) => f.endsWith('.mjs'));
|
||||
const scriptFiles = fs.readdirSync(scriptsDir).filter((f) => f.endsWith('.mjs'));
|
||||
|
||||
for (const file of seedFiles) {
|
||||
const seedPath = path.join(seedDir, file);
|
||||
const destPath = path.join(scriptsDir, file);
|
||||
for (const file of scriptFiles) {
|
||||
try {
|
||||
fs.copyFileSync(seedPath, destPath);
|
||||
const name = file.replace(/\.mjs$/, '');
|
||||
const now = new Date().toISOString();
|
||||
meta.scripts.push({
|
||||
@@ -106,7 +101,7 @@ function seedScripts(): void {
|
||||
updatedAt: now,
|
||||
});
|
||||
} catch (err) {
|
||||
log.warn('[script-store-service] Failed to copy seed file', file, err);
|
||||
log.warn('[script-store-service] Failed to seed script', file, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +249,8 @@ async function confirmDelete(id: string) {
|
||||
confirmButtonText: t('common.delete', 'Delete'),
|
||||
cancelButtonText: t('common.cancel', 'Cancel'),
|
||||
type: 'warning',
|
||||
lockScroll: false,
|
||||
closeOnClickModal: false,
|
||||
},
|
||||
);
|
||||
await store.deleteScript(id);
|
||||
|
||||
Reference in New Issue
Block a user