编辑 | blame | 历史 | 原始文档

企业微信模块(活动 / 通知 / 通讯录)- 前端联调方案

涉及页面

  • 活动管理(列表 + 新建/编辑弹窗)
  • 活动详情(含报名记录列表、报名统计、二维码展示)
  • 通知管理(列表 + 新建/编辑弹窗)
  • 成员选择器(推送时挑选部门/成员,数据来自企业微信通讯录)
  • 活动报名落地页(**不需要前端开发**,由后端直接渲染 HTML,见文末说明)

本次新增能力

能力 说明
发起活动 创建草稿 → 编辑 → 发布
推送给成员 通过企业微信应用消息推送,成员点消息里的按钮直达报名页
报名二维码 后端生成 PNG,可后台展示/下载打印
扫码报名 成员扫码打开报名页,填姓名+手机号提交,**免登录**

API

所有接口前缀 /admin-api。

活动管理

方法 路径 权限标识 说明
POST /wxcp/activity/create wxcp:activity:create 创建活动(存为草稿)
PUT /wxcp/activity/update wxcp:activity:update 修改活动
DELETE /wxcp/activity/delete wxcp:activity:delete 删除活动
GET /wxcp/activity/get wxcp:activity:query 活动详情
GET /wxcp/activity/page wxcp:activity:query 活动分页
PUT /wxcp/activity/publish wxcp:activity:update 发布活动
PUT /wxcp/activity/finish wxcp:activity:update 结束活动
PUT /wxcp/activity/cancel wxcp:activity:update 取消活动

活动分页请求参数:

参数 类型 必填 说明
pageNo Integer 是 页码
pageSize Integer 是 每页条数
title String 否 活动标题,模糊匹配
status Integer 否 状态:0草稿 1已发布 2已结束 3已取消
pushStatus Integer 否 推送状态:0未推送 1已推送
startTime DateTime[] 否 活动开始时间范围,格式 yyyy-MM-dd HH:mm:ss

创建/修改请求参数:

参数 类型 必填 说明
id Long 修改时必填 编号
title String 是 活动标题,≤128 字符
content String 否 活动详情
coverUrl String 否 封面图地址
location String 否 活动地点,≤255 字符
startTime DateTime 否 活动开始时间
endTime DateTime 否 活动结束时间
signupStartTime DateTime 否 报名开始时间
signupEndTime DateTime 否 报名结束时间
signupLimit Integer 是 报名上限,**不限传 0**
pushScope Integer 是 推送范围:0全员 1指定部门 2指定成员
pushTarget String 否 推送目标,逗号分隔;范围选 1 或 2 时必填
remark String 否 备注

活动响应新增字段:

字段 类型 说明
statusName String 状态名,如「已发布」
pushScopeName String 推送范围名,如「全员」
signupCount Integer 已报名人数
pushStatus Integer 0未推送 1已推送
pushTime DateTime 最近推送时间

推送与二维码

方法 路径 权限标识 说明
POST /wxcp/activity/push wxcp:activity:push 推送给企业微信成员
GET /wxcp/activity/qrcode wxcp:activity:query 获取报名二维码(返回 PNG)
GET /wxcp/activity/signup-url wxcp:activity:query 获取报名页地址

推送请求参数:

参数 类型 必填 说明
id Long 是 活动编号
pushScope Integer 否 覆盖活动上的推送范围,不传则沿用
pushTarget String 否 覆盖活动上的推送目标,不传则沿用

推送响应:

{ "code": 0, "data": { "success": true, "errCode": 0, "message": "推送成功" } }

二维码接口: 直接返回 image/png 字节流,不是 JSON。
页面里把这个 URL 当图片地址用即可(如 <img :src="...">),需要带令牌时自行拼查询参数。

报名记录

方法 路径 权限标识 说明
GET /wxcp/activity/signup/page wxcp:signup:query 报名记录分页
PUT /wxcp/activity/signup/cancel wxcp:signup:update 取消报名
PUT /wxcp/activity/signup/check-in wxcp:signup:update 签到

分页请求参数: activityId、name(模糊)、mobile(模糊)、status

响应字段: id、activityId、activityTitle、wxUserId、name、mobile、deptName、status、statusName、signupTime、checkInTime、remark

