# GYXX Flow 运维手册 ## 日常检查 ```bash uv run gyxx doctor --json uv run gyxx schedule status uv run gyxx list lark-cli --profile hermes-analyzer auth status --json --verify lark-cli --profile hermes-analyzer auth check --scope "im:message.send_as_user im:message" --json ``` 两条 lark-cli 检查必须在实际运行调度服务的系统账户下执行。业务消息统一由该 profile 的 user 身份投递;只有日报卡片的图片预上传因接口限制使用同 profile 的 bot 身份。不要用 交互登录账户的授权结果代替 NSSM/systemd 服务账户验证。 Linux 服务同时检查: ```bash systemctl status gyxx-flow.service journalctl -u gyxx-flow.service --since today ``` 工作流失败时,使用 `workflow_id`、业务日期和 `run_id` 对照 `/logs`、运行记录、节点产物和副作用账本。 ## 手工执行 ```bash uv run gyxx run --date 2026-08-01 uv run gyxx run --date 2026-08-01 --execute uv run gyxx scripts list --json uv run gyxx scripts run --date 2026-08-01 uv run gyxx scripts run --date 2026-08-01 --execute ``` `gyxx run` 接受 23 个调度工作流和已注册的手动工作流;补采和维护操作使用 `gyxx scripts run`。两类入口都默认 dry-run,只有业务日期、凭据、浏览器登录态、PostgreSQL、lark-cli user 身份,以及工作流确实需要大模型时对应的 Hermes 角色全部确认后才使用 `--execute`。 | 手动场景 | 命令 ID | 日期行为 | |---|---|---| | 内容映射重建 | `content.mapping.rebuild` | 业务日期只用于运行审计 | | 内容失败任务重试 | `content.failed.retry` | 业务日期只用于运行审计 | | 内容日报重跑 | `gyxx backfill content.metrics.daily` | 使用 `--from/--to` 指定日期范围 | | 京东自营品牌单日回采 | `shop.jd_self_operated.collect_brand` | `--date` 自动成为起止日期 | | 商品历史补采 | `product.backfill.run` | `--date` 自动成为 `--from/--to` | | 商品评价补采 | `product.review.orchestrate` | `--date` 自动成为目标日期 | | 天猫旗舰店和箱包店视频上传 | `product.video_upload.run` | 业务日期用于运行审计;默认顺序扫描两店,由 PostgreSQL 附件级账本防重 | | 京东旗舰店视频上传 | `product.jd_video_upload.run` | 业务日期只用于运行审计;从固定凌云air记录锚点按飞书视图顺序扫描,日期可为空 | | 采购单更新 | `supply.workflow.run` | 自动选择 `mcp-run purchase-order-update` | 命令的额外脚本参数使用可重复的 `--arg=<值>` 传入。`supply.workflow.run --execute` 会进入真实 ERP 修改链路,必须在任务文件、目标范围和回滚条件全部复核后执行。 ### 天猫视频上传工作流 天猫视频上传注册为手动幂等工作流 `product.video_upload`,不会被常驻调度器自动触发。前端“立即运行”窗口会显示“光影行星旗舰店 / 光影行星鑫华达专卖店:龙虾仔”单选下拉框,并允许填写天猫话题完整名称或关键词;正式执行只处理所选店铺,话题搜索结果按包含关系选中。默认 dry-run 只生成运行记录并跳过浏览器节点;确认飞书待传记录、对应淘宝光合店铺的登录态和 PostgreSQL 后,再显式正式执行: ```bash uv run gyxx run product.video_upload --date 2026-08-07 uv run gyxx run product.video_upload --date 2026-08-07 --execute ``` 前端把店铺选择作为受限运行参数传给脚本,只允许 `flagship` 或 `luggage`。脚本先读取飞书并应用所选店铺路由,再写入/读取附件级账本;只有存在可领取的未上传附件时才启动有头 Chrome、登录对应账号并上传。旗舰店只选择“天猫上传”未勾选且有附件的光影行星男/女记录;箱包店只选择女性、全部款式命中箱包店白名单且有附件的记录。两店分别使用 `GUANGHE_USERNAME` / `GUANGHE_PASSWORD` 和 `GUANGHE_LUGGAGE_USERNAME` / `GUANGHE_LUGGAGE_PASSWORD`,箱包店当前账号为 `光影行星鑫华达专卖店:龙虾仔`,密码配置保持不变,并保留独立浏览器 Profile。发生登录或页面错误时保留窗口供人工定位,排查完成后手动关闭。 每次正式扫描都会把视频附件写入 PostgreSQL 附件级发布账本,防重身份由视频 `file_token + 目标账号 + 飞书记录` 构成。账本状态为 `published` 的附件在下次执行时自动跳过,因此同一业务日期可以安全重跑并发现新增附件。旗舰店仍只在一条飞书记录的全部附件发布成功后回写“天猫上传”;箱包店不借用该勾选状态,是否已上传完全以自己的目标账号账本为准。 首次正式执行会读取 `config/tmall-video-publication-backfill.json`,将 2026-07-26 箱包店旧日志中可按 `record_id + file_token + 文件名` 再次核验的 25 个明确成功附件回填为 `published`。配置与当前飞书任一身份不一致都会停止,不会静默猜测。该回填不依赖部署机保留旧 `var/` 日志文件;证据路径与成功行号已固化在配置中供审计。 只有淘宝光合页面出现明确成功回执后才把附件记为 `published`。点击发布后超时、浏览器中断或回执无法确认时,必须记为 `ambiguous` 并停止自动重发;先在对应店铺的作品管理中按账号、附件和飞书记录人工核对,再做审计式对账,不能通过更换业务日期或重复运行绕过。 单条续跑或指定附件使用公开命令,并通过可重复的 `--arg` 传参。下面的命令会停在正式发布前,核对无误后才能去掉 `--stop-before-publish`: ```bash uv run gyxx scripts run product.video_upload.run --date 2026-08-07 --arg=--record-id --arg=RECORD_ID --arg=--stop-before-publish --execute ``` ### 京东视频上传工作流 京东视频上传注册为手动幂等工作流 `product.jd_video_upload`。它不会被常驻调度器自动触发;同一业务日期可以重复执行。每次都从飞书视图中的固定凌云air记录 `recvrXTRWWFXeJ`(含)扫描到视图末尾,不依赖“日期”字段。真正的防重键是 PostgreSQL 中的 `视频 file_token + 目标账号 + 飞书记录`: ```bash uv run gyxx run product.jd_video_upload --date 2026-08-07 uv run gyxx run product.jd_video_upload --date 2026-08-07 --execute ``` 框架 dry-run 不启动子进程,不下载附件、不写数据库也不打开京东。前端控制台点击“京东视频上传”会重新扫描锚点之后的视图后缀:新建的记录即使日期为空也能被发现;既有后缀记录后来新增第二个视频附件时,新 `file_token` 也会形成独立任务。已入账的同一 `record_id + file_token` 不会重复发布。锚点丢失或重复时脚本拒绝退化为全表扫描,避免误发历史内容。组合款在下载素材前直接跳过。正式执行按视图顺序逐条处理:有图片时设置飞书封面;没有图片时保留京东从视频生成的默认封面;生成 5-27 字标题、关联同款同色商品、选择相关话题和标签。只有页面出现明确成功回执后才把账本写为 `published`;点击发布后超时或浏览器中断会写为 `ambiguous` 并停止,必须先在京东内容管理中人工核对,不能自动重发。 商品关联只按页面商品标题中的款式名做受控模糊匹配,再由直连多模态大模型判断包体颜色;价格和 SPU 不参与查询或勾选。同款同色商品可多选,整个表单最多 10 个。SPU 仅作为可选审计信息;组合款视频当前主动跳过。 首次登录或遇到验证码时,使用公开命令限定一条记录并停在发布按钮前: ```bash uv run gyxx scripts run product.jd_video_upload.run --date 2026-08-07 --arg=--record-id --arg=RECORD_ID --arg=--manual-login --arg=--stop-before-publish --execute ``` 首次部署或多京东账号部署必须显式配置稳定且不可变的 `JD_VIDEO_ACCOUNT_KEY`;已有单账号账本时,前端运行会从 JD 渠道唯一账号 cohort 自动解析,数据库不保存登录账号明文。浏览器由 Scrapling 隐身会话启动真实 Chrome,默认使用该命令独立的 Profile、Cookie 和 Storage State,不能改成其他京东采集任务的共享目录。需要复用一个已启动且已验证的京麦 Chrome 会话时,使用运行时绑定注入的 `GYXX_BROWSER_CDP_URL`;脚本只借用唯一的现有 context,并在退出时保留原浏览器及其页面。 ### 主图周工作流 主图调度的唯一工作流 ID 是 `product.main_image.weekly`,每周日 08:30 启动。图同时运行 JD、TM 两个无依赖分支;一个平台失败不会取消、跳过或回滚另一个平台的采集、PG upsert 和飞书插入。两个分支全部结束后再汇总工作流状态:任一平台失败时整体状态为失败,并在错误摘要中标明具体平台和错误,另一平台已经成功的结果继续保留。 两个平台默认都在采集后执行飞书主图表插入和本地 PostgreSQL `main_image_creatives` upsert。执行前必须同时确认两套浏览器登录态、飞书身份和本地数据库;排障时分别检查 `jd`、`tmall` 节点以及对应插入脚本日志,不能只以采集文件存在判断双 sink 已完成。 ### 三平台电商费用日报 唯一工作流 ID 是 `product.ecommerce_costs.daily`,每天 10:00 由项目内 Python 调度器运行, 业务日期为前一天;天猫、京东、抖音三个下载分支并行启动,各自完成下载后再导入。天猫流程先进入万相台商品报表选择昨日,提交下载任务;任务在下载列表显示“生成成功” 后下载 ZIP、做路径安全校验并解压 CSV,随后将商品级广告指标幂等写入 `product_daily_metrics.raw_data.tm_ad_metrics`。商品款式先按 `dim_style.tm_spus` 的商品 ID 匹配, 匹配不到再按商品名称做精确包含匹配,并在节点内保留 `style_name` 与 `style_match_method`(`product_id`/`product_name`/`ambiguous`/`unmatched`)。它不会覆盖同一商品日期 已有的访客、成交等经营日报字段;data-hub 产品生命进程从该节点读取广告成交金额和花费并计算投产比、电商费比。 正式服务必须注入 `WANXIANG_ACCOUNT`、`WANXIANG_PASSWORD`、`GYXX_DATA_ROOT` 和 `GYXX_POSTGRES_DSN`。默认浏览器 Profile 是 `\state\browser-profiles\wanxiang-ads`,登录失效时不能在另一个 Profile 中登录后 期待服务自动获得状态。 手工验证或补采某一天时,先 dry-run,再显式执行完整工作流: ```powershell uv run gyxx run product.ecommerce_costs.daily --date 2026-08-17 uv run gyxx run product.ecommerce_costs.daily --date 2026-08-17 --execute ``` 如果登录态失效,使用有头的采集命令(不要给它加 `--headless`)完成验证码/滑块,再单独导入: ```powershell uv run gyxx scripts run product.tmall_wanxiang_ads.collect --date 2026-08-17 --execute uv run gyxx scripts run product.import.tmall_ads --date 2026-08-17 --execute ``` 原始文件位于 `\data\raw\product_commerce\tmall_wanxiang_ads\\`,其中 `manifest.json` 记录 ZIP 和解压出的 CSV。定时工作流每次都会进入商品报表点击“下载报表”,在日期范围 选择“昨日”并点击“确定”,再到下载列表等待“生成成功”。若只需重新解析已下载文件,可以跳过采集步骤 重跑导入;默认导入以 manifest 列出的本次 CSV 为准,避免同一日期目录中历史 CSV 被重复合并;重复导入同一日期和商品不会产生重复行。采集命令手工重试时若不加 `--force-request`,仍可 复用下载列表中已有的“生成成功”任务。 排障顺序: 1. 检查 `gyxx schedule status`、服务日志和对应 `run_id`,确认失败发生在申请、下载、解压还是入库。 2. 检查同一 Profile 是否仍能打开万相台商品报表;登录失效时在有头命令中人工完成验证。 3. 检查日期目录中的 `manifest.json`、CSV 表头和 `日期/主体ID/主体名称`;ZIP 存在不代表数据库已导入。 4. 检查 PostgreSQL 的 `product_daily_metrics` 是否存在 `platform='tm'`、目标日期和商品 ID,且 `raw_data->'tm_ad_metrics'` 已更新;确认经营日报其他 JSON 节点仍保留。 5. 只有在外部状态核对清楚后才按同一业务日期重跑,不能用换日期或重复申请掩盖下载结果不明。 ## 调度操作 ```bash uv run gyxx schedule run --dry-run --once uv run gyxx schedule status sudo systemctl restart gyxx-flow.service ``` 调度服务也只加载显式指定的受控环境文件: ```bash uv run gyxx schedule run --env-file /etc/gyxx-flow/gyxx-flow.env ``` 业务时间只在 `config/schedules.json` 中维护。systemd 负责进程守护,Python scheduler 负责全部业务定时;不要重复注册 cron、systemd timer 或 Windows 任务计划。 需要停用单个工作流时,优先修改该工作流的调度启用状态,先 dry-run,再重启服务。其他模块继续运行。 ## 数据和浏览器状态 生产 `GYXX_DATA_ROOT` 必须位于源码目录之外,Linux 推荐 `/var/lib/gyxx-flow`: - `data/raw/`:原始采集结果,不按临时文件清理。 - `data/normalized`、`data/curated`:清洗、标准化和聚合数据。 - `data/exports`:Markdown、Excel 等交付文件。 - `state/browser//