feat(发布计划): 改按名字发(文件名 名字_日期_编号)+ 账号管理整页下线 + 自动切号一轮发完
发布计划不再绑设备、不再依赖账号台账:上传文件名 `名字_日期_编号`(标题行 `标题 || 正文_名字_日期_编号`),运行时读本机当前抖音昵称取计划;靠循环块 「一轮把本机待发的号跑完」自动切号,一直发到发完。 · 解析/配对换键:右锚定认名字(不许含下划线、不许纯数字 —— 不合法直接拒收并说清原因), 删掉三处"手机号必须命中台账"的校验,加索引 ix_video_plan_name_date(启动时补建) · 新步骤三个:读本机账号名字 / 切换账号(**按名字点控件**、切完回读校验、遇登录页停本设备)/ 循环本机待发的号(试过不回头、跑一轮没进展就换号、停止·超时·上限三个干净出口) · 发布骨架改 18 步:读名字 → 校验账号(cmp_source=account_target)→ 推送(**推送前重读昵称核对**) → 抖音流程 → 标记结果;push_release 的 account 默认 name · 账号管理整页下线:删 core/ledger.py(serial_of 迁到 core/device_pool.py)、6 个 /api/ledger*、 「账号」页与 ledger.js、设备池「账号」列、设备端账号块;发布计划升为一级页签; device_account 表与 42 行历史数据保留、仍在备份清单内(**停用不等于删数据**) · 人工入口「按名字找设备」:新增 core/account_probe.py(只读探测、跳过在跑任务的设备) + POST /api/video_plan/push_by_account,没设备登着的号逐条报出来; 推送时把"实际是谁发的"写进 posted_serial / posted_device_name · 通知:新增 task.account.switch_failed / task.account.need_login · schema v12(posted_*)/ v13(device.cur_account_name / cur_name_at) · 文档同步:TASK_DEV / API / DATA_MODEL / ARCHITECTURE / NOTIFY / DEVICE_AGENT / DEPLOY / DEVELOPMENT / README / .env.example(两个抖音控件选择器抓一次填 .env) · 新增 scripts/tests/:6 套用例 + run_all.py(临时库 + 假设备,不碰真实数据、不连真机)
This commit is contained in:
@@ -511,9 +511,9 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
{% endif %}
|
||||
<div class="tabs">
|
||||
<button class="tab active" data-tab="monitor" onclick="showTab('monitor')">监控</button>
|
||||
<button class="tab" data-tab="account" onclick="showTab('account')" data-perm="devices">账号</button>
|
||||
<button class="tab" data-tab="tasks" onclick="showTab('tasks')">任务</button>
|
||||
<button class="tab" data-tab="logs" onclick="showTab('logs')" data-perm="logs">日志</button>
|
||||
<button class="tab" data-tab="plan" onclick="showTab('plan')" data-perm="devices">发布计划</button>
|
||||
<button class="tab" data-tab="users" onclick="showTab('users')" data-perm="admin">用户</button>
|
||||
<button class="tab" data-tab="tools" onclick="showTab('tools')" data-perm="admin">工具</button>
|
||||
<button class="tab" data-tab="agent" onclick="showTab('agent')" data-perm="admin">AI 控制台</button>
|
||||
@@ -582,64 +582,20 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<div id="jobs-grid" class="jobs-grid"></div>
|
||||
</div>
|
||||
|
||||
<!-- ========== Tab: 账号(台账) ========== -->
|
||||
<div id="tab-account" class="tab-panel">
|
||||
<div class="page-title">账号</div>
|
||||
<div class="page-sub">每台设备上登录的抖音账号(谁在哪台机器上、卡在不在机内、能不能发视频)</div>
|
||||
<!-- ========== Tab: 发布计划 ========== -->
|
||||
<div id="tab-plan" class="tab-panel">
|
||||
<div class="page-title">发布计划</div>
|
||||
<div class="page-sub">每个视频 = 一条计划:<b>文件名里的名字</b>(= 抖音昵称)+ 发布日期 + 编号,
|
||||
到日子由任务推到手机、按名字找设备/账号发布(谁在机内、能不能发视频由运行时现场读名字判断)</div>
|
||||
|
||||
<div class="sub-tabs">
|
||||
<button class="sub-tab active" data-sub="ledger" onclick="showSubTab('account','ledger')">账号台账</button>
|
||||
<button class="sub-tab" data-sub="plan" onclick="showSubTab('account','plan')">发布计划</button>
|
||||
</div>
|
||||
|
||||
<!-- 子分栏 1:账号台账 -->
|
||||
<div class="sub-panel active" id="account-sub-ledger">
|
||||
<div class="toolbar">
|
||||
<button class="btn btn-primary" onclick="openLedgerModal('')" data-perm="devices">新增账号</button>
|
||||
<button class="btn" onclick="openLedgerImport()" data-perm="devices">粘贴导入</button>
|
||||
<button class="btn" onclick="loadLedger()">刷新</button>
|
||||
<select class="form-control" id="ledger-device" style="width:140px" onchange="ledgerDeviceChanged()">
|
||||
<option value="">全部设备</option>
|
||||
</select>
|
||||
<input class="form-control list-search" id="search-ledger" placeholder="搜索设备号/账号名/抖音号/手机号...">
|
||||
<span class="text-muted" id="ledger-stats"></span>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead><tr>
|
||||
<th data-sort="device_name" onclick="_lpSort('ledger','device_name')">设备号</th>
|
||||
<th data-sort="douyin_id" onclick="_lpSort('ledger','douyin_id')">抖音号</th>
|
||||
<th>手机号</th>
|
||||
<th>注册时间</th>
|
||||
<th>卡在机内</th>
|
||||
<th>可发视频</th>
|
||||
<th>简介</th>
|
||||
<th>备注</th>
|
||||
<th>操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="tb-ledger"></tbody>
|
||||
</table>
|
||||
<div class="list-pager" id="pager-ledger"></div>
|
||||
|
||||
<div class="help">
|
||||
这张台账有三个用处:① 人在机器旁时对照(手机端 Agent 的「身份大字页」也会显示本机账号);
|
||||
② 任务的「条件判断」可以直接从这里取号(编辑器里把<b>候选值来源</b>选成「本机台账」,
|
||||
就不用把几十个号手写进去);③ 设备池里能看到每台登记了几个号。<br>
|
||||
⚠ 台账里的抖音号是<b>纯号</b>(如 <code>35377983067</code>),只当"比对用的候选值"。
|
||||
<b>不要</b>拿它去填「去重」的身份元素 —— 身份比对的是元素原文
|
||||
(<code>抖音号:35377983067</code>),格式不同会让去重<b>静默失效</b>。
|
||||
</div>
|
||||
</div><!-- /account-sub-ledger -->
|
||||
|
||||
<!-- 子分栏 2:视频发布计划 -->
|
||||
<div class="sub-panel" id="account-sub-plan">
|
||||
<div>
|
||||
<div class="toolbar" style="flex-wrap:wrap">
|
||||
<button class="btn btn-primary" onclick="document.getElementById('rp-video-input').click()"
|
||||
data-perm="devices">上传视频</button>
|
||||
<button class="btn" onclick="document.getElementById('rp-title-input').click()"
|
||||
data-perm="devices">上传标题/正文</button>
|
||||
<button class="btn btn-primary" onclick="rpPushAll()" data-perm="devices"
|
||||
title="把今天所有「待发布/失败」的计划按设备推到手机上(每台设备串行推)">一键推送(今天)</button>
|
||||
title="把今天所有「待发布/失败」的计划推给「现在登着对应名字」的设备(按名字找设备;同台设备串行推)">一键推送(今天)</button>
|
||||
<button class="btn" onclick="rpExportLinks()">导出链接 CSV</button>
|
||||
<button class="btn" onclick="loadReleasePlan()">刷新</button>
|
||||
<select class="form-control" id="rp-range" style="width:130px" onchange="rpRangeChanged()">
|
||||
@@ -655,7 +611,7 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<option value="failed,unknown">失败/未知</option>
|
||||
<option value="skipped">已跳过</option>
|
||||
</select>
|
||||
<input class="form-control list-search" id="search-release" placeholder="搜索账号/抖音号/标题/文件名...">
|
||||
<input class="form-control list-search" id="search-release" placeholder="搜索名字/标题/文件名...">
|
||||
<span class="text-muted" id="rp-stats"></span>
|
||||
</div>
|
||||
|
||||
@@ -681,7 +637,7 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<summary style="cursor:pointer;color:var(--text-light)">明细表(与时间线同一份数据)</summary>
|
||||
<table class="table table-sm" style="margin-top:8px">
|
||||
<thead><tr>
|
||||
<th>发布日期</th><th>设备号</th><th>抖音号</th><th>编号</th><th>视频文件</th>
|
||||
<th>发布日期</th><th>名字</th><th>由哪台发出</th><th>编号</th><th>视频文件</th>
|
||||
<th>标题</th><th>正文</th><th>状态</th><th>分享链接</th><th>操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="tb-release"></tbody>
|
||||
@@ -689,10 +645,10 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
</details>
|
||||
|
||||
<div class="help">
|
||||
视频文件名规则 <code>手机号_日期_编号</code>(编号可省略,日期如 <code>20260912</code> 就是发布日期);
|
||||
标题 txt 每行 <code>标题 || 正文 _手机号_日期_编号</code>(正文可省;也能写成 <code>手机号_日期_编号_标题 || 正文</code>)(<b>两种写法都认</b>,编号都可省略,标题里可以有下划线、可以有 <code>#话题</code>;<code>#</code> 开头的行<b>只要认得出手机号/日期就当标题</b>,认不出才当注释忽略)。
|
||||
<b>手机号必须在「账号台账」里</b>,否则拒收。<br>
|
||||
上传后自动按 (手机号, 日期, 编号) 配对:有编号按编号精确对,没编号按顺序配 ——
|
||||
视频文件名规则 <code>名字_日期_编号</code>(<b>名字 = 抖音上的昵称</b>;编号可省略,日期如 <code>20260912</code> 就是发布日期);
|
||||
标题 txt 每行 <code>标题 || 正文_名字_日期_编号</code>(<code>||</code> 后面是正文、可省略;编号可省,标题/正文里可以有下划线、可以有 <code>#话题</code>;<code>#</code> 开头的行<b>只要认得出名字/日期就当标题</b>,认不出才当注释忽略)。
|
||||
<b>名字里不能有下划线、不能是纯数字</b>(那样切不出名字来),不满足会直接拒收并说明原因。<br>
|
||||
上传后自动按 (名字, 日期, 编号) 配对:有编号按编号精确对,没编号按顺序配 ——
|
||||
<b>没传标题的视频不会被推送</b>(先在计划页改标题或补传标题)。<br>
|
||||
<b>平台只负责把视频推到手机</b>(推到 <code>/sdcard/DCIM/Camera/</code>、把文件时间改成"现在"好排在相册最前、触发相册刷新并<b>按路径</b>校验进了索引、
|
||||
把标题写进手机剪贴板);**抖音里怎么发由你在任务里自己写步骤** ——
|
||||
@@ -705,7 +661,7 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
|
||||
<input type="file" id="rp-video-input" multiple accept="video/*" style="display:none" onchange="rpPickVideos(this)">
|
||||
<input type="file" id="rp-title-input" accept=".txt" style="display:none" onchange="rpPickTitles(this)">
|
||||
</div><!-- /account-sub-plan -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== Tab 2: 任务 ========== -->
|
||||
@@ -1411,7 +1367,6 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<thead><tr>
|
||||
<th>serial</th><th>名称</th><th>型号</th><th>在线</th><th>状态</th>
|
||||
<th title="设备指纹(ro.serialno):采集到之后,设备换 IP 才能被自动认领">指纹</th>
|
||||
<th title="这台设备在「账号」页登记了几个抖音号(点数字看明细)">账号</th>
|
||||
<th>添加时间</th><th>操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="tb-devpool"></tbody>
|
||||
@@ -1609,7 +1564,6 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<script src="/static/admin/steplog.js"></script>
|
||||
<script src="/static/admin/recorder.js"></script>
|
||||
<script src="/static/admin/dedup.js"></script>
|
||||
<script src="/static/admin/ledger.js"></script>
|
||||
<script src="/static/admin/release.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user