feat(companion): 全面扩展同城生活陪伴体系(陪吃·陪喝·陪玩),完成TDD测试与安全核销闭环
这个提交包含在:
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 陪伴服务赛道与品类管理核心
|
||||
* 支持【线上游戏陪玩】与【同城线下陪玩·陪吃·陪喝】多维服务形态
|
||||
*/
|
||||
|
||||
export enum CompanionTrack {
|
||||
ONLINE_GAME = 'ONLINE_GAME', // 线上游戏陪玩 (王者/和平/LOL等)
|
||||
OFFLINE_PLAY = 'OFFLINE_PLAY', // 线下同城陪玩 (桌游/剧本杀/运动/漫展)
|
||||
OFFLINE_MEAL = 'OFFLINE_MEAL', // 线下同城陪吃 (网红探店/火锅/餐厅饭搭子)
|
||||
OFFLINE_DRINK = 'OFFLINE_DRINK', // 线下同城陪喝 (咖啡下午茶/茶室清吧)
|
||||
}
|
||||
|
||||
export enum ExpenseBurdenType {
|
||||
AA_SHARE = 'AA_SHARE', // 现场消费 AA 制各自付
|
||||
BUYER_TREAT = 'BUYER_TREAT', // 客户全包请客
|
||||
SELF_CARE = 'SELF_CARE', // 大神自理
|
||||
}
|
||||
|
||||
export interface ServiceItem {
|
||||
id: string;
|
||||
track: CompanionTrack;
|
||||
title: string;
|
||||
gameName?: string;
|
||||
city?: string;
|
||||
venueType?: string;
|
||||
unitPriceCents: number;
|
||||
unit: string;
|
||||
}
|
||||
|
||||
export interface CreateServiceItemDto {
|
||||
track: CompanionTrack;
|
||||
title: string;
|
||||
gameName?: string;
|
||||
city?: string;
|
||||
venueType?: string;
|
||||
unitPriceCents: number;
|
||||
unit: string;
|
||||
}
|
||||
|
||||
// 严禁私人隐蔽场所列表 (安全风控红线)
|
||||
const UNSAFE_VENUE_PATTERNS = [/私人住宅/, /私人公寓/, /酒店客房/, /私密/];
|
||||
|
||||
export class ServiceCategoryManager {
|
||||
private idCounter = 1000;
|
||||
|
||||
getAllTracks(): CompanionTrack[] {
|
||||
return [
|
||||
CompanionTrack.ONLINE_GAME,
|
||||
CompanionTrack.OFFLINE_PLAY,
|
||||
CompanionTrack.OFFLINE_MEAL,
|
||||
CompanionTrack.OFFLINE_DRINK,
|
||||
];
|
||||
}
|
||||
|
||||
getExpenseBurdenTypes(): ExpenseBurdenType[] {
|
||||
return [
|
||||
ExpenseBurdenType.AA_SHARE,
|
||||
ExpenseBurdenType.BUYER_TREAT,
|
||||
ExpenseBurdenType.SELF_CARE,
|
||||
];
|
||||
}
|
||||
|
||||
createServiceItem(dto: CreateServiceItemDto): ServiceItem {
|
||||
if (dto.track === CompanionTrack.ONLINE_GAME) {
|
||||
if (!dto.gameName || dto.gameName.trim() === '') {
|
||||
throw new Error('线上游戏陪玩服务必须指定具体游戏品类');
|
||||
}
|
||||
} else {
|
||||
// 线下陪玩、陪吃、陪喝安全校验
|
||||
if (!dto.city || dto.city.trim() === '') {
|
||||
throw new Error('线下陪伴服务必须指定服务城市');
|
||||
}
|
||||
|
||||
if (dto.venueType) {
|
||||
for (const pattern of UNSAFE_VENUE_PATTERNS) {
|
||||
if (pattern.test(dto.venueType)) {
|
||||
throw new Error('安全风控触发: 线下陪伴服务仅限在合法的公开商业场所履约,禁止私人住宅或私密空间');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: `srv_${++this.idCounter}`,
|
||||
track: dto.track,
|
||||
title: dto.title,
|
||||
gameName: dto.gameName,
|
||||
city: dto.city,
|
||||
venueType: dto.venueType,
|
||||
unitPriceCents: dto.unitPriceCents,
|
||||
unit: dto.unit,
|
||||
};
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户