Files
18xchat/assets/Scripts/chat18x/data/GirlData.ts
T
2025-08-28 17:22:25 +08:00

366 lines
12 KiB
TypeScript

/**
* 技师数据
*/
import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
// 分类的数据结构
interface CategoryBucket {
// 技师的简要数据
briefs: Map<number, proto.cs.IGirlBrief>;
// 技师的详细数据
details: Map<number, proto.cs.IGirlDetail>;
// 技师的id
girlIds: number[];
}
export class GirlData extends BaseData {
// 大分类
private _categories = new Map<string, CategoryBucket>();
// 列表索引
private _dailyRecommend: number[] = [];
public reset(): void {
this._categories.clear();
}
public clear(): void {
this._categories.clear();
}
public destroy(): void {
super.destroy();
this._categories = null;
}
/** 保障 _categories 存在 */
private ensureCategories(): Map<string, CategoryBucket> {
if (!this._categories) {
this._categories = new Map<string, CategoryBucket>();
}
return this._categories;
}
/** 获取或创建分类桶 */
private ensureBucket(categoryId: string): CategoryBucket {
const cats = this.ensureCategories();
let bucket = cats.get(categoryId);
if (!bucket) {
bucket = {
briefs: new Map<number, proto.cs.IGirlBrief>(),
details: new Map<number, proto.cs.IGirlDetail>(),
girlIds: [],
};
cats.set(categoryId, bucket);
}
return bucket;
}
/** 取分类下的全部 girlIds(若分类不存在返回空数组) */
public getGirlIds(categoryId: string): number[] {
const b = this.ensureCategories().get(categoryId);
return b ? b.girlIds : [];
}
/** --------------------------------------------------------- 技师的简要数据 --------------------------------------------------------- */
// 解析技师简要数据,一个
private parseOneGirlBrief(data: proto.cs.IGirlBrief): proto.cs.IGirlBrief | null {
if (!data) return null;
const oneData: proto.cs.IGirlBrief = {
id: data.id, // id
name: data.name, // 名字
age: data.age, // 年龄
tagKey: data.tagKey, // 标签
priceType: data.priceType, // 付费类型
price: data.price, // 价格
avatar: data.avatar, // 头像
star: data.star, // 星级
};
return oneData;
}
// 解析技师简要数据,多个
private parseAllGirlBrief(data: proto.cs.IGirlBrief[]): proto.cs.IGirlBrief[] | null {
if (!data) return null;
let allData = [];
for (const value of data) {
const oneData: proto.cs.IGirlBrief = this.parseOneGirlBrief(value);
if (oneData) {
allData.push(oneData);
}
}
return allData;
}
/** 保存技师的简要数据 */
public setGirlBriefs(categoryId: string, data: proto.cs.ICSGetGirlListRes): void {
let allData = this.parseAllGirlBrief(data.girls);
if (!allData) return;
const bucket = this.ensureBucket(categoryId);
if (allData) {
for (const g of allData) {
const id = g.id;
bucket.briefs.set(id, g);
// TODO,去重
bucket.girlIds.push(id);
}
}
console.log("保存技师的简要数据: ", bucket);
}
/** 取某分类 + girlId 的简要信息 */
private getGrilBrief(categoryId: string, girlId: number): proto.cs.IGirlBrief | null {
const b = this.ensureCategories().get(categoryId);
if (!b) return null;
return b.briefs.get(girlId) ?? null;
}
/** 获取名字 */
public getGrilName(categoryId: string, girlId: number): string {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return "";
return oneData.name;
}
/** 获取年龄 */
public getGrilAge(categoryId: string, girlId: number): number {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0;
return oneData.age;
}
/** 获取标签 */
public getGrilTagKey(categoryId: string, girlId: number): string {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return "";
return oneData.tagKey;
}
/** 获取付费类型 */
public getGrilPriceType(categoryId: string, girlId: number): number {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0;
return oneData.priceType;
}
/** 获取价格 */
public getGrilPrice(categoryId: string, girlId: number): number {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0;
return oneData.price;
}
/** 获取头像 */
public getGrilAvatar(categoryId: string, girlId: number): string {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return "";
return oneData.avatar;
}
/** 获取星级 */
public getGrilStar(categoryId: string, girlId: number): number {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0;
return oneData.star;
}
/** --------------------------------------------------------- 技师的详细数据 --------------------------------------------------------- */
// 解析技师图片数据,一个
private parseOneGirlPhoto(data: proto.cs.IGirlPhoto): proto.cs.IGirlPhoto | null {
if (!data) return null;
const oneData: proto.cs.IGirlPhoto = {
pic: data.pic, // 图片路径
isRelease: data.isRelease, // 是否解锁
price: data.price, // 价格
};
return oneData;
}
// 解析技师图片数据,多个
private parseAllGirlPhoto(data: proto.cs.IGirlPhoto[]): proto.cs.IGirlPhoto[] | null {
if (!data) return null;
let allData = [];
for (const value of data) {
const oneData: proto.cs.IGirlPhoto = this.parseOneGirlPhoto(value);
if (oneData) {
allData.push(oneData);
}
}
return allData;
}
// 解析技师详细数据,一个
private parseOneGirlDetail(data: proto.cs.IGirlDetail): proto.cs.IGirlDetail | null {
if (!data) return null;
const photoData = this.parseAllGirlPhoto(data.photos);
const briefData = this.parseOneGirlBrief(data.brief);
const oneData: proto.cs.IGirlDetail = {
brief: briefData, // 技师简要数据
desc: data.desc, // 技师描述
photos: photoData, // 技师图片列表
isRelease: data.isRelease, // 技师是否解锁
chatCount: data.chatCount, // 剩余聊天次数
};
return oneData;
}
// 解析技师详细数据,多个
private parseAllGirlDetail(data: proto.cs.IGirlDetail[]): proto.cs.IGirlDetail[] | null {
if (!data) return null;
let allData = [];
for (const value of data) {
const oneData: proto.cs.IGirlDetail = this.parseOneGirlDetail(value);
if (oneData) {
allData.push(oneData);
}
}
return allData;
}
/** 保存技师的详细数据 */
public setGirlDetails(categoryId: string, data: proto.cs.ICSGetGirlDetailRes): void {
const d = this.parseOneGirlDetail(data.detail);
if (!d) return;
const bucket = this.ensureBucket(categoryId);
// id
const id = d.brief?.id ?? 0;
// 合并简要
if (d.brief) {
bucket.briefs.set(id, d.brief);
// TODO,去重
bucket.girlIds.push(id);
}
// 写入详情
bucket.details.set(id, d);
console.log("保存技师的详细数据: ", bucket);
}
/** 取某分类 + girlId 的详细信息 */
public getGrilDetail(categoryId: string, girlId: number): proto.cs.IGirlDetail | null {
const b = this.ensureCategories().get(categoryId);
if (!b) return null;
return b.details.get(girlId) ?? null;
}
/** 获取技师描述 */
public getGrilDesc(categoryId: string, girlId: number): string {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return "";
return oneData.desc;
}
/** 获取技师是否解锁 */
public getGrilIsRelease(categoryId: string, girlId: number): boolean {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return false;
return oneData.isRelease;
}
/** 获取技师剩余聊天次数 */
public getGrilChatCount(categoryId: string, girlId: number): number {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return 0;
return oneData.chatCount;
}
/** 获取技师图片数据,通过 index */
public getGrilPhotoData(categoryId: string, girlId: number, index: number): proto.cs.IGirlPhoto | null {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData || !oneData.photos) return null;
// 下标越界保护
if (index < 0 || index >= oneData.photos.length) return null;
return oneData.photos[index] ?? null;
}
/** 获取技师图片的路径 */
public getGrilPhotoPic(categoryId: string, girlId: number, index: number): string {
let oneData = this.getGrilPhotoData(categoryId, girlId, index);
if (!oneData) return "";
return oneData.pic;
}
/** 获取技师图片是否解锁 */
public getGrilPhotoIsRelease(categoryId: string, girlId: number, index: number): boolean {
let oneData = this.getGrilPhotoData(categoryId, girlId, index);
if (!oneData) return false;
return oneData.isRelease;
}
/** 获取技师图片的价格 */
public getGrilPhotoPrice(categoryId: string, girlId: number, index: number): number {
let oneData = this.getGrilPhotoData(categoryId, girlId, index);
if (!oneData) return 0;
return oneData.price;
}
/** --------------------------------------------------------- 每日推荐 --------------------------------------------------------- */
/** 每日推荐:只维护 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;
}
}