feat: 更新 created_by_message_id 逻辑,仅在内容或状态变化时进行更新
This commit is contained in:
parent
bf1549b88b
commit
26cbe7aa2d
108
convert_pdf.py
108
convert_pdf.py
@ -1,108 +0,0 @@
|
||||
import fitz
|
||||
from docx import Document
|
||||
from docx.shared import Pt, Cm, RGBColor
|
||||
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
|
||||
|
||||
pdf_path = r'C:\Users\qwer\.picobot\media\ws\aa56c052-ea10-4bc1-aed4-7d06770b6fd9_夜读 _ 明白了这4点,就不难养出有主体性的孩子.pdf'
|
||||
output_path = r'C:\Users\qwer\.picobot\media\夜读_明白了这4点_就不难养出有主体性的孩子.docx'
|
||||
|
||||
pdf_doc = fitz.open(pdf_path)
|
||||
doc = Document()
|
||||
|
||||
# 页面边距
|
||||
for section in doc.sections:
|
||||
section.top_margin = Cm(2.54)
|
||||
section.bottom_margin = Cm(2.54)
|
||||
section.left_margin = Cm(3.18)
|
||||
section.right_margin = Cm(3.18)
|
||||
|
||||
# 正文样式
|
||||
style = doc.styles['Normal']
|
||||
style.font.name = '宋体'
|
||||
style.font.size = Pt(12)
|
||||
style.paragraph_format.line_spacing = 1.5
|
||||
style.paragraph_format.first_line_indent = Pt(24)
|
||||
|
||||
def add_run(paragraph, text, bold=False, size=None, color=None, italic=False, font_name=None):
|
||||
run = paragraph.add_run(text)
|
||||
run.bold = bold
|
||||
if size: run.font.size = Pt(size)
|
||||
if color: run.font.color.rgb = RGBColor(*color)
|
||||
run.italic = italic
|
||||
if font_name: run.font.name = font_name
|
||||
return run
|
||||
|
||||
# 收集所有文本
|
||||
full_text = []
|
||||
for i, page in enumerate(pdf_doc):
|
||||
text = page.get_text().strip()
|
||||
if text:
|
||||
full_text.append(text)
|
||||
|
||||
all_text = '\n'.join(full_text)
|
||||
lines = [l.strip() for l in all_text.split('\n') if l.strip()]
|
||||
|
||||
# 定义段落标记
|
||||
sections_headers = ['塑教育,提倡积极养育', '懂互动,给予丰盈幸福',
|
||||
'有边界,养出人生底气', '稳情绪,才能赢得孩子']
|
||||
skip_lines = ['南方都市报电商官方账号。', '南都甄选', '公众号']
|
||||
|
||||
first = True
|
||||
for line in lines:
|
||||
# 跳过广告行
|
||||
if line in skip_lines:
|
||||
continue
|
||||
|
||||
# 主标题
|
||||
if first:
|
||||
p = doc.add_paragraph()
|
||||
p.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||||
p.paragraph_format.first_line_indent = Pt(0)
|
||||
p.paragraph_format.space_after = Pt(12)
|
||||
add_run(p, line, bold=True, size=22, font_name='黑体')
|
||||
first = False
|
||||
|
||||
# 引用句(引号开头结尾、较短)
|
||||
elif (line.startswith('"') and line.endswith('"')) or \
|
||||
(line.startswith('"') and line.endswith('"') and len(line) < 60):
|
||||
p = doc.add_paragraph()
|
||||
p.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||||
p.paragraph_format.first_line_indent = Pt(0)
|
||||
p.paragraph_format.space_before = Pt(6)
|
||||
p.paragraph_format.space_after = Pt(6)
|
||||
add_run(p, line, italic=True, size=12, color=(102, 102, 102))
|
||||
|
||||
# 日期来源
|
||||
elif line in ['2026年6月14日 22:28 广东', '南方都市报']:
|
||||
p = doc.add_paragraph()
|
||||
p.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
||||
p.paragraph_format.first_line_indent = Pt(0)
|
||||
add_run(p, line, size=10.5, color=(128, 128, 128))
|
||||
|
||||
# 4个小标题
|
||||
elif line in sections_headers:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.first_line_indent = Pt(0)
|
||||
p.paragraph_format.space_before = Pt(18)
|
||||
p.paragraph_format.space_after = Pt(6)
|
||||
add_run(p, line, bold=True, size=15, font_name='黑体')
|
||||
|
||||
# 作者信息
|
||||
elif any(line.startswith(x) for x in ['作者:', '统筹:', '图片:', '投稿邮箱:']):
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.first_line_indent = Pt(0)
|
||||
add_run(p, line, size=10.5, color=(128, 128, 128))
|
||||
|
||||
# 末尾信息
|
||||
elif '转载自' in line or '把世界当成' in line:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.first_line_indent = Pt(0)
|
||||
p.paragraph_format.space_before = Pt(6)
|
||||
add_run(p, line, size=10.5, color=(102, 102, 102))
|
||||
|
||||
else:
|
||||
doc.add_paragraph(line)
|
||||
|
||||
pdf_doc.close()
|
||||
doc.save(output_path)
|
||||
print('转换完成!')
|
||||
@ -186,21 +186,44 @@ impl BusToolCallEmitter {
|
||||
.unwrap_or_default()
|
||||
.as_secs() as i64;
|
||||
|
||||
// 读取现有 DB 记录,独立对比决定 created_by_message_id 是否更新
|
||||
let existing = self.store.list_todos(&scope_key).unwrap_or_default();
|
||||
let existing_map: std::collections::HashMap<&str, &crate::storage::TodoRecord> =
|
||||
existing.iter().map(|r| (r.id.as_str(), r)).collect();
|
||||
|
||||
let records: Vec<crate::storage::TodoRecord> = todos_array
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(idx, item)| {
|
||||
let id = item.get("id")?.as_str()?;
|
||||
let content = item.get("content")?.as_str()?;
|
||||
let status = item.get("status")?.as_str()?;
|
||||
|
||||
// 仅 content 或 status 实际变化时更新 created_by_message_id
|
||||
let changed = match existing_map.get(id) {
|
||||
Some(old) => old.content != content || old.status != status,
|
||||
None => true, // 新项
|
||||
};
|
||||
|
||||
let msg_id = if changed {
|
||||
message.tool_call_id.clone()
|
||||
} else {
|
||||
existing_map
|
||||
.get(id)
|
||||
.and_then(|r| r.created_by_message_id.clone())
|
||||
};
|
||||
|
||||
Some(crate::storage::TodoRecord {
|
||||
id: item.get("id")?.as_str()?.to_string(),
|
||||
id: id.to_string(),
|
||||
scope_key: scope_key.clone(),
|
||||
session_id: session_id.clone(),
|
||||
topic_id: topic_id.clone(),
|
||||
content: item.get("content")?.as_str()?.to_string(),
|
||||
status: item.get("status")?.as_str()?.to_string(),
|
||||
content: content.to_string(),
|
||||
status: status.to_string(),
|
||||
priority: "medium".to_string(),
|
||||
created_at: now + idx as i64,
|
||||
updated_at: now,
|
||||
created_by_message_id: message.tool_call_id.clone(),
|
||||
created_by_message_id: msg_id,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -221,21 +221,44 @@ impl SubAgentEmitter {
|
||||
.unwrap_or_default()
|
||||
.as_secs() as i64;
|
||||
|
||||
// 读取现有 DB 记录,独立对比决定 created_by_message_id 是否更新
|
||||
let existing = self.store.list_todos(scope_key).unwrap_or_default();
|
||||
let existing_map: std::collections::HashMap<&str, &crate::storage::TodoRecord> =
|
||||
existing.iter().map(|r| (r.id.as_str(), r)).collect();
|
||||
|
||||
let records: Vec<crate::storage::TodoRecord> = todos_array
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(idx, item)| {
|
||||
let id = item.get("id")?.as_str()?;
|
||||
let content = item.get("content")?.as_str()?;
|
||||
let status = item.get("status")?.as_str()?;
|
||||
|
||||
// 仅 content 或 status 实际变化时更新 created_by_message_id
|
||||
let changed = match existing_map.get(id) {
|
||||
Some(old) => old.content != content || old.status != status,
|
||||
None => true, // 新项
|
||||
};
|
||||
|
||||
let msg_id = if changed {
|
||||
message.tool_call_id.clone()
|
||||
} else {
|
||||
existing_map
|
||||
.get(id)
|
||||
.and_then(|r| r.created_by_message_id.clone())
|
||||
};
|
||||
|
||||
Some(crate::storage::TodoRecord {
|
||||
id: item.get("id")?.as_str()?.to_string(),
|
||||
id: id.to_string(),
|
||||
scope_key: scope_key.clone(),
|
||||
session_id: scope_key.clone(),
|
||||
topic_id: None,
|
||||
content: item.get("content")?.as_str()?.to_string(),
|
||||
status: item.get("status")?.as_str()?.to_string(),
|
||||
content: content.to_string(),
|
||||
status: status.to_string(),
|
||||
priority: "medium".to_string(),
|
||||
created_at: now + idx as i64,
|
||||
updated_at: now,
|
||||
created_by_message_id: message.tool_call_id.clone(),
|
||||
created_by_message_id: msg_id,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -144,8 +144,8 @@ impl Tool for TodoWriteTool {
|
||||
None => return Ok(error_result("todo_write requires session_id or topic_id in tool context")),
|
||||
};
|
||||
|
||||
// 2. 提取当前消息 ID(用于记录待办的创建来源)
|
||||
let message_id = context.message_id.clone();
|
||||
// 2. 提取当前 tool call ID(用于定位修改该项的 tool 消息,前端用 tool_call_id 作为 data-message-id)
|
||||
let message_id = context.tool_call_id.clone();
|
||||
|
||||
// 3. 解析入参
|
||||
let todos_array = match args.get("todos").and_then(|v| v.as_array()) {
|
||||
@ -219,11 +219,18 @@ impl Tool for TodoWriteTool {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 仅在 content 或 status 实际变化时更新 created_by_message_id
|
||||
let changed = old_item.content != content
|
||||
|| old_item.status.as_str() != new_status.as_str();
|
||||
processed_items.push(TodoItem {
|
||||
id,
|
||||
content,
|
||||
status: new_status.as_str().to_string(),
|
||||
created_by_message_id: message_id.clone(),
|
||||
created_by_message_id: if changed {
|
||||
message_id.clone()
|
||||
} else {
|
||||
old_item.created_by_message_id.clone()
|
||||
},
|
||||
});
|
||||
} else if merge_mode {
|
||||
// merge 模式:id 不匹配,尝试 content fallback
|
||||
@ -239,11 +246,17 @@ impl Tool for TodoWriteTool {
|
||||
validation_errors.push(format!("Item '{}': {}", content, err));
|
||||
continue;
|
||||
}
|
||||
// content 匹配上说明 content 不变,仅需比较 status
|
||||
let changed = old_item.status.as_str() != new_status.as_str();
|
||||
processed_items.push(TodoItem {
|
||||
id: old_item.id.clone(),
|
||||
content,
|
||||
status: new_status.as_str().to_string(),
|
||||
created_by_message_id: message_id.clone(),
|
||||
created_by_message_id: if changed {
|
||||
message_id.clone()
|
||||
} else {
|
||||
old_item.created_by_message_id.clone()
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// 全新项
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user