公开接口(免登录,前端**不需要**调用)

方法 路径 说明
GET /wxcp/activity/signup-page?id={活动编号} 报名落地页 HTML,由后端渲染
POST /wxcp/activity/signup 提交报名(支持 content 文字 + blobIds 附件)

报名统计与附件

方法 路径 权限标识 说明
GET /wxcp/activity/stats?id= wxcp:activity:query 报名统计
GET /wxcp/activity/signup/attachments?signupId= wxcp:signup:query 某条报名上传的图片/附件

统计响应:

{
  "activityId": 1, "activityTitle": "2026春季团建活动",
  "signupLimit": 50, "totalSignup": 1,
  "signedUpCount": 1, "checkedInCount": 0, "canceledCount": 0,
  "remaining": 49, "signupPercent": 2, "checkInPercent": 0,
  "deptStats":      [{ "name": "技术部", "count": 3 }],
  "dateStats":      [{ "name": "2026-09-29", "count": 1 }],
  "sourceStats":    [{ "name": "企业微信身份", "count": 0 }, { "name": "表单填写", "count": 1 }]
}

remaining / signupPercent 在活动**不限名额**(signupLimit=0)时为 null,前端要显示"不限"。
统计**不含已取消**的报名,所以 totalSignup ≠ 报名记录总条数。

通知管理

方法 路径 权限标识 说明
POST /wxcp/notice/create wxcp:notice:create 创建通知(存为草稿)
PUT /wxcp/notice/update wxcp:notice:update 修改通知
DELETE /wxcp/notice/delete wxcp:notice:delete 删除通知
GET /wxcp/notice/get wxcp:notice:query 通知详情
GET /wxcp/notice/page wxcp:notice:query 通知分页
PUT /wxcp/notice/publish wxcp:notice:update 发布通知
PUT /wxcp/notice/revoke wxcp:notice:update 撤回通知
POST /wxcp/notice/push wxcp:notice:push 推送通知

通知与活动的差异:

项 活动 通知
推送消息类型 文本卡片(带「立即报名」按钮跳报名页) 纯文本
正文长度 由卡片模板限制 超过 600 字**自动截断**并提示到系统内查看
状态 草稿/已发布/已结束/已取消 草稿/已发布/已撤回
推送前提 必须「已发布」 必须「已发布」

企业微信通讯录

方法 路径 权限标识 说明
GET /wxcp/member/department/tree wxcp:member:query 部门树(含 children)
GET /wxcp/member/department/list wxcp:member:query 部门平铺列表(做下拉更方便)
GET /wxcp/member/list?departmentId=&fetchChild= wxcp:member:query 成员列表

成员响应字段: userId(推送时填这个)、name、mobile、email、avatar、position、gender、status、departmentIds、departmentNames

这几个接口是**实时调用企业微信**的,企业微信对通讯录接口有频率限制。前端请做缓存(如打开选择器时拉一次),**不要**在搜索框里每输入一个字符就请求一次。

业务流程与数据带入

  1. 新建活动 → 保存为**草稿**,此时扫码报名会提示「报名已结束」
  2. 点「发布」→ 状态变「已发布」,此时二维码和报名页才可用
  3. 点「推送」→ 成员企业微信收到卡片消息,标题为活动标题,正文含**活动时间 / 地点 / 报名截止 / 名额**,按钮「立即报名」直达报名页
  4. 成员点按钮或扫码 → 打开报名页 → 填姓名和手机号 → 提交
  5. 报名成功 → 活动 signupCount 自动 +1
  6. 后台在活动详情的报名记录列表里可看到该成员,可执行「取消报名」「签到」

数据带入关系:

来源 目标 带入内容
活动编辑保存 推送消息 标题、时间、地点、报名截止、名额
活动编号 二维码内容 {signupUrlPrefix}/admin-api/wxcp/activity/signup-page?id={id}
扫码报名 报名记录 活动编号

字段展示规则

字段 展示位置 说明
title 列表、详情 活动标题,点击进详情
statusName 列表、详情 用后端返回的中文名,前端不要自己映射
startTime ~ endTime 列表、详情 活动时间范围
signupCount / signupLimit 列表、详情 0/50 这种形式;上限为 0 时显示「不限」
pushStatus / pushTime 列表、详情 未推送 / 已推送 + 时间
pushScopeName 详情 推送范围中文名
qrcode(图片) 详情 报名二维码,需支持下载
statusName(报名) 报名列表 已报名 / 已取消 / 已签到

