用 tampermonkey 脚本实现滴答清单任务顺延

以前我用 AHK 实现过滴答清单的任务顺延,在这里 https://zhuanlan.zhihu.com/p/681570615。这个方案的缺点是需要保持滴清单在前台,同时我不能操作鼠标和键盘干扰 AHK 脚本运行。有一天突然想到,滴答清单有 web 版本,那么利用  tampermonkey 脚本 应该能达到相同效果。

愿景,要达到的效果是 每天的超期任务,顺延到今天。

需求分析,需要执行一系列的动作。包括点击某个控件,在新弹出的某些控制上再点击,诸如此类。

技术原型,需要能 找到特定控件、点击特定控件。此外,还要有入口。我尝试了裁入即触发脚本,失败了。时间久远,我已经想不起来到底是脚本没运行,还是脚本运行找不到控件。总之,我改成了在界面上加了个大按钮,每次手动点击这个按钮触发脚本运行。

动作顺列如下。

第1步 入口

第2步 把分组切换到按 时间,这样会出现 顺延 按钮。

第3步 把分组切换回按 清单。

定位控件的方法是根据 css 的 class 或者 xpath。写代码时,我打开 w3school | css 页面,当作忘记语法时的速查表。

实现过程 略,参见文末的代码。

这个方法和 AHK脚本 相比,优点是可以不必把滴答清单置于前台,甚至把滴答清单的页面或浏览器最小化也没有影响;不独占鼠标和键盘,因为代码调用 click 函数,而不是发送鼠标和键盘事件。

跑了两三个月以后,有一天突然不好使了。用手动完成了两三天,找时间看了一遍动作过程,有按钮不点击了。F12看源代码,发现滴答清单的 web 升级过。这时 AI 已经相当成熟,所以把那段 html 截下来问了豆包,请她给出代码。把这段代码插入到我原有的脚本里,一切又顺畅了。

表面上看,这是一段方便工作的脚本。实质上,在技术路线选择和技术手段上,这属于 软件工程的 自动化测试。有同学告诉我,这个现在叫作 RPA (rpa robotic process automation)。虽然核心的业务逻辑非常简单,但是仍然要花些时间,主要的精力消耗在如何定位控件上。遥想当年 Unix 系统通过 重定向和管道机制,仅解析文本,就能够方便地做各种自动化的工作。后来出现了人类用起来方便的 GUI 界面,机器的自动化变得比以前麻烦很多,最主要的原因就是找控件麻烦而琐碎。也许以后 AI 高度发展,自动化的动作又可以非常普及了吧。

此文也发布在以下站点。
----
知乎 https://www.zhihu.com/people/yang-gui-fu-52

独立博客 https://younggift.net/

微信公众号 杨贵福
----
以下是我曾经发布博客的站点,有些旧文。
----
豆瓣 - 因为审核"我的日记",不再更新。
https://www.douban.com/people/younggift/?_i=0098558fqLUL9h

CSDN – 因为要求我登记手机号码的原因是“为了您的安全”,不再更新。
https://blog.csdn.net/younggift?type=blog

blogsopt – 因为从我的机器不可达,无法更新

附 代码

// ==UserScript==

// @name 滴答清单 顺延

// @namespace http://tampermonkey.net/

// @version 2025-01-18

// @description try to take over the world!

// @author Young

// @match https://dida365.com/webapp/

// @icon https://cncdn.dida365.com/static/img/favicon.ico

// @grant none

// ==/UserScript==

$('body').append('<font color=red><input type="button" value="顺延" id="CP" border=1></input></font>')

$("#CP").css("position", "fixed").css("top", 200).css("left", 150).css("color","white").css("background-color","#04AA6D").css("padding","15px 32px");

$('#CP').click(function(){

gogogo();

});

(function() {

'use strict';

// alert("here.");

}

)();

function sleep1(time) {

time*=1000

return new Promise(resolve => {

setTimeout(() => {

resolve();

}, time);

});

}

async function gogogo()

{

// 今天

$("p:contains('今天')")[0].click();

await sleep1(2);

// 上下箭头

$("#group-order-option").click();

await sleep1(2);

// 分组

$("div[data-key='groupBy']").click();

await sleep1(2);

// 时间

//$("div[data-key='dueDate']").click();

// 20250321 问了豆包

$('li[data-menu-id*="dueDate"]').eq(0).click();

// 上下箭头,收起菜单

// $("#group-order-option").click();

$('div[id="group-order-option"]').click();

await sleep1(2);

// 折叠 "今天" 如果是展开的

if($("span > svg.-rotate-90").length==0 && $("h6:contains('今天')").length!=0)

$("h6:contains('今天')")[0].click();

await sleep1(2);

// 顺延 如果顺延不存在,不会有影响

$("div:contains('顺延')[tabindex='0']").click();

await sleep1(2);

// 确认"顺延"

$("button:contains('顺延')").click();

await sleep1(2);

// 上下箭头

$("#group-order-option").click();

await sleep1(2);

// 分组

$("div[data-key='groupBy']").click();

await sleep1(2);

// 清单

//$("div[data-key='project']").click();

// 20250321 问了豆包

$('li[data-menu-id*="project"]').eq(0).click();

await sleep1(4);

// 上下箭头

//$("#group-order-option").click();

$('div[id="group-order-option"]').click();

await sleep1(2);

alert("顺延完成。");

}

Leave a Reply

Your email address will not be published. Required fields are marked *