diff --git a/cmd/imtestaudit/main.go b/cmd/imtestaudit/main.go index cf8e226..337c3bc 100644 --- a/cmd/imtestaudit/main.go +++ b/cmd/imtestaudit/main.go @@ -42,40 +42,41 @@ type result struct { } type audit struct { - baseURL string - wsURL string - apiKey string - tenantCode string - client *http.Client - results []result - tokenA string - userA string - usernameA string - phoneA string - passA string - tokenB string - userB string - usernameB string - phoneB string - passB string - groupTopic string - groupVer int - groupQR string - friendReq string - p2pTopic string - meQR string - meQRPurpose string - meetingID string - meetingVer int - dailyID string - dailyVer int - monthlyID string - monthlyVer int - actionTok string - abuseReason string - profileVer int - privacyVer int - feedbackCat string + baseURL string + wsURL string + apiKey string + tenantCode string + client *http.Client + results []result + tokenA string + userA string + usernameA string + phoneA string + passA string + tokenB string + userB string + usernameB string + phoneB string + passB string + groupTopic string + groupVer int + groupQR string + friendReq string + p2pTopic string + meQR string + meQRPurpose string + meetingID string + meetingVer int + dailyID string + dailyVer int + monthlyID string + monthlyVer int + mailboxNoticeVersion string + actionTok string + abuseReason string + profileVer int + privacyVer int + feedbackCat string } func main() { @@ -265,8 +266,11 @@ func (a *audit) run() { return fmt.Sprintf("report_id=%s version=%d", a.monthlyID, a.monthlyVer) }) a.testHTTP("9", "9.monthly-stats", "月报统计", "GET", "/v1/im/reports/monthly/statistics?month="+month, nil, a.tokenA, false, []int{200}, nil) - a.testHTTP("9", "9.mailbox-config", "总经理信箱配置", "GET", "/v1/im/executive-mailbox/config", nil, a.tokenA, false, []int{200}, nil) - a.testHTTP("9", "9.mailbox-submit", "总经理信箱提交", "POST", "/v1/im/executive-mailbox/submissions", map[string]any{"subject": "联调建议", "content": "自动化测试提交", "anonymous": false, "attachment_file_ids": []string{}, "notice_version": "v1"}, a.tokenA, true, []int{200, 400, 403}, nil) + a.testHTTP("9", "9.mailbox-config", "总经理信箱配置", "GET", "/v1/im/executive-mailbox/config", nil, a.tokenA, false, []int{200}, func(r imResp) string { + a.mailboxNoticeVersion = asString(dig(r.Data, "notice", "version")) + return "notice_version=" + a.mailboxNoticeVersion + }) + a.testHTTP("9", "9.mailbox-submit", "总经理信箱提交", "POST", "/v1/im/executive-mailbox/submissions", map[string]any{"subject": "联调建议", "content": "自动化测试提交", "anonymous": false, "attachment_file_ids": []string{}, "notice_version": a.mailboxNoticeVersion}, a.tokenA, true, []int{200, 400, 403}, nil) a.testHTTP("10", "10.me", "我的账号", "GET", "/v1/im/me", nil, a.tokenA, false, []int{200}, nil) a.testHTTP("10", "10.profile", "个人资料", "GET", "/v1/im/me/profile", nil, a.tokenA, false, []int{200}, func(r imResp) string { diff --git a/docs/test/im_frontend_backend_1_11_testenv_results_2026-08-20.md b/docs/test/im_frontend_backend_1_11_testenv_results_2026-08-20.md index 24269ab..20f32ce 100644 --- a/docs/test/im_frontend_backend_1_11_testenv_results_2026-08-20.md +++ b/docs/test/im_frontend_backend_1_11_testenv_results_2026-08-20.md @@ -3,45 +3,35 @@ ## 1. 测试范围 - 对照文档:`docs/IM-前后端对接文档.md` -- 测试时间:`2026-08-20 22:59:05 +0800` +- 测试时间:`2026-08-20 23:15:31 +0800` - 测试环境:`https://api.118im.com` - WebSocket:`wss://api.118im.com/v0/channels` - 租户:`default` -- 测试账号 A:`a35758000` / `15535758000` / `usrv5HSlKE-PQk` -- 测试账号 B:`b35758000` / `15635758000` / `usrmHgqblBLy8Q` +- 测试账号 A:`a98656000` / `15598656000` / `usr--xhFVUQ8Qs` +- 测试账号 B:`b98656000` / `15698656000` / `usrkzrIHX2xBXc` - API Key 与 Token 已脱敏,不在文档中展开。 ## 2. 总体结论 -本轮按前后端对接文档从第 1 章到第 11 章直接访问测试环境接口,共执行 `96` 项,符合预期 `85` 项,不符合预期 `11` 项。符合预期不等于业务全链路完全验收;部分接口以 404/405/409/403 作为当前文档标注的未实现、无数据或权限分支记录。 +本轮按前后端对接文档从第 1 章到第 11 章直接访问测试环境接口,共执行 `98` 项,符合预期 `97` 项,不符合预期 `1` 项。符合预期不等于业务全链路完全验收;部分接口以 404/405/409/403 作为当前文档标注的未实现、无数据或权限分支记录。 | 章 | 符合预期 | 不符合预期 | | --- | ---: | ---: | -| 1 | 12 | 2 | +| 1 | 16 | 0 | | 2 | 4 | 0 | -| 3 | 2 | 2 | -| 4 | 5 | 1 | +| 3 | 4 | 0 | +| 4 | 6 | 0 | | 5 | 12 | 0 | -| 6 | 19 | 2 | +| 6 | 21 | 0 | | 7 | 5 | 1 | | 8 | 2 | 0 | -| 9 | 12 | 2 | +| 9 | 14 | 0 | | 10 | 8 | 0 | -| 11 | 4 | 1 | +| 11 | 5 | 0 | ## 3. 需要关注的问题 -- `1.6a` POST `/v1/im/auth/verification-codes`:HTTP `502`,code `0`,reason ``。未返回 challenge_id -- `1.7a` POST `/v1/im/security/challenges`:HTTP `502`,code `0`,reason ``。challenge_id= -- `3.conv-settings` GET `/v1/im/conversations/p2pv5HSlKE-PQmYeCpuUEvLxA/settings`:HTTP `502`,code `0`,reason ``。 -- `3.conv-messages` GET `/v1/im/conversations/p2pv5HSlKE-PQmYeCpuUEvLxA/messages?since=1&limit=20`:HTTP `502`,code `0`,reason ``。 -- `4.forward-targets` GET `/v1/im/forward-targets?query=&cursor=`:HTTP `404`,code `0`,reason ``。 -- `6.ann-latest` GET `/v1/im/groups/grppe4qw1ad4QQ/announcements/latest`:HTTP `500`,code `90000`,reason `INTERNAL_ERROR`。 -- `6.ann-put` PUT `/v1/im/groups/grppe4qw1ad4QQ/announcements/current`:HTTP `500`,code `90000`,reason `INTERNAL_ERROR`。 - `7.favorite-batch` POST `/v1/im/favorites/batch`:HTTP `405`,code `30002`,reason `METHOD_NOT_ALLOWED`。 -- `9.mailbox-config` GET `/v1/im/executive-mailbox/config`:HTTP `500`,code `90000`,reason `INTERNAL_ERROR`。 -- `9.mailbox-submit` POST `/v1/im/executive-mailbox/submissions`:HTTP `500`,code `90000`,reason `INTERNAL_ERROR`。 -- `11.abuse-reasons` GET `/v1/im/reports/abuse/reasons?target_type=user`:HTTP `500`,code `90000`,reason `INTERNAL_ERROR`。reason= ## 4. 分章明细 @@ -50,14 +40,16 @@ | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | | `1.1` | 企业码解析 | `POST` | `/v1/im/tenants/resolve` | 200 | `0/` | 通过 | tenant=default endpoints=https://api.118im.com/v1/im | -| `1.2A-code` | 注册发码 a35758000 | `POST` | `/v1/im/auth/verification-codes` | 200 | `0/` | 通过 | challenge_id=frGG...cN-C | -| `1.2A-verify` | 注册验证码校验 a35758000 | `POST` | `/v1/im/auth/verification-codes/frGGY0QrywDO98cxSmKWcN-C/verify` | 200 | `0/` | 通过 | verification_token=ywPa...iDMI | -| `1.2A-ws-acc` | WebSocket hi+acc 注册 a35758000 | `WS` | `/v0/channels` | 0 | `0/` | 通过 | user=usrv5HSlKE-PQk token=AwEA...MZw9 | -| `1.2B-code` | 注册发码 b35758000 | `POST` | `/v1/im/auth/verification-codes` | 200 | `0/` | 通过 | challenge_id=Lg5n...oIsP | -| `1.2B-verify` | 注册验证码校验 b35758000 | `POST` | `/v1/im/auth/verification-codes/Lg5nd34yIlk8KIXw0nv0oIsP/verify` | 200 | `0/` | 通过 | verification_token=ZihI...ovI8 | -| `1.2B-ws-acc` | WebSocket hi+acc 注册 b35758000 | `WS` | `/v0/channels` | 0 | `0/` | 通过 | user=usrmHgqblBLy8Q token=AwEA...9zCX | -| `1.6a` | 忘记密码发码 | `POST` | `/v1/im/auth/verification-codes` | 502 | `0/` | 未通过 | 未返回 challenge_id | -| `1.7a` | 二次身份验证发起 | `POST` | `/v1/im/security/challenges` | 502 | `0/` | 未通过 | challenge_id= | +| `1.2A-code` | 注册发码 a98656000 | `POST` | `/v1/im/auth/verification-codes` | 200 | `0/` | 通过 | challenge_id=CDk2...OJRB | +| `1.2A-verify` | 注册验证码校验 a98656000 | `POST` | `/v1/im/auth/verification-codes/CDk2pfsTzVTcHZ4ToFWLOJRB/verify` | 200 | `0/` | 通过 | verification_token=w4q6...t_xs | +| `1.2A-ws-acc` | WebSocket hi+acc 注册 a98656000 | `WS` | `/v0/channels` | 0 | `0/` | 通过 | user=usr--xhFVUQ8Qs token=AwEA...awQ6 | +| `1.2B-code` | 注册发码 b98656000 | `POST` | `/v1/im/auth/verification-codes` | 200 | `0/` | 通过 | challenge_id=DVmh...ZWZ0 | +| `1.2B-verify` | 注册验证码校验 b98656000 | `POST` | `/v1/im/auth/verification-codes/DVmh4897_KsYDoIdof9aZWZ0/verify` | 200 | `0/` | 通过 | verification_token=Vyvk...sGBg | +| `1.2B-ws-acc` | WebSocket hi+acc 注册 b98656000 | `WS` | `/v0/channels` | 0 | `0/` | 通过 | user=usrkzrIHX2xBXc token=AwEA...gsYR | +| `1.6b` | 忘记密码验证码校验 | `POST` | `/v1/im/auth/password-reset/challenges/XOuAkUsIQgDsddmRSmaigs12/verify` | 200 | `0/` | 通过 | reset_token=XOuA...BSvE | +| `1.6a` | 忘记密码发码 | `POST` | `/v1/im/auth/verification-codes` | 200 | `0/` | 通过 | challenge_id=XOuA...gs12 | +| `1.7b` | 二次身份验证码校验 | `POST` | `/v1/im/security/challenges/PapKGWb1YkgkoM2GOISkhWrF/verify` | 200 | `0/` | 通过 | action_token=_udB...ddt4 | +| `1.7a` | 二次身份验证发起 | `POST` | `/v1/im/security/challenges` | 200 | `0/` | 通过 | challenge_id=PapK...hWrF | | `1.8` | 实名状态查询 | `GET` | `/v1/im/security/realname` | 200 | `0/` | 通过 | | | `1.8-submit` | 实名提交 | `POST` | `/v1/im/security/realname/submissions` | 200 | `0/` | 通过 | | | `1.11` | 设置独立密码 | `POST` | `/v1/im/settings/independent-password` | 400 | `30040/PASSWORD_POLICY_VIOLATION` | 通过 | | @@ -68,7 +60,7 @@ | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | -| `2.1` | Bootstrap | `GET` | `/v1/im/bootstrap` | 200 | `0/` | 通过 | entries=true limits=false | +| `2.1` | Bootstrap | `GET` | `/v1/im/bootstrap` | 200 | `0/` | 通过 | entries=true limits=true | | `2.search` | 会话搜索 | `GET` | `/v1/im/search/conversations?q=&cursor=` | 200 | `0/` | 通过 | | | `2.sys` | 系统通知列表 | `GET` | `/v1/im/system-notifications?limit=20` | 200 | `0/` | 通过 | | | `2.sys-read` | 系统通知已读不存在 ID | `POST` | `/v1/im/system-notifications/nonexistent/read` | 404 | `30044/CHALLENGE_EXPIRED` | 通过 | | @@ -77,64 +69,64 @@ | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | -| `3.context` | P2P 会话上下文 | `GET` | `/v1/im/conversations/p2pv5HSlKE-PQmYeCpuUEvLxA/context` | 200 | `0/` | 通过 | | +| `3.context` | P2P 会话上下文 | `GET` | `/v1/im/conversations/p2p--xhFVUQ8QuTOsgdfbEFdw/context` | 200 | `0/` | 通过 | | | `3.p2p-create` | 创建 P2P 会话目标接口 | `POST` | `/v1/im/conversations/p2p` | 405 | `30002/METHOD_NOT_ALLOWED` | 通过 | | -| `3.conv-settings` | 会话设置查询 | `GET` | `/v1/im/conversations/p2pv5HSlKE-PQmYeCpuUEvLxA/settings` | 502 | `0/` | 未通过 | | -| `3.conv-messages` | 会话消息列表 | `GET` | `/v1/im/conversations/p2pv5HSlKE-PQmYeCpuUEvLxA/messages?since=1&limit=20` | 502 | `0/` | 未通过 | | +| `3.conv-settings` | 会话设置查询 | `GET` | `/v1/im/conversations/p2p--xhFVUQ8QuTOsgdfbEFdw/settings` | 200 | `0/` | 通过 | | +| `3.conv-messages` | 会话消息列表 | `GET` | `/v1/im/conversations/p2p--xhFVUQ8QuTOsgdfbEFdw/messages?since=1&limit=20` | 200 | `0/` | 通过 | | ### 第 4 章 | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | -| `4.forward-targets` | 转发目标列表 | `GET` | `/v1/im/forward-targets?query=&cursor=` | 404 | `0/` | 未通过 | | +| `4.forward-targets` | 转发目标列表 | `GET` | `/v1/im/forward-targets?query=&cursor=` | 200 | `0/` | 通过 | | | `4.forward` | 消息逐条转发 | `POST` | `/v1/im/messages/forward` | 404 | `0/` | 通过 | | | `4.bundle` | 合并转发详情 | `GET` | `/v1/im/forward-bundles/fbundle_missing?cursor=` | 404 | `0/` | 通过 | | -| `4.recall` | 消息撤回不存在 seq | `POST` | `/v1/im/topics/p2pv5HSlKE-PQmYeCpuUEvLxA/messages/1/recall` | 404 | `30004/MALFORMED_REQUEST` | 通过 | | -| `4.revision` | 消息编辑不存在 seq | `POST` | `/v1/im/topics/p2pv5HSlKE-PQmYeCpuUEvLxA/messages/1/revisions` | 404 | `30004/MALFORMED_REQUEST` | 通过 | | -| `4.receipts` | 消息回执查询 | `GET` | `/v1/im/topics/p2pv5HSlKE-PQmYeCpuUEvLxA/messages/1/receipts?cursor=` | 200 | `0/` | 通过 | | +| `4.recall` | 消息撤回不存在 seq | `POST` | `/v1/im/topics/p2p--xhFVUQ8QuTOsgdfbEFdw/messages/1/recall` | 404 | `30004/MALFORMED_REQUEST` | 通过 | | +| `4.revision` | 消息编辑不存在 seq | `POST` | `/v1/im/topics/p2p--xhFVUQ8QuTOsgdfbEFdw/messages/1/revisions` | 404 | `30004/MALFORMED_REQUEST` | 通过 | | +| `4.receipts` | 消息回执查询 | `GET` | `/v1/im/topics/p2p--xhFVUQ8QuTOsgdfbEFdw/messages/1/receipts?cursor=` | 200 | `0/` | 通过 | | ### 第 5 章 | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | -| `5.search` | 用户搜索 B | `GET` | `/v1/im/users/search?q=b35758000&type=account&cursor=` | 200 | `0/` | 通过 | | -| `5.profile` | 查看 B 资料 | `GET` | `/v1/im/users/b35758000/profile` | 403 | `30005/PERMISSION_DENIED` | 通过 | | -| `5.user-qr` | 查看 B 加好友二维码 | `POST` | `/v1/im/users/b35758000/qrcodes` | 403 | `30005/PERMISSION_DENIED` | 通过 | | -| `5.friend-create` | 创建好友申请 A->B | `POST` | `/v1/im/friend-requests` | 200 | `0/` | 通过 | request_id=frq_Z8SqjqK1iNg | -| `5.friend-accept` | B 同意好友申请 | `POST` | `/v1/im/friend-requests/frq_Z8SqjqK1iNg/accept` | 200 | `0/` | 通过 | topic=p2pv5HSlKE-PQmYeCpuUEvLxA | +| `5.search` | 用户搜索 B | `GET` | `/v1/im/users/search?q=b98656000&type=account&cursor=` | 200 | `0/` | 通过 | | +| `5.profile` | 查看 B 资料 | `GET` | `/v1/im/users/b98656000/profile` | 403 | `30005/PERMISSION_DENIED` | 通过 | | +| `5.user-qr` | 查看 B 加好友二维码 | `POST` | `/v1/im/users/b98656000/qrcodes` | 403 | `30005/PERMISSION_DENIED` | 通过 | | +| `5.friend-create` | 创建好友申请 A->B | `POST` | `/v1/im/friend-requests` | 200 | `0/` | 通过 | request_id=frq_4BCvvh7aJaQ | +| `5.friend-accept` | B 同意好友申请 | `POST` | `/v1/im/friend-requests/frq_4BCvvh7aJaQ/accept` | 200 | `0/` | 通过 | topic=p2p--xhFVUQ8QuTOsgdfbEFdw | | `5.friends` | 好友列表 | `GET` | `/v1/im/friends?query=&initial=&cursor=` | 200 | `0/` | 通过 | | | `5.requests` | 好友申请列表 | `GET` | `/v1/im/friend-requests?direction=inbound&status=all&cursor=` | 200 | `0/` | 通过 | | | `5.blocks` | 黑名单列表 | `GET` | `/v1/im/blocks?cursor=` | 200 | `0/` | 通过 | | -| `5.block-put` | 拉黑 B | `PUT` | `/v1/im/blocks/usrmHgqblBLy8Q` | 200 | `0/` | 通过 | | -| `5.block-del` | 解除拉黑 B | `DELETE` | `/v1/im/blocks/usrmHgqblBLy8Q` | 200 | `0/` | 通过 | | -| `5.me-qr` | 我的二维码 | `POST` | `/v1/im/me/qrcodes` | 200 | `0/` | 通过 | qr_token=eyJ2...umSY | +| `5.block-put` | 拉黑 B | `PUT` | `/v1/im/blocks/usrkzrIHX2xBXc` | 200 | `0/` | 通过 | | +| `5.block-del` | 解除拉黑 B | `DELETE` | `/v1/im/blocks/usrkzrIHX2xBXc` | 200 | `0/` | 通过 | | +| `5.me-qr` | 我的二维码 | `POST` | `/v1/im/me/qrcodes` | 200 | `0/` | 通过 | qr_token=eyJ2...J5N8 | | `5.qr-resolve` | 二维码解析 | `POST` | `/v1/im/qrcodes/resolve` | 200 | `0/` | 通过 | | ### 第 6 章 | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | -| `6.create` | 创建群 | `POST` | `/v1/im/groups` | 200 | `0/` | 通过 | topic=grppe4qw1ad4QQ version=1 | +| `6.create` | 创建群 | `POST` | `/v1/im/groups` | 200 | `0/` | 通过 | topic=grp4ch145Ku80k version=1 | | `6.list` | 群列表 | `GET` | `/v1/im/groups?category=owned&query=&cursor=` | 200 | `0/` | 通过 | | -| `6.detail` | 群详情 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ` | 200 | `0/` | 通过 | | -| `6.patch` | 更新群资料 | `PATCH` | `/v1/im/groups/grppe4qw1ad4QQ` | 200 | `0/` | 通过 | version=2 | -| `6.settings` | 群设置 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/settings` | 200 | `0/` | 通过 | | -| `6.member-settings` | 群个人设置 | `PATCH` | `/v1/im/groups/grppe4qw1ad4QQ/member-settings` | 200 | `0/` | 通过 | | -| `6.my-profile` | 群内昵称 | `PUT` | `/v1/im/groups/grppe4qw1ad4QQ/members/me/profile` | 409 | `20009/VERSION_CONFLICT` | 通过 | | -| `6.members` | 群成员 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/members?query=&cursor=&mentionable=true` | 200 | `0/` | 通过 | | -| `6.member-profile` | 群成员资料 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/members/usrmHgqblBLy8Q/profile` | 200 | `0/` | 通过 | | -| `6.qrcode` | 群二维码 | `POST` | `/v1/im/groups/grppe4qw1ad4QQ/qrcodes` | 200 | `0/` | 通过 | qr_token=eyJ2...Kzjo | -| `6.invite` | 群邀请 | `POST` | `/v1/im/groups/grppe4qw1ad4QQ/invitations` | 200 | `0/` | 通过 | | -| `6.join-requests` | 入群申请列表 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/join-requests?status=pending&cursor=` | 200 | `0/` | 通过 | | -| `6.summary` | 群概要 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/summary` | 200 | `0/` | 通过 | | -| `6.ann-latest` | 群公告最新 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/announcements/latest` | 500 | `90000/INTERNAL_ERROR` | 未通过 | | -| `6.ann-put` | 发布群公告 | `PUT` | `/v1/im/groups/grppe4qw1ad4QQ/announcements/current` | 500 | `90000/INTERNAL_ERROR` | 未通过 | | -| `6.governance` | 群治理配置 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/governance` | 200 | `0/` | 通过 | | -| `6.governance-patch` | 更新群治理配置 | `PATCH` | `/v1/im/groups/grppe4qw1ad4QQ/governance` | 409 | `20009/VERSION_CONFLICT` | 通过 | | -| `6.role-limits` | 管理员数量限制 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/role-limits` | 200 | `0/` | 通过 | | -| `6.admins` | 管理员列表 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/members?role=admin&cursor=` | 200 | `0/` | 通过 | | -| `6.mutes` | 禁言列表 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/mutes?cursor=` | 200 | `0/` | 通过 | | -| `6.files` | 群文件列表 | `GET` | `/v1/im/groups/grppe4qw1ad4QQ/files?query=&type=&cursor=` | 200 | `0/` | 通过 | | +| `6.detail` | 群详情 | `GET` | `/v1/im/groups/grp4ch145Ku80k` | 200 | `0/` | 通过 | | +| `6.patch` | 更新群资料 | `PATCH` | `/v1/im/groups/grp4ch145Ku80k` | 200 | `0/` | 通过 | version=2 | +| `6.settings` | 群设置 | `GET` | `/v1/im/groups/grp4ch145Ku80k/settings` | 200 | `0/` | 通过 | | +| `6.member-settings` | 群个人设置 | `PATCH` | `/v1/im/groups/grp4ch145Ku80k/member-settings` | 200 | `0/` | 通过 | | +| `6.my-profile` | 群内昵称 | `PUT` | `/v1/im/groups/grp4ch145Ku80k/members/me/profile` | 409 | `20009/VERSION_CONFLICT` | 通过 | | +| `6.members` | 群成员 | `GET` | `/v1/im/groups/grp4ch145Ku80k/members?query=&cursor=&mentionable=true` | 200 | `0/` | 通过 | | +| `6.member-profile` | 群成员资料 | `GET` | `/v1/im/groups/grp4ch145Ku80k/members/usrkzrIHX2xBXc/profile` | 200 | `0/` | 通过 | | +| `6.qrcode` | 群二维码 | `POST` | `/v1/im/groups/grp4ch145Ku80k/qrcodes` | 200 | `0/` | 通过 | qr_token=eyJ2...cq2U | +| `6.invite` | 群邀请 | `POST` | `/v1/im/groups/grp4ch145Ku80k/invitations` | 200 | `0/` | 通过 | | +| `6.join-requests` | 入群申请列表 | `GET` | `/v1/im/groups/grp4ch145Ku80k/join-requests?status=pending&cursor=` | 200 | `0/` | 通过 | | +| `6.summary` | 群概要 | `GET` | `/v1/im/groups/grp4ch145Ku80k/summary` | 200 | `0/` | 通过 | | +| `6.ann-latest` | 群公告最新 | `GET` | `/v1/im/groups/grp4ch145Ku80k/announcements/latest` | 200 | `0/` | 通过 | | +| `6.ann-put` | 发布群公告 | `PUT` | `/v1/im/groups/grp4ch145Ku80k/announcements/current` | 200 | `0/` | 通过 | | +| `6.governance` | 群治理配置 | `GET` | `/v1/im/groups/grp4ch145Ku80k/governance` | 200 | `0/` | 通过 | | +| `6.governance-patch` | 更新群治理配置 | `PATCH` | `/v1/im/groups/grp4ch145Ku80k/governance` | 409 | `20009/VERSION_CONFLICT` | 通过 | | +| `6.role-limits` | 管理员数量限制 | `GET` | `/v1/im/groups/grp4ch145Ku80k/role-limits` | 200 | `0/` | 通过 | | +| `6.admins` | 管理员列表 | `GET` | `/v1/im/groups/grp4ch145Ku80k/members?role=admin&cursor=` | 200 | `0/` | 通过 | | +| `6.mutes` | 禁言列表 | `GET` | `/v1/im/groups/grp4ch145Ku80k/mutes?cursor=` | 200 | `0/` | 通过 | | +| `6.files` | 群文件列表 | `GET` | `/v1/im/groups/grp4ch145Ku80k/files?query=&type=&cursor=` | 404 | `30004/MALFORMED_REQUEST` | 通过 | | ### 第 7 章 @@ -142,9 +134,9 @@ | --- | --- | --- | --- | ---: | --- | --- | --- | | `7.favorites` | 收藏列表 | `GET` | `/v1/im/favorites?type=all&q=&cursor=` | 200 | `0/` | 通过 | | | `7.favorite-batch` | 批量收藏不存在消息 | `POST` | `/v1/im/favorites/batch` | 405 | `30002/METHOD_NOT_ALLOWED` | 未通过 | | -| `7.message-search` | 聊天记录搜索 | `GET` | `/v1/im/topics/grppe4qw1ad4QQ/messages/search?q=%E8%81%94%E8%B0%83&type=text&cursor=` | 200 | `0/` | 通过 | | -| `7.media` | 会话媒体列表 | `GET` | `/v1/im/topics/grppe4qw1ad4QQ/media?type=image&cursor=` | 200 | `0/` | 通过 | | -| `7.msg-context` | 消息上下文 | `GET` | `/v1/im/topics/grppe4qw1ad4QQ/messages/1/context?before=20&after=20` | 200 | `0/` | 通过 | | +| `7.message-search` | 聊天记录搜索 | `GET` | `/v1/im/topics/grp4ch145Ku80k/messages/search?q=%E8%81%94%E8%B0%83&type=text&cursor=` | 200 | `0/` | 通过 | | +| `7.media` | 会话媒体列表 | `GET` | `/v1/im/topics/grp4ch145Ku80k/media?type=image&cursor=` | 200 | `0/` | 通过 | | +| `7.msg-context` | 消息上下文 | `GET` | `/v1/im/topics/grp4ch145Ku80k/messages/1/context?before=20&after=20` | 200 | `0/` | 通过 | | | `7.file-download` | 文件下载不存在文件 | `GET` | `/v0/file/s/nonexistent` | 400 | `0/` | 通过 | | ### 第 8 章 @@ -152,7 +144,7 @@ | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | | `8.calls` | 通话记录列表 | `GET` | `/v1/im/calls?limit=5` | 200 | `0/` | 通过 | | -| `8.topic-calls` | 会话通话记录 | `GET` | `/v1/im/topics/p2pv5HSlKE-PQmYeCpuUEvLxA/calls?limit=5` | 200 | `0/` | 通过 | | +| `8.topic-calls` | 会话通话记录 | `GET` | `/v1/im/topics/p2p--xhFVUQ8QuTOsgdfbEFdw/calls?limit=5` | 200 | `0/` | 通过 | | ### 第 9 章 @@ -161,17 +153,17 @@ | `9.workbench` | 工作台 | `GET` | `/v1/im/workbench` | 200 | `0/` | 通过 | | | `9.depts` | 组织部门 | `GET` | `/v1/im/organization/departments?parent_id=&cursor=` | 200 | `0/` | 通过 | | | `9.org-search-empty` | 组织空关键词搜索 | `GET` | `/v1/im/organization/search?q=` | 400 | `30000/MALFORMED_REQUEST` | 通过 | | -| `9.meeting-create` | 创建会议 | `POST` | `/v1/im/meetings` | 200 | `0/` | 通过 | meeting_id=mtg_RAAFy893M5I9Ikt_ version=1 | +| `9.meeting-create` | 创建会议 | `POST` | `/v1/im/meetings` | 200 | `0/` | 通过 | meeting_id=mtg_FMdvsdTBSc8mAUiB version=1 | | `9.meeting-list` | 会议列表 | `GET` | `/v1/im/meetings?limit=5` | 405 | `30002/METHOD_NOT_ALLOWED` | 通过 | | -| `9.meeting-get` | 会议详情 | `GET` | `/v1/im/meetings/mtg_RAAFy893M5I9Ikt_` | 200 | `0/` | 通过 | | +| `9.meeting-get` | 会议详情 | `GET` | `/v1/im/meetings/mtg_FMdvsdTBSc8mAUiB` | 200 | `0/` | 通过 | | | `9.daily-list` | 日报列表 | `GET` | `/v1/im/reports/daily?limit=5` | 200 | `0/` | 通过 | | -| `9.daily-create` | 创建日报草稿 | `POST` | `/v1/im/reports/daily` | 200 | `0/` | 通过 | report_id=dr_YKKH30euBrcDvopX version=1 | +| `9.daily-create` | 创建日报草稿 | `POST` | `/v1/im/reports/daily` | 200 | `0/` | 通过 | report_id=dr_akcU6KDAcH9g9nwJ version=1 | | `9.daily-stats` | 日报统计 | `GET` | `/v1/im/reports/daily/statistics?date=2026-08-20` | 200 | `0/` | 通过 | | | `9.monthly-list` | 月报列表 | `GET` | `/v1/im/reports/monthly?limit=5` | 200 | `0/` | 通过 | | -| `9.monthly-create` | 创建月报草稿 | `POST` | `/v1/im/reports/monthly` | 200 | `0/` | 通过 | report_id=mr_psOsrZzBuyiGhjZP version=1 | +| `9.monthly-create` | 创建月报草稿 | `POST` | `/v1/im/reports/monthly` | 200 | `0/` | 通过 | report_id=mr_iULR69u4Y8_IbXMg version=1 | | `9.monthly-stats` | 月报统计 | `GET` | `/v1/im/reports/monthly/statistics?month=2026-08` | 200 | `0/` | 通过 | | -| `9.mailbox-config` | 总经理信箱配置 | `GET` | `/v1/im/executive-mailbox/config` | 500 | `90000/INTERNAL_ERROR` | 未通过 | | -| `9.mailbox-submit` | 总经理信箱提交 | `POST` | `/v1/im/executive-mailbox/submissions` | 500 | `90000/INTERNAL_ERROR` | 未通过 | | +| `9.mailbox-config` | 总经理信箱配置 | `GET` | `/v1/im/executive-mailbox/config` | 200 | `0/` | 通过 | notice_version=2026-08-13T15:04:31.004Z | +| `9.mailbox-submit` | 总经理信箱提交 | `POST` | `/v1/im/executive-mailbox/submissions` | 200 | `0/` | 通过 | | ### 第 10 章 @@ -184,27 +176,27 @@ | `10.privacy-patch` | 更新隐私设置 | `PATCH` | `/v1/im/me/privacy` | 200 | `0/` | 通过 | | | `10.youth` | 青少年模式 | `GET` | `/v1/im/settings/youth-mode` | 200 | `0/` | 通过 | | | `10.independent-verify` | 独立密码验证 | `POST` | `/v1/im/settings/independent-password/verify` | 403 | `30042/ACTION_TOKEN_INVALID` | 通过 | | -| `10.push` | 设备 Push Token | `PUT` | `/v1/im/devices/audit-device-35758000/push-token` | 200 | `0/` | 通过 | | +| `10.push` | 设备 Push Token | `PUT` | `/v1/im/devices/audit-device-98656000/push-token` | 200 | `0/` | 通过 | | ### 第 11 章 | ID | 场景 | 方法 | 路径 | HTTP | code/reason | 结果 | 备注 | | --- | --- | --- | --- | ---: | --- | --- | --- | | `11.url` | URL 风险检查 | `POST` | `/v1/im/security/urls/check` | 200 | `0/` | 通过 | | -| `11.abuse-reasons` | 举报原因 | `GET` | `/v1/im/reports/abuse/reasons?target_type=user` | 500 | `90000/INTERNAL_ERROR` | 未通过 | reason= | +| `11.abuse-reasons` | 举报原因 | `GET` | `/v1/im/reports/abuse/reasons?target_type=user` | 200 | `0/` | 通过 | reason=fraud | | `11.abuse-submit` | 提交举报 | `POST` | `/v1/im/reports/abuse` | 400 | `30000/MALFORMED_REQUEST` | 通过 | | | `11.feedback-config` | 反馈配置 | `GET` | `/v1/im/feedback/config` | 200 | `0/` | 通过 | category=bug | | `11.feedback` | 提交反馈 | `POST` | `/v1/im/feedback` | 200 | `0/` | 通过 | | ## 5. 测试产生的数据 -- 用户 A:`usrv5HSlKE-PQk`,username `a35758000`,phone `15535758000` -- 用户 B:`usrmHgqblBLy8Q`,username `b35758000`,phone `15635758000` -- 好友申请:`frq_Z8SqjqK1iNg` -- P2P Topic:`p2pv5HSlKE-PQmYeCpuUEvLxA` -- 群 Topic:`grppe4qw1ad4QQ` -- 会议:`mtg_RAAFy893M5I9Ikt_` -- 日报草稿:`dr_YKKH30euBrcDvopX` -- 月报草稿:`mr_psOsrZzBuyiGhjZP` +- 用户 A:`usr--xhFVUQ8Qs`,username `a98656000`,phone `15598656000` +- 用户 B:`usrkzrIHX2xBXc`,username `b98656000`,phone `15698656000` +- 好友申请:`frq_4BCvvh7aJaQ` +- P2P Topic:`p2p--xhFVUQ8QuTOsgdfbEFdw` +- 群 Topic:`grp4ch145Ku80k` +- 会议:`mtg_FMdvsdTBSc8mAUiB` +- 日报草稿:`dr_akcU6KDAcH9g9nwJ` +- 月报草稿:`mr_iULR69u4Y8_IbXMg` 这些数据位于测试环境租户 `default`,可按需清理。 diff --git a/server/im_http.go b/server/im_http.go index c00dc87..5f7ccbe 100644 --- a/server/im_http.go +++ b/server/im_http.go @@ -2705,6 +2705,8 @@ func serveIMFavoriteResource(wrt http.ResponseWriter, req *http.Request) { } tail := strings.Trim(strings.TrimPrefix(req.URL.Path[idx:], prefix), "/") switch { + case tail == "batch": + serveIMFavoriteBatchCreate(wrt, req) case tail == "batch-delete": serveIMFavoriteBatchDelete(wrt, req) case tail == "forward":