业务规则说明

场景 规则
创建活动 一律存为草稿,不可直接创建为已发布
修改活动 已结束、已取消的活动不可修改;草稿和已发布可改
推送前提 活动必须是「已发布」状态,草稿状态推送会报「活动尚未发布,请先发布后再推送」
推送范围=全员 使用企业微信 @all,即应用可见范围内所有人
推送范围=指定成员 pushTarget 填成员账号(UserId),多个用**英文逗号**分隔
推送范围=指定部门 pushTarget 填部门 ID,多个用英文逗号分隔
推送失败 接口返回 success=false + 企业微信错误码,**不会抛异常**;前端应把 message 直接提示给用户
推送成功后 活动 pushStatus 置 1、pushTime 记录时间;重复推送会覆盖这两个字段
报名时间窗口 未到 signupStartTime 或已过 signupEndTime 均不能报名
报名名额 signupLimit=0 表示不限;已满时提示「报名人数已满」
重复报名 有企业微信身份按成员账号判重;普通浏览器按**手机号**判重
取消后重新报名 复用原记录,不会产生第二条历史
取消报名 活动 signupCount 自动 -1

注意事项

  • 二维码接口返回的是图片二进制,不是 JSON,不要用普通 request 封装去取,直接用图片 URL。
  • signupLimit 必填,不限要传 0 而不是留空,否则会校验失败。
  • 推送范围选「指定部门/成员」时 pushTarget 不能为空,否则报「推送目标不能为空」。
  • 推送是**同步**调用企业微信接口,成员多时可能耗时 1~3 秒,前端按钮要有 loading。
  • 活动 content 字段在报名页是**按纯文本渲染**的(做了 HTML 转义防 XSS)。如果活动详情需要富文本排版,需要另行接入富文本白名单过滤,当前版本不支持。
  • 报名页地址依赖后端配置 wx.cp.signup-url-prefix(当前为 http://wcf.viphk.nnhk.cc)。该地址必须是**成员手机能访问到的外网地址**,否则二维码扫出来打不开。
  • 报名记录里的 wxUserId 只有在**企业微信内打开报名页且带上了参数**时才有值;普通浏览器扫码报名时为空,此时按手机号去重。
  • 权限标识需要在「系统管理 → 菜单管理」里配置好,否则接口会返回 403。
  • 推送目标用的是 userId(成员账号,如 LiuYi),不是姓名、也不是手机号。 从通讯录接口取 userId 填进 pushTarget。
  • 附件上传走 system 模块的公共上传接口:报名页先调 POST /admin-api/system/storage-blob/public-upload(表单字段名 files)拿到 blobId,再把 blobIds 随报名提交,由**服务端**完成与报名记录的绑定。管理后台查附件用 /wxcp/activity/signup/attachments。
  • 报名的 recordType 固定为 wxcp_activity_signup,已注册进 system 模块的 StorageRecordTypeEnum 白名单。以后新增别的附件关联类型,必须同步注册,否则绑定会报「无效的记录类型」。
  • 通讯录接口**实时调企业微信**,有频率限制,前端务必缓存,不要随输入实时请求。
  • 通知正文超过 600 字会**自动截断**(企业微信文本消息有长度上限),截断提示会写在消息末尾。

关于报名落地页

报名页 GET /admin-api/wxcp/activity/signup-page?id=xxx 由**后端直接渲染 HTML**(含内联样式和少量 JS),前端**无需开发**。

这样做的原因:二维码必须指向一个成员手机能直接打开的页面,而后端渲染可以立即跑通「推送 → 扫码 → 报名」闭环,不必等前端排期。若后续希望改为前端 SPA 页面,把二维码内容改成前端路由地址即可,后端接口(/wxcp/activity/signup)不用动。

该页面的路径刻意放在 /admin-api 下(而非 /app-api),因为前端 Vite 开发代理只转发 /admin-api,放 /app-api 会导致扫码后请求打到前端静态服务返回 404。