fix(日报): "提醒未提交成员"改用组织架构接口凑候选名单,不再必现400

后端问题清单"新增2"记录过:POST /reports/daily/reminders 要求调用方传入完整候选
user_ids 名单(服务端只做"从候选里筛出未交的人再提醒",不会自己算全公司名单),
但前端一直传空数组,必然命中服务端"user_ids为空"的400校验。

重新核实时发现这条其实不是后端缺口——GET /organization/members 不传 q/department_id
时就会返回调用者可见范围内的全部在职成员(分页),这个接口本来就在会议参会人选择器
里用着,只是"提醒未提交成员"这个按钮没有复用它。改为点击时先分页拉取全部组织成员
user_id,再传给提醒接口;组织架构为空时给出明确提示而不是让请求再次落入400。

已在浏览器验证请求格式(limit=100,与后端实际接受的参数一致)和空组织架构下的
兜底提示;当前测试租户组织架构数据本身为空,未能覆盖"真的有人被提醒"这条路径,
但接口契约已对照 im_be 源码逐字段核实。
This commit is contained in:
Your Name
2026-09-06 12:07:24 +08:00
parent 623f7dc40f
commit 4fc65b0f40
4 changed files with 36 additions and 8 deletions
+2 -2
View File
@@ -767,8 +767,8 @@ export const getOrganizationDepartmentMembers = (departmentId, cursor = '') =>
// server/im_http_test.go's own request fixtures. This function used to send `query`, silently making
// every caller's search box a no-op (server ignores the unrecognized param and returns the unfiltered
// list every time).
export const getOrganizationMembers = ({query = '', departmentId = '', cursor = ''} = {}) =>
imGet('/organization/members' + qs({q: query, department_id: departmentId, cursor}));
export const getOrganizationMembers = ({query = '', departmentId = '', cursor = '', limit = ''} = {}) =>
imGet('/organization/members' + qs({q: query, department_id: departmentId, cursor, limit}));
export const searchOrganization = (query = '', types = 'department,user', cursor = '') =>
imGet('/organization/search' + qs({q: query, types, cursor}));
export const getMeetings = (cursor = '', limit = 20) => imGet('/meetings' + qs({limit, cursor}));
+15 -2
View File
@@ -754,9 +754,22 @@ function DailyReportList({team, myUserId, onToast}) {
return hay.includes(query);
});
// TenantDailyReportRemind (server/db/mysql/tenant_adapter.go) filters *out of a candidate list the
// caller supplies* down to whoever hasn't submitted today -- it doesn't compute "everyone" itself,
// and rejects an empty user_ids with 400. GET /organization/members with no q/department_id already
// returns every member the caller can see (paginated), which is exactly the candidate pool this
// button's "提醒未提交成员" wording implies -- so page through it here rather than reporting this as
// a backend gap, matching how getOrganizationMembers is already used for the meeting attendee picker.
const remindMissing = () => {
sendDailyReminders(toDateInputValue(new Date())).then(_ => onToast('已提醒未提交成员'))
.catch(err => onToast(err.message || '提醒失败'));
const collectAllMembers = (cursor, acc) =>
getOrganizationMembers({cursor, limit: 100}).then(d => {
const next = acc.concat((d.items || []).map(m => m.user_id));
return d.has_more && d.next_cursor ? collectAllMembers(d.next_cursor, next) : next;
});
collectAllMembers('', []).then(userIds => {
if (!userIds.length) { onToast('组织架构里没有可提醒的成员'); return; }
return sendDailyReminders(toDateInputValue(new Date()), userIds).then(_ => onToast('已提醒未提交成员'));
}).catch(err => onToast(err.message || '提醒失败'));
};
return <div className="workplace-page report-list-page">