🔄 卡若AI 同步 2026-02-27 05:21 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 14 个
This commit is contained in:
@@ -48,6 +48,7 @@ python3 "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台
|
||||
2. 写入前校验标题月份;不匹配拒绝写入。
|
||||
3. 写入后打开对应月份文档。
|
||||
4. 默认登记内容包含:目标进度、卡点、下一步、运营登记说明。
|
||||
5. **TNTWF 格式**:仅 **W(工作)** 和 **F(反馈)** 有复选框;T(目标)、N(过程)、T(思考) 为纯文本,无勾选框。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -93,7 +93,15 @@ python3 "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台
|
||||
|
||||
---
|
||||
|
||||
## 7. 推荐填写模板
|
||||
## 7. TNTWF 格式与复选框规则
|
||||
|
||||
- **T(目标)、N(过程)、T(思考)**:纯文本,无复选框。
|
||||
- **W(工作)、F(反馈)**:任务列表,带复选框,可勾选完成。
|
||||
- 覆盖已有日志:`write_today_0227.py --overwrite` 或脚本支持 `--overwrite` 时使用。
|
||||
|
||||
---
|
||||
|
||||
## 8. 推荐填写模板
|
||||
|
||||
- 今日主题:卡若AI / 接口 / 网站 / 运营报表
|
||||
- 完成度:例如 `55%`
|
||||
@@ -103,7 +111,7 @@ python3 "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台
|
||||
|
||||
---
|
||||
|
||||
## 8. 故障排查
|
||||
## 9. 故障排查
|
||||
|
||||
- 提示 Token 失败:先重新执行一次,触发静默刷新
|
||||
- 写入失败(字段校验):缩短单条文本长度后重试
|
||||
@@ -111,7 +119,7 @@ python3 "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台
|
||||
|
||||
---
|
||||
|
||||
## 9. 关联文件
|
||||
## 10. 关联文件
|
||||
|
||||
- 子技能:`02_卡人(水)/水桥_平台对接/飞书管理/卡若的飞书日志_SKILL.md`
|
||||
- 主技能:`02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md`
|
||||
|
||||
@@ -204,21 +204,23 @@ def build_blocks(date_str, tasks):
|
||||
'style': {'done': False, 'align': 1}}})
|
||||
blocks.append({'block_type': 2, 'text': {'elements': [{'text_run': {'content': '{'}}], 'style': {}}})
|
||||
|
||||
# TNTWF格式,标注清楚
|
||||
# TNTWF格式:仅 W(工作) F(反馈) 有复选框,T/N/T 为纯文本
|
||||
labels = [
|
||||
('T', 't_targets', '目标'),
|
||||
('N', 'n_process', '过程'),
|
||||
('T', 't_thoughts', '思考'),
|
||||
('W', 'w_work', '工作'),
|
||||
('F', 'f_feedback', '反馈')
|
||||
('T', 't_targets', '目标', False),
|
||||
('N', 'n_process', '过程', False),
|
||||
('T', 't_thoughts', '思考', False),
|
||||
('W', 'w_work', '工作', True),
|
||||
('F', 'f_feedback', '反馈', True)
|
||||
]
|
||||
|
||||
for label, key, name in labels:
|
||||
for label, key, name, use_todo in labels:
|
||||
items = task.get(key, [])
|
||||
if items:
|
||||
blocks.append({'block_type': 2, 'text': {'elements': [{'text_run': {'content': f'{label} ({name})', 'text_element_style': {'bold': True}}}], 'style': {}}})
|
||||
for item in items:
|
||||
blocks.append({'block_type': 17, 'todo': {'elements': [{'text_run': {'content': item}}], 'style': {'done': False}}})
|
||||
if use_todo:
|
||||
blocks.append({'block_type': 17, 'todo': {'elements': [{'text_run': {'content': item}}], 'style': {'done': False}}})
|
||||
else:
|
||||
blocks.append({'block_type': 2, 'text': {'elements': [{'text_run': {'content': item}}], 'style': {}}})
|
||||
|
||||
blocks.append({'block_type': 2, 'text': {'elements': [{'text_run': {'content': '}'}}], 'style': {}}})
|
||||
blocks.append({'block_type': 2, 'text': {'elements': [{'text_run': {'content': ''}}], 'style': {}}})
|
||||
@@ -246,8 +248,39 @@ def resolve_wiki_token_for_date(date_str, explicit_wiki_token=None):
|
||||
return CONFIG['MONTH_WIKI_TOKENS'][month]
|
||||
return CONFIG['WIKI_TOKEN']
|
||||
|
||||
def write_log(token, date_str=None, tasks=None, wiki_token=None):
|
||||
"""写入日志(倒序插入:新日期在最上面)"""
|
||||
def _find_date_section_block_ids(blocks, date_str, doc_id):
|
||||
"""找到某日期区块的 block_id 列表(用于覆盖删除)"""
|
||||
date_re = re.compile(r'\d+\s*月\s*\d+\s*日')
|
||||
start_i = None
|
||||
for i, block in enumerate(blocks):
|
||||
for key in ['heading4', 'text']:
|
||||
if key in block:
|
||||
for el in block[key].get('elements', []):
|
||||
c = el.get('text_run', {}).get('content', '')
|
||||
if date_str in c:
|
||||
start_i = i
|
||||
break
|
||||
if start_i is not None:
|
||||
break
|
||||
if start_i is None:
|
||||
return []
|
||||
# 从 start_i 向后收集,直到遇到下一个日期标题
|
||||
ids = []
|
||||
for i in range(start_i, len(blocks)):
|
||||
b = blocks[i]
|
||||
bid = b.get('block_id')
|
||||
if not bid:
|
||||
continue
|
||||
# 若遇下一个日期 heading4,停止
|
||||
if i > start_i and 'heading4' in b:
|
||||
for el in b.get('heading4', {}).get('elements', []):
|
||||
if date_re.search(el.get('text_run', {}).get('content', '')):
|
||||
return ids
|
||||
ids.append(bid)
|
||||
return ids
|
||||
|
||||
def write_log(token, date_str=None, tasks=None, wiki_token=None, overwrite=False):
|
||||
"""写入日志(倒序插入:新日期在最上面);overwrite=True 时先删后写"""
|
||||
headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}
|
||||
|
||||
if not date_str or not tasks:
|
||||
@@ -264,27 +297,58 @@ def write_log(token, date_str=None, tasks=None, wiki_token=None):
|
||||
doc_id = node['obj_token']
|
||||
doc_title = node.get('title', '')
|
||||
|
||||
# 防串月:日期月份与文档标题不一致时拒绝写入
|
||||
# 防串月
|
||||
month = parse_month_from_date_str(date_str)
|
||||
if month and f"{month}月" not in doc_title:
|
||||
print(f"❌ 月份校验失败:{date_str} 不应写入《{doc_title}》")
|
||||
return False
|
||||
|
||||
# 获取blocks检查日期是否存在
|
||||
r = requests.get(f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/blocks",
|
||||
headers=headers, params={'page_size': 500}, timeout=30)
|
||||
blocks = r.json().get('data', {}).get('items', [])
|
||||
headers=headers, params={'document_revision_id': -1, 'page_size': 500}, timeout=30)
|
||||
blk_data = r.json().get('data', {})
|
||||
blocks = blk_data.get('items', [])
|
||||
|
||||
# 检查是否已存在
|
||||
exists = False
|
||||
for block in blocks:
|
||||
for key in ['heading4', 'text']:
|
||||
if key in block:
|
||||
for el in block[key].get('elements', []):
|
||||
if 'text_run' in el and date_str in el['text_run'].get('content', ''):
|
||||
print(f"✅ {date_str} 日志已存在,无需重复写入")
|
||||
return True
|
||||
exists = True
|
||||
break
|
||||
if exists:
|
||||
break
|
||||
|
||||
# 找插入位置(倒序:插入到"本月最重要的任务"标题后,即第一个位置)
|
||||
if exists and overwrite:
|
||||
to_del = _find_date_section_block_ids(blocks, date_str, doc_id)
|
||||
if to_del:
|
||||
try:
|
||||
for i in range(0, len(to_del), 20):
|
||||
batch = to_del[i:i+20]
|
||||
body = {"requests": [{"block_id": bid} for bid in batch]}
|
||||
rd = requests.post(f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/blocks/batch_delete",
|
||||
headers=headers, json=body, timeout=30)
|
||||
try:
|
||||
j = rd.json()
|
||||
except Exception:
|
||||
j = {}
|
||||
if j.get('code') != 0:
|
||||
print(f"⚠️ 覆盖删除失败: {j.get('msg', rd.text[:80])},请手动删飞书中 {date_str} 后重试")
|
||||
break
|
||||
else:
|
||||
r = requests.get(f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/blocks",
|
||||
headers=headers, params={'document_revision_id': -1, 'page_size': 500}, timeout=30)
|
||||
blocks = r.json().get('data', {}).get('items', [])
|
||||
exists = False
|
||||
except Exception as e:
|
||||
print(f"⚠️ 覆盖删除异常: {e},请手动删飞书中 {date_str} 后重试")
|
||||
|
||||
if exists:
|
||||
print(f"✅ {date_str} 日志已存在,无需重复写入(可用 --overwrite 覆盖)")
|
||||
return True
|
||||
|
||||
# 找插入位置(倒序:插入到"本月最重要的任务"标题后)
|
||||
insert_index = 1
|
||||
for i, block in enumerate(blocks):
|
||||
if block.get('parent_id') == doc_id and 'heading2' in block:
|
||||
|
||||
@@ -24,19 +24,19 @@ def build_tasks_0227():
|
||||
"events": ["一人公司Agent", "玩值电竞", "重要未完成项", "飞书日志迭代"],
|
||||
"quadrant": "重要紧急",
|
||||
"t_targets": [
|
||||
"一人公司Agent→视频切片/文章/直播/小程序/朋友圈/聚合 (5%)",
|
||||
"玩值电竞→Docker部署与功能推进 (第二) (25%)",
|
||||
"一人公司Agent→视频切片/文章/直播/小程序/朋友圈/聚合 (5%) 【自2月17日迭代】",
|
||||
"玩值电竞→Docker部署与功能推进 (第二) (25%) 【自2月17日迭代】",
|
||||
"卡若AI 4项优化→减重+收口+规则+输出+护栏 (执行中)",
|
||||
"飞书日志→每日迭代+进度百分比更新 (100%)",
|
||||
],
|
||||
"n_process": [
|
||||
"【一人公司】视频切片分发、文章全网、每日直播、小程序、朋友圈→聚合平台",
|
||||
"【玩值电竞】Docker 3001,MongoDB wanzhi_esports,持续迭代",
|
||||
"【重要未完成】卡若AI优化、书小程序、玉宁直播等持续迭代",
|
||||
"【重要未完成】卡若AI优化、书小程序、玉宁直播等 自2月17日持续迭代",
|
||||
"【昨日2月26】卡若AI 56%、一场创业实验→永平、GitHub yongpxu-soul",
|
||||
],
|
||||
"t_thoughts": [
|
||||
"一人公司第一、玩值电竞第二;重要未完成项加入今日迭代",
|
||||
"一人公司第一、玩值电竞第二;未完成进度自2月17日迭代至今日",
|
||||
],
|
||||
"w_work": ["一人公司Agent", "玩值电竞", "卡若AI优化", "飞书日志登记"],
|
||||
"f_feedback": [
|
||||
@@ -50,9 +50,14 @@ def build_tasks_0227():
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--overwrite", action="store_true", help="覆盖已有当日日志")
|
||||
args = parser.parse_args()
|
||||
|
||||
date_str = "2月27日"
|
||||
print("=" * 50)
|
||||
print(f"📝 写入飞书日志:{date_str}")
|
||||
print(f"📝 写入飞书日志:{date_str}" + (" [覆盖]" if args.overwrite else ""))
|
||||
print("=" * 50)
|
||||
|
||||
token = get_token_silent()
|
||||
@@ -62,7 +67,7 @@ def main():
|
||||
|
||||
tasks = build_tasks_0227()
|
||||
target_wiki_token = resolve_wiki_token_for_date(date_str)
|
||||
ok = write_log(token, date_str, tasks, target_wiki_token)
|
||||
ok = write_log(token, date_str, tasks, target_wiki_token, overwrite=args.overwrite)
|
||||
if ok:
|
||||
open_result(target_wiki_token)
|
||||
print(f"✅ {date_str} 日志写入成功")
|
||||
|
||||
@@ -165,3 +165,4 @@
|
||||
| 2026-02-26 00:31:13 | 🔄 卡若AI 同步 2026-02-26 00:31 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 14 个 |
|
||||
| 2026-02-26 00:43:29 | 🔄 卡若AI 同步 2026-02-26 00:43 | 更新:运营中枢工作台 | 排除 >20MB: 14 个 |
|
||||
| 2026-02-26 16:43:05 | 🔄 卡若AI 同步 2026-02-26 16:41 | 更新:金仓、水桥平台对接、卡木、运营中枢工作台 | 排除 >20MB: 14 个 |
|
||||
| 2026-02-27 05:06:58 | 🔄 卡若AI 同步 2026-02-27 05:06 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 14 个 |
|
||||
|
||||
@@ -168,3 +168,4 @@
|
||||
| 2026-02-26 00:31:13 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-26 00:31 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-26 00:43:29 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-26 00:43 | 更新:运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-26 16:43:05 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-26 16:41 | 更新:金仓、水桥平台对接、卡木、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-27 05:06:58 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-27 05:06 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
|
||||
Reference in New Issue
Block a user