398 lines
25 KiB
Python
398 lines
25 KiB
Python
"""预存「商业态势总览」演示数据(task-data 数据交付 · 第一块对接)。
|
||
|
||
对齐前端页面(code-1 仓库)``#/situation-overview/action/business-overview?positionId=planning``
|
||
的 mock 逻辑(``features/business-overview/mock/businessTimelineSnapshots.js``):
|
||
|
||
- 默认任务 ``BUSINESS-OVERVIEW-DEMO``(对方系统任务号,前端对接用它);
|
||
- 13 期时间轴刻度 = 页面小时刻度:2026-06-17 22:00 → 2026-06-18 10:00(每小时一期,
|
||
Beijing;最后一期为「当前期」);
|
||
- 每期 ``block_1`` payload = 页面 ``createBusinessTimelineSnapshot`` 同构 JSON
|
||
(整页 dashboard 对象,前端拿到即可直接渲染),按同一 slot 公式选相位;
|
||
- ``block_1`` 标题置为「商业态势总览」,其余块保持默认。
|
||
|
||
幂等:重复运行会先级联删除演示任务再重建(不影响其它任务)。
|
||
|
||
用法(在 backend 目录)
|
||
======================
|
||
::
|
||
|
||
PYTHONPATH=. uv run python scripts/seed_business_overview_demo.py # 预存
|
||
PYTHONPATH=. uv run python scripts/seed_business_overview_demo.py --dry-run # 只打印不写库
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import asyncio
|
||
import logging
|
||
from datetime import datetime, timedelta, timezone
|
||
|
||
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
||
logger = logging.getLogger("seed_business_overview_demo")
|
||
|
||
SOURCE_TASK_ID = "BUSINESS-OVERVIEW-DEMO"
|
||
TZ_BEIJING = timezone(timedelta(hours=8))
|
||
# 前端 BUSINESS_TIMELINE_ANCHOR = new Date(2026, 5, 18, 10, 30)(本地时区,页面按北京时区使用)。
|
||
ANCHOR = datetime(2026, 6, 18, 10, 30, tzinfo=TZ_BEIJING)
|
||
# 页面小时刻度:13 个刻度、终点 = 锚点整点,逐小时回退(与截图范围一致)。
|
||
TICK_COUNT = 13
|
||
|
||
|
||
def timeline_ticks() -> list[datetime]:
|
||
end = ANCHOR.replace(minute=0, second=0, microsecond=0)
|
||
return [end - timedelta(hours=TICK_COUNT - 1 - index) for index in range(TICK_COUNT)]
|
||
|
||
|
||
# ── 前端 dashboardViews.overview(BusinessOverviewDashboard.vue,逐字对齐) ────
|
||
|
||
BASE_DASHBOARD: dict = {
|
||
"leftTitle": "经营概览",
|
||
"signalTitle": "经营信号",
|
||
"actionTitle": "本月重点动作",
|
||
"watchTitle": "经营关注",
|
||
"pageTitle": "商业态势总览",
|
||
"pageDescription": "围绕收入增长、回款效率与商机质量,实时掌握经营节奏。",
|
||
"briefs": [
|
||
{"title": "当前判断", "label": "经营主线", "description": "收入增长保持稳定,当前工作重点从获取增量转向提升重点项目的签约确定性。", "tone": "blue"},
|
||
{"title": "协同重点", "label": "本周推进", "description": "销售、交付与客户成功团队围绕到期客户建立共跟机制,确保信息与行动同步。", "tone": "green"},
|
||
{"title": "需持续关注", "label": "节奏风险", "description": "部分项目的审批周期仍有不确定性,应提前准备替代推进路径。", "tone": "amber"},
|
||
],
|
||
"objectives": [
|
||
{"name": "年度收入目标", "label": "核心目标", "category": "财务增长", "description": "保持收入目标达成率在 82% 以上,确保二季度末进入集中签约窗口。", "level": "core"},
|
||
{"name": "重点客户续约", "label": "关键目标", "category": "客户经营", "description": "提前锁定 12 个到期项目的续约与增购机会,提升存量收入质量。", "level": "key"},
|
||
{"name": "回款效率提升", "label": "潜力目标", "category": "现金流", "description": "分层推进逾期账款治理,保障季度现金流目标稳定达成。", "level": "potential"},
|
||
],
|
||
"events": [],
|
||
"operatingMetrics": [
|
||
{"label": "年度确认收入", "value": "¥128.6M", "change": "+18.4%", "tone": "positive"},
|
||
{"label": "回款达成率", "value": "94.7%", "change": "+3.1pct", "tone": "positive"},
|
||
{"label": "活跃客户数", "value": "286", "change": "+22", "tone": "positive"},
|
||
{"label": "重点商机金额", "value": "¥348.2M", "change": "环比 +9.6%", "tone": "neutral"},
|
||
],
|
||
"headlineMetrics": [
|
||
{"label": "年度收入目标", "value": "¥156.0M", "change": "达成 82.4%", "tone": "positive"},
|
||
{"label": "综合毛利率", "value": "31.8%", "change": "同比 +1.7pct", "tone": "positive"},
|
||
{"label": "销售费用率", "value": "12.6%", "change": "预算内", "tone": "neutral"},
|
||
],
|
||
"businessNarratives": [],
|
||
"insights": [],
|
||
"priorities": [
|
||
{"index": "01", "title": "华东渠道拓展", "description": "完成 3 家核心伙伴的联合方案签约,扩大区域覆盖。", "status": "推进中", "tone": "blue"},
|
||
{"index": "02", "title": "大客户续约提升", "description": "聚焦 12 个到期项目,提前锁定续约与增购机会。", "status": "重点", "tone": "amber"},
|
||
{"index": "03", "title": "回款专项治理", "description": "分层跟进逾期账款,确保季度现金流目标达成。", "status": "进行中", "tone": "blue"},
|
||
],
|
||
"signals": [
|
||
{"title": "商机储备充足", "description": "中高概率商机覆盖未来两个季度收入目标的 2.2 倍。", "tone": "positive"},
|
||
{"title": "产品组合持续优化", "description": "高毛利订阅业务占比提升至 46%,盈利结构更加稳健。", "tone": "positive"},
|
||
{"title": "客户活跃度提升", "description": "核心客户月活与增购意向同步上行,续费基础良好。", "tone": "blue"},
|
||
],
|
||
"watchItems": [
|
||
{"title": "两项重点商机审批周期延长", "description": "预计影响 ¥16.8M 的当季确认节奏,已进入管理层协同跟进。", "level": "中风险", "tone": "medium"},
|
||
{"title": "区域回款进度存在差异", "description": "西南区域 30 天以上应收占比高于整体均值 4.2 个百分点。", "level": "关注", "tone": "low"},
|
||
],
|
||
"visualization": {"type": "trend", "title": "收入与经营目标趋势"},
|
||
"chart": {
|
||
"title": "收入与经营目标趋势",
|
||
"actualName": "确认收入",
|
||
"targetName": "经营目标",
|
||
"barName": "毛利率",
|
||
"ariaLabel": "近十二个月确认收入、经营目标与毛利率趋势图",
|
||
"leftAxisName": "收入(百万元)",
|
||
"rightAxisName": "毛利率",
|
||
"months": ["7月", "8月", "9月", "10月", "11月", "12月", "1月", "2月", "3月", "4月", "5月", "6月"],
|
||
"actual": [7.2, 8.1, 8.8, 9.6, 10.4, 11.8, 8.7, 9.3, 10.5, 11.2, 12.1, 13.4],
|
||
"target": [7.5, 8.3, 9.1, 9.8, 10.7, 12.2, 9.0, 9.6, 10.9, 11.5, 12.6, 13.0],
|
||
"bar": [28.1, 28.7, 29.2, 30.1, 29.8, 30.6, 30.2, 30.9, 31.3, 31.1, 31.6, 31.8],
|
||
"leftAxisMax": 16,
|
||
"leftAxisInterval": 4,
|
||
"rightAxisMin": 20,
|
||
"rightAxisMax": 40,
|
||
"rightAxisInterval": 5,
|
||
"rightAxisSuffix": "%",
|
||
},
|
||
}
|
||
|
||
# ── 前端 timelinePhases(businessTimelineSnapshots.js,逐字对齐) ─────────────
|
||
|
||
TIMELINE_PHASES: list[dict] = [
|
||
{
|
||
"name": "实时校准",
|
||
"summary": "重点项目签约口径完成最新校准,经营节奏保持在目标区间。",
|
||
"chartDelta": 0,
|
||
"marginDelta": 0,
|
||
"briefs": [
|
||
{"label": "实时判断", "description": "重点项目签约口径完成最新校准,确认收入与经营目标之间的差距继续收窄。"},
|
||
{"label": "联合跟进", "description": "销售、交付与客户成功团队已同步最新客户反馈,关键行动进入同频推进。"},
|
||
{"label": "审批观察", "description": "两项重点商机仍等待客户内部审批,需要保留替代推进路径与资源窗口。"},
|
||
],
|
||
"objectives": [
|
||
{"description": "根据最新签约反馈,将年度收入目标达成率稳定在 82% 以上,并锁定季度末确认窗口。"},
|
||
{"description": "完成 12 个重点续约项目的责任人与下一步动作校准,优先保障高价值客户。"},
|
||
{"description": "按账龄与区域更新回款清单,保障本月现金流目标可追踪、可纠偏。"},
|
||
],
|
||
"events": [
|
||
{"title": "重点商机口径完成实时校准", "content": "华东 3 个渠道项目更新商务状态,预计新增确认收入 ¥8.6M。", "topic": "签约推进"},
|
||
{"title": "续约客户反馈同步至共跟清单", "content": "客户成功团队补齐关键使用场景,销售侧已更新下一次沟通动作。", "topic": "客户经营"},
|
||
{"title": "区域回款风险完成重新分层", "content": "西南区域两笔应收进入专项协同,责任人与预计到账节点已明确。", "topic": "现金流"},
|
||
],
|
||
"narratives": [
|
||
{"title": "收入节奏", "value": "健康", "description": "最新确认口径显示,重点项目仍按季度目标窗口稳定推进。"},
|
||
{"title": "客户结构", "value": "优化", "description": "订阅与增购机会占比继续提升,收入质量保持改善趋势。"},
|
||
{"title": "资金回笼", "value": "可控", "description": "高风险应收已进入专项协同,当前未形成新增重大敞口。"},
|
||
],
|
||
"insights": [
|
||
{"label": "增长动能", "highlight": "华东渠道与重点客户续约", "description": "仍是当前最确定的增量来源。"},
|
||
{"label": "即时建议", "highlight": "维持重点项目逐单校准,", "description": "避免审批变化影响季度确认节奏。"},
|
||
],
|
||
},
|
||
{
|
||
"name": "签约提速",
|
||
"summary": "渠道项目释放积极信号,当前窗口应优先推动商务条款确认。",
|
||
"chartDelta": 0.24,
|
||
"marginDelta": 0.18,
|
||
"briefs": [
|
||
{"label": "机会增强", "description": "两项高概率商机完成决策人确认,预计签约节奏较上一时点提前。"},
|
||
{"label": "商务协同", "description": "法务与交付资源已提前介入,联合处理付款条件和实施边界。"},
|
||
{"label": "资源提醒", "description": "售前资源短时集中,需要优先保障本周具备成交条件的重点项目。"},
|
||
],
|
||
"objectives": [
|
||
{"description": "抓住高概率项目的商务窗口,优先完成收入确认条件与合同边界核验。"},
|
||
{"description": "围绕续约增购项目补齐决策链信息,推动 4 个项目进入报价确认。"},
|
||
{"description": "将回款条款前置到合同协商环节,降低后续账期拉长风险。"},
|
||
],
|
||
"events": [
|
||
{"title": "华东渠道项目进入商务确认", "content": "核心伙伴已接受联合报价框架,合同条款进入最终核验。", "topic": "渠道拓展"},
|
||
{"title": "战略客户增购范围得到确认", "content": "客户新增两个业务场景,预计提升本次续约合同价值。", "topic": "客户增购"},
|
||
{"title": "售前资源启动优先级调度", "content": "两名解决方案专家转入高概率项目,保障本周方案澄清效率。", "topic": "资源协同"},
|
||
],
|
||
"narratives": [
|
||
{"title": "签约窗口", "value": "提速", "description": "高概率项目的商务条件趋于清晰,适合集中推动确认。"},
|
||
{"title": "增购空间", "value": "扩大", "description": "客户新增使用场景带动服务包与订阅组合机会。"},
|
||
{"title": "资源负荷", "value": "偏高", "description": "售前能力短时集中,需控制低概率项目的并行投入。"},
|
||
],
|
||
"insights": [
|
||
{"label": "最佳动作", "highlight": "优先完成付款条件和交付边界确认,", "description": "可进一步缩短合同流转周期。"},
|
||
{"label": "转化预测", "highlight": "高概率项目若按计划签约,", "description": "本月确认收入有望上调约 ¥2.1M。"},
|
||
],
|
||
},
|
||
{
|
||
"name": "续约推进",
|
||
"summary": "重点客户续约反馈集中回流,客户经营成为当前主要推进线。",
|
||
"chartDelta": 0.12,
|
||
"marginDelta": 0.1,
|
||
"briefs": [
|
||
{"label": "客户反馈", "description": "续约客户对服务稳定性评价积极,但希望进一步明确增购后的交付节奏。"},
|
||
{"label": "场景共创", "description": "客户成功团队正在补齐业务收益案例,为增购报价提供量化依据。"},
|
||
{"label": "决策风险", "description": "部分客户尚未确认最终预算归属,需要加强业务与采购双线沟通。"},
|
||
],
|
||
"objectives": [
|
||
{"description": "保持年度目标节奏,同时将存量客户贡献作为本周收入确定性的主要支撑。"},
|
||
{"description": "围绕 12 个重点客户逐一确认预算、决策人和续约范围,提升续约确定性。"},
|
||
{"description": "把续约付款节点纳入共跟清单,避免合同确认与实际到账节奏脱节。"},
|
||
],
|
||
"events": [
|
||
{"title": "重点续约客户完成价值复盘", "content": "客户确认现有服务达到预期,并提出新增数据分析场景。", "topic": "客户经营"},
|
||
{"title": "增购方案进入联合测算", "content": "销售与交付共同评估资源投入,准备输出分阶段报价方案。", "topic": "方案共创"},
|
||
{"title": "客户预算路径完成补充核验", "content": "4 个续约项目已明确预算归属,后续转入采购沟通。", "topic": "预算确认"},
|
||
],
|
||
"narratives": [
|
||
{"title": "客户意愿", "value": "积极", "description": "重点客户续约意愿稳定,增购讨论逐步进入量化阶段。"},
|
||
{"title": "价值证明", "value": "补强", "description": "业务收益案例正在完善,有利于缩短客户内部决策时间。"},
|
||
{"title": "预算路径", "value": "待确认", "description": "少量项目仍需同步业务负责人和采购侧预算口径。"},
|
||
],
|
||
"insights": [
|
||
{"label": "客户策略", "highlight": "用业务收益案例支撑增购报价,", "description": "比单纯价格优惠更有利于稳定续约价值。"},
|
||
{"label": "协同建议", "highlight": "销售与客户成功共同参加下一轮沟通,", "description": "同步解决价值与交付问题。"},
|
||
],
|
||
},
|
||
{
|
||
"name": "回款预警",
|
||
"summary": "区域到账节奏出现短时偏差,当前应优先压实高账龄应收责任。",
|
||
"chartDelta": -0.32,
|
||
"marginDelta": -0.26,
|
||
"briefs": [
|
||
{"label": "现金流提醒", "description": "西南区域两笔重点应收预计到账时间后移,月度回款预测需要下修。"},
|
||
{"label": "专项处置", "description": "财务与客户负责人已建立逐笔跟进机制,优先处理高账龄款项。"},
|
||
{"label": "目标影响", "description": "若本周未形成明确付款承诺,可能影响月末现金流安全边际。"},
|
||
],
|
||
"objectives": [
|
||
{"description": "收入目标保持不变,但新增合同需同步核验付款条件和客户信用情况。"},
|
||
{"description": "续约项目继续推进,并将历史回款表现纳入商务条款决策。"},
|
||
{"description": "集中处置 30 天以上应收,明确管理层协同事项与最晚到账节点。"},
|
||
],
|
||
"events": [
|
||
{"title": "区域到账预测出现偏差", "content": "两笔应收未按原计划进入付款流程,财务已发起风险提示。", "topic": "回款预警"},
|
||
{"title": "高账龄款项启动管理层协同", "content": "客户负责人补充付款障碍与决策链信息,形成逐笔处置方案。", "topic": "专项治理"},
|
||
{"title": "新增合同付款条件复核", "content": "商务团队统一检查首付款比例与账期,防止新增现金流风险。", "topic": "合同风控"},
|
||
],
|
||
"narratives": [
|
||
{"title": "到账节奏", "value": "承压", "description": "区域回款偏差扩大,需要以逐笔承诺替代笼统预测。"},
|
||
{"title": "风险敞口", "value": "中等", "description": "当前问题集中在少数高价值款项,仍具备专项化解条件。"},
|
||
{"title": "处置进度", "value": "已启动", "description": "财务、销售与管理层已进入联合跟进状态。"},
|
||
],
|
||
"insights": [
|
||
{"label": "风险动作", "highlight": "优先取得客户书面付款承诺,", "description": "并同步准备分期或节点化替代方案。"},
|
||
{"label": "经营影响", "highlight": "收入确认暂不受影响,", "description": "但现金流预测需保留约 ¥3.4M 风险缓冲。"},
|
||
],
|
||
},
|
||
{
|
||
"name": "资源协同",
|
||
"summary": "跨团队依赖集中显现,经营重点转向资源排期与关键节点保障。",
|
||
"chartDelta": 0.08,
|
||
"marginDelta": -0.08,
|
||
"briefs": [
|
||
{"label": "执行判断", "description": "商机质量保持稳定,交付与售前资源能否按期到位成为主要约束。"},
|
||
{"label": "排期协同", "description": "重点项目已按收入贡献与成交概率重新排序,资源将向前两级项目倾斜。"},
|
||
{"label": "交付提醒", "description": "两个项目存在并行上线需求,需要提前确认实施负责人和验收条件。"},
|
||
],
|
||
"objectives": [
|
||
{"description": "通过资源优先级调度保障高价值项目按期签约与确认,稳定年度目标节奏。"},
|
||
{"description": "对重点续约项目同步售前、交付和客户成功排期,减少内部等待时间。"},
|
||
{"description": "将资源投入与回款节点联动管理,优先保障付款条件清晰的项目。"},
|
||
],
|
||
"events": [
|
||
{"title": "重点项目资源优先级完成调整", "content": "售前与交付排期按项目价值重新排序,优先保障高概率机会。", "topic": "资源调度"},
|
||
{"title": "并行上线项目启动依赖核验", "content": "实施负责人、环境准备与验收标准已进入联合确认。", "topic": "交付协同"},
|
||
{"title": "跨部门问题转入日清机制", "content": "未闭环依赖将在每日经营例会上更新责任人与处理时限。", "topic": "机制优化"},
|
||
],
|
||
"narratives": [
|
||
{"title": "资源供给", "value": "趋紧", "description": "重点项目进入集中阶段,售前与交付资源需要动态调度。"},
|
||
{"title": "项目排序", "value": "已校准", "description": "当前优先级已综合收入贡献、成交概率、付款质量。"},
|
||
{"title": "协同效率", "value": "改善", "description": "跨部门问题进入日清机制,等待时间开始缩短。"},
|
||
],
|
||
"insights": [
|
||
{"label": "资源原则", "highlight": "优先保障高概率、高价值、付款清晰项目,", "description": "暂停低确定性定制投入。"},
|
||
{"label": "节奏建议", "highlight": "每日校准一次关键依赖,", "description": "确保资源变化及时反映到经营预测。"},
|
||
],
|
||
},
|
||
]
|
||
|
||
|
||
# ── 前端 createBusinessTimelineSnapshot 的 Python 复刻 ───────────────────────
|
||
|
||
|
||
def _positive_modulo(value: int, divisor: int) -> int:
|
||
return value % divisor
|
||
|
||
|
||
def _two_digits(value: int) -> str:
|
||
return f"{value:02d}"
|
||
|
||
|
||
def _format_snapshot_time(moment: datetime) -> str:
|
||
return f"{_two_digits(moment.month)}-{_two_digits(moment.day)} {_two_digits(moment.hour)}:{_two_digits(moment.minute)}"
|
||
|
||
|
||
def _merge_rows(source: list[dict], patches: list[dict]) -> list[dict]:
|
||
return [{**item, **(patches[index] if index < len(patches) else {})} for index, item in enumerate(source)]
|
||
|
||
|
||
def _adjust_series(values: list[float], delta: float) -> list[float]:
|
||
length = max(len(values), 1)
|
||
return [round(float(value) + delta * ((index + 1) / length), 1) for index, value in enumerate(values)]
|
||
|
||
|
||
def build_snapshot(moment: datetime) -> dict:
|
||
"""复刻 ``createBusinessTimelineSnapshot(baseDashboard, timestamp)``。"""
|
||
minute_slot = round((moment - ANCHOR).total_seconds() / 60)
|
||
slot = minute_slot + minute_slot // 5 + minute_slot // 60
|
||
phase = TIMELINE_PHASES[_positive_modulo(slot, len(TIMELINE_PHASES))]
|
||
time_label = _format_snapshot_time(moment)
|
||
events = [
|
||
{**event, "date": (moment - timedelta(minutes=17 * index)).strftime("%H:%M")}
|
||
for index, event in enumerate(phase["events"])
|
||
]
|
||
snapshot = dict(BASE_DASHBOARD)
|
||
snapshot.update(
|
||
{
|
||
"pageDescription": f"{phase['summary']} 当前展示 {time_label} 经营快照。",
|
||
"snapshotName": phase["name"],
|
||
"snapshotTime": moment.isoformat(),
|
||
"briefs": _merge_rows(BASE_DASHBOARD["briefs"], phase["briefs"]),
|
||
"objectives": _merge_rows(BASE_DASHBOARD["objectives"], phase["objectives"]),
|
||
"events": events,
|
||
"businessNarratives": phase["narratives"],
|
||
"insights": phase["insights"],
|
||
"chart": {
|
||
**BASE_DASHBOARD["chart"],
|
||
"ariaLabel": f"{time_label} {BASE_DASHBOARD['chart']['ariaLabel']}",
|
||
"actual": _adjust_series(BASE_DASHBOARD["chart"]["actual"], phase["chartDelta"]),
|
||
"bar": _adjust_series(BASE_DASHBOARD["chart"]["bar"], phase["marginDelta"]),
|
||
},
|
||
}
|
||
)
|
||
return snapshot
|
||
|
||
|
||
# ── 预存主流程 ───────────────────────────────────────────────────────────────
|
||
|
||
|
||
async def _run(dry_run: bool) -> int:
|
||
from deerflow.config import get_app_config
|
||
from deerflow.persistence.engine import close_engine, get_session_factory, init_engine_from_config
|
||
from deerflow.persistence.task_analysis import make_task_analysis_store
|
||
from deerflow.runtime.task_analysis.data_delivery import submit_block_data
|
||
|
||
config = get_app_config()
|
||
await init_engine_from_config(config.database)
|
||
sf = get_session_factory()
|
||
store = make_task_analysis_store(sf)
|
||
|
||
ticks = timeline_ticks()
|
||
snapshots = {tick: build_snapshot(tick) for tick in ticks}
|
||
|
||
if dry_run:
|
||
for tick in ticks:
|
||
snap = snapshots[tick]
|
||
logger.info("期 %s → %s · %s · %s", ticks.index(tick) + 1, tick.isoformat(), snap["snapshotName"], snap["pageDescription"][:40])
|
||
await close_engine()
|
||
return 0
|
||
|
||
# 幂等:演示任务已存在则级联删除后重建。
|
||
existing = await store.get_task_by_source(SOURCE_TASK_ID)
|
||
if existing is not None:
|
||
logger.info("演示任务已存在(id=%s),删除后重建", existing["id"])
|
||
await store.delete_task_cascade(existing["id"])
|
||
|
||
task = await store.create_task(
|
||
{
|
||
"source_task_id": SOURCE_TASK_ID,
|
||
"name": "商业态势总览(演示)",
|
||
"description": "定时数据交付演示任务:13 期小时刻度(2026-06-17 22:00 → 2026-06-18 10:00),block_1 = 商业态势总览页面数据。",
|
||
}
|
||
)
|
||
await store.update_block_defs(task["id"], [{"block_key": "block_1", "title": "商业态势总览"}])
|
||
|
||
for index, tick in enumerate(ticks, start=1):
|
||
period = await store.open_period(task["id"], source="cron", opened_at=tick)
|
||
result = await submit_block_data(store, task_id=task["id"], block_key="block_1", data=snapshots[tick])
|
||
logger.info(
|
||
"期 %s/%s opened_at=%s 相位=%s keys=%s",
|
||
period["period_index"], TICK_COUNT, tick.isoformat(), snapshots[tick]["snapshotName"], result["keys"],
|
||
)
|
||
|
||
logger.info("")
|
||
logger.info("预存完成。前端对接:")
|
||
logger.info(" 任务号 source_task_id = %s", SOURCE_TASK_ID)
|
||
logger.info(" 块定义 GET /api/task-analysis/external/tasks/%s/blocks", SOURCE_TASK_ID)
|
||
logger.info(" 时间轴 GET /api/task-analysis/external/tasks/%s/periods", SOURCE_TASK_ID)
|
||
logger.info(" 单期数据 GET /api/task-analysis/external/tasks/%s/periods/{n|latest}", SOURCE_TASK_ID)
|
||
|
||
await close_engine()
|
||
return 0
|
||
|
||
|
||
def main() -> int:
|
||
parser = argparse.ArgumentParser(description="预存商业态势总览演示数据(13 期小时刻度 + block_1 快照)")
|
||
parser.add_argument("--dry-run", action="store_true", help="只打印将生成的期与相位,不写库")
|
||
args = parser.parse_args()
|
||
try:
|
||
return asyncio.run(_run(args.dry_run))
|
||
except Exception:
|
||
logger.exception("预存失败")
|
||
return 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|