From e48aa3afdd69c63a55d73cef7a8f20c804ae706e Mon Sep 17 00:00:00 2001 From: karuo Date: Tue, 3 Mar 2026 10:15:45 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=84=20=E5=8D=A1=E8=8B=A5AI=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=202026-03-03=2010:15=20|=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=EF=BC=9A=E6=B0=B4=E6=A1=A5=E5=B9=B3=E5=8F=B0=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=E3=80=81=E5=8D=A1=E6=9C=A8=E3=80=81=E7=81=AB=E7=82=AC=E3=80=81?= =?UTF-8?q?=E8=BF=90=E8=90=A5=E4=B8=AD=E6=9E=A2=E5=8F=82=E8=80=83=E8=B5=84?= =?UTF-8?q?=E6=96=99=E3=80=81=E8=BF=90=E8=90=A5=E4=B8=AD=E6=9E=A2=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E5=8F=B0=20|=20=E6=8E=92=E9=99=A4=20>20MB:=2014=20?= =?UTF-8?q?=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../水桥_平台对接/Soul创业实验/上传/推送逻辑.md | 1 + .../水桥_平台对接/Soul创业实验/写作/写作规范.md | 6 +- .../智能纪要/脚本/auto_cookie_and_export.py | 96 ++++++--- .../智能纪要/脚本/feishu_minutes_one_url.py | 60 +++++- .../智能纪要/脚本/playwright_default_browser.py | 192 ++++++++++++++++++ .../智能纪要/脚本/浏览器控制台_复制妙记文字.js | 35 ++++ .../智能纪要/脚本/逆向获取Cookie并下载单条.py | 2 +- 02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md | 8 + .../飞书管理/脚本/write_0303_feishu_log.py | 77 +++++++ .../木叶_视频内容/视频切片/Soul竖屏切片_SKILL.md | 6 +- .../木叶_视频内容/视频切片/参考资料/README.md | 13 ++ .../视频切片/参考资料/高光识别提示词.md | 7 +- .../视频切片/脚本/identify_highlights.py | 2 +- .../木叶_视频内容/视频切片/脚本/soul_enhance.py | 100 ++++++--- 04_卡火(火)/火炬_全栈消息/读书笔记/SKILL.md | 33 ++- .../参考资料/卡若读书笔记格式_固定规则.md | 1 + .../2026-03-03_综合复盘_大目标与本月完成度.md | 50 +++++ 运营中枢/工作台/gitea_push_log.md | 1 + 运营中枢/工作台/代码管理.md | 1 + 19 files changed, 613 insertions(+), 78 deletions(-) create mode 100644 02_卡人(水)/水桥_平台对接/智能纪要/脚本/playwright_default_browser.py create mode 100644 02_卡人(水)/水桥_平台对接/智能纪要/脚本/浏览器控制台_复制妙记文字.js create mode 100644 02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0303_feishu_log.py create mode 100644 03_卡木(木)/木叶_视频内容/视频切片/参考资料/README.md create mode 100644 运营中枢/工作台/2026-03-03_综合复盘_大目标与本月完成度.md diff --git a/02_卡人(水)/水桥_平台对接/Soul创业实验/上传/推送逻辑.md b/02_卡人(水)/水桥_平台对接/Soul创业实验/上传/推送逻辑.md index ec012582..13500bf6 100644 --- a/02_卡人(水)/水桥_平台对接/Soul创业实验/上传/推送逻辑.md +++ b/02_卡人(水)/水桥_平台对接/Soul创业实验/上传/推送逻辑.md @@ -18,6 +18,7 @@ - **脚本**:永平项目下 `scripts/send_chapter_poster_to_feishu.py` - **依赖**:`pip install requests Pillow`;飞书应用凭证写在 `scripts/.env.feishu`(FEISHU_APP_ID、FEISHU_APP_SECRET)。 - **固定群 webhook**:脚本内置默认发到 **Soul 彩民团队** 飞书群,webhook 为 `https://open.feishu.cn/open-apis/bot/v2/hook/14a7e0d3-864d-4709-ad40-0def6edba566`。无需复制链接,直接运行命令即可。 +- **自定义 webhook(--webhook)**:用 `--webhook "https://..."` 可指定其他群。**推送前必须确认**:目标群名称含有「瘦」或「IP」,否则不要推送;脚本无法从 webhook 获知群名,需人工在飞书里核对。 - **命令示例**(上传完成后执行): ```bash diff --git a/02_卡人(水)/水桥_平台对接/Soul创业实验/写作/写作规范.md b/02_卡人(水)/水桥_平台对接/Soul创业实验/写作/写作规范.md index 6a8d86ba..72f71850 100644 --- a/02_卡人(水)/水桥_平台对接/Soul创业实验/写作/写作规范.md +++ b/02_卡人(水)/水桥_平台对接/Soul创业实验/写作/写作规范.md @@ -8,7 +8,9 @@ | 项目 | 规范 | |:---|:---| -| **「我」** | **整篇文章最多出现三次**。多用「这边」「直接」「就」「场上」等替代;成稿后全文搜索「我」,超过 3 处必须改写。 | +| **「我」** | **整篇文章最多出现三次**(仅指叙述者视角;对话引用里的「我」不占名额)。成稿后全文搜索「我」,超过 3 处必须改写。 | +| **「这边」「那边」** | **不要用**。改用灵活表述:房主、场上、就、手头、这种模式、知识星球/小程序 等指代或省略主语。 | +| **「回答说」** | **不要用**。房主是强势角色,文章目的是让读者产生深度认同感;房主的话用**直接陈述**呈现,不写「回答说,……」,让语气与性格一致、话一出口就立住。 | | **「卡若」** | 每篇最多提一次;不需要时可完全不出现。 | --- @@ -47,7 +49,7 @@ - **推进方式**:时间线或事件线,逻辑清晰(如「有人问 → 回答」「3 号问 → …」) - **分段**:每段一个主题,小主题隐于叙述中,不列段头小标题 - **穿插**:细节、对话、观点分析 -- **多用对话**:增强真实感(「X 号问」「有人问」「直接回答」「这边说」等) +- **多用对话**:增强真实感(「X 号问」「有人问」等);房主的话**直接接在问句后**,不写「回答说」,语气强势、可认同。 - **分享句(两处,强制)**:约 20% 处一句、结尾一句,各不超过 50 字,围绕本节主题、紧扣内容,留余味或可执行。**不要出现「干货」二字**,不要用「干货:」或「**干货**:」等格式,直接写一句金句即可,可单独成段。 --- diff --git a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/auto_cookie_and_export.py b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/auto_cookie_and_export.py index 0f1c4991..b37403a7 100644 --- a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/auto_cookie_and_export.py +++ b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/auto_cookie_and_export.py @@ -86,7 +86,7 @@ OUT_DIR = Path("/Users/karuo/Documents/聊天记录/soul") def run_playwright_page_export(from_num: int, to_num: int) -> int: - """在 Playwright 页面内直接请求导出,绕过 Cookie,保证成功。""" + """在 Playwright 用系统默认浏览器打开,页面内直接请求导出,复用已有登录/Cookie。""" import re items = [(n, t, tok, d) for n, t, tok, d in SOUL_ITEMS if from_num <= n <= to_num] if not items: @@ -96,12 +96,29 @@ def run_playwright_page_export(from_num: int, to_num: int) -> int: except ImportError: print("❌ 需安装 playwright: pip install playwright && playwright install chromium", file=sys.stderr) return 1 - import tempfile - ud = tempfile.mkdtemp(prefix="feishu_export_") + sys.path.insert(0, str(SCRIPT_DIR)) + try: + from playwright_default_browser import launch_playwright_with_default_browser + except ImportError: + launch_playwright_with_default_browser = None try: with sync_playwright() as p: - ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000) - pg = ctx.pages[0] if ctx.pages else ctx.new_page() + if launch_playwright_with_default_browser: + ctx, get_page, cleanup = launch_playwright_with_default_browser(p, headless=False, timeout=15000) + pg = get_page() + else: + import tempfile + ud = tempfile.mkdtemp(prefix="feishu_export_") + ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000) + pg = ctx.pages[0] if ctx.pages else ctx.new_page() + + def cleanup(): + try: + ctx.close() + except Exception: + pass + import shutil + shutil.rmtree(ud, ignore_errors=True) pg.goto(MINUTES_URL, wait_until="domcontentloaded", timeout=25000) print(" ⚠️ 请在此窗口登录飞书妙记(看到列表即可),等待 90 秒…") time.sleep(90) @@ -128,47 +145,66 @@ def run_playwright_page_export(from_num: int, to_num: int) -> int: except Exception as e: print(f" ❌ {topic}: {e}") time.sleep(1) - ctx.close() + try: + cleanup() + except Exception: + pass print(f"✅ 页面内导出完成 {saved}/{len(items)} 场,目录: {OUT_DIR}") return 0 - finally: - import shutil - shutil.rmtree(ud, ignore_errors=True) + except Exception as e: + print(f"❌ Playwright 导出异常: {e}", file=sys.stderr) + return 1 def collect_cookie_via_playwright_standalone() -> str: - """Playwright 启动独立 Chromium,用户登录后抓 Cookie。""" + """Playwright 用系统默认浏览器打开,用户登录后抓 Cookie,复用已有登录态。""" try: from playwright.sync_api import sync_playwright except ImportError: return "" - import tempfile - ud = tempfile.mkdtemp(prefix="feishu_cookie_") + sys.path.insert(0, str(SCRIPT_DIR)) + try: + from playwright_default_browser import launch_playwright_with_default_browser + except ImportError: + launch_playwright_with_default_browser = None cookie_str = "" try: with sync_playwright() as p: - ctx = p.chromium.launch_persistent_context( - user_data_dir=ud, - headless=False, - args=["--start-maximized"], - viewport={"width": 1280, "height": 900}, - timeout=15000, - ) - try: + if launch_playwright_with_default_browser: + ctx, get_page, cleanup = launch_playwright_with_default_browser(p, headless=False, timeout=15000) + pg = get_page() + else: + import tempfile + ud = tempfile.mkdtemp(prefix="feishu_cookie_") + ctx = p.chromium.launch_persistent_context( + user_data_dir=ud, + headless=False, + args=["--start-maximized"], + viewport={"width": 1280, "height": 900}, + timeout=15000, + ) pg = ctx.pages[0] if ctx.pages else ctx.new_page() + + def cleanup(): + try: + ctx.close() + except Exception: + pass + import shutil + shutil.rmtree(ud, ignore_errors=True) + try: pg.goto(MINUTES_URL, wait_until="domcontentloaded", timeout=25000) except Exception: - pg = ctx.new_page() if not ctx.pages else ctx.pages[0] - try: - pg.goto(MINUTES_URL, wait_until="domcontentloaded", timeout=25000) - except Exception: - pass + pass print(" ⚠️ 请在此窗口完成飞书妙记登录(输入账号密码直到看到列表),等待 120 秒…") time.sleep(120) cookies = ctx.cookies("https://cunkebao.feishu.cn") if not cookies: cookies = ctx.cookies() - ctx.close() + try: + cleanup() + except Exception: + pass seen = set() parts = [] for c in cookies: @@ -176,12 +212,8 @@ def collect_cookie_via_playwright_standalone() -> str: seen.add(c["name"]) parts.append(f"{c['name']}={c.get('value','')}") cookie_str = "; ".join(parts) - finally: - import shutil - try: - shutil.rmtree(ud, ignore_errors=True) - except Exception: - pass + except Exception as e: + print(f" Playwright 取 Cookie 失败: {e}", file=sys.stderr) return cookie_str if len(cookie_str) > 200 else "" diff --git a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/feishu_minutes_one_url.py b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/feishu_minutes_one_url.py index 6f1ef846..6e2a61c0 100644 --- a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/feishu_minutes_one_url.py +++ b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/feishu_minutes_one_url.py @@ -71,18 +71,37 @@ def export_via_cookie(object_token: str) -> str | None: def export_via_playwright_page(object_token: str, title: str = "", wait_sec: int = 30) -> str | None: - """Playwright 打开妙记页,在页面内 fetch 导出接口(带 credentials),无感拿正文。""" + """Playwright 用系统默认浏览器打开妙记页,在页面内 fetch 导出接口(带 credentials),复用已有登录/Cookie。""" try: from playwright.sync_api import sync_playwright except ImportError: return None - import tempfile - ud = tempfile.mkdtemp(prefix="feishu_one_") + sys.path.insert(0, str(SCRIPT_DIR)) + try: + from playwright_default_browser import launch_playwright_with_default_browser + except ImportError: + launch_playwright_with_default_browser = None result = [None] + cleanup = lambda: None + try: with sync_playwright() as p: - ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000) - pg = ctx.pages[0] if ctx.pages else ctx.new_page() + if launch_playwright_with_default_browser: + ctx, get_page, cleanup = launch_playwright_with_default_browser(p, headless=False, timeout=15000) + pg = get_page() + else: + import tempfile + ud = tempfile.mkdtemp(prefix="feishu_one_") + ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000) + pg = ctx.pages[0] if ctx.pages else ctx.new_page() + + def cleanup(): + try: + ctx.close() + except Exception: + pass + import shutil + shutil.rmtree(ud, ignore_errors=True) pg.goto(f"https://cunkebao.feishu.cn/minutes/{object_token}", wait_until="domcontentloaded", timeout=25000) print(f" 页面已打开,等待 {wait_sec} 秒(若未登录请先登录)…") time.sleep(wait_sec) @@ -115,11 +134,38 @@ def export_via_playwright_page(object_token: str, title: str = "", wait_sec: int result[0] = text elif len(text) > 400: result[0] = text + # 兜底:从页面 DOM 抓取正文(先点「文字记录」再取整页或大块文本) + if not result[0]: + try: + # 尝试点击「文字记录」tab 再取内容 + for label in ["文字记录", "文字"]: + try: + pg.get_by_text(label, exact=False).first.click(timeout=3000) + time.sleep(1.5) + break + except Exception: + pass + dom_text = pg.evaluate("""() => { + let out = ''; + const candidates = document.querySelectorAll('[class*="content"], [class*="paragraph"], [class*="segment"], [class*="transcript"], [class*="record"], .ne-doc-body, [role="main"]'); + for (const el of candidates) { + const t = (el.innerText || el.textContent || '').trim(); + if (t.length > 800 && (t.includes(':') || t.includes(':') || /\\d{1,2}:\\d{2}:\\d{2}/.test(t))) { out = t; break; } + } + if (!out) out = document.body.innerText || document.body.textContent || ''; + return out; + }""") + if dom_text and len(dom_text.strip()) > 300: + result[0] = dom_text.strip() + except Exception: + pass except Exception as e: print(f" Playwright 失败: {e}", file=sys.stderr) finally: - import shutil - shutil.rmtree(ud, ignore_errors=True) + try: + cleanup() + except Exception: + pass return result[0] diff --git a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/playwright_default_browser.py b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/playwright_default_browser.py new file mode 100644 index 00000000..7410a853 --- /dev/null +++ b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/playwright_default_browser.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +""" +检测系统默认浏览器,并用该浏览器启动 Playwright,优先使用其用户数据目录以保留登录/Cookie。 +供 feishu_minutes_one_url、auto_cookie_and_export、逆向获取Cookie并下载单条 等脚本使用。 +""" +from __future__ import annotations + +import platform +import subprocess +import sys +from pathlib import Path + + +def get_system_default_browser(): + """ + 检测系统当前使用的默认浏览器。 + 返回 (engine, channel, profile_path): + - engine: "chromium" | "webkit" | "firefox" + - channel: 仅 chromium 时有效,"chrome" | "msedge" | "chromium" | None + - profile_path: 用户数据目录,用于复用登录态;None 表示不使用系统 profile + """ + system = platform.system() + home = Path.home() + + if system == "Darwin": # macOS + # 优先读取系统默认 HTTP/HTTPS 处理程序 + try: + out = subprocess.run( + ["defaults", "read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"], + capture_output=True, + text=True, + timeout=5, + ) + if out.returncode == 0 and out.stdout: + for line in out.stdout.splitlines(): + if "https" in line.lower() or "http" in line.lower(): + continue + # 解析 LSHandlers 较复杂,改为按应用存在性检测 + except Exception: + pass + + # 按优先级检测已安装的浏览器(与多数用户习惯一致:Chrome/Edge 常用) + apps = [ + ("Google Chrome", "chromium", "chrome", home / "Library/Application Support/Google/Chrome"), + ("Microsoft Edge", "chromium", "msedge", home / "Library/Application Support/Microsoft Edge"), + ("Chromium", "chromium", "chromium", home / "Library/Application Support/Chromium"), + ("Safari", "webkit", None, None), + ("Firefox", "firefox", None, home / "Library/Application Support/Firefox"), + ] + for app_name, engine, channel, profile in apps: + app_path = Path(f"/Applications/{app_name}.app") + if app_path.exists(): + if engine == "firefox" and profile: + # Firefox 使用 Profiles/xxx.default 子目录 + profiles = profile / "Profiles" + if profiles.exists(): + for d in profiles.iterdir(): + if d.is_dir() and (d / "prefs.js").exists(): + profile = d + break + else: + profile = None + out_profile = str(profile) if profile and profile.exists() else None + return (engine, channel, out_profile) + # 若都未找到,退回 Chromium(Playwright 自带) + return ("chromium", None, None) + + if system == "Windows": + try: + out = subprocess.run( + ["reg", "query", "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\https\\UserChoice", "/v", "ProgId"], + capture_output=True, + text=True, + timeout=5, + ) + if out.returncode == 0 and "chrome" in out.stdout.lower(): + return ("chromium", "chrome", None) + if out.returncode == 0 and "edge" in out.stdout.lower(): + return ("chromium", "msedge", None) + except Exception: + pass + return ("chromium", None, None) + + return ("chromium", None, None) + + +def launch_playwright_with_default_browser(sync_playwright, headless: bool = False, timeout: int = 15000): + """ + 使用系统默认浏览器启动 Playwright,返回 (context_or_browser, page_getter, cleanup)。 + page_getter 用于获取当前 page(可能是 context.pages[0] 或 new_page)。 + cleanup 用于关闭 context/browser。 + 若使用持久 context,则尽量复用系统 profile,避免 Cookie 无法登录。 + """ + import tempfile + p = sync_playwright + engine, channel, profile_path = get_system_default_browser() + + if engine == "chromium": + channel_info = f" (channel={channel})" if channel else "" + print(f" 使用系统浏览器: Chromium 系{channel_info},profile={profile_path or '临时目录'}") + + # 优先尝试用系统 profile 启动(已登录则直接用) + if profile_path and channel: + try: + ctx = p.chromium.launch_persistent_context( + profile_path, + channel=channel, + headless=headless, + timeout=timeout, + args=["--no-first-run"], + ) + page = ctx.pages[0] if ctx.pages else ctx.new_page() + + def cleanup(): + try: + ctx.close() + except Exception: + pass + + return ctx, lambda: page, cleanup + except Exception as e: + if "already in use" in str(e).lower() or "User data directory" in str(e): + print(f" 系统浏览器正在使用中,改用临时目录(请在新窗口内登录一次): {e}") + else: + print(f" 使用系统 profile 失败,改用临时目录: {e}") + + # 使用临时目录 + 指定 channel(仍为系统安装的 Chrome/Edge) + user_data = tempfile.mkdtemp(prefix="feishu_playwright_") + try: + kwargs = {"headless": headless, "timeout": timeout} + if channel: + kwargs["channel"] = channel + ctx = p.chromium.launch_persistent_context(user_data, **kwargs) + page = ctx.pages[0] if ctx.pages else ctx.new_page() + + def cleanup(): + try: + ctx.close() + except Exception: + pass + import shutil + shutil.rmtree(user_data, ignore_errors=True) + + return ctx, lambda: page, cleanup + except Exception: + import shutil + shutil.rmtree(user_data, ignore_errors=True) + raise + + if engine == "webkit": + print(" 使用系统浏览器: Safari (WebKit)") + browser = p.webkit.launch(headless=headless) + ctx = browser + page = browser.new_page() + + def cleanup(): + try: + browser.close() + except Exception: + pass + + return ctx, lambda: page, cleanup + + if engine == "firefox": + print(" 使用系统浏览器: Firefox") + browser = p.firefox.launch(headless=headless) + ctx = browser + page = browser.new_page() + + def cleanup(): + try: + browser.close() + except Exception: + pass + + return ctx, lambda: page, cleanup + + # 默认 + print(" 使用 Playwright 自带 Chromium") + user_data = tempfile.mkdtemp(prefix="feishu_playwright_") + ctx = p.chromium.launch_persistent_context(user_data, headless=headless, timeout=timeout) + page = ctx.pages[0] if ctx.pages else ctx.new_page() + + def cleanup(): + try: + ctx.close() + except Exception: + pass + import shutil + shutil.rmtree(user_data, ignore_errors=True) + + return ctx, lambda: page, cleanup diff --git a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/浏览器控制台_复制妙记文字.js b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/浏览器控制台_复制妙记文字.js new file mode 100644 index 00000000..93af5061 --- /dev/null +++ b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/浏览器控制台_复制妙记文字.js @@ -0,0 +1,35 @@ +/** + * 在已打开的飞书妙记页面(cunkebao.feishu.cn/minutes/xxx)按 F12 → Console 粘贴整段运行, + * 会提取当前页「文字记录」区域文字并复制到剪贴板,同时打印到控制台。 + */ +(function () { + function getText() { + const candidates = document.querySelectorAll( + '[class*="content"], [class*="paragraph"], [class*="segment"], [class*="transcript"], [class*="record"], .ne-doc-body, [role="main"]' + ); + for (const el of candidates) { + const t = (el.innerText || el.textContent || "").trim(); + if (t.length > 800 && (t.includes(":") || t.includes(":") || /\d{1,2}:\d{2}:\d{2}/.test(t))) { + return t; + } + } + return (document.body && (document.body.innerText || document.body.textContent)) || ""; + } + const text = getText().trim(); + if (!text) { + console.warn("未找到长文本,请先点击「文字记录」选项卡再运行本脚本。"); + return; + } + const title = (document.title || "妙记").replace(/\s*\|\s*.*$/, ""); + const out = "标题: " + title + "\n\n文字记录:\n\n" + text; + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(out).then(function () { + console.log("已复制到剪贴板,共 " + out.length + " 字。可粘贴到记事本保存。"); + }).catch(function () { + console.log(out.slice(0, 500) + "\n...(共 " + out.length + " 字,请手动选择上方输出复制)"); + }); + } else { + console.log(out.slice(0, 2000) + "\n...(共 " + out.length + " 字)"); + } + console.log("前 500 字预览:", out.slice(0, 500)); +})(); diff --git a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/逆向获取Cookie并下载单条.py b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/逆向获取Cookie并下载单条.py index b0196e0d..b3b7a17c 100644 --- a/02_卡人(水)/水桥_平台对接/智能纪要/脚本/逆向获取Cookie并下载单条.py +++ b/02_卡人(水)/水桥_平台对接/智能纪要/脚本/逆向获取Cookie并下载单条.py @@ -122,7 +122,7 @@ def main() -> int: try: from feishu_minutes_one_url import export_via_playwright_page print(" Cookie 导出 401,改用 Playwright 页面内获取…") - text = export_via_playwright_page(token, title=title, wait_sec=45) + text = export_via_playwright_page(token, title=title, wait_sec=60) except Exception as e: print(" Playwright 兜底失败:", e, file=sys.stderr) if text: diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md b/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md index e7b44f25..1bfd4cb0 100755 --- a/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md +++ b/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md @@ -347,6 +347,14 @@ python3 scripts/feishu_wiki_create_doc.py --parent KNf7wA8Rki1NSdkkSIqcdFtTnWb - JSON 格式:与 `团队入职流程与新人登记表_feishu_blocks.json` 相同,含 `children` 数组(飞书 docx blocks)。 +### 读书笔记发飞书(链接与子目录) + +- **原则**:读书笔记写完后同步发到飞书知识库,发到**指定链接(父节点)下的对应子目录**。 +- **链接分析**:飞书知识库链接格式为 `https://cunkebao.feishu.cn/wiki/`,其中 `wiki/` 后的 `node_token` 即为父节点;若读书笔记放在「读书笔记」节点下,则用该节点 token 为 parent;若其下还有分类子目录(个人提升/创业/商业思维/投资/人际关系),则先在对应子节点下再建文档。 +- **目录结构建议**:父节点 = 读书笔记根(如「2、我写的日记」或「读书笔记」)→ 其下可建子目录「读书笔记」或按分类建「个人提升」「创业」等 → 单篇笔记为该目录下的一篇文档。 +- **执行**:用统一文章上传脚本,`--parent` 取目标父节点 token(即链接中的 node_token),`--title` 与本地笔记标题一致,`--md` 指向 `个人/2、我写的日记/读书笔记/xxx.md`。若需按分类落子目录,需先有该分类子节点 token,再以该 token 为 parent 创建文档。 +- **配置**:读书笔记默认本地路径为 `个人/2、我写的日记/读书笔记/`;飞书父节点 token 可配置为环境变量 `FEISHU_READING_WIKI_PARENT` 或写在读书笔记 Skill 的「飞书读书笔记配置」中;用户提供飞书「读书笔记」节点链接后,从链接提取 token 填入即可。 + --- ## 飞书导出 JSON 按原格式上传 diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0303_feishu_log.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0303_feishu_log.py new file mode 100644 index 00000000..978a07d9 --- /dev/null +++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0303_feishu_log.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +""" +写入 3月3日 飞书日志到 3 月文档。昨日目标与今年总目标一致,百分比按总目标;今日 20 条视频 + 1 朋友圈,视频 Skill 四屏切片完成 20 个视频。 +""" +import os +import sys +from pathlib import Path + +SCRIPT_DIR = Path(__file__).resolve().parent +sys.path.insert(0, str(SCRIPT_DIR)) + +from auto_log import get_token_silent, write_log, open_result, CONFIG + + +def _get_march_wiki_token(): + raw = (CONFIG.get("MONTH_WIKI_TOKENS") or {}).get(3) or os.environ.get("FEISHU_MARCH_WIKI_TOKEN") or "" + return (raw or "").strip() or None + + +def build_tasks_0303(): + """3月3日:昨日目标一致、总目标一致、百分比按此;今日 20 条视频 + 1 朋友圈;视频 Skill 四屏切片 20 个;百分比。""" + return [ + { + "person": "卡若", + "events": ["今日复盘", "本月与最终目标", "今日核心", "视频Skill四屏切片"], + "quadrant": "重要紧急", + "t_targets": [ + "昨日目标与今年总目标一致,百分比按总目标执行", + "本月目标约 12%,距最终目标差 88%", + "今日核心:每天 20 条 Soul 视频 + 20:00 发 1 条朋友圈", + "视频 Skill 四屏切片:完成 20 个视频(当日完成度见反馈)", + ], + "n_process": [ + "【复盘】昨日目标一致、今年总目标一致,百分比按 2026年整体目标 对齐", + "【2月突破执行】延续 3 月,本月/最终目标百分比已按进度写入", + "【今日】20 条视频(四屏切片)+ 1 条朋友圈;视频切片 Skill 操作执行", + ], + "t_thoughts": [ + "今日一条核心:20 条 Soul 视频 + 8 点 1 条朋友圈,持续拉齐与最终目标", + "四屏切片完成 20 个视频,按当日完成数看百分比", + ], + "w_work": [ + "20 条 Soul 视频(四屏切片)", + "20:00 发 1 条朋友圈", + "视频 Skill 操作", + "飞书日志", + ], + "f_feedback": [ + "本月/最终目标 12% / 100%,差 88%", + "今日核心→20 条 Soul + 8 点朋友圈 🔄", + "四屏切片 20 条→当日完成度待填 % 🔄", + ], + } + ] + + +def main(): + token = get_token_silent() + if not token: + print("❌ 无法获取飞书 Token") + sys.exit(1) + march_token = _get_march_wiki_token() + if not march_token: + print("❌ 未配置 3 月文档,请设置 FEISHU_MARCH_WIKI_TOKEN") + sys.exit(1) + tasks = build_tasks_0303() + ok = write_log(token, "3月3日", tasks, march_token, overwrite=False) + if ok: + open_result(march_token) + print("✅ 3月3日 飞书日志已写入") + else: + print("❌ 写入失败") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/03_卡木(木)/木叶_视频内容/视频切片/Soul竖屏切片_SKILL.md b/03_卡木(木)/木叶_视频内容/视频切片/Soul竖屏切片_SKILL.md index 0fb1f154..2722a39f 100644 --- a/03_卡木(木)/木叶_视频内容/视频切片/Soul竖屏切片_SKILL.md +++ b/03_卡木(木)/木叶_视频内容/视频切片/Soul竖屏切片_SKILL.md @@ -17,7 +17,7 @@ ## 二、视频结构:提问→回答 + 前3秒高光 + 去语助词 -- **前3秒**:先看片段有没有人提问;**有提问**则把**提问的问题**放到前3秒(封面/前贴),先展示问题再播回答;无提问则用金句/悬念作 hook。 +- **每个话题前均优先提问→回答**:先看片段有没有人提问;**有提问**则把**提问的问题**放到前3秒(封面/前贴),先展示问题再播回答;无提问则用金句/悬念作 hook。 - **成片链路**:前3秒展示问题(或金句)→ 正片回答 → **整片去除语助词**(提问与回答部分均由 soul_enhance 清理)。 - **高光**:按「3秒高光亮点」剪,每段 30~300 秒完整语义单元;高光识别若有提问须填 `question`,且 `hook_3sec` 与之一致。 @@ -50,8 +50,8 @@ ## 五、成片:封面 + 字幕 + 竖屏 -- **封面**:竖屏 498×1080 内**不超出界面**;深色渐变背景(墨绿→绿)、左上角 Soul logo、标题文字**严格居中**且左右留白 44px,多行自动换行不裁切。 -- **字幕**:封面结束后才显示,**居中**在竖屏内;语助词由 soul_enhance 统一清理。重新加字幕时加 `--force-burn-subs`。 +- **封面**:竖屏 498×1080 内**不超出界面**;**半透明质感**(背景 alpha=165,透出底层画面);深色渐变(墨绿→绿)、左上角 Soul logo、标题文字**严格居中**且左右留白 44px,多行自动换行不裁切。透明度在 `soul_enhance.py` 中由 `VERTICAL_COVER_ALPHA` 调节(0~255)。 +- **字幕**:封面结束后才显示,**居中**在竖屏内;烧录用**图像 overlay**(每张字幕图 `-loop 1` + `enable=between(t,a,b)`),若系统 FFmpeg 带 libass 可改用 SRT+subtitles 滤镜;语助词由 soul_enhance 统一清理。重新加字幕时加 `--force-burn-subs`。 - **竖屏**:498×1080,crop 参数与 `参考资料/竖屏中段裁剪参数说明.md` 一致 --- diff --git a/03_卡木(木)/木叶_视频内容/视频切片/参考资料/README.md b/03_卡木(木)/木叶_视频内容/视频切片/参考资料/README.md new file mode 100644 index 00000000..1d9a1f43 --- /dev/null +++ b/03_卡木(木)/木叶_视频内容/视频切片/参考资料/README.md @@ -0,0 +1,13 @@ +# 视频切片 · 参考资料 + +本目录为视频切片 Skill 的参考资料,若出现「Unable to open 高光识别提示词.md」类错误,请用下面方式之一打开: + +- **本目录下的文件**:[高光识别提示词.md](./高光识别提示词.md) +- **快速打开**:在 Cursor 中 `Cmd+P`(或 Ctrl+P),输入 `高光识别提示词`,选择 `参考资料/高光识别提示词.md` + +| 文件 | 说明 | +|------|------| +| 高光识别提示词.md | AI 高光识别用提示词(Hook/CTA/提问→回答) | +| 视频结构_提问回答与高光.md | 提问→回答结构、前3秒、去语助词 | +| 竖屏中段裁剪参数说明.md | Soul 竖屏 498×1080 crop 参数 | +| 主题片段提取规则.md | 按章节主题提取片段规则 | diff --git a/03_卡木(木)/木叶_视频内容/视频切片/参考资料/高光识别提示词.md b/03_卡木(木)/木叶_视频内容/视频切片/参考资料/高光识别提示词.md index 859cd9a7..5ae76bed 100644 --- a/03_卡木(木)/木叶_视频内容/视频切片/参考资料/高光识别提示词.md +++ b/03_卡木(木)/木叶_视频内容/视频切片/参考资料/高光识别提示词.md @@ -1,6 +1,7 @@ # 高光识别提示词 -> 所有输出(Hook、CTA、标题)统一**简体中文**。 +> 所有输出(Hook、CTA、标题)统一**简体中文**。 +> 本文件路径:`视频切片/参考资料/高光识别提示词.md`(卡若AI 项目内) 用于分析视频文字稿,识别最有传播力的片段,并生成前3秒Hook和结尾CTA。 @@ -48,9 +49,9 @@ - 吊人胃口的开场 - "接下来这段更精彩" -# 提问→回答 结构(前3秒优先用提问) +# 提问→回答 结构(每个话题前均优先) -**成片结构**:先展示**提问**(前3秒),再进入**回答**(正片)。若片段里有人提问,必须把**提问的问题**放到前3秒。 +**每个话题/高光片段均优先采用提问→回答形式**:先展示**提问**(前3秒),再进入**回答**(正片)。若片段里有人提问,必须把**提问的问题**放到前3秒。 1. **判断**:看该高光片段文字稿中是否有人提问(观众/连麦者问的问题)。 2. **若有提问**: diff --git a/03_卡木(木)/木叶_视频内容/视频切片/脚本/identify_highlights.py b/03_卡木(木)/木叶_视频内容/视频切片/脚本/identify_highlights.py index 897ec480..b532e2b3 100644 --- a/03_卡木(木)/木叶_视频内容/视频切片/脚本/identify_highlights.py +++ b/03_卡木(木)/木叶_视频内容/视频切片/脚本/identify_highlights.py @@ -159,7 +159,7 @@ def _build_prompt(transcript: str, clip_count: int) -> str: txt = transcript[:5000] if len(transcript) > 5000 else transcript return f"""识别视频文字稿中的 {clip_count} 个高光片段,直接输出 JSON 数组,第一个字符必须是 [。 -重要:若某片段里有人提问(观众/连麦者问的问题),必须提取提问内容填 question,且 hook_3sec 用该提问。成片前3秒先展示提问,再播回答。 +重要:每个话题均优先提问→回答。若某片段里有人提问(观众/连麦者问的问题),必须提取提问内容填 question,且 hook_3sec 用该提问;成片前3秒先展示提问,再播回答。 示例(有提问): [{{"title":"普通人怎么敢跟ZF搞","start_time":"01:12:30","end_time":"01:15:30","question":"普通人怎么敢跟ZF搞?","hook_3sec":"普通人怎么敢跟ZF搞?","cta_ending":"{DEFAULT_CTA}","transcript_excerpt":"维权起头跑通就成生意","reason":"提问+回答完整"}}] diff --git a/03_卡木(木)/木叶_视频内容/视频切片/脚本/soul_enhance.py b/03_卡木(木)/木叶_视频内容/视频切片/脚本/soul_enhance.py index 3346621c..4a89ecf4 100644 --- a/03_卡木(木)/木叶_视频内容/视频切片/脚本/soul_enhance.py +++ b/03_卡木(木)/木叶_视频内容/视频切片/脚本/soul_enhance.py @@ -89,6 +89,13 @@ FILLER_WORDS = [ '怎么说呢', '你知道吗', '我跟你说', '好', '对', 'OK', 'ok', ] +# 不烧录的无关/模板句(仅整句完全匹配或极短规则说明,避免误杀正片对白) +SKIP_SUBTITLE_PHRASES = ( + "回复1", "回复 1", "排序分享", "上麦后按格式介绍自己", "进资源泡泡群", "做矩阵切片", + "合作私聊", "群主必", "时间5~10分钟", "我能帮到大家什么", "我需要什么帮助", + "廿四先生", "进来陪你聊天", "建房领开工红包", +) + # 关键词高亮(重点突出,按长度排序避免短词覆盖长词) KEYWORDS = [ '100万', '50万', '30万', '10万', '5万', '1万', @@ -118,6 +125,8 @@ SOUL_GREEN_DARK = (0, 160, 80) VERTICAL_COVER_TOP = (12, 32, 24) # 深墨绿 VERTICAL_COVER_BOTTOM = (8, 48, 36) # 略亮绿 VERTICAL_COVER_PADDING = 44 # 左右留白,保证文字不贴边、不超出 +# 成片封面半透明质感:背景层 alpha,便于透出底层画面 +VERTICAL_COVER_ALPHA = 165 # 0~255,越大越不透明 # 样式配置 STYLE = { @@ -243,6 +252,53 @@ def parse_srt_for_clip(srt_path, start_sec, end_sec): return subtitles + +def _filter_relevant_subtitles(subtitles): + """只过滤整句为规则/模板的条目,保留所有对白与重复句以便字幕连续""" + out = [] + for sub in subtitles: + text = (sub.get("text") or "").strip() + if len(text) < 2: + continue + if text in SKIP_SUBTITLE_PHRASES: + continue + out.append(sub) + return out + + +def _sec_to_srt_time(sec): + """秒数转为 SRT 时间格式 HH:MM:SS,mmm""" + h = int(sec) // 3600 + m = (int(sec) % 3600) // 60 + s = int(sec) % 60 + ms = int((sec - int(sec)) * 1000) + return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}" + + +def write_clip_srt(srt_path, subtitles, cover_duration): + """写出用于烧录的 SRT(仅保留封面结束后的字幕,时间已相对片段)""" + lines = [] + idx = 1 + for sub in subtitles: + start, end = sub['start'], sub['end'] + if end <= cover_duration: + continue + start = max(start, cover_duration) + text = (sub.get('text') or '').strip().replace('\n', ' ') + if not text: + continue + lines.append(str(idx)) + lines.append(f"{_sec_to_srt_time(start)} --> {_sec_to_srt_time(end)}") + lines.append(text) + lines.append("") + idx += 1 + if not lines: + return None + with open(srt_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + return srt_path + + def _is_mostly_chinese(text): if not text or not isinstance(text, str): return False @@ -350,14 +406,14 @@ def get_cover_font(size): return ImageFont.load_default() -def _draw_vertical_gradient(draw, width, height, top_rgb, bottom_rgb): - """绘制竖屏封面用深色渐变背景,高级感""" +def _draw_vertical_gradient(draw, width, height, top_rgb, bottom_rgb, alpha=255): + """绘制竖屏封面用深色渐变背景;alpha<255 时为半透明质感""" for y in range(height): t = y / max(height - 1, 1) r = int(top_rgb[0] + (bottom_rgb[0] - top_rgb[0]) * t) g = int(top_rgb[1] + (bottom_rgb[1] - top_rgb[1]) * t) b = int(top_rgb[2] + (bottom_rgb[2] - top_rgb[2]) * t) - draw.rectangle([0, y, width, y + 1], fill=(r, g, b)) + draw.rectangle([0, y, width, y + 1], fill=(r, g, b, alpha)) def create_cover_image(hook_text, width, height, output_path, video_path=None): @@ -370,13 +426,12 @@ def create_cover_image(hook_text, width, height, output_path, video_path=None): is_vertical = (width, height) == (VERTICAL_W, VERTICAL_H) if is_vertical: - # 竖屏成片:高级深色渐变背景,不依赖视频帧,保证不超出界面 - img = Image.new('RGB', (width, height), VERTICAL_COVER_TOP) + # 竖屏成片:半透明质感封面,渐变背景带 alpha,透出底层画面 + img = Image.new('RGBA', (width, height), (*VERTICAL_COVER_TOP, VERTICAL_COVER_ALPHA)) draw = ImageDraw.Draw(img) - _draw_vertical_gradient(draw, width, height, VERTICAL_COVER_TOP, VERTICAL_COVER_BOTTOM) - # 轻微半透明暗角,让文字更突出 - overlay = Image.new('RGBA', (width, height), (0, 0, 0, 100)) - img = img.convert('RGBA') + _draw_vertical_gradient(draw, width, height, VERTICAL_COVER_TOP, VERTICAL_COVER_BOTTOM, alpha=VERTICAL_COVER_ALPHA) + # 轻微半透明暗角,不盖死 + overlay = Image.new('RGBA', (width, height), (0, 0, 0, 60)) img = Image.alpha_composite(img, overlay) draw = ImageDraw.Draw(img) else: @@ -687,7 +742,7 @@ def enhance_clip(clip_path, output_path, highlight_info, temp_dir, transcript_pa create_cover_image(hook_text, out_w, out_h, cover_img, clip_path) print(f" ✓ 封面生成") - # 2. 字幕逻辑:有字幕/图片则跳过,无则烧录中文 + # 2. 字幕逻辑:有字幕则烧录(图像 overlay:每张图 -loop 1 才能按时间 enable 显示) sub_images = [] do_burn_subs = not skip_subs and (force_burn_subs or not detect_burned_subs(clip_path)) if skip_subs: @@ -709,8 +764,10 @@ def enhance_clip(clip_path, output_path, highlight_info, temp_dir, transcript_pa for sub in subtitles: if not _is_mostly_chinese(sub['text']): sub['text'] = _translate_to_chinese(sub['text']) or sub['text'] - print(f" ✓ 字幕解析 ({len(subtitles)}条),已转中文") - for i, sub in enumerate(subtitles[:50]): + # 仅过滤整句为规则/模板的条目,保留所有对白(含重复句,保证字幕连续) + subtitles = _filter_relevant_subtitles(subtitles) + print(f" ✓ 字幕解析 ({len(subtitles)}条)") + for i, sub in enumerate(subtitles): img_path = os.path.join(temp_dir, f'sub_{i:04d}.png') create_subtitle_image(sub['text'], out_w, out_h, img_path) sub_images.append({'path': img_path, 'start': sub['start'], 'end': sub['end']}) @@ -740,22 +797,19 @@ def enhance_clip(clip_path, output_path, highlight_info, temp_dir, transcript_pa current_video = cover_output print(f" ✓ 封面烧录") - # 5.2 分批烧录字幕(封面结束后才显示,不盖住封面) + # 5.2 烧录字幕(图像 overlay;每张图 -loop 1 才能按 enable=between(t,a,b) 显示) if sub_images: - batch_size = 8 + batch_size = 5 for batch_idx in range(0, len(sub_images), batch_size): batch = sub_images[batch_idx:batch_idx + batch_size] - inputs = ['-i', current_video] for img in batch: - inputs.extend(['-i', img['path']]) - + inputs.extend(['-loop', '1', '-i', img['path']]) filters = [] last_output = '0:v' for i, img in enumerate(batch): input_idx = i + 1 output_name = f'v{i}' - # 封面结束后才显示字幕,不盖住封面 sub_start = max(img['start'], cover_duration) if sub_start < img['end']: enable = f"between(t,{sub_start:.3f},{img['end']:.3f})" @@ -763,22 +817,20 @@ def enhance_clip(clip_path, output_path, highlight_info, temp_dir, transcript_pa else: filters.append(f"[{last_output}]copy[{output_name}]") last_output = output_name - filter_complex = ';'.join(filters) batch_output = os.path.join(temp_dir, f'sub_batch_{batch_idx}.mp4') - cmd = [ 'ffmpeg', '-y', *inputs, '-filter_complex', filter_complex, '-map', f'[{last_output}]', '-map', '0:a', '-c:v', 'libx264', '-preset', 'fast', '-crf', '22', - '-c:a', 'copy', batch_output + '-c:a', 'copy', '-shortest', batch_output ] - - result = subprocess.run(cmd, capture_output=True) + result = subprocess.run(cmd, capture_output=True, text=True) + if result.returncode != 0: + print(f" ⚠ 字幕批次 {batch_idx} 报错: {(result.stderr or '')[-500:]}", file=sys.stderr) if result.returncode == 0 and os.path.exists(batch_output): current_video = batch_output - print(f" ✓ 字幕烧录") # 5.3 加速10% + 音频同步 diff --git a/04_卡火(火)/火炬_全栈消息/读书笔记/SKILL.md b/04_卡火(火)/火炬_全栈消息/读书笔记/SKILL.md index 8447b35e..f9ac91f5 100644 --- a/04_卡火(火)/火炬_全栈消息/读书笔记/SKILL.md +++ b/04_卡火(火)/火炬_全栈消息/读书笔记/SKILL.md @@ -1,16 +1,39 @@ --- name: 读书笔记 -description: 五行结构化读书笔记。触发词:拆解这本书、写入读书笔记、读书笔记、五行拆书、XMind笔记、卡读、金水木火土。使用金水木火土五行框架拆解书籍,自动写入XMind。包含完整的拆书提示词、XMind写入脚本、操作流程。 +description: 五行结构化读书笔记。触发词:拆解这本书、写入读书笔记、读书笔记、五行拆书、XMind笔记、卡读、金水木火土。使用金水木火土五行框架拆解书籍,自动写入XMind;本地默认存 2、我写的日记/读书笔记,写完后可同步发飞书知识库对应子目录。 group: 火 -triggers: 拆解这本书、五行拆书、读书笔记 +triggers: 拆解这本书、五行拆书、读书笔记、读书笔记发飞书 owner: 火炬 -version: "1.0" -updated: "2026-02-16" +version: "1.1" +updated: "2026-03-03" --- # 读书笔记 -为卡若提供五行结构化读书笔记服务,支持自动写入 XMind。 +为卡若提供五行结构化读书笔记服务,支持自动写入 XMind;**本地固定存放 + 可选飞书同步**。 + +## 默认存放路径(强制) + +- **本地**:`/Users/karuo/Documents/个人/2、我写的日记/读书笔记/` +- 文件名:`作者或主题_书名或简称_读书笔记.md`(例:`曾仕强_易经_读书笔记.md`、`Dan_Koe_如何在一天内彻底改造你的人生_读书笔记.md`) +- 格式与规则见:`运营中枢/参考资料/卡若读书笔记格式_固定规则.md` + +## 飞书同步(写完后发到飞书链接下子目录) + +- **原则**:读书笔记写完后,**同时发到飞书知识库**指定链接下的**对应子目录**,与本地「2、我写的日记/读书笔记」一致。 +- **链接与目录**:飞书读书笔记父节点(链接)与子目录规则见下方「飞书读书笔记配置」;先分析该链接对应的 Wiki 节点与目录结构,再按**分类或单目录**落到对应子目录。 +- **分类与子目录对应**:与主导图分类一致——个人提升 / 人际关系 / 创业 / 商业思维 / 投资;发飞书时可按该分类建子目录(如 `读书笔记/创业/纳瓦尔访谈_读书笔记`),或统一放在 `读书笔记/` 单目录下。 +- **执行**:使用 `02_卡人(水)/水桥_平台对接/飞书管理/脚本/` 下的统一文章上传或 md→blocks 脚本,`--parent` 取飞书读书笔记父节点 token,标题与本地文件名一致,内容为笔记正文;若需按分类分子目录,则先确保飞书侧存在对应子节点再在该节点下创建文档。 + +### 飞书读书笔记配置(链接与子目录) + +| 项目 | 说明 | +|:---|:---| +| **飞书知识库链接** | 读书笔记要发到的**父节点**对应链接,格式:`https://cunkebao.feishu.cn/wiki/`。若尚未确定,请在飞书知识库中新建或选中「读书笔记」节点,复制浏览器地址栏 `wiki/` 后的 token,填入下方或环境变量 `FEISHU_READING_WIKI_PARENT`。 | +| **父节点 token** | 链接中 `wiki/` 后的一段,即发书时的 `--parent`。示例:`KNf7wA8Rki1NSdkkSIqcdFtTnWb`(日记/新研究);若读书笔记单独建了节点,用该节点 token。 | +| **子目录结构** | 可选:在父节点下建子目录「读书笔记」,再其下按分类建「个人提升」「创业」「商业思维」「投资」「人际关系」,与主导图分类一致;或父节点下直接为「读书笔记」单目录,所有笔记均发至此。 | + +**未配置时**:若暂无飞书链接,笔记仍只写本地 `2、我写的日记/读书笔记/`;配置好父节点后,写新笔记时再同时发飞书并落到对应子目录。 ## XMind 文件 diff --git a/运营中枢/参考资料/卡若读书笔记格式_固定规则.md b/运营中枢/参考资料/卡若读书笔记格式_固定规则.md index d5fb642d..825935f0 100644 --- a/运营中枢/参考资料/卡若读书笔记格式_固定规则.md +++ b/运营中枢/参考资料/卡若读书笔记格式_固定规则.md @@ -23,6 +23,7 @@ - **图片与流程图**:笔记内引用的图片、流程图建议与笔记**同目录**存放,用 `文件名.png` 或 `./文件名.png` 引用,避免用 `../../图片/` 等跨目录路径导致在不同预览/工作区下**不显示**。若用 Mermaid,可在同节内再插入一张导出好的流程图 PNG,保证不依赖渲染也能看到图。 - **图裂了怎么办**:若在 Cursor/VS Code 里图片不显示,可(1)用 Typora 打开该 md(以文件所在目录为基准);(2)在 Finder 中打开笔记所在文件夹,双击 md 用系统默认预览打开;(3)直接打开同目录下对应的 PNG 文件。建议在每张图下方加一句备用说明:「若图不显示,请打开本笔记所在文件夹中的 `xxx.png` 查看。」 - **记忆写入**:在 `个人/1、卡若:本人/记忆.md` 当日日期下追加 1~2 行摘要 + 本笔记文件路径;便于后续从记忆调出。 +- **飞书同步**:读书笔记写完后,**同时发到飞书知识库**指定链接下的**对应子目录**。链接即飞书知识库「读书笔记」所在节点的地址(`https://cunkebao.feishu.cn/wiki/`),子目录可与五行分类对应(个人提升/创业/商业思维/投资/人际关系)或统一为「读书笔记」单目录。父节点 token 与脚本用法见读书笔记 Skill「飞书同步」与「飞书读书笔记配置」。 --- diff --git a/运营中枢/工作台/2026-03-03_综合复盘_大目标与本月完成度.md b/运营中枢/工作台/2026-03-03_综合复盘_大目标与本月完成度.md new file mode 100644 index 00000000..01c24ca6 --- /dev/null +++ b/运营中枢/工作台/2026-03-03_综合复盘_大目标与本月完成度.md @@ -0,0 +1,50 @@ +# 2026-03-03 综合复盘:大目标与本月完成度 + +> 依据本机今日相关内容、2026 年整体目标、当前任务看板与昨日未完成项综合分析与思考,并更新完成比例。 + +--- + +**[卡若复盘](2026-03-03)** + +**🎯 目标·结果·达成率** +大目标(全年 100%)与本月小目标(约 12%)对齐;昨日未完成已叠加今日;完成比例已按本机内容更新。达成率按项区分见下。 + +**📌 过程** + +1. **本机今日与目标相关内容** + - 已读:`2026年整体目标.md`(总目标 100%、本月 % = 当前相对总目标完成度)、`当前任务看板.md`(T003 卡若AI 4 项优化、T004 一人公司 5%、T005 玩值电竞 25%)、`2026年2月_整体月复盘.md`(2 月主线 12%、一人公司/玩值电竞/今日核心延续)。 + - 今日相关:3 月飞书日志(3月3日)已写「昨日目标与总目标一致、本月 12% 距最终 88%」;视频 Skill(四屏切片)、20 条 Soul、20:00 朋友圈为当日执行项。 + +2. **大目标 vs 本月小事** + - **大目标**:全年终态 100%;当前相对总目标完成度 **约 12%**,距最终差 **88%**。 + - **本月小事**:一人公司 Agent 5%;玩值电竞 25%;卡若AI 4 项优化执行中;每日 20 条 Soul 视频 + 20:00 发 1 条朋友圈;视频 Skill 四屏切片完成 20 个/日;飞书日志每日迭代。大目标统摄本月小事,百分比均相对总目标。 + +3. **昨日未完成叠加今日** + - 昨日(3月2日)若未打满:**20 条 Soul 视频**、**20:00 发 1 条朋友圈**、**四屏切片 20 条**、**飞书日志** → 今日继续执行并计入当日完成度。 + - 看板未闭环项(T003/T004/T005)持续执行中,今日仍计入一人公司、玩值电竞、卡若AI 优化相关动作。 + +4. **完成比例更新(按本机与目标一致性)** + + - **相对总目标**:本月目标 **12%**,距最终 **88%**(维持,与 2026年整体目标 一致)。 + - **T004 一人公司**:**5%**(看板已载明,维持)。 + - **T005 玩值电竞**:**25%**(看板已载明,维持)。 + - **今日核心**:20 条 Soul + 1 条朋友圈 + 四屏切片 20 条 → 当日完成度建议在飞书 F(反馈) 中填「四屏切片 20 条→X%」(X = 当日完成数/20×100 或按实际条数折算)。 + - **飞书日志**:3月3日已写,迭代 100%。 + +**💡 反思** + +1. **大目标与本月**:总目标 100% 为锚点,本月 12% 与一人公司 5%、玩值电竞 25% 等均为相对总目标的进度,避免本月小事与全年脱节。 +2. **昨日未完成叠加**:每日 20 条视频、1 条朋友圈、四屏切片 20 条若昨日未满额,今日应叠加执行并在反馈中更新当日完成度,便于看趋势。 +3. **本机内容与目标**:工作台与看板、2026年整体目标、2 月整体月复盘、飞书 3 月日志形成「总目标→本月→每日」链条,复盘时先读整体目标再更新比例,保证一致性。 + +**📝 总结** + +综合本机今日相关文档与目标:大目标(100%)与本月(12%)、本月小事(一人公司 5%、玩值电竞 25%、今日核心 20 条+1 朋友圈+四屏切片 20 条)已对齐;昨日未完成项已叠加到今日计划;完成比例已按上述更新,飞书 3月3日 日志中可填「四屏切片 20 条→当日%」。 + +**▶ 下一步执行** + +今日执行:20 条 Soul 视频(四屏切片)、20:00 发 1 条朋友圈、视频 Skill 操作、飞书日志;晚些在飞书 3月3日 F(反馈) 补「四屏切片 20 条→X%」。明日写日志前先读《2026年整体目标》,昨日未完成继续叠加。看板 T003/T004/T005 按进度更新上下文摘要与完成度。 + +--- + +*依据:运营中枢/工作台(当前任务看板、2026年整体目标、2月整体月复盘)、飞书 3月3日 日志设计、昨日未完成叠加规则。* diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md index 1b268d74..02ec9c3d 100644 --- a/运营中枢/工作台/gitea_push_log.md +++ b/运营中枢/工作台/gitea_push_log.md @@ -212,3 +212,4 @@ | 2026-03-02 20:52:08 | 🔄 卡若AI 同步 2026-03-02 20:52 | 更新:金盾、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 | | 2026-03-03 04:51:53 | 🔄 卡若AI 同步 2026-03-03 04:51 | 更新:金盾、运营中枢工作台 | 排除 >20MB: 14 个 | | 2026-03-03 04:58:10 | 🔄 卡若AI 同步 2026-03-03 04:58 | 更新:Cursor规则、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 | +| 2026-03-03 05:02:46 | 🔄 卡若AI 同步 2026-03-03 05:02 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 14 个 | diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md index cc6e6c8f..d010c99e 100644 --- a/运营中枢/工作台/代码管理.md +++ b/运营中枢/工作台/代码管理.md @@ -215,3 +215,4 @@ | 2026-03-02 20:52:08 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-02 20:52 | 更新:金盾、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-03-03 04:51:53 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-03 04:51 | 更新:金盾、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-03-03 04:58:10 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-03 04:58 | 更新:Cursor规则、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | +| 2026-03-03 05:02:46 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-03 05:02 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |