diff --git a/docs/IM-前后端对接文档.md b/docs/IM-前后端对接文档.md index 33d0870..29e9e1c 100644 --- a/docs/IM-前后端对接文档.md +++ b/docs/IM-前后端对接文档.md @@ -2195,8 +2195,8 @@ X-Tinode-APIKey: <预置的普通 API Key> | `POST /v1/im/meetings/{id}/cancel` | `{"version":2,"reason":"时间冲突"}` | `{"meeting_id":"mtg_1","state":"cancelled","version":3}` | | `POST /v1/im/meetings/{id}/reminders` | `{}` | `{"meeting_id":"mtg_1","items":[{"user_id":"usr...","status":"sent"}]}` | | `PUT /v1/im/meetings/{meeting_id}/my-response` | `{"response":"accepted","version":1}` | `{"meeting_id":"mtg_1","my_response":"accepted","version":2,"response_at":"2026-08-20T09:00:00Z"}` | -| `GET /v1/im/reports/daily?scope=mine&from=&to=&status=&cursor=` | Query only | `{"items":[{"report_id":"dr_1","report_date":"2026-08-20","status":"draft","draft_updated_at":"2026-08-20T09:00:00Z","submitted_at":null,"read_state":"unread"}],"next_cursor":"","permissions":{"can_create":true,"makeup_allowed_days":7}}` | -| `GET /v1/im/reports/daily?scope=managed&date=&status=submitted\|missing&department_id=&cursor=` | Query only | `{"items":[{"report_id":"dr_1","author":{"user_id":"usr...","display_name":"张三"},"report_date":"2026-08-20","status":"submitted","submitted_at":"2026-08-20T09:00:00Z","read_state":"unread"}],"next_cursor":"","permissions":{"can_remind_unsubmitted":true,"can_view_managed":true}}` | +| `GET /v1/im/reports/daily?scope=mine&from=&to=&status=&cursor=` | Query only | `{"items":[{"report_id":"dr_1","report_date":"2026-08-20","content_short":"今日完成联调和问题回归...","status":"draft","draft_updated_at":"2026-08-20T09:00:00Z","submitted_at":null,"read_state":"unread"}],"next_cursor":"","permissions":{"can_create":true,"makeup_allowed_days":7}}` | +| `GET /v1/im/reports/daily?scope=managed&date=&status=submitted\|missing&department_id=&cursor=` | Query only | `{"items":[{"report_id":"dr_1","author":{"user_id":"usr...","display_name":"张三"},"report_date":"2026-08-20","content_short":"完成日报提交和项目同步...","status":"submitted","submitted_at":"2026-08-20T09:00:00Z","read_state":"unread"}],"next_cursor":"","permissions":{"can_remind_unsubmitted":true,"can_view_managed":true}}` | | `POST /v1/im/reports/daily` | `{"report_date":"2026-08-20"}` | `{"report_id":"dr_1","report_date":"2026-08-20","content":"","attachments":[],"status":"draft","version":1,"permissions":{"can_edit":true,"can_submit":true,"can_view":true}}` | | `PUT /v1/im/reports/daily/{id}/draft` | `{"content":"今日完成联调","attachments":[],"version":1}` | `{"report_id":"dr_1","content":"今日完成联调","attachments":[],"status":"draft","version":2,"draft_updated_at":"2026-08-20T09:00:00Z"}` | | `POST /v1/im/reports/daily/{id}/submit` | `{"version":2}` | `{"report_id":"dr_1","status":"submitted","submitted_at":"2026-08-20T09:00:00Z","version":3}` | diff --git a/server/im_http.go b/server/im_http.go index e7dca2c..5887631 100644 --- a/server/im_http.go +++ b/server/im_http.go @@ -7168,6 +7168,7 @@ func dailyReportListPayload(report types.DailyReport) map[string]any { "report_id": report.ReportID, "author_id": report.AuthorID.UserId(), "report_date": report.ReportDate.Format("2006-01-02"), + "content_short": monthlyReportPreview(report.Content), "status": report.Status, "draft_updated_at": report.UpdatedAt.UTC().Format(time.RFC3339Nano), "read_state": report.ReadState, diff --git a/server/im_http_test.go b/server/im_http_test.go index ae7671a..8819ea4 100644 --- a/server/im_http_test.go +++ b/server/im_http_test.go @@ -2419,6 +2419,42 @@ func TestServeIMDailyReportStatisticsAndReminders(t *testing.T) { } } +func TestServeIMDailyReportsListIncludesContentPreview(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + expectIMBearer(t, ctrl, "token-1", 7, 42) + oldDailyReports := store.DailyReports + now := time.Now().UTC().Round(time.Millisecond) + reports := &testDailyReportsStore{report: &types.DailyReport{ + ReportID: "dr_test", + AuthorID: 42, + ReportDate: time.Date(2026, 8, 14, 0, 0, 0, 0, time.UTC), + Content: strings.Repeat("日报", 80), + Status: types.DailyReportStatusDraft, + ReadState: "unread", + Version: 1, + CreatedAt: now, + UpdatedAt: now, + }} + store.DailyReports = reports + defer func() { store.DailyReports = oldDailyReports }() + + req := httptest.NewRequest(http.MethodGet, "/v1/im/reports/daily?scope=mine", nil) + req.Header.Set("Authorization", "Bearer token-1") + rec := httptest.NewRecorder() + serveIMDailyReports(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("status: got %d, want %d; body=%s", rec.Code, http.StatusOK, rec.Body.String()) + } + data := decodeIMHTTPResponse(t, rec).Data.(map[string]any) + items := data["items"].([]any) + item := items[0].(map[string]any) + if item["content_short"] != strings.Repeat("日报", 60)+"..." { + t.Fatalf("unexpected daily report preview: %#v", item["content_short"]) + } +} + func TestServeIMMonthlyReportsCreate(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish()