export const CONTENT_POST_TYPES = [ 'ORGANIZATION_INTRO', 'PUBLIC_WELFARE_NEWS', 'SERVICE_STORY', 'NOTICE', 'FAQ', ] as const; export type ContentPostType = (typeof CONTENT_POST_TYPES)[number]; export const CONTENT_POST_TYPE_LABELS: Record = { ORGANIZATION_INTRO: '机构介绍', PUBLIC_WELFARE_NEWS: '公益动态', SERVICE_STORY: '服务故事', NOTICE: '通知公告', FAQ: '常见问题', }; export const CONTENT_POST_STATUSES = ['DRAFT', 'PENDING_REVIEW', 'PUBLISHED', 'ARCHIVED'] as const; export type ContentPostStatus = (typeof CONTENT_POST_STATUSES)[number]; export const CONTENT_POST_STATUS_LABELS: Record = { DRAFT: '草稿', PENDING_REVIEW: '待审核', PUBLISHED: '已发布', ARCHIVED: '已归档', }; export interface ContentPostListItem { publicId: string; type: ContentPostType; title: string; summary: string; status: ContentPostStatus; revision: number; publishedAt: string | null; updatedAt: string; } export interface ContentStatusHistoryItem { fromStatus: ContentPostStatus | null; toStatus: ContentPostStatus; reasonCode: string; note: string | null; createdAt: string; } export interface ContentPostDetail extends ContentPostListItem { content: string; coverFilePublicId: string | null; privacyReviewedAt: string | null; reviewedAt: string | null; history: ContentStatusHistoryItem[]; } export interface PaginatedContentPostsResponse { items: ContentPostListItem[]; page: number; pageSize: number; total: number; } export interface ContentPostDetailResponse { post: ContentPostDetail; idempotentReplay?: boolean; } export interface CreateContentPostRequest { clientRequestId: string; type: ContentPostType; title: string; summary: string; content: string; coverFilePublicId?: string; } export interface UpdateContentPostRequest extends Omit< CreateContentPostRequest, 'clientRequestId' > { expectedRevision: number; } export interface TransitionContentPostRequest { clientRequestId: string; targetStatus: ContentPostStatus; note: string; privacyReviewed?: true; } export const NOTIFICATION_TYPES = [ 'APPLICATION_SUBMITTED', 'APPLICATION_ACCEPTED', 'SERVICE_ARRANGED', 'SERVICE_COMPLETED', 'FOLLOW_UP_PENDING', 'ACTIVITY_REGISTRATION_RESULT', ] as const; export type NotificationType = (typeof NOTIFICATION_TYPES)[number]; export const NOTIFICATION_TYPE_LABELS: Record = { APPLICATION_SUBMITTED: '申请已提交', APPLICATION_ACCEPTED: '申请已受理', SERVICE_ARRANGED: '服务已安排', SERVICE_COMPLETED: '服务已完成', FOLLOW_UP_PENDING: '待回访', ACTIVITY_REGISTRATION_RESULT: '活动报名结果', }; export interface NotificationItem { publicId: string; type: NotificationType; title: string; body: string; resourceType: string | null; resourcePublicId: string | null; readAt: string | null; createdAt: string; } export interface PaginatedNotificationsResponse { items: NotificationItem[]; page: number; pageSize: number; total: number; unreadCount: number; } export interface NotificationPreferenceItem { type: NotificationType; inAppEnabled: boolean; wechatEnabled: boolean; authorizedAt: string | null; } export interface NotificationPreferencesResponse { items: NotificationPreferenceItem[]; wechatAdapterConfigured: boolean; } export interface UpdateNotificationPreferencesRequest { items: Array<{ type: NotificationType; inAppEnabled: boolean; wechatEnabled: boolean }>; } export interface NotificationDeliveryItem { publicId: string; notificationPublicId: string; type: NotificationType; channel: 'WECHAT_SUBSCRIPTION'; status: 'PENDING' | 'PROCESSING' | 'SENT' | 'FAILED' | 'DEAD'; attemptCount: number; nextAttemptAt: string; lastAttemptAt: string | null; errorCode: string | null; createdAt: string; } export interface PaginatedNotificationDeliveriesResponse { items: NotificationDeliveryItem[]; page: number; pageSize: number; total: number; }