149 lines
3.9 KiB
TypeScript
149 lines
3.9 KiB
TypeScript
/**
|
|
* 技师数据
|
|
*/
|
|
import { BaseData } from "./BaseData";
|
|
import proto from 'db://assets/Scripts/proto/proto.pb.js';
|
|
|
|
export interface GirlBriefVO {
|
|
id: number;
|
|
name: string;
|
|
age: number;
|
|
tagKey: string;
|
|
priceType: number;
|
|
price: number; // 用 number 存(i64 转)
|
|
avatar: string;
|
|
star: number;
|
|
}
|
|
|
|
export interface GirlPhotoVO {
|
|
pic: string;
|
|
isRelease: boolean;
|
|
price: number;
|
|
}
|
|
|
|
export interface GirlDetailVO {
|
|
id: number; // = brief.id
|
|
desc: string;
|
|
isRelease: boolean;
|
|
chatCount: number;
|
|
photos: GirlPhotoVO[];
|
|
}
|
|
|
|
export class GirlData extends BaseData {
|
|
// 实体归一化
|
|
private _briefs = new Map<number, GirlBriefVO>();
|
|
private _details = new Map<number, GirlDetailVO>();
|
|
|
|
// 列表索引
|
|
private _dailyRecommend: number[] = [];
|
|
private _categoryPages = new Map<number, Map<number, number[]>>(); // category -> (page -> [girlId])
|
|
|
|
get briefById() { return this._briefs; }
|
|
get detailById() { return this._details; }
|
|
get dailyRecommendIds() { return this._dailyRecommend; }
|
|
|
|
|
|
public reset(): void {
|
|
this._briefs.clear();
|
|
this._details.clear();
|
|
this._dailyRecommend = [];
|
|
this._categoryPages.clear();
|
|
}
|
|
|
|
public clear(): void {
|
|
this._briefs.clear();
|
|
this._details.clear();
|
|
this._dailyRecommend = [];
|
|
this._categoryPages.clear();
|
|
}
|
|
|
|
public destroy(): void {
|
|
super.destroy();
|
|
this._briefs = null;
|
|
this._details = null;
|
|
this._dailyRecommend = null;
|
|
this._categoryPages = null;
|
|
}
|
|
|
|
/** 合并 Brief 列表到缓存(去重+覆盖最新字段) */
|
|
mergeBriefs(list: pb.cs.IGirlBrief[] | pb.cs.GirlBrief[]): void {
|
|
for (const g of list) {
|
|
const id = g.id!;
|
|
this._briefs.set(id, {
|
|
id,
|
|
name: g.name || "",
|
|
age: g.age || 0,
|
|
tagKey: g.tagKey || "",
|
|
priceType: g.priceType || 0,
|
|
price: i64(g.price),
|
|
avatar: g.avatar || "",
|
|
star: g.star || 0,
|
|
});
|
|
}
|
|
}
|
|
|
|
/** 每日推荐:只维护 id 索引,实体来自 _briefs */
|
|
applyDailyRecommend(res: pb.cs.ICSDailyRecommendRes): void {
|
|
const girls = res.girls ?? [];
|
|
this.mergeBriefs(girls);
|
|
this._dailyRecommend = girls.map(g => g.id!);
|
|
}
|
|
|
|
/** 分类分页列表:category + page -> id[] */
|
|
applyGirlList(category: number, page: number, res: pb.cs.ICSGetGirlListRes): void {
|
|
const girls = res.girls ?? [];
|
|
this.mergeBriefs(girls);
|
|
|
|
if (!this._categoryPages.has(category)) {
|
|
this._categoryPages.set(category, new Map());
|
|
}
|
|
const pages = this._categoryPages.get(category)!;
|
|
pages.set(page, girls.map(g => g.id!));
|
|
}
|
|
|
|
/** 详情:合并 brief + detail */
|
|
applyGirlDetail(res: pb.cs.ICSGetGirlDetailRes): void {
|
|
const d = res.detail!;
|
|
const b = d.brief!;
|
|
this.mergeBriefs([b]);
|
|
|
|
const vo: GirlDetailVO = {
|
|
id: b.id!,
|
|
desc: d.desc || "",
|
|
isRelease: !!d.isRelease,
|
|
chatCount: d.chatCount || 0,
|
|
photos: (d.photos ?? []).map(p => ({
|
|
pic: p.pic || "",
|
|
isRelease: !!p.isRelease,
|
|
price: p.price || 0,
|
|
})),
|
|
};
|
|
this._details.set(vo.id, vo);
|
|
}
|
|
|
|
/** 页面读取:根据分类+页获取 id 列表 */
|
|
getPageIds(category: number, page: number): number[] {
|
|
const pages = this._categoryPages.get(category);
|
|
return pages?.get(page) ?? [];
|
|
}
|
|
|
|
/** 本地变更:聊天次数变更(成功买次数后) */
|
|
incChatCount(girlId: number, delta: number) {
|
|
const d = this._details.get(girlId);
|
|
if (d) d.chatCount = Math.max(0, d.chatCount + delta);
|
|
}
|
|
|
|
/** 本地变更:解锁技师/照片(例如购买后或服务器回调) */
|
|
setGirlReleased(girlId: number, v: boolean) {
|
|
const d = this._details.get(girlId);
|
|
if (d) d.isRelease = v;
|
|
}
|
|
setPhotoReleased(girlId: number, pic: string, v: boolean) {
|
|
const d = this._details.get(girlId);
|
|
if (!d) return;
|
|
const p = d.photos.find(x => x.pic === pic);
|
|
if (p) p.isRelease = v;
|
|
}
|
|
|
|
}
|