feat: 完成会员消息触达模块页面与交互

This commit is contained in:
2026-03-04 11:36:49 +08:00
parent 058ec9c142
commit 3056b56082
26 changed files with 3485 additions and 0 deletions

View File

@@ -282,4 +282,5 @@ export async function getMemberCouponPickerApi(params: {
);
}
export * from './message-reach';
export * from './stored-card';

View File

@@ -0,0 +1,283 @@
/**
* 文件职责:会员消息触达模块 API 契约定义。
*/
import { requestClient } from '#/api/request';
/** 消息状态。 */
export type MemberMessageReachStatus =
| 'draft'
| 'failed'
| 'pending'
| 'sending'
| 'sent';
/** 消息渠道。 */
export type MemberMessageReachChannel = 'inapp' | 'sms' | 'wechat-mini';
/** 目标人群类型。 */
export type MemberMessageAudienceType = 'all' | 'tag';
/** 发送时间类型。 */
export type MemberMessageScheduleType = 'immediate' | 'scheduled';
/** 模板分类。 */
export type MemberMessageTemplateCategory = 'marketing' | 'notice' | 'recall';
/** 页面统计。 */
export interface MemberMessageReachStatsDto {
conversionRate: number;
monthlySentCount: number;
openRate: number;
reachMemberCount: number;
}
/** 消息列表查询。 */
export interface MemberMessageReachListQuery {
channel?: MemberMessageReachChannel;
keyword?: string;
page: number;
pageSize: number;
status?: MemberMessageReachStatus;
}
/** 消息列表项。 */
export interface MemberMessageReachListItemDto {
audienceText: string;
channels: MemberMessageReachChannel[];
conversionRate: number;
estimatedReachCount: number;
messageId: string;
openRate: number;
scheduledAt?: string;
sentAt?: string;
status: MemberMessageReachStatus;
title: string;
}
/** 消息列表结果。 */
export interface MemberMessageReachListResultDto {
items: MemberMessageReachListItemDto[];
page: number;
pageSize: number;
totalCount: number;
}
/** 收件明细。 */
export interface MemberMessageReachRecipientDto {
channel: MemberMessageReachChannel;
convertedAt?: string;
errorMessage?: string;
memberId: string;
mobile?: string;
openId?: string;
readAt?: string;
sentAt?: string;
status: 'failed' | 'pending' | 'sent';
}
/** 消息详情。 */
export interface MemberMessageReachDetailDto {
audienceTags: string[];
audienceText: string;
audienceType: MemberMessageAudienceType;
channels: MemberMessageReachChannel[];
content: string;
conversionRate: number;
convertedCount: number;
estimatedReachCount: number;
lastError?: string;
messageId: string;
openRate: number;
readCount: number;
recipients: MemberMessageReachRecipientDto[];
scheduleType: MemberMessageScheduleType;
scheduledAt?: string;
sentAt?: string;
sentCount: number;
status: MemberMessageReachStatus;
templateId?: string;
title: string;
}
/** 保存消息请求。 */
export interface SaveMemberMessageReachPayload {
audienceTags: string[];
audienceType: MemberMessageAudienceType;
channels: MemberMessageReachChannel[];
content: string;
messageId?: string;
scheduleType: MemberMessageScheduleType;
scheduledAt?: string;
storeId?: string;
submitAction: 'draft' | 'send';
templateId?: string;
title: string;
}
/** 删除消息请求。 */
export interface DeleteMemberMessageReachPayload {
messageId: string;
}
/** 调度元信息。 */
export interface MemberMessageDispatchMetaDto {
hangfireJobId?: string;
messageId: string;
scheduleType: MemberMessageScheduleType;
scheduledAt?: string;
status: MemberMessageReachStatus;
}
/** 目标估算请求。 */
export interface EstimateMemberMessageAudiencePayload {
audienceType: MemberMessageAudienceType;
tags: string[];
}
/** 目标估算响应。 */
export interface MemberMessageAudienceEstimateDto {
reachCount: number;
}
/** 模板列表查询。 */
export interface MemberMessageTemplateListQuery {
category?: MemberMessageTemplateCategory;
keyword?: string;
page: number;
pageSize: number;
}
/** 模板 DTO。 */
export interface MemberMessageTemplateDto {
category: MemberMessageTemplateCategory;
content: string;
lastUsedAt?: string;
name: string;
templateId: string;
usageCount: number;
}
/** 模板列表结果。 */
export interface MemberMessageTemplateListResultDto {
items: MemberMessageTemplateDto[];
page: number;
pageSize: number;
totalCount: number;
}
/** 保存模板请求。 */
export interface SaveMemberMessageTemplatePayload {
category: MemberMessageTemplateCategory;
content: string;
name: string;
templateId?: string;
}
/** 删除模板请求。 */
export interface DeleteMemberMessageTemplatePayload {
templateId: string;
}
/** 查询页面统计。 */
export async function getMemberMessageReachStatsApi(params?: {
storeId?: string;
}) {
return requestClient.get<MemberMessageReachStatsDto>(
'/member/message-reach/stats',
{
params,
},
);
}
/** 查询消息列表。 */
export async function getMemberMessageReachListApi(
params: MemberMessageReachListQuery,
) {
return requestClient.get<MemberMessageReachListResultDto>(
'/member/message-reach/list',
{
params,
},
);
}
/** 查询消息详情。 */
export async function getMemberMessageReachDetailApi(params: {
messageId: string;
}) {
return requestClient.get<MemberMessageReachDetailDto>(
'/member/message-reach/detail',
{
params,
},
);
}
/** 保存消息。 */
export async function saveMemberMessageReachApi(
payload: SaveMemberMessageReachPayload,
) {
return requestClient.post<MemberMessageDispatchMetaDto>(
'/member/message-reach/save',
payload,
);
}
/** 删除消息。 */
export async function deleteMemberMessageReachApi(
payload: DeleteMemberMessageReachPayload,
) {
return requestClient.post('/member/message-reach/delete', payload);
}
/** 估算触达人数。 */
export async function estimateMemberMessageAudienceApi(
payload: EstimateMemberMessageAudiencePayload,
) {
return requestClient.post<MemberMessageAudienceEstimateDto>(
'/member/message-reach/audience/estimate',
payload,
);
}
/** 查询模板列表。 */
export async function getMemberMessageTemplateListApi(
params: MemberMessageTemplateListQuery,
) {
return requestClient.get<MemberMessageTemplateListResultDto>(
'/member/message-reach/template/list',
{
params,
},
);
}
/** 查询模板详情。 */
export async function getMemberMessageTemplateDetailApi(params: {
templateId: string;
}) {
return requestClient.get<MemberMessageTemplateDto>(
'/member/message-reach/template/detail',
{
params,
},
);
}
/** 保存模板。 */
export async function saveMemberMessageTemplateApi(
payload: SaveMemberMessageTemplatePayload,
) {
return requestClient.post<MemberMessageTemplateDto>(
'/member/message-reach/template/save',
payload,
);
}
/** 删除模板。 */
export async function deleteMemberMessageTemplateApi(
payload: DeleteMemberMessageTemplatePayload,
) {
return requestClient.post('/member/message-reach/template/delete', payload);
}