开发日志251125

date
Nov 25, 2025
slug
开发日志251125
status
Published
tags
计算机
AI
summary
最近工作效率太低了 一边要画图一边要做群控系统 画图倒是简单 群控系统尤其要求我的思路连贯 每次一打断都要花很多时间找回思路 本来就一知半解解决问题更困难了 我现在都不知道昨天写了些什么东西了…
type
Post
最近工作效率太低了 一边要画图一边要做群控系统 画图倒是简单 群控系统尤其要求我的思路连贯 每次一打断都要花很多时间找回思路 本来就一知半解解决问题更困难了
我现在都不知道昨天写了些什么东西了

目前主函数代码如下
        logInfo.i('主程序开始运行...');

        // 1.读取全局配置
        const globalConfig = await loadGlobalConfig();
        logInfo.s('加载全局配置成功');
        const keywords = globalConfig.keywords || [];// 获取关键词列表

        //2.获取设备列表
        logInfo.i('正在请求设备列表...');
        ws.send('{ "action":"List" }');
        phoneList = await waitForMessage();  // 当前设备列表
        logInfo.s(`获取到 ${phoneList.length} 台设备`);
        for (const [i, phone] of phoneList.entries()) {
            const configItem = globalConfig.phones.find(item => item.id === String(phone.no));// 查找对应配置项
        }

        logInfo.s('主程序执行完毕!');
现在可以根据已连接的设备找到对应的本地配置文件 目前老版的本地配置文件如下:
{
    "id": "1",
    "platform": "抖音",
    "videoType": "门窗低价引流1",
    "config": {
        "type": "门窗",
        "region": "同城",
        "brand": "静窗",
        "purpose": "品牌宣传"
    }
}
配置文件结构有些混乱不知所云 我打算按如下流程重新分配
flowchart TD
    A[设备池] --> B[平台]
    
    B --> C[抖音]
    B --> D[B]
    B --> E[其他平台...]
    
    C --> F[账号类型]
    D --> F
    E --> F
    
    F --> G[公司/品牌官方号]
    F --> H[同行/竞品号]
    F --> I[达人/测评号]
    F --> J[路人/素人号]
    
    G --> K[分别执行脚本]
    H --> K
    I --> K
    J --> K
    
不同的账号类型需要在后续流程中动态分配 配置文件简化如下
{
    "id": "手机编号",
    "platform": "运行平台",
    "accountType": "账户类型(品牌号/路人号)",
    "region": "同城 全国"
}
先识别账户类型 然后在分配脚本的时候根据不同的设备类型去分配脚本
但是我想到一个问题 现在的架构或许无法异步多线程加载这么多东西 我要先写一个简单代码去测试是否可以多线程运行

借由Grok的帮助 现在可以实现多线程加载
//main.js 
// 为每个设备匹配配置并启动异步处理
const devicePromises = [];
for (const phone of phoneList) {
    let configItem = globalConfig.phones.find(item => item.id === String(phone.no));// 查找对应配置项
    if (configItem) {
        console.log(phone);
        logInfo.i(`设备 ${phone.no}  设备ID ${phone.deviceId} 配置:平台=${configItem.platform}, 账号类型=${configItem.accountType}`);
        devicePromises.push(processDevice(phone, configItem));
    } else {
        logInfo.w(`设备 ${phone.no} 未找到配置,跳过`);
    }
}
// 异步等待设备结果(通过轮询Node.js API实现)
async function waitForDeviceResult(deviceId) {
    while (true) {
        const res = await fetch(`/api/getresult?deviceId=${deviceId}`);
        if (!res.ok) {
            logInfo.e(`获取设备 ${deviceId} 结果失败`);
            await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒重试
            continue;
        }
        const data = await res.json();
        if (data) {
            return data;
        }
        await new Promise(resolve => setTimeout(resolve, 1000)); // 每1秒轮询一次
    }
}

