# Click Gap 数据看板 运行目标是 **mac2**。另一个独立的外部 AppsFlyer 任务每天把汇总结果写入 SQLite;本项目不调用该任务、不访问 AppsFlyer、Superset 或其它提取 API,只从固定数据库只读查询并发布静态 JSON。 固定数据库:`/Users/ads-center/Documents/database/af_click_gap.db`。数据库必须预先存在 `click_gap` 表,脚本不建表、不迁移、不写入数据库。表要求包含: ```text pid TEXT NOT NULL, dt TEXT NOT NULL, attr_platform TEXT NOT NULL, pkg_name TEXT NOT NULL, shareit_clicks REAL NOT NULL, af_clicks REAL NOT NULL, installs_ua REAL NOT NULL, clicks_diff REAL NOT NULL, clicks_diff_rate REAL, updated_at TEXT NOT NULL ``` 主键必须为 `(pid, dt, pkg_name)`。脚本只读取 `pid='shareit'`,并校验字段、日期、数值、重复业务键和有限数值。 ## 输出协议 - `data/YYYYMMDD.json`:直接 JSON 数组;最近 7 天每天生成一个文件,即使当天无数据也生成 `[]`。 - `data/index.json`:包含 `schema_version`、`generated_at` 和最近 7 天的 `data/YYYYMMDD.json` 清单。 - 每行字段为 `dt`(`YYYYMMDD`)、`attr_platform`、`pkg_name`、`shareit_clicks`、`af_clicks`、`installs_ua`、`clicks_diff`、`clicks_diff_rate`;最后一项可以为 `null`。 默认日期边界为运行日往前 6 天至运行日,首尾包含,共 7 天。手工补数使用 `--start-date` 和 `--end-date`,两者必须同时提供且最多 7 天。 ## 手工运行 ```sh cd /Users/shareit./Library/CloudStorage/OneDrive-个人/ubuntu/Gitea/af-click-gap python3 -m py_compile scripts/af_click_gap_pipeline.py python3 scripts/af_click_gap_pipeline.py --help python3 scripts/af_click_gap_pipeline.py --dry-run python3 scripts/af_click_gap_pipeline.py --push # 写 JSON,commit 并 push python3 scripts/af_click_gap_pipeline.py --no-push # 写 JSON 和 commit,不 push python3 scripts/af_click_gap_pipeline.py --start-date 2026-10-10 --end-date 2026-10-16 --no-push ``` `--dry-run` 只读取数据库并在仓库外临时目录生成、校验 JSON,不写 `data` 或 Git。正式运行先原子替换数据文件,再执行 Git;数据库查询或校验失败不会发布文件。push 失败会保留本地 commit,不会 force push。工作区存在本任务之外的未提交改动时,脚本拒绝继续。 ## 看板 `index.html` 是无构建依赖的静态页面,读取并校验 `data/index.json` 及其清单,支持日期范围、包名筛选和表头排序。直接打开文件或执行 `python3 -m http.server` 后访问即可。 ## mac2 launchd 模板文件为 `launchd/com.roasbloom.af-click-gap.plist.template`,必须在 mac2 使用实际 Python 路径和项目路径渲染后安装: ```sh cd /Users/shareit./Library/CloudStorage/OneDrive-个人/ubuntu/Gitea/af-click-gap mkdir -p "$HOME/Library/Logs/af-click-gap" "$HOME/Library/LaunchAgents" PY=$(command -v python3) sed -e "s#__MAC2_PYTHON3__#$PY#" -e "s#__PROJECT_DIR__#$PWD#g" -e "s#__LOG_DIR__#$HOME/Library/Logs/af-click-gap#g" launchd/com.roasbloom.af-click-gap.plist.template > /tmp/com.roasbloom.af-click-gap.plist plutil -lint /tmp/com.roasbloom.af-click-gap.plist cp /tmp/com.roasbloom.af-click-gap.plist "$HOME/Library/LaunchAgents/" launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/com.roasbloom.af-click-gap.plist" ``` 卸载:`launchctl bootout "gui/$(id -u)/com.roasbloom.af-click-gap"` 后删除 LaunchAgents 中的 plist。日志写在 mac2 用户日志目录;数据库、`.env`、密钥、日志和缓存均不会提交。 ## Git 创建和推送 远程仓库约定为 Gitea `https://git.ops.roasbloom.site/liuji/af-click-gap.git`。创建前应检查仓库是否已存在,确认不存在后使用 macOS Keychain 中已有的 Git 凭证创建,再在本地配置 `origin` 并推送当前 `main` 分支。认证信息只通过现有 credential helper 使用,不写入本项目或命令输出。 ## 验证和安全 ```sh python3 -m py_compile scripts/af_click_gap_pipeline.py python3 scripts/af_click_gap_pipeline.py --help plutil -lint launchd/com.roasbloom.af-click-gap.plist.template python3 -m json.tool data/index.json ``` 禁止提交数据库文件、`.env*`、密钥、日志、浏览器状态、缓存或临时文件;`.gitignore` 已覆盖这些类型。