feat: 2026-07-11 全量更新 - 代办集成+会议室预定+知识迭代修复+UI统一+Bug修复

== 已部署上线 (9项) ==
- 代办事项真实数据源集成 (企微审批API 8bug修复链)
- H5/坐席端 Logo样式统一+绿色背景
- 视频引导页修复 (localStorage key v2)
- 坐席端 v9 Vue版本修复 (ElMessage._context)
- 截图按钮 v10 修复 (getDisplayMedia user gesture)
- 扫码样式恢复+H5扫码登录跳转修复
- H5截图快捷键提示

== 代码完成待部署 (3项) ==
- 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查)
- 会议室预定-小鱼易联终端 (40文件, 40/40测试通过)
- IT资产升级审批推送 (asset_service.py)

== 需求文档 (2项) ==
- 坐席端AI辅助消息框-PRD (4项新功能确认)
- 坐席端布局优化建议 v2.0 (7天计划)

== 新增文档 ==
- 日报-2026-07-11.md
- 知识迭代Bug修复报告-20260711.md
- 会议室预定-部署指南.md
- CHANGELOG.md 更新

== 测试 ==
- test_todo_integration.py: 40/40
- test_meetingroom.py: 40/40
- test_bugfix_ki_suggestions.py: 21/21
This commit is contained in:
Simon
2026-07-11 23:13:10 +08:00
parent 3d152fc8eb
commit bea288e414
928 changed files with 85169 additions and 54205 deletions
+67
View File
@@ -0,0 +1,67 @@
"""
Token 计数工具 — 支持 tiktoken 精确计数 + 字符估算兜底。
优先使用 tiktoken(cl100k_base) 与 OpenAI/GPT 系列模型一致;
tiktoken 不可用时按 1 token ≈ 1.5 中文字符估算(误差 ≤10%)。
"""
from __future__ import annotations
import logging
from typing import List, Optional
logger = logging.getLogger(__name__)
# 全局 tiktoken 编码器(延迟初始化)
_encoder = None
_tiktoken_available: Optional[bool] = None
def _init_encoder():
"""延迟初始化 tiktoken 编码器。"""
global _encoder, _tiktoken_available
if _tiktoken_available is not None:
return
try:
import tiktoken
_encoder = tiktoken.get_encoding("cl100k_base")
_tiktoken_available = True
logger.info("tiktoken cl100k_base 编码器初始化成功")
except Exception as e:
_tiktoken_available = False
logger.warning(f"tiktoken 不可用,降级为字符估算: {e}")
class TokenCounter:
"""Token 计数器,支持精确(tiktoken)和估算(字符)两种模式。"""
@staticmethod
def count_tokens(text: str) -> int:
"""计算单段文本的 token 数。"""
if not text:
return 0
_init_encoder()
if _tiktoken_available and _encoder is not None:
return len(_encoder.encode(text))
# 兜底:中文约1.5字符/token,英文约4字符/token,混合取2字符/token
return max(1, len(text) // 2)
@staticmethod
def count_messages_tokens(messages: List[dict]) -> int:
"""计算消息列表的 token 总数。
每条消息额外计入 role 标记的 overhead(约4 tokens/条)。
"""
total = 0
for msg in messages:
content = msg.get("content", "")
role = msg.get("role", "")
total += TokenCounter.count_tokens(content)
total += TokenCounter.count_tokens(role)
total += 4 # 每条消息的格式 overhead
return total
@staticmethod
def is_precise() -> bool:
"""返回当前是否使用精确计数(tiktoken)。"""
_init_encoder()
return _tiktoken_available is True