技术方案 · v1.0

写字楼租赁家具资产管理系统 · 企业微信对接

把「AI 拍照盘点 / 全屋扫拍比对 / 巡检 / 退租验收」的现场作业搬进企业微信工作台,让物业管家不带电脑也能干活;把待办、审批、告警推到人手上,不再靠电话和微信群催。

适配:家具资产库 v2(32 张表) 对接范围:免登 · 通讯录 · 消息待办 · 审批流 · H5 工作台 文档日期:2026-10-16

0方案总览

四条链路,共用一套鉴权与事件底座。先看全局结构,再逐条拆。

企业微信开放平台 OAuth 网页授权 JS-SDK(拍照/上传) 消息 / 待办下发 审批模板与审批单 通讯录同步接口 事件回调推送 5 秒超时 / 重推 3 次 可信域名校验 对接接入层 免登网关 code → access_token → userid 本地账号匹配 / 自动建档 签发会话票据(JWT) 回调网关 验签 → AES 解密 → 落库 立即响应 → 异步消费 事件幂等(event_key) 消息 / 待办服务 模板渲染 · 收件人解析 幂等去重 · 失败重试退避 发送日志与送达统计 access_token 统一缓存刷新 令牌桶限流(防 45009) 审批单 ↔ 业务单据桥接 家具资产业务服务 AI 拍照盘点 / 全屋扫拍比对 巡检 / 报修 / 退租验收 搬迁调拨 / 报废 / 理赔 折旧计提 / 台账 / 看板 审批状态机与台账回写 图片归档(PDF/照片) 业务事件总线 盘点提交 / 派单 / 待审 / 到期 → 触发模板化消息推送 → 触发企微审批发起 / 待办创建 数据层 wecom_config 配置 wecom_department_map wecom_message_log wecom_callback_log wecom_approval_ref wecom_todo_ref 既有 32 张业务表 sys_user 补 wecom_userid photo_file 补上传渠道 单据补来源渠道字段
一句话说清分工:企业微信负责「人和入口」——身份、触达、审批、相机;系统负责「数据和判定」——AI 识别、特征比对、台账、折旧。AI 识别结果一律不直接生效,必须经人工审核(PRD 第四章硬约束),企微只是把「该谁来审」这件事推到人面前。

1前置准备与配置清单

这些必须在写代码之前做完,缺一项后面全部跑不通。

1.1 企微管理后台操作清单

