chore: 删除抖音养号任务类型,平台只保留 generic_steps

tasks/douyin/(task_type=douyin_nurture)整体删除,唯一任务类型是 generic_steps。
所有默认值/文档/接口示例同步改成 generic_steps:

- tasks/:删 douyin 包;__init__ 只注册 generic;base.py/generic 注释改为照 generic 抄
- 默认值:core/models.py(列默认 + 旧 JSON 迁移默认)、core/task_manager.py TaskJob、
  web/tasks_api.py 建任务默认、static/admin/tasks.js 新建任务默认
- core/task_manager.py:去掉 douyin 专属的"清理废弃 comment 参数"迁移块,改为**启动时告警**
  仍残留已删类型的任务(只告警不改数据);run_job_now 对已删类型直接返回明确错误,
  不再"报已触发、线程里静默失败"
- 清理残留:douyin_running 状态位(无任何读取方)、core/__init__、core/actions/*、
  core/logger.py 注释里的抖音示例
- 文档:README(特性/目录树/类型表/参数表/示例)、TASK_DEV(目录树/注册说明/模板引用)、
  ARCHITECTURE(注册示例/action 注册表示例)、API.md(task_types 与任务 JSON 示例)、
  AI_TASK_GEN(P1 去掉 douyin 预设)、DEVELOPMENT
- 注:示例里"抖音"作为**App 名**(MCP 列应用、AI 建任务的需求举例)保留,与任务类型无关

自测(全部通过):类型列表只剩 generic_steps;建任务不传类型默认 generic_steps;传
douyin_nurture 被 400 拒;库里塞残留旧类型任务 → 启动日志告警 + 执行返回明确错误 +
不自动删用户数据;前端新建任务下拉 1 项且默认选中、界面建任务成功;监控页卡片两个按钮 +
覆盖设备正常。临时任务/数据验完已清理,任务集合复原。
This commit is contained in:
2026-09-10 21:43:08 +08:00
parent 86c65236a2
commit 98cdc39224
23 changed files with 75 additions and 555 deletions
+12 -18
View File
@@ -62,18 +62,13 @@ platform-tools/
│ ├── __init__.py # create_action_registry / register_action / should_trigger
│ └── base.py # BaseAction 全局基类
├── tasks/ # 任务定义层
│ ├── __init__.py # 聚合导出 + import 各任务包触发注册(from .douyin/.generic import task)
│ ├── __init__.py # 聚合导出 + import 各任务包触发注册(from .generic import task)
│ ├── base.py # BaseTask 基类 + _TASK_TYPES + register_task/list_task_types/get_task_class
│ ├── douyin/ # 抖音养号(task_type=douyin_nurture,示例)
│ │ ├── __init__.py
│ │ ├── task.py # DEFAULT_PARAMS + Worker + Task + @register_task
│ │ └── actions/
│ │ ├── __init__.py # 先 from .base import ACTIONS,再 from . import like
│ │ ├── base.py # ACTIONS = create_action_registry()
│ │ └── like.py # @register_action(ACTIONS) LikeAction
│ └── generic/ # 通用步骤任务(task_type=generic_steps,步骤编辑器编排)
│ └── generic/ # 通用步骤任务(task_type=generic_steps,当前唯一任务类型)
│ ├── __init__.py
│ └── task.py # STEP_TYPES + Worker + Task(按 steps 顺序执行)+ test_step
│
│ # 新增专属任务类型时:按同样结构建 <app>/(见 §6「新增任务类型」的骨架)
├── templates/admin/
│ ├── monitor.html # 单页应用(7 Tab + 页内子分栏,纯前端渲染)
│ ├── login.html # 登录页
@@ -130,9 +125,9 @@ platform-tools/
### 2.1 TaskType — 任务类型
一个 `TaskType` 描述"做什么"(例如抖音养号、通用步骤),由 `Task` 子类 + `Worker` 子类 + `DEFAULT_PARAMS` 组成。每个 `TaskType` 注册到全局 `_TASK_TYPES` 字典,key 为任务类型字符串,value 为 `Task` 类。
一个 `TaskType` 描述"做什么"(例如通用步骤、某个 App 的专属养号流程),由 `Task` 子类 + `Worker` 子类 + `DEFAULT_PARAMS` 组成。每个 `TaskType` 注册到全局 `_TASK_TYPES` 字典,key 为任务类型字符串,value 为 `Task` 类。
> **注册位置**:`_TASK_TYPES` 及 `register_task` / `list_task_types` / `get_task_class` **定义在 `tasks/base.py`**;`tasks/__init__.py` 只做两件事——`from .base import ...` 聚合导出,以及 `from .douyin/.generic import task` 触发各任务包注册。**当前已注册的 task_type 仅 `douyin_nurture` 与 `generic_steps`**,前端"新建任务"下拉来自 `GET /api/task_types`。新增 task_type 需在 `tasks/` 下建子包、用 `@register_task` 装饰,并在 `tasks/__init__.py` 加 `from .xxx import task`,然后**重启 web** 生效。
> **注册位置**:`_TASK_TYPES` 及 `register_task` / `list_task_types` / `get_task_class` **定义在 `tasks/base.py`**;`tasks/__init__.py` 只做两件事——`from .base import ...` 聚合导出,以及 `from .generic import task` 触发各任务包注册。**当前已注册的 task_type 只有 `generic_steps`(通用步骤)**,前端"新建任务"下拉来自 `GET /api/task_types`。新增 task_type 需在 `tasks/` 下建子包、用 `@register_task` 装饰,并在 `tasks/__init__.py` 加 `from .xxx import task`,然后**重启 web** 生效。
```python
# tasks/base.py
@@ -151,7 +146,7 @@ def get_task_class(task_type):
`TaskJob` 是"什么时候、在哪些设备上、用什么参数执行某个 TaskType"的持久化计划,存于 SQLite(`data/users.db` 的 `task_job` 表)。包含字段:
- `task_type` — 任务类型(对应 `_TASK_TYPES` 的 key;当前仅 `douyin_nurture` / `generic_steps`)
- `task_type` — 任务类型(对应 `_TASK_TYPES` 的 key;当前仅 `generic_steps`,新建任务不传时默认就是它)
- `target` — 目标设备:`{"mode": "all"|"group"|"serial", "group_name": "", "serial": ""}`,默认 `{"mode":"all"}`
- `params` — 任务参数(与 `DEFAULT_PARAMS` 深合并)。含两个隐藏开关:
- `skip_offline`(默认 **true**)— serial/group 模式先跳过本机 adb 不可达(离线)的设备
@@ -198,11 +193,11 @@ Worker 通过 `self.set_progress(**fields)` 上报进度,前端统一解析展
**示例**:
```python
# 抖音任务(有数量限制)
# 有数量限制的任务
self.set_progress(done=5, total=80, unit="视频",
action_counts={"like": 3}, elapsed=120)
# 抖音任务(仅时长限制,无数量)
# 仅时长限制(无数量)的任务
self.set_progress(done=5, total=0, unit="视频",
action_counts={"like": 3}, elapsed=120)
@@ -346,7 +341,7 @@ adb + u2 **只读连接**试执行单步并验证选择器,返回 `result` = *
> **签名提醒**:以下模板的 `Worker.__init__` / `Task.create_worker` **已去掉 `stf_client` / `stf`
> 参数**——现行签名是 `BaseWorker.__init__(self, serial, params=None, daemon=True)`、
> `Task.create_worker(self, serial, params)`(对照 `tasks/douyin/task.py`),新增任务照此抄,
> `Task.create_worker(self, serial, params)`(对照 `tasks/generic/task.py`),新增任务照此抄,
> 不要再带 stf 形参。
### 步骤 1:在 `tasks/` 下建 `kuaishou/` 子包
@@ -629,7 +624,6 @@ from . import task # noqa: F401 触发 @register_task 注册
```python
# tasks/__init__.py
from .base import BaseTask, register_task, list_task_types, get_task_class
from .douyin import task # noqa: F401
from .generic import task # noqa: F401
from .kuaishou import task # noqa: F401 ← 新增这一行
```
@@ -1029,7 +1023,7 @@ from .base import ACTIONS, ... # 1. 先建注册表
from . import like # 2. 再导入各 action,触发 @register_action
```
`tasks/__init__.py` 同理:先 `from .base import BaseTask`,再 `from . import douyin`、`from . import generic`。
`tasks/__init__.py` 同理:先 `from .base import BaseTask`,再 `from . import generic`(新增类型往下加)。
### 10.2 中文输入
@@ -1130,7 +1124,7 @@ self.set_progress(videos_watched=5, round_idx=3)
- [ ] 长循环内周期性调用 `self.heartbeat()`
- [ ] `tasks/<app>/actions/__init__.py` 先 `from .base import ACTIONS` 再导入各 action
- [ ] 每个 Action 有 `action_type` / `name` / `default_params` / `execute`,返回 `True/False`
- [ ] `Task.create_worker` 做 actions 参数级深合并(照抄抖音模板)
- [ ] `Task.create_worker` 做 actions 参数级深合并(照抄 `tasks/generic/task.py`)
- [ ] `tasks/__init__.py` 已 `from .<app> import task` 注册
- [ ] 日志用 `get_logger("task.<app>")` / `get_logger("action.<app>.<name>")`,无 `print`
- [ ] 定位元素优先 `description` / `descriptionContains`,resourceId 多候选,xpath 用相对定位