🔄 卡若AI 同步 2026-03-06 13:24 | 更新:Cursor规则、水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个

This commit is contained in:
2026-03-06 13:24:00 +08:00
parent 8d392d7ba5
commit f0d0213d94
7 changed files with 211 additions and 34 deletions

View File

@@ -71,6 +71,9 @@ alwaysApply: true
### 工作台路径
- `/Users/karuo/Documents/个人/卡若AI/`
### MD 预览(全局)
- 所有 .md 的打开/预览一律用 **Markdown Preview Enhanced** 单界面方式;已在 Cursor User 设置中配置 `workbench.editorAssociations: "*.md": "markdown-preview-enhanced"`,科室及任何对话中打开 .md 均按此方式,不改用内置预览或双界面。
### 项目与端口注册表(有变更时必更)
- 凡**项目、端口、启动命令或部署流程**有更新/变更,须同步更新 **`运营中枢/工作台/项目与端口注册表.md`**(含注册项目列表与版本记录),使该 doc 始终保持最新。

View File

@@ -39,6 +39,12 @@ python3 /Users/karuo/Documents/个人/卡若AI/02_卡人/水桥_平台
- `python3 feishu_token_cli.py set-march-token <token>` → 将 3 月文档 node token 写入本地(`.feishu_month_wiki_tokens.json`),写日志时自动使用
- `python3 feishu_token_cli.py get-march-token` → 输出当前 3 月 wiki token环境变量 > 本地文件)
**Token 自动获取(无 token 时)**:写今日日志(如 `write_today_with_summary.py`)时,若未配置当月(如 3 月)文档 token脚本会**自动通过飞书 API** 用 2 月文档所在知识空间列出节点、匹配标题含「3月」的文档将 token 写入 `.feishu_month_wiki_tokens.json` 后继续写入,无需手动配置。若自动获取失败(如空间内无 3 月文档),再提示用命令行:`python3 feishu_token_cli.py set-march-token <从飞书地址栏复制的 token>`
**Token 出现问题时的处理**若出现「获取文档失败」或「token 无效」,一律用命令行处理:先 `get-access-token` 确保登录有效,再 `set-march-token <正确 token>` 写入当月文档 token写日志脚本会优先使用本地已保存的 token确保能写入飞书。
**今日日志 + 配图**`write_today_with_summary.py` 写入成功后会自动生成一张「今日进度」图(本月 12%、距目标 88% 等)并上传插入到当日飞书文档;若插入图片 API 报错,图片会保存在 `参考资料/今日进度_XX.png`,可手动拖入飞书文档。
**自动完成**
1.**静默Token刷新** → 优先使用 refresh_token 自动刷新(无需授权);也可命令行 `get-access-token`
2.**检查服务** → 自动启动后端服务

View File