操作位置配置项拿到什么 / 注意
我的企业 → 企业信息 记录 CorpID ww******** 或 18 位数字
应用管理 → 自建 → 创建应用 应用名称「家具资产管理」,上传 logo,设置可见范围 拿到 AgentID 和 Secret(Secret 只显示一次,务必存好)
应用 → 网页授权及 JS-SDK 填写可信域名,下载校验文件 把 WW_verify_xxxx.txt 放到域名根目录,必须可公网访问且 Content-Type: text/plain
应用 → 接收消息 设置 API 接收 URL、Token、EncodingAESKey 回调 URL 必须 HTTPS、公网可达;校验通过后才会保存成功
应用 → 工作台应用主页 填 H5 主页 URL(https://asset.xxx.com/mobile/) 用户从工作台点击直接进这个页;企微会追加 code 参数
安全与管理 → 管理工具 → 通讯录同步 开启并记录通讯录同步 Secret 与应用的 Secret 不是同一个,同步接口必须用它
安全与管理 → 企业可信 IP 把服务器出口 IP 加白 若企业开启此策略而未加白,所有接口报 60020
应用管理 → 审批 → 创建模板 建「家具资产调拨申请」「报废申请」「理赔定损」三个模板 拿到 template_id 和每个控件的 ControlID

1.2 需要落库的凭据(写进 wecom_config)

base.corpid
企业 ID,明文存
agent.agentid
自建应用 AgentID,明文存
agent.secret
is_encrypted=1 应用 Secret,密文存
contact.secret
is_encrypted=1 通讯录同步 Secret,密文存
auth.token
is_encrypted=1 回调签名 Token
auth.encoding_aes_key
is_encrypted=1 43 位 EncodingAESKey
agent.home_url / trusted_domain
应用主页与可信域名,明文存
凭据落库红线:Secret、Token、EncodingAESKey 属于企业级密钥。禁止明文入库——应用侧须先经 KMS 或 AES-GCM 加密再写 wecom_config.config_value。生产更推荐托管在配置中心(Apollo/Nacos)或 K8s Secret,表里只留引用键。wecom_access_token_cache.access_token 同理。

2链路一:免登 + 通讯录同步

2.1 免登流程(H5 静默授权)

目标是「从企微工作台点开应用 = 已登录」,全程无输入、无跳登录页。

1
用户在企微
点击工作台「家具资产管理」,企微打开应用主页并自动追加参数
https://asset.xxx.com/mobile/?code=CODE&state=STATE
2
H5 前端
把 code 原样透传给后端,不落地存储
GET /api/wecom/oauth/login?code=CODE
3
免登网关 → 企微
换取企业凭证(本地缓存优先,7200s 有效,提前 300s 刷新)
GET /cgi-bin/gettoken?corpid=&corpsecret= 或 POST /cgi-bin/stable_token
4
免登网关 → 企微
用 code 换成员身份,拿到 userid
GET /cgi-bin/auth/getuserinfo?access_token=&code=
5
免登网关
按 sys_user.wecom_userid 查本地账号:
· 命中 → 直接建会话
· 未命中 → 看 contact.auto_create_user:为 1 则自动建档(bind_type=2,角色取 contact.default_role_code),为 0 则返回「未授权,请联系管理员」
6
免登网关
签发会话票据(JWT / HttpOnly Cookie),回写 last_login_time、last_login_channel=2
7
H5 前端
拿到会话,跳回用户原本想去的页面(state 里存的目标路由)

关键接口与参数

接口说明
GET /cgi-bin/gettoken取 access_token,返回 {access_token, expires_in:7200}。注意 同一 Secret 多次获取可能互相顶掉,必须集中缓存,不要每个请求都取
POST /cgi-bin/stable_token稳定版取 token,推荐:不限制调用频率,返回结果稳定,不用自己抢锁
GET /cgi-bin/auth/getuserinfocode → userid。新接口,老接口 /cgi-bin/user/getuserinfo 已废弃,别再用
GET /cgi-bin/auth/getuserdetail用 user_ticket 换手机号、头像等详情。需 scope=snsapi_privateinfo,此时用户会看到一次授权确认页
GET /cgi-bin/user/get按 userid 查通讯录详情(姓名、部门、岗位),用于自动建档补全字段

手动授权的 URL 拼装(用于非工作台入口,如分享出去的链接)

https://open.weixin.qq.com/connect/oauth2/authorize
  ?appid={CorpID}                 // 注意:企业微信网页授权用 CorpID,不是 AgentID
  &redirect_uri={URLEncode(回调地址)}
  &response_type=code
  &scope=snsapi_base              // 静默授权,只拿 userid;要手机号用 snsapi_privateinfo
  &state={业务侧防重放串}
  &agentid={AgentID}              // 这个参数不能省,决定用哪个应用的授权
  #wechat_redirect                // 井号必须带上
三个最容易踩的坑:
① code 只能用一次、5 分钟过期。前端若在多个接口里重复提交同一个 code,第二次必定失败。正确做法:code 只在登录接口消费,之后一律用会话票据。
② 前端路由切换(history.pushState)不会重新走授权,会话过期时必须重新跳 oauth2/authorize,而不是直接刷当前页。
③ scope=snsapi_privateinfo 不是静默的,会弹授权页。手机号属于敏感信息,能不要就不要——用通讯录同步拿到的 mobile 就够了。

2.2 通讯录同步

两种方式,建议都要

方式接口用途与注意
全量对账 GET /cgi-bin/department/list
POST /cgi-bin/user/list_id
POST /cgi-bin/user/get
首次初始化 + 每日凌晨兜底对账。推荐 list_id 拉全量 userid(支持游标翻页),再用 user/get 批量查详情(单次最多 100 个)。
注意 老的 user/list 有 10000 条上限,大企业会漏人
事件增量 回调 event=change_contact 成员/部门变动实时同步,秒级生效。ChangeType 取值:create_user / update_user / delete_user / create_party / update_party / delete_party / update_tag
为什么必须两条腿走路:回调是「尽力送达」——企微在 5 秒内没收到响应会重推 3 次,3 次都失败就永久丢弃,不再补发。所以纯靠回调一定会有漏网之鱼,必须配一个全量对账任务兜底。对账频率不用高,每天一次足够。

字段映射

企微字段落地位置转换规则
useridsys_user.wecom_userid唯一键,账号主锚点
namesys_user.real_name直接覆盖
mobilesys_user.mobile直接覆盖
positionsys_user.wecom_position直接覆盖
department[0]sys_user.wecom_dept_id取主部门
department[0]sys_role_building关键一步:部门 → wecom_department_map.building_id → 楼栋,自动生成数据权限,实现 PRD 六.3 多楼栋隔离
avatarsys_user.wecom_avatar直接覆盖
status(1启用/2禁用/4未激活/5退出)sys_user.user_status非 1 一律视为停用
成员被删除怎么办?企微侧删除成员是不可逆事件。wecom_config.contact.sync_disable_strategy 三选一:
· 1 只停用本地账号(默认,推荐)——保留历史单据的操作人归属,否则盘点记录会变成「无主」;
· 2 保留不动——适合人员流动大、账号要复用的场景;
· 3 一并删除——不推荐,会破坏 furniture_operation_log 等审计链。
本地账号与企微账号冲突处理:若按手机号能匹配到已存在的本地账号,执行「绑定」而不是新建(bind_type=1),并把该账号的 username 保留,保证历史操作日志不会断链。

3链路二:消息推送 + 待办

3.1 触发点矩阵

这张表是消息链路的需求正文,模板已在 wecom_message_template 里预置好 14 条,改文案不需要发版。

业务事件接收角色消息类型待办跳转目标
盘点任务下发物业管家textcard✓/mobile/inventory/task?id=
低置信识别预警运营主管textcard✓/mobile/inventory/review?taskId=
盘点结果待审核运营主管textcard✓/inventory/audit?taskId=
盘点审核结果回推执行人textcard—/inventory/detail?taskId=
调拨单待审批运营主管textcard✓/transfer/detail?id=
调拨审批结果发起人textcard—/transfer/detail?id=
报修派单维修工程师textcard✓/repair/detail?id=
报修完工确认运营 / 物业textcard—/repair/detail?id=
巡检任务到期物业 / 运营textcard✓/inspect/plan?id=
合同到期 · 退租提醒招商 / 运营textcard✓/checkout/create?unitId=
理赔定损待审核运营主管textcard✓/claim/detail?id=
资产报废待审批总经理 / 运营textcard✓/scrap/detail?id=
月度折旧计提完成财务 / 总经理textcard—/finance/depreciation?month=
AI 识别任务异常运营主管textcard✓/inventory/detail?taskId=

3.2 发送接口与报文

POST https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN
Content-Type: application/json

{
  "touser": "zhangsan|lisi",          // 多个用 | 分隔
  "msgtype": "textcard",
  "agentid": 1000002,
  "textcard": {
    "title": "资产调拨单待审批",             // ≤128 字节
    "description": "调拨单号:TF-20261016-0001\n资产组:305单元标准办公套\n迁移路径:A栋305 → B栋208",
    "url": "https://asset.xxx.com/transfer/detail?id=128",
    "btntxt": "去审批"
  },
  "enable_id_trans": 0,                  // 不开 userid 转 openid
  "enable_duplicate_check": 1,           // 企微侧去重,强烈建议开
  "duplicate_check_interval": 1800        // 去重窗口,最小 1800 秒
}

返回 {"errcode":0,"errmsg":"ok","msgid":"..."},把 msgid 写回 wecom_message_log 作为送达凭据。

3.3 可靠性设计(这块不做,上线必挨骂)

机制做法
幂等去重 写入时构造 dedup_key = 模板编码 + 业务ID + 接收人 + 批次,靠 uk_dedup_key 唯一索引拦重复。同时开企微侧 enable_duplicate_check 做第二道防线。
为什么需要 一次审批驳回后重新提交,很容易把同一条消息再推一遍
失败重试 发送失败按 send_status=2 落库,next_retry_time 做指数退避(60s → 5min → 30min),超过 message.max_retry(默认 3 次)置为 4 已放弃 并告警
token 治理 集中缓存 + 提前 300s 刷新 + 刷新加分布式锁。同一 Secret 并发获取 token 会互相顶掉,这是最常见的线上事故来源
限流保护 企微各接口有调用频率上限,超限返回 45009。网关侧按接口维度做令牌桶,批量推送要分片 + 间隔
可观测 视图 v_wecom_message_stat 看送达率,v_wecom_message_pending_retry 看待重试。送达率低于阈值告警

常见错误码处置

errcode含义处置
40014 / 42001access_token 非法 / 已过期清缓存强刷 token 后重试一次;连续出现要查是否多实例互相顶号
40001Secret 错误或凭证无效配置问题,不重试,直接告警
45009接口调用超过频率限制退避重试,并检查限流配置
60011 / 301002无权限操作指定成员成员不在应用可见范围内,检查可见范围配置
60020访问 IP 不在白名单把服务器出口 IP 加入企业可信 IP
81013userid 不存在该成员已离职或非本企业,标记本地账号停用,不重试
-1系统繁忙可重试

3.4 待办(todo)与消息的差别

消息推了就推了,待办是「必须点掉」的——它会挂在企微「待办」列表里,完成前一直提醒。凡是需要「某人必须处理」的,都应该同时下待办,对应模板里的 todo_flag=1。

4链路三:审批流对接

4.1 两种模式,选哪个

模式做法取舍
A · 企微审批承载
推荐
审批单在企微里走,系统只负责提交申请、接收状态回调 优点:审批人、节点、加签、抄送、催办全部白送,不用自研;审批记录在企微留痕,领导习惯
代价:审批流一改就要同步改字段映射(配置化可缓解)
B · 系统内自研 + 企微通知 系统自己管审批状态机,企微只发待办提醒 优点:业务逻辑完全可控,字段怎么变都行
代价:审批引擎、催办、加签全要自己做,工作量翻倍
落地建议:调拨、报废、理赔定损这三类走模式 A(审批人是固定的运营主管 / 总经理,流程简单);盘点结果审核走模式 B(要在系统内看差异明细、逐条修正,企微页面承载不了这种密集交互)。这样既省了审批引擎,又不牺牲核心业务的体验。

4.2 发起审批与状态回调

1
业务系统
调拨单 AI 比对完成、进入待审核,组装审批表单数据
2
业务 → 企微
提交审批申请,按 wecom_approval_template_ref.field_mapping 把业务字段填进对应控件
POST /cgi-bin/oa/applyevent
3
业务系统
拿到 sp_no(企微审批单号),写入 wecom_approval_ref,建立业务单据 ↔ 审批单双向映射
4
企微 → 回调网关
审批状态变更时推送事件
Event=open_approval_change&ChangeType=update_status
5
回调网关
验签 → 解密 → 落 wecom_callback_log → 5 秒内返回 → 异步消费
6
业务服务
按 sp_no 找业务单据,状态映射后回写业务状态字段;若通过,则执行台账变更(调拨:批量更新资产组所在房间)
7
业务服务
给发起人回推结果消息,关闭相关待办

4.3 状态机映射(核心,必须逐个对齐)

企微 Status 含义 调拨单
transfer_status
报废单
scrap_status
要做什么
1审批中保持 1(待审核)保持 0(待审批)无需动作,等回调
2已通过2 审核通过1 审批通过 关键 执行台账批量变更:更新资产组位置、写 furniture_asset_change_log、生成调拨单归档
3已驳回3 驳回2 驳回记录审批意见,回推发起人
4已撤销(发起人主动)退回 1退回 0台账未变更,无需回滚
6通过后撤销需回滚需回滚 最麻烦 此刻台账已经生效,必须走逆向回滚:资产组位置改回 source_unit_id,并补一条变更留痕说明「审批撤销回滚」
7已删除退回 1退回 0同撤销处理,关注是否已生效
Status=6「通过后撤销」是这类对接最容易被漏掉的分支。审批通过后台账位置已经改了、调拨单已经归档了,此时发起人撤销,如果代码只处理了 2 和 3,台账就会永久错位——而资产位置错了,意味着下一次盘点一定对不上、下一次退租一定算错账。务必把回滚逻辑单独实现并做测试用例。
回调响应超时是审批链路的高频故障:企微要求 5 秒内响应,超时即重推。绝不能在回调处理里做耗时的台账批量更新或数据库大事务。标准姿势:验签 → 落 wecom_callback_log → 立即返回空串 → 异步任务消费。同时用 event_key 唯一索引保证重推不会重复执行。

4.4 定时补偿

回调会丢(超时 3 次即弃),所以必须有一个补偿任务:

5链路四:H5 工作台应用

5.1 页面清单

页面对应 PRD核心能力
工作台首页PRD 2.9待办卡片(待盘点 / 待复核 / 待审批)、快捷入口、今日任务
AI 拍照盘点PRD 2.2 模式一调原生相机连拍 → 上传 → 识别进度 → 品类数量清单 → 人工增删 → 差异高亮 → 提交送审
低置信复核PRD 四.3逐条确认 AI 判定,遮挡/堆叠场景人工兜底
全屋扫拍比对PRD 2.2 模式二环绕拍摄抽帧 → 空间去重 → 与搬迁前快照比对 → 匹配/缺失/新增三分类
巡检任务PRD 2.5计划列表 → 房间逐间巡检 → 破损上报
退租验收PRD 三.5全屋盘点 → 破损识别 → 定损确认 → 移交单签署
报修工单PRD 2.5接单、维修前照片、完工上传维修后照片、录配件成本
待办审批PRD 2.4 / 三.6调拨审批预览、报废审批、差异确认

5.2 JS-SDK 接入

签名(服务端算,前端只拿结果)

// 1) 取 jsapi_ticket(用应用的 access_token),有效期 7200s,必须缓存
GET /cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN

// 2) 拼接并 sha1
string1 = "jsapi_ticket=" + ticket
        + "&noncestr="    + nonceStr
        + "&timestamp="   + timestamp
        + "&url="         + 当前页面完整URL(不含 # 及其后片段)

signature = sha1(string1)

// 3) 前端注入配置
wx.config({
  beta: true,                 // 企业微信必须传 true
  debug: false,
  appId: CORPID,              // 注意:企业微信传的是企业 CorpID,不是 AgentID
  timestamp: timestamp,
  nonceStr: nonceStr,
  signature: signature,
  jsApiList: ["chooseImage", "getLocalImgData", "uploadImage",
              "previewImage", "getLocation", "scanQRCode"]
});
url 必须与前端发起签名的页面 URL 完全一致(协议、域名、路径、查询串全都要一致,但要剔除 # 后面的部分)。SPA 应用里常见失败原因就是前端在 history.pushState 之后才调签名接口,拿到的 url 与实际不符。

拍照与上传(两个真实大坑)

wx.chooseImage({
  count: 9,
  sizeType: ["compressed"],           // 必须压缩,原图 base64 会爆内存
  sourceType: ["camera", "album"],
  success: function(res){
    var localIds = res.localIds;
    wx.getLocalImgData({
      localId: localIds[0],
      success: function(r){
        var base64 = r.localData;

        // ⚠ 坑一:iOS 返回值带 "data:image/jpeg;base64," 前缀,Android 不带
        base64 = base64.replace(/^data:image\/\w+;base64,/, "");

        // ⚠ 坑二:别把 base64 塞进 JSON 字段传,走 multipart/form-data
        上传到业务服务器(base64);
      }
    });
  }
});
上传方式说明
方式 A
wx.uploadImage
上传到企微临时素材,拿 serverId(3 天后过期),再由服务端调媒体下载接口取回。
不推荐 多一跳、要处理过期、还要额外下载
方式 B
wx.getLocalImgData
推荐
直接拿 base64 传自己的服务器,落对象存储,furniture_photo_file 记 URL。链路短、无过期问题、与现有归档设计一致

5.3 弱网离线拍照(PRD 2.9 硬性要求)

写字楼地下车库、空置楼层信号差是常态,必须支持离线拍摄后补传。

  1. 拍照后先生成客户端唯一标识 client_uuid(UUID v4),图片存 IndexedDB,同时写一条 upload_status=0 待上传 的本地队列记录
  2. 检测到网络恢复(online 事件 + 定时探测)后,逐张以 multipart 补传
  3. 服务端以 client_uuid 做幂等(uk_client_uuid 唯一索引),重复补传不会产生重复记录
  4. 补传成功置 upload_status=1,失败置 2 并累计 retry_count,超过 5 次提示用户手动重试
  5. IndexedDB 中的图片在处理完成后清理,避免撑爆手机存储
离线状态下 AI 识别怎么办?推荐策略:本地只做拍摄与暂存,不做识别。识别必须联网上服务端(PRD 方案 A 是调第三方视觉大模型 API)。离线时页面给明确提示「已暂存 N 张,联网后自动上传识别」,而不是假装在识别。

6数据库改造

改动全部收在独立脚本 wecom_integration_ddl.sql 里,不修改家具资产库原有字段语义,可重复执行。

6.1 新增表(10 张)

表名归属链路职责
wecom_config配置凭据与开关集中管理,敏感项加密标记
wecom_access_token_cache配置token 缓存与过期时间,避免并发顶号
wecom_department_map通讯录部门 ↔ 楼栋映射,多楼栋数据权限的来源
wecom_sync_log通讯录同步批次日志,增量对账的可追溯依据
wecom_message_template消息14 条文案模板,运营改文案不用发版
wecom_message_log消息推送底账:幂等、重试、送达统计
wecom_callback_log事件回调落库 + 事件幂等 + 处理状态追踪
wecom_approval_template_ref审批业务类型 ↔ 审批模板与控件映射
wecom_approval_ref审批业务单据 ↔ sp_no 桥接与状态映射
wecom_todo_ref审批待办下发与关闭回收

6.2 既有表改造(字段级)

表新增字段用途
sys_user wecom_userid(唯一)
wecom_dept_id / wecom_position
wecom_avatar
bind_type / bind_time
last_login_channel / sync_time
免登身份锚点;password 同时放宽为可空(免登用户无密码)
furniture_photo_file source_channel
wecom_userid
wecom_media_id
retry_count
区分 PC / 企微 H5 来源,支撑离线补传与重试统计
furniture_inventory_task exec_channel
exec_wecom_userid
盘点在哪执行、谁执行的,配合 PRD 2.7 盘点方式统计
furniture_repair_order source_channel
report_wecom_userid
区分租户自助报修与物业代报
sys_integration_log (仅扩展 system_code 注释) 把企业微信纳入对接系统枚举,复用现有接口日志表

6.3 配套视图(5 个)

视图用途
v_wecom_user_bind用户绑定情况总览:谁绑了、绑到哪个部门、映射到哪栋楼
v_wecom_message_pending_retry发送失败待重试清单,含挂起时长,直接可做告警数据源
v_wecom_message_stat按模板统计送达率 / 重试率 / 放弃率
v_wecom_approval_overview企微审批单总览,含状态中文映射与同步来源
v_wecom_callback_health近 7 天回调健康度:验签失败数、处理失败数、重复事件数

6.4 幂等改造手法

MySQL 原生不支持 ADD COLUMN IF NOT EXISTS,脚本里内置了两个辅助过程,基于 information_schema 判存后再执行动态 DDL:

CALL sp_add_column_if_absent('sys_user', 'wecom_userid',
  'VARCHAR(64) DEFAULT NULL COMMENT ''企微成员userid,唯一''');
CALL sp_add_index_if_absent('sys_user', 'uk_wecom_userid', '`wecom_userid`', 1);

因此 整份脚本可以重复执行,不用担心「字段已存在」报错中断后续语句。

7安全、容错与上线

7.1 回调加解密(必须自己实现,别抄错)

直接使用企微官方提供的各语言加解密库(WXBizMsgCrypt),不要手写 AES 填充逻辑——PKCS7 填充与去除的边界处理很容易出错。

7.2 降级策略(企微挂了系统不能挂)

故障场景降级行为
企微接口不可用消息进重试队列;审批降级为系统内自研审批流;业务完全不受影响
回调长时间无响应定时补偿任务主动拉取状态,业务链路自愈
token 获取持续失败告警 + 暂停推送,避免无效重试打爆队列
企微应用被停用wecom_config.base.enable=0 一键关闭对接,系统回落到站内通知 + PC 端作业

核心原则:企业微信是「入口与触达层」,不是业务依赖。任何时刻把 base.enable 置 0,系统都应能凭 PC 端完整跑完家具资产管理全流程。

7.3 上线步骤

阶段内容出口条件
P0配置与连通性回调地址校验通过;token 能取到;测试消息能发到自己
P1免登 + 通讯录同步指定测试账号免登成功;部门 → 楼栋映射正确;数据权限生效
P2H5 工作台 + 拍照盘点真机(iOS + Android 各一台)走通完整盘点流程;重点验 base64 前缀兼容
P3消息推送 + 待办14 条模板各触发一次;断网重试验证;待办能正常关闭
P4审批流调拨走通「提交→通过→台账变更」;单独验 Status=6 通过后撤销的回滚
P5灰度与全量先开一栋楼,跑满一个巡检周期无异常再全量

7.4 验收清单

  1. 企微工作台点开应用,无需任何输入即进入工作台首页,且能看到自己的待办
  2. 新入职员工在企微被加入对应部门后,无需人工操作即可正常使用并拥有正确的楼栋数据权限
  3. 手机断网状态下拍摄 5 张家具照片,恢复网络后全部自动补传且无重复
  4. iOS 与 Android 两端拍照上传均成功(base64 前缀差异已兼容)
  5. 盘点任务下发后 10 秒内,物业管家企微收到消息与待办,点击直达对应任务页
  6. 低置信识别结果触发待复核提醒,且复核前该盘点单无法提交审核(PRD 四.3 硬约束)
  7. 调拨单在企微审批通过后,系统台账位置已自动更新,且变更留痕完整
  8. 审批「通过后撤销」时,台账位置正确回滚到原房间
  9. 同一单据重复推送不会产生多条消息(幂等生效)
  10. 企微接口整体不可用时,PC 端可完成全部业务操作(降级可用)

7.5 风险清单

风险等级应对
审批「通过后撤销」未做回滚,台账错位高单独实现回滚用例并纳入回归测试(见 7.4 第 8 条)
回调 5 秒超时导致事件丢失高落库即响应 + 异步消费 + 定时补偿三重保障
token 并发获取互相顶号中用稳定版接口 stable_token,或加分布式锁集中刷新
通讯录同步覆盖掉本地手工配置的角色中同步只更新企微来源字段,不触碰本地分配的角色;bind_type=3 的本地账号跳过同步
iOS / Android base64 前缀差异导致上传失败中统一正则剔除前缀;双端真机必须都测
企微可见范围配置错误,导致消息发不出去(60011)低上线前逐个接收角色核对应用可见范围
审批模板字段变更后代码未同步低字段映射走 wecom_approval_template_ref.field_mapping 配置,改配置不发版

8交付物清单

文件说明
furniture_asset_init.sql家具资产库 v1 建库脚本(14 张表)
furniture_asset_init_v2.sql家具资产库 v2(32 张表,含存储过程与迁移脚本)
furniture_asset_prototype.htmlPC 端单文件原型(10 个模块,含 AI 盘点与扫拍比对流程)
wecom_integration_ddl.sql本方案配套:企微对接数据库改造脚本(10 新表 + 5 视图 + 20 处列改造)
wecom_integration_design.html本方案文档
furniture_asset_wecom_mobile.html企微工作台移动端原型(可点击演示)