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
+186
View File
@@ -0,0 +1,186 @@
# =============================================================================
# 企微IT智能服务台 — 业务联系人模型
# =============================================================================
# 说明:对应数据库 business_contacts 表,存储非IT业务部门联系人信息
# 当员工提出的问题不属于IT服务台服务范围时,系统通过 Dify 意图识别
# 判定业务类别,从本表查询对应联系人,推送名片卡片到聊天中。
# 员工点击「联系TA」可跳转企微单聊(openEnterpriseChat)。
#
# 业务类别(business_category)取值:
# 行政 / 人力资源 / 财务 / 法务 / 行政-物业
# =============================================================================
from datetime import datetime
from sqlalchemy import Boolean, DateTime, Index, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class BusinessContact(Base):
"""业务联系人模型 — 对应 business_contacts 表。
存储非IT业务部门联系人信息,用于路由推荐功能。
当 Dify 判定消息为非IT业务路由时,按 business_category 查询本表,
取第一条 is_active=True 的联系人,推送名片卡片。
Attributes:
id: 主键,自增
name: 联系人姓名
gender: 性别(male/female
department: 部门名称(如「行政部」)
position: 岗位(如「设备管理岗」)
responsibility: 负责业务描述(如「打印机/复印机/扫描仪」)
extension: 分机号
service_area: 服务区域/办公地点
wecom_userid: 企微用户ID(用于 openEnterpriseChat 调用)
avatar_url: 头像URL(为空时用姓名首字渲染)
business_category: 业务类别(行政/人力资源/财务/法务/行政-物业)
is_active: 是否启用
created_at: 创建时间
updated_at: 更新时间
"""
__tablename__ = "business_contacts"
# 主键:自增整数
id: Mapped[int] = mapped_column(
Integer,
primary_key=True,
autoincrement=True,
comment="主键",
)
# 联系人姓名
name: Mapped[str] = mapped_column(
String(50),
nullable=False,
comment="联系人姓名",
)
# 性别(male/female
gender: Mapped[str] = mapped_column(
String(10),
nullable=False,
default="male",
comment="性别(male/female",
)
# 部门名称
department: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="部门名称",
)
# 岗位
position: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="岗位",
)
# 负责业务描述
responsibility: Mapped[str] = mapped_column(
String(500),
nullable=False,
comment="负责业务描述",
)
# 分机号
extension: Mapped[str | None] = mapped_column(
String(20),
nullable=True,
default=None,
comment="分机号",
)
# 服务区域/办公地点
service_area: Mapped[str | None] = mapped_column(
String(200),
nullable=True,
default=None,
comment="服务区域/办公地点",
)
# 企微用户ID(用于 wx.invoke('openEnterpriseChat', {userids: '...'}) 调用)
wecom_userid: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="企微用户ID",
)
# 头像URL(为空时前端用姓名首字渐变色块渲染)
avatar_url: Mapped[str | None] = mapped_column(
String(500),
nullable=True,
default=None,
comment="头像URL(为空用姓名首字渲染)",
)
# 业务类别(与 Dify 输出的 business_category 对应)
# 取值:行政 / 人力资源 / 财务 / 法务 / 行政-物业
business_category: Mapped[str] = mapped_column(
String(50),
nullable=False,
comment="业务类别(行政/人力资源/财务/法务/行政-物业)",
)
# 是否启用
is_active: Mapped[bool] = mapped_column(
Boolean,
nullable=False,
default=True,
comment="是否启用",
)
# 创建时间
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
comment="创建时间",
)
# 更新时间
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
onupdate=datetime.now,
comment="更新时间",
)
# 索引定义
__table_args__ = (
# 按业务类别 + 是否启用查询(路由推荐时使用)
Index("idx_business_contacts_category", "business_category", "is_active"),
)
def to_dict(self) -> dict:
"""将联系人信息转为字典(用于 extra_data 透传给前端)。
Returns:
dict: 联系人完整信息
"""
return {
"id": self.id,
"name": self.name,
"gender": self.gender,
"department": self.department,
"position": self.position,
"responsibility": self.responsibility,
"extension": self.extension or "",
"service_area": self.service_area or "",
"wecom_userid": self.wecom_userid,
"avatar_url": self.avatar_url or "",
"business_category": self.business_category,
}
def __repr__(self) -> str:
"""联系人对象的字符串表示,方便调试。"""
return (
f"<BusinessContact(id={self.id}, name={self.name}, "
f"category={self.business_category})>"
)