// 异步处理单个设备任务链(序列执行任务,基于结果决定下一个)
async function processDevice(phone, config) {
    const platform = config.platform;
    const accountType = config.accountType;
    const deviceId = phone.deviceId;
    const deviceNo = phone.no;

    // 初始任务(根据平台和账号类型决定初始任务)
    let currentTask = '';
    if (platform === '抖音' && accountType === '品牌号') {
        currentTask = '发布视频';
    } else if (platform === '抖音' && accountType === '路人号') {
        currentTask = '刷视频';
    } else if (platform === '抖音' && accountType === '同行号') {
        currentTask = '视频评论点赞';
    } else {
        logInfo.e(`设备 ${deviceId} 未知初始任务,跳过`);
        return;
    }

    // 可以根据需要调整循环次数或添加break条件;这里假设执行3次循环作为示例,避免无限
    for (let i = 0; i < 3; i++) {
        const scriptPath = await getScriptPath(platform, currentTask);
        if (!scriptPath) {
            logInfo.e(`设备 ${deviceNo}(${deviceId}) 无法获取脚本路径,停止处理`);
            break;
        }

        logInfo.i(`设备 ${deviceNo}(${deviceId}) 执行任务:${currentTask} (脚本: ${scriptPath})`);

        // 通过WebSocket发送执行指令(针对单个设备)
        send({
            "action": "ExecuteAutoJs",
            "comm": {
                "deviceIds": deviceId, // 只针对当前设备
                "filePath": scriptPath
            }
        });

        // 等待手机通过HTTP报告结果到Node.js,然后轮询获取
        const { log: deviceLog, result } = await waitForDeviceResult(deviceId);
        logInfo.s(`设备 ${deviceNo}(${deviceId}) 返回日志:${deviceLog}, 结果:${result}`);

        // 根据返回结果决定下一个任务(示例逻辑:假设result是'success'则推进,否则重试)
        if (result === 'success') {
            if (platform === '抖音' && accountType === '品牌号') {
                currentTask = '点赞视频'; // 示例:下一个任务
            } else if (platform === '小红书' && accountType === '路人机') {
                currentTask = '发帖子'; // 示例:下一个任务
            }
        } else {
            logInfo.w(`设备 ${deviceNo}(${deviceId}) 任务失败,重试当前任务:${currentTask}`);
            i--; // 重试不计入循环
        }

        // 可选:添加延迟避免频繁执行
        await new Promise(resolve => setTimeout(resolve, 5000)); // 5秒间隔
    }

    logInfo.s(`设备 ${deviceNo}(${deviceId}) 处理完成`);
}
// server.js
// 新增端点:接收手机报告的日志和结果
app.post('/api/report', (req, res) => {
    const { deviceId, log, result } = req.body;
    if (!deviceId) {
        return res.status(400).json({ error: '缺少deviceId' });
    }
    deviceResults[deviceId] = { log, result };
    console.log(`收到设备 ${deviceId} 报告:log=${log}, result=${result}`);
    res.json({ status: 'OK' });
});

// 新增端点:获取设备结果(供前端轮询,获取后清除)
app.get('/api/getresult', (req, res) => {
    const deviceId = req.query.deviceId;
    if (!deviceId) {
        return res.status(400).json({ error: '缺少deviceId' });
    }
    const data = deviceResults[deviceId] || null;
    if (data) {
        delete deviceResults[deviceId]; // 获取后清除,避免重复
    }
    res.json(data);
});
  
// auto.js
let deviceId = files.read("/sdcard/SN.txt").trim();
var url = "http://192.168.11.199/api/report";
r = http.postJson(url, {
    deviceId: deviceId,
    log: "日志信息",
    result: "success"  // 或者 "fail"
});
网页端异步加载和执行脚本 server端设置接收端口 手机端执行结束后发送一个post请求
现在可以通过 adb shell getprop ro.serialno > /sdcard/SN.txt 指令将sn码一次性写入本地 然后就可以通过本地调用的方式间接获取到设备序列号以用于反馈信息
 

© Dominic Hodpel 2022 - 2025