@@ -240,6 +240,71 @@ def parse_month_from_date_str(date_str):
return None
MONTH_TOKENS_FILE = os.path.join(os.path.dirname(__file__), ".feishu_month_wiki_tokens.json")
def _try_auto_fetch_march_token(access_token):
"""无 3 月 token 时通过 API 自动获取:用 2 月文档所在 space 列出节点匹配标题含「3月」的节点并写入本地。返回 token 或 None。"""
feb_token = (CONFIG.get("MONTH_WIKI_TOKENS") or {}).get(2) or CONFIG.get("WIKI_TOKEN")
if not feb_token:
return None
headers = {"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"}
try:
r = requests.get(
"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node",
params={"token": feb_token},
headers=headers,
timeout=15,
)
j = r.json()
if j.get("code") != 0:
return None
data = j.get("data", {})
node = data.get("node", {})
space_id = node.get("space_id") or data.get("space_id")
if not space_id:
return None
# 列出空间下节点(可能需分页)
page_token = None
for _ in range(5):
params = {"page_size": 50}
if page_token:
params["page_token"] = page_token
r2 = requests.get(
f"https://open.feishu.cn/open-apis/wiki/v2/spaces/{space_id}/nodes",
params=params,
headers=headers,
timeout=15,
)
j2 = r2.json()
if j2.get("code") != 0:
break
items = j2.get("data", {}).get("items", [])
for n in items:
title = (n.get("title") or "")
if "3月" in title or "3 月" in title:
tok = n.get("node_token") or n.get("obj_token") or n.get("token")
if tok:
data = {}
if os.path.exists(MONTH_TOKENS_FILE):
try:
with open(MONTH_TOKENS_FILE, encoding="utf-8") as f:
data = json.load(f)
except Exception:
pass
data["3"] = tok
with open(MONTH_TOKENS_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print("✅ 已通过 API 自动获取 3 月文档 token 并写入本地")
return tok
page_token = j2.get("data", {}).get("page_token")
if not page_token or not j2.get("data", {}).get("has_more"):
break
except Exception as e:
print(f"⚠️ 自动获取 3 月 token 异常: {e}")
return None
def _get_month_wiki_token(month):
"""当月 wiki token3 月优先 环境变量 > 本地 .feishu_month_wiki_tokens.json > CONFIG"""
if month == 3:
@@ -247,9 +312,8 @@ def _get_month_wiki_token(month):
if v:
return v
try:
path = os.path.join(os.path.dirname(__file__), ".feishu_month_wiki_tokens.json")
if os.path.exists(path):
with open(path, encoding="utf-8") as f:
if os.path.exists(MONTH_TOKENS_FILE):
with open(MONTH_TOKENS_FILE, encoding="utf-8") as f:
v = (json.load(f).get("3") or "").strip()
if v:
return v
@@ -311,16 +375,36 @@ def write_log(token, date_str=None, tasks=None, wiki_token=None, overwrite=False
if not date_str or not tasks:
date_str, tasks = get_today_tasks()
target_wiki_token = resolve_wiki_token_for_date(date_str, wiki_token)
month = parse_month_from_date_str(date_str)
if not target_wiki_token:
month = parse_month_from_date_str(date_str)
print(f" 未配置当月文档 token{month or '?'} 月请设置 FEISHU_MARCH_WIKI_TOKEN 或对应环境变量)")
return False
if month == 3:
print("🔄 未配置 3 月 token,尝试通过 API 自动获取...")
target_wiki_token = _try_auto_fetch_march_token(token)
if not target_wiki_token:
print(f"❌ 未配置当月文档 token{month or '?'} 月请用 feishu_token_cli.py set-march-token <token> 或设置环境变量)")
return False
# 获取文档ID
# 获取文档ID(若为 3 月且 get_node 失败,可再尝试自动获取后重试一次)
r = requests.get(f"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={target_wiki_token}",
headers=headers, timeout=30)
if r.json().get('code') != 0 and month == 3:
target_wiki_token = _try_auto_fetch_march_token(token)
if target_wiki_token:
r = requests.get(f"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={target_wiki_token}",
headers=headers, timeout=30)
if r.json().get('code') != 0:
print(f"❌ 获取文档失败")
# 若本地曾保存过无效 token清除以便下次可重新自动获取或手动 set
try:
if os.path.exists(MONTH_TOKENS_FILE) and month == 3:
with open(MONTH_TOKENS_FILE, encoding="utf-8") as f:
data = json.load(f)
if (data.get("3") or "").strip() == (target_wiki_token or "").strip():
data["3"] = ""
with open(MONTH_TOKENS_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception:
pass
print(f"❌ 获取文档失败(当月 token 无效或网络异常,可用 feishu_token_cli.py set-march-token 写入正确 token")
return False
node = r.json()['data']['node']
doc_id = node['obj_token']

View File

@@ -1,8 +1,10 @@
#!/usr/bin/env python3
"""
今日飞书日志:搜索全库+聊天/纪要后的最近进度总结汇总 + 每天切片20个视频 + 成交1980及全链路 + 目标百分比写清楚。
无 3 月 token 时会自动通过 API 获取;写入成功后生成一张今日进度图并上传到飞书文档。
"""
import sys
import requests
from datetime import datetime
from pathlib import Path
@@ -11,6 +13,76 @@ sys.path.insert(0, str(SCRIPT_DIR))
from auto_log import get_token_silent, write_log, open_result, resolve_wiki_token_for_date
REF_DIR = SCRIPT_DIR.parent / "参考资料"
def _generate_progress_image(date_str: str) -> Path | None:
"""生成今日进度图(本月 12% 距目标 88%),返回图片路径;无 Pillow 则返回 None。"""
try:
from PIL import Image, ImageDraw, ImageFont
except ImportError:
return None
out = REF_DIR / f"今日进度_{date_str.replace('', '').replace('', '')}.png"
REF_DIR.mkdir(parents=True, exist_ok=True)
w, h = 480, 160
img = Image.new("RGB", (w, h), color=(255, 252, 240))
draw = ImageDraw.Draw(img)
try:
font = ImageFont.truetype("/System/Library/Fonts/PingFang.ttc", 28)
font_small = ImageFont.truetype("/System/Library/Fonts/PingFang.ttc", 20)
except Exception:
font = ImageFont.load_default()
font_small = font
draw.text((20, 30), f"今日进度 · {date_str}", fill=(60, 60, 60), font=font)
draw.text((20, 75), "本月 12% / 距目标 88%", fill=(180, 80, 60), font=font)
draw.text((20, 115), "20 切片 · 1980 全链路", fill=(80, 80, 80), font=font_small)
img.save(out)
return out
def _get_doc_id(token: str, wiki_token: str) -> str | None:
"""根据 wiki node token 获取文档 obj_token。"""
r = requests.get(
"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node",
params={"token": wiki_token},
headers={"Authorization": f"Bearer {token}"},
timeout=15,
)
if r.json().get("code") != 0:
return None
return r.json().get("data", {}).get("node", {}).get("obj_token")
def _upload_and_insert_image(token: str, doc_id: str, image_path: Path, date_str: str) -> bool:
"""上传图片到文档并插入到当日标题后。"""
from write_0301_feishu_log import upload_image_to_feishu, insert_image_block
file_token = upload_image_to_feishu(token, doc_id, image_path)
if not file_token:
return False
# 获取文档 blocks找到 date_str 所在位置,在其后插入
r = requests.get(
f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/blocks",
params={"document_revision_id": -1, "page_size": 500},
headers={"Authorization": f"Bearer {token}"},
timeout=15,
)
if r.json().get("code") != 0:
return False
items = r.json().get("data", {}).get("items", [])
root = [b for b in items if b.get("parent_id") == doc_id]
idx = None
for i, b in enumerate(root):
for key in ("heading4", "text"):
if key in b:
for el in b[key].get("elements", []):
if date_str in el.get("text_run", {}).get("content", ""):
idx = i
break
if idx is not None:
break
insert_at = (idx + 2) if idx is not None else 1
return insert_image_block(token, doc_id, file_token, image_path.name, insert_at)
def build_tasks_today_with_summary():
"""今日:最近进度汇总 + 每天20切片 + 1980成交及全链路 + 目标百分比"""
@@ -69,13 +141,24 @@ def main():
target_wiki_token = resolve_wiki_token_for_date(date_str)
ok = write_log(token, date_str, tasks, target_wiki_token, overwrite=True)
if ok:
target_wiki_token = resolve_wiki_token_for_date(date_str)
doc_id = _get_doc_id(token, target_wiki_token) if target_wiki_token else None
if doc_id:
img_path = _generate_progress_image(date_str)
if img_path and img_path.exists():
if _upload_and_insert_image(token, doc_id, img_path, date_str):
print("✅ 今日进度图已上传并插入飞书文档")
else:
print(f"⚠️ 图片已生成:{img_path},可手动拖入飞书文档")
else:
print("💡 未安装 Pillow 或生成失败,可手动添加配图")
open_result(target_wiki_token)
print(f"{date_str} 飞书日志已更新(含进度汇总与目标百分比)")
sys.exit(0)
print("❌ 写入失败")
ref_path = SCRIPT_DIR.parent / "参考资料" / f"{date_str}_飞书日志正文_三件事与未完成.md"
ref_path = SCRIPT_DIR.parent / "参考资料" / f"{date_str}_飞书日志_进度汇总与百分比.md"
if ref_path.exists():
print(f"💡 可复制 {ref_path} 内容到飞书当月文档手动粘贴")
print(f"💡 可复制 {ref_path} 内容到飞书 3 月文档「{date_str}」下粘贴")
sys.exit(1)

View File

@@ -1,6 +1,6 @@
# Cursor 文档预览配置说明
> 更新2026-03-06。**去掉本机原有 Markdown 预览****只用 Markdown Preview Enhanced 插件的预览模式与显示风格**;不搞错、不敷衍
> 更新2026-03-06。**点 .md 只出现一个界面**,且该界面为 **Markdown Preview Enhanced 插件的预览**(增强预览、非代码);不用本机原有预览、不出现两个面板
---
@@ -8,51 +8,50 @@
**Cursor User settings**`~/Library/Application Support/Cursor/User/settings.json`)中:
**去掉本机内置预览,不把 .md 关联到内置预览**
**.md 默认用插件的 Enhanced 预览打开,且只显示一个界面**
```json
"workbench.editorAssociations": {
"*.md": "default"
"*.md": "markdown-preview-enhanced"
}
```
效果:.md 不再用本机「Markdown 原来的那个」预览;点开 .md 先以源码编辑器打开
效果:点击 .md 后**直接只打开一个界面**,即 **Markdown Preview Enhanced 插件的预览**(增强页面),不是代码编辑页,也不是左右两个面板
**只用插件的预览模式,并自动打开插件预览(显示格式=插件风格)**
**不自动再开侧边预览,避免出现两个界面**
```json
"markdown-preview-enhanced.automaticallyShowPreviewOfMarkdownBeingEdited": true,
"markdown-preview-enhanced.openPreviewToTheSide": true
"markdown-preview-enhanced.automaticallyShowPreviewOfMarkdownBeingEdited": false
```
效果:打开 .md 后,**Markdown Preview Enhanced 插件**会自动在侧边打开预览,**你看到的预览界面和格式就是插件的Enhanced风格**,不是本机原有的那个预览
效果:不会在已有预览旁再自动打开一个侧边预览,保证**只显示一个**
---
## 预览时一律用插件(不用本机原有)
## 需要改源码时
- **显示的格式**:必须是 **Markdown Preview Enhanced 插件** 的预览样式,不是 Cursor 内置的 Markdown 预览。
- **如何打开插件预览**
- **⌘⇧V**:打开插件预览(主预览)
- **⌘K V**:在侧边打开插件预览(编辑+预览同屏)
- **命令面板**⇧⌘P→ 输入 `Markdown Preview Enhanced` → 选「Open Preview」或「Open Preview to the Side」。
- **不要点标签栏的「Preview」**:那个会打开本机原有预览,会搞混;只用上面快捷键或命令面板,确保是插件的预览。
当前点 .md 默认是**插件的 Enhanced 预览(单界面)**。若要编辑源码:
已在 `keybindings.json` 中解除本机预览的 ⌘⇧V / ⌘K V 绑定,并改为只打开 Markdown Preview Enhanced保证按快捷键时**一定是插件的预览模式与风格**
- **右键该 .md 标签** →「Reopen Editor With...」→ 选 **「Text Editor」**,即可切到源码编辑
---
## 相关设置(已有)
- `workbench.editorAssociations``"*.md": "default"` → 本机原有预览**已去掉**,不用于 .md
- `markdown-preview-enhanced.automaticallyShowPreviewOfMarkdownBeingEdited`: **true**打开 .md 后自动用**插件**在侧边出预览,**显示格式=插件风格**。
- 内置 `markdown.preview.*` 仅影响本机预览,**不影响插件**;当前配置下预览界面一律是插件的。
- `workbench.editorAssociations``"*.md": "markdown-preview-enhanced"` → 点 .md **只出一个界面**,且是**插件的增强预览**
- `markdown-preview-enhanced.automaticallyShowPreviewOfMarkdownBeingEdited`: **false**不再自动开侧边,**确定只显示一个**。
**上述配置保证:本机原有增强预览去掉,只用 Markdown Preview Enhanced 插件的预览模式与显示格式;不搞错。**
上述配置保证:**点一下只出现一个界面,是默认的插件 Enhanced 预览,不是代码页,没有两个。**
---
## 若仍出现本机预览或两个预览
## 最终确认:普通预览已关掉,只用 Enhanced PREVIEW
- 不要点击标签栏上的「Preview」否则会打开本机原有预览。
- 关掉多出来的本机预览标签,以后只用 **⌘⇧V** 或 **⌘K V**或命令面板「Markdown Preview Enhanced: Open Preview」确保看到的是**插件的**预览界面与风格
- **打开 .md**`workbench.editorAssociations: "*.md": "markdown-preview-enhanced"` → 一定是 **Enhanced** 的 Preview不是普通/内置预览。
- **快捷键**`keybindings.json` 已解除内置 `markdown.showPreview` / `markdown.showPreviewToSide`⌘⇧V、⌘K V 只触发 **markdown-preview-enhanced**,普通预览不会通过快捷键打开
- **不要点标签栏「Preview」**:该按钮会调出内置预览;只用 Enhanced 时通过点 .md已关联或命令面板「Markdown Preview Enhanced: Open Preview」即可。
- **自动侧边**`automaticallyShowPreviewOfMarkdownBeingEdited: false`,不会多出一个界面。
当前设置无误;打开 .md = 只出现 **Enhanced 的 Preview**,普通预览已关掉。
**若仍打开为内置预览**:在左侧资源管理器对任意 .md 文件**右键** → **Open With** → 选 **Markdown Preview Enhanced**可编辑的增强预览若弹出「Configure default editor for '*.md'」则选它,即可强制去掉内置、以后都用 Enhanced。

View File

@@ -244,3 +244,4 @@
| 2026-03-06 12:41:57 | 🔄 卡若AI 同步 2026-03-06 12:41 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-06 12:42:08 | 🔄 卡若AI 同步 2026-03-06 12:42 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-06 13:07:01 | 🔄 卡若AI 同步 2026-03-06 13:06 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-06 13:09:56 | 🔄 卡若AI 同步 2026-03-06 13:09 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 |

View File

@@ -247,3 +247,4 @@
| 2026-03-06 12:41:57 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-06 12:41 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-06 12:42:08 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-06 12:42 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-06 13:07:01 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-06 13:06 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-06 13:09:56 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-06 13:09 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |