2025-08-26 11:10:15 +08:00
|
|
|
/**
|
2025-09-08 15:10:51 +08:00
|
|
|
* 技师数据,统一访问入口
|
2025-08-26 11:10:15 +08:00
|
|
|
*/
|
|
|
|
|
import { BaseData } from "./BaseData";
|
2025-09-08 15:10:51 +08:00
|
|
|
import { GirlBriefData } from "./GirlBriefData";
|
|
|
|
|
import { GirlDetailData } from "./GirlDetailData";
|
|
|
|
|
import { GirlUnlockData } from "./GirlUnlockData";
|
|
|
|
|
import { GirlChatData } from "./GirlChatData";
|
|
|
|
|
import { GirlFavorabilityData } from "./GirlFavorabilityData";
|
2025-10-08 15:47:32 +08:00
|
|
|
import { GirlRankData } from "./GirlRankData";
|
2025-10-08 13:38:45 +08:00
|
|
|
import { GirlOtherData } from "./GirlOtherData";
|
2025-09-08 15:10:51 +08:00
|
|
|
import { DataId } from "./DataManager";
|
2025-09-09 19:21:05 +08:00
|
|
|
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
2025-09-20 15:52:38 +08:00
|
|
|
import { PriceType } from "../../schema/schema";
|
2025-09-21 19:49:08 +08:00
|
|
|
import { logger } from "db://assets/Scripts/Main/Common/Logger";
|
2025-08-26 11:10:15 +08:00
|
|
|
|
2025-08-28 17:22:04 +08:00
|
|
|
// 分类的数据结构
|
|
|
|
|
interface CategoryBucket {
|
|
|
|
|
// 技师的简要数据
|
2025-09-08 15:10:51 +08:00
|
|
|
briefs: Map<number, GirlBriefData>;
|
2025-08-28 17:22:04 +08:00
|
|
|
// 技师的详细数据
|
2025-09-08 15:10:51 +08:00
|
|
|
details: Map<number, GirlDetailData>;
|
|
|
|
|
// 技师的解锁数据
|
|
|
|
|
unlocks: Map<number, GirlUnlockData>;
|
|
|
|
|
// 技师的聊天数据
|
2025-09-09 19:21:05 +08:00
|
|
|
chats: Map<number, GirlChatData>;
|
2025-09-08 15:10:51 +08:00
|
|
|
// 技师的好感度数据
|
2025-09-09 19:21:05 +08:00
|
|
|
favorability: Map<number, GirlFavorabilityData>;
|
2025-10-08 13:38:45 +08:00
|
|
|
// 技师的其他数据
|
|
|
|
|
other: Map<number, GirlOtherData>;
|
2025-08-28 17:22:04 +08:00
|
|
|
// 技师的id
|
|
|
|
|
girlIds: number[];
|
2025-08-26 11:10:15 +08:00
|
|
|
}
|
|
|
|
|
|
2025-08-29 11:29:21 +08:00
|
|
|
// 每日推荐专用分类
|
2025-09-09 19:21:05 +08:00
|
|
|
const DAILY_BUCKET = "__daily__";
|
2025-08-29 11:29:21 +08:00
|
|
|
|
2025-08-26 11:10:15 +08:00
|
|
|
export class GirlData extends BaseData {
|
2025-08-28 17:22:04 +08:00
|
|
|
// 大分类
|
|
|
|
|
private _categories = new Map<string, CategoryBucket>();
|
2025-10-08 15:47:32 +08:00
|
|
|
// 排行榜数据
|
|
|
|
|
private _rankData: GirlRankData;
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
super();
|
|
|
|
|
this._rankData = new GirlRankData();
|
|
|
|
|
this._rankData.init?.(DataId.GirlRank);
|
|
|
|
|
}
|
2025-08-26 11:10:15 +08:00
|
|
|
|
|
|
|
|
public reset(): void {
|
2025-08-28 17:22:04 +08:00
|
|
|
this._categories.clear();
|
2025-10-08 15:47:32 +08:00
|
|
|
this._rankData.clear();
|
2025-08-26 11:10:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public clear(): void {
|
2025-08-28 17:22:04 +08:00
|
|
|
this._categories.clear();
|
2025-10-08 15:47:32 +08:00
|
|
|
this._rankData.clear();
|
2025-08-26 11:10:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public destroy(): void {
|
|
|
|
|
super.destroy();
|
2025-08-28 17:22:04 +08:00
|
|
|
this._categories = null;
|
2025-10-08 15:47:32 +08:00
|
|
|
this._rankData = null;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
|
|
|
|
/** 保障 _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 = {
|
2025-09-08 15:10:51 +08:00
|
|
|
briefs: new Map<number, GirlBriefData>(),
|
|
|
|
|
details: new Map<number, GirlDetailData>(),
|
|
|
|
|
unlocks: new Map<number, GirlUnlockData>(),
|
|
|
|
|
chats: new Map<number, GirlChatData>(),
|
|
|
|
|
favorability: new Map<number, GirlFavorabilityData>(),
|
2025-10-08 13:38:45 +08:00
|
|
|
other: new Map<number, GirlOtherData>(),
|
2025-08-28 17:22:04 +08:00
|
|
|
girlIds: [],
|
|
|
|
|
};
|
|
|
|
|
cats.set(categoryId, bucket);
|
|
|
|
|
}
|
|
|
|
|
return bucket;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-08-28 17:22:04 +08:00
|
|
|
/** 取分类下的全部 girlIds(若分类不存在返回空数组) */
|
|
|
|
|
public getGirlIds(categoryId: string): number[] {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
return b ? b.girlIds : [];
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 保存技师列表 */
|
2025-10-08 15:47:32 +08:00
|
|
|
public setGirlList(categoryId: string, data: proto.cs.ICSGetGirlListRes): void {
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!data) return;
|
|
|
|
|
this.setGirlBrief(categoryId, data.girls);
|
|
|
|
|
this.setGirlUnlock(categoryId, data.girls);
|
|
|
|
|
this.setGirlFavorability(categoryId, data.girls);
|
2025-10-08 13:38:45 +08:00
|
|
|
this.setGirlOther(categoryId, data.girls);
|
2025-09-09 11:14:27 +08:00
|
|
|
const bucket = this.ensureBucket(categoryId);
|
2025-09-21 19:49:08 +08:00
|
|
|
logger.log("保存类别 ", categoryId, " 的技师列表: ", bucket);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 保存技师详细数据 */
|
2025-10-08 15:47:32 +08:00
|
|
|
public setGirlDetailData(categoryId: string, data: proto.cs.ICSGetGirlDetailRes): void {
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!data) return;
|
2025-09-09 19:21:05 +08:00
|
|
|
let details = [];
|
2025-09-08 15:10:51 +08:00
|
|
|
details.push(data.girl);
|
|
|
|
|
this.setGirlBrief(categoryId, details);
|
|
|
|
|
this.setGirlDetail(categoryId, details);
|
|
|
|
|
this.setGirlUnlock(categoryId, details);
|
|
|
|
|
this.setGirlChat(categoryId, details);
|
|
|
|
|
this.setGirlFavorability(categoryId, details);
|
2025-10-08 13:38:45 +08:00
|
|
|
this.setGirlOther(categoryId, details);
|
2025-09-09 11:14:27 +08:00
|
|
|
const bucket = this.ensureBucket(categoryId);
|
2025-09-21 19:49:08 +08:00
|
|
|
logger.log("保存类别 ", categoryId, " 的详细数据: ", bucket);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 保存可聊天的技师数据 */
|
|
|
|
|
public setCanChatGirlData(data: proto.cs.ICSGetLastChatListRes): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
let canChatList = data.LastChatList;
|
|
|
|
|
// 遍历
|
|
|
|
|
for (const oneData of canChatList) {
|
|
|
|
|
let briefData = oneData.girl;
|
|
|
|
|
let categoryId = briefData.category;
|
|
|
|
|
this.mergeOneBrief(categoryId.toString(), briefData);
|
|
|
|
|
this.refreshGirlUnlock(oneData);
|
|
|
|
|
this.refreshGirlFavorability(oneData);
|
|
|
|
|
this.refreshGirlChat(oneData);
|
|
|
|
|
}
|
|
|
|
|
const cats = this.ensureCategories();
|
|
|
|
|
logger.log("保存可聊天的技师数据: ", cats);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
|
2025-10-09 16:46:57 +08:00
|
|
|
/** 保存收藏列表 */
|
|
|
|
|
public setBookmarkGirlList(data: proto.cs.ICSGetBookmarkRes): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
let arrayData = data.girls;
|
|
|
|
|
// 遍历
|
|
|
|
|
for (const oneData of arrayData) {
|
|
|
|
|
let briefData = oneData.girl;
|
|
|
|
|
let categoryId = briefData.category;
|
|
|
|
|
this.mergeOneBrief(categoryId.toString(), briefData);
|
|
|
|
|
let theArray = [];
|
|
|
|
|
theArray.push(oneData);
|
|
|
|
|
this.setGirlUnlock(categoryId.toString(), theArray);
|
|
|
|
|
this.setGirlFavorability(categoryId.toString(), theArray);
|
|
|
|
|
this.setGirlOther(categoryId.toString(), theArray);
|
|
|
|
|
}
|
|
|
|
|
const cats = this.ensureCategories();
|
|
|
|
|
logger.log("保存收藏列表后,大分类的数据: ", cats);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-08 13:38:45 +08:00
|
|
|
/** --------------------------------------------------------- 每日推荐 --------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/** 保存每日推荐:放入特殊分类 DAILY_BUCKET,并维护 id 索引 */
|
|
|
|
|
public setDailyRecommend(data: proto.cs.ICSDailyRecommendRes): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
this.mergeOneBrief(DAILY_BUCKET, data.girl);
|
|
|
|
|
const bucket = this.ensureBucket(DAILY_BUCKET);
|
|
|
|
|
logger.log("保存每日推荐: ", bucket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 判断每日推荐是否存在 */
|
|
|
|
|
public isDailyRecommendIn(): boolean {
|
|
|
|
|
const bucket = this.ensureCategories().get(DAILY_BUCKET);
|
|
|
|
|
if (!bucket) return false;
|
|
|
|
|
return bucket.girlIds.length > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 获取推荐id */
|
|
|
|
|
public getRecommendGirlId(): number {
|
|
|
|
|
const bucket = this.ensureBucket(DAILY_BUCKET);
|
|
|
|
|
const girlIds = bucket.girlIds;
|
|
|
|
|
const length = girlIds.length;
|
|
|
|
|
if (length <= 0) return 0;
|
|
|
|
|
return girlIds[length - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 获取每日推荐的简要数据 */
|
|
|
|
|
private getRecommendGrilBrief(): GirlBriefData | null {
|
|
|
|
|
const recId = this.getRecommendGirlId();
|
|
|
|
|
if (recId <= 0) return null;
|
|
|
|
|
const data = this.getGrilBrief(DAILY_BUCKET, recId);
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 获取名字 */
|
|
|
|
|
public getRecommendGrilName(): string {
|
|
|
|
|
let oneData = this.getRecommendGrilBrief();
|
|
|
|
|
if (!oneData) return "";
|
|
|
|
|
return oneData.getGrilName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 获取头像路径 */
|
|
|
|
|
public getRecommendGrilAvatar(): string {
|
|
|
|
|
let oneData = this.getRecommendGrilBrief();
|
|
|
|
|
if (!oneData) return "";
|
|
|
|
|
return oneData.getGrilAvatar();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-08 15:47:32 +08:00
|
|
|
/** --------------------------------------------------------- 技师的排行榜数据 --------------------------------------------------------- */
|
|
|
|
|
|
2025-10-09 14:20:34 +08:00
|
|
|
/** 清空 排行榜数据 */
|
|
|
|
|
public clearGirlRank(): void {
|
|
|
|
|
if (!this._rankData) return;
|
|
|
|
|
this._rankData.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-08 15:47:32 +08:00
|
|
|
/** 保存 排行榜数据 */
|
|
|
|
|
public setGirlRank(rankType: proto.cs.EnmRankType, data: proto.cs.ICSGetRankRes): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
let arrayData = data.girls;
|
|
|
|
|
// 遍历
|
|
|
|
|
for (const oneData of arrayData) {
|
|
|
|
|
let briefData = oneData.girl;
|
|
|
|
|
let categoryId = briefData.category;
|
|
|
|
|
this.mergeOneBrief(categoryId.toString(), briefData);
|
|
|
|
|
let theArray = [];
|
|
|
|
|
theArray.push(oneData);
|
|
|
|
|
this.setGirlUnlock(categoryId.toString(), theArray);
|
|
|
|
|
this.setGirlFavorability(categoryId.toString(), theArray);
|
|
|
|
|
this.setGirlOther(categoryId.toString(), theArray);
|
|
|
|
|
}
|
|
|
|
|
this._rankData.setRankData(rankType, arrayData);
|
|
|
|
|
const cats = this.ensureCategories();
|
|
|
|
|
logger.log("保存排行榜数据后,大分类的数据: ", cats);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 添加 排行榜数据 */
|
|
|
|
|
public addRankData(rankType: proto.cs.EnmRankType, data: proto.cs.ICSGetRankRes): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
let arrayData = data.girls;
|
|
|
|
|
// 遍历
|
|
|
|
|
for (const oneData of arrayData) {
|
|
|
|
|
let briefData = oneData.girl;
|
|
|
|
|
let categoryId = briefData.category;
|
|
|
|
|
this.mergeOneBrief(categoryId.toString(), briefData);
|
|
|
|
|
let theArray = [];
|
|
|
|
|
theArray.push(oneData);
|
|
|
|
|
this.setGirlUnlock(categoryId.toString(), theArray);
|
|
|
|
|
this.setGirlFavorability(categoryId.toString(), theArray);
|
|
|
|
|
this.setGirlOther(categoryId.toString(), theArray);
|
|
|
|
|
}
|
|
|
|
|
this._rankData.addRankData(rankType, arrayData);
|
|
|
|
|
const cats = this.ensureCategories();
|
|
|
|
|
logger.log("添加排行榜数据后,大分类的数据: ", cats);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 获取排行榜技师 id,根据排行榜类型 */
|
|
|
|
|
public getRankIdsByType(rankType: proto.cs.EnmRankType): number[] {
|
|
|
|
|
if (!this._rankData) return [];
|
|
|
|
|
const ids = this._rankData.getRankIdsByType(rankType);
|
|
|
|
|
return ids;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-28 17:22:04 +08:00
|
|
|
/** --------------------------------------------------------- 技师的简要数据 --------------------------------------------------------- */
|
2025-09-09 19:21:05 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/**
|
|
|
|
|
* 合并一个简要数据到指定分类;并维护 girlIds 顺序(去重追加)
|
|
|
|
|
*/
|
|
|
|
|
private mergeOneBrief(categoryId: string, data: proto.cs.IGirls): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
const bucket = this.ensureBucket(categoryId);
|
|
|
|
|
// 用一个临时 Set 保存已有的 id,加速去重
|
|
|
|
|
const existed = new Set<number>(bucket.girlIds);
|
|
|
|
|
let id = data.id;
|
|
|
|
|
const one = this.parseOneGirlBrief(data);
|
|
|
|
|
if (!one) return;
|
|
|
|
|
bucket.briefs.set(id, one);
|
|
|
|
|
if (!existed.has(id)) {
|
|
|
|
|
bucket.girlIds.push(id);
|
|
|
|
|
}
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 合并一批简要数据到指定分类;并维护 girlIds 顺序(去重追加)
|
|
|
|
|
*/
|
2025-09-09 19:21:05 +08:00
|
|
|
private mergeBriefs(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
respOrList: proto.cs.IGirlData[]
|
|
|
|
|
): void {
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!respOrList) return;
|
|
|
|
|
const bucket = this.ensureBucket(categoryId);
|
|
|
|
|
// 用一个临时 Set 保存已有的 id,加速去重
|
|
|
|
|
const existed = new Set<number>(bucket.girlIds);
|
|
|
|
|
|
|
|
|
|
for (const g of respOrList) {
|
|
|
|
|
const one = this.parseOneGirlBrief(g.girl);
|
|
|
|
|
if (!one) continue;
|
|
|
|
|
bucket.briefs.set(g.id, one);
|
|
|
|
|
|
|
|
|
|
if (!existed.has(g.id)) {
|
|
|
|
|
bucket.girlIds.push(g.id);
|
|
|
|
|
existed.add(g.id);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
private parseOneGirlBrief(data: proto.cs.IGirls): GirlBriefData | null {
|
2025-08-28 17:22:04 +08:00
|
|
|
if (!data) return null;
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = new GirlBriefData();
|
|
|
|
|
oneData.init?.(DataId.GirlBrief);
|
|
|
|
|
oneData.setData(data);
|
2025-08-28 17:22:04 +08:00
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 保存技师的简要数据 */
|
2025-09-08 15:10:51 +08:00
|
|
|
private setGirlBrief(categoryId: string, data: proto.cs.IGirlData[]): void {
|
|
|
|
|
this.mergeBriefs(categoryId, data);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 取某分类 + girlId 的简要数据 */
|
2025-09-09 19:21:05 +08:00
|
|
|
private getGrilBrief(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number
|
|
|
|
|
): GirlBriefData | null {
|
2025-08-28 17:22:04 +08:00
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return null;
|
|
|
|
|
return b.briefs.get(girlId) ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-15 16:22:31 +08:00
|
|
|
/** 技师的简要信息是否存在 */
|
|
|
|
|
public isGirlBriefIn(categoryId: string, girlId: number): boolean {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return false;
|
|
|
|
|
return b.briefs.has(girlId);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-15 16:22:31 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取名字键 */
|
2025-08-28 17:22:04 +08:00
|
|
|
public getGrilName(categoryId: string, girlId: number): string {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getGrilName();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
|
|
|
|
/** 获取年龄 */
|
2025-09-08 15:10:51 +08:00
|
|
|
public getGrilAge(categoryId: string, girlId: number): string {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "0";
|
|
|
|
|
return oneData.getGrilAge();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 获取主题枚举 */
|
|
|
|
|
public getGrilCategory(categoryId: string, girlId: number): number {
|
2025-08-28 17:22:04 +08:00
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getGrilCategory();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取标签键 */
|
2025-08-28 17:22:04 +08:00
|
|
|
public getGrilTagKey(categoryId: string, girlId: number): string {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getGrilTagKey();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-26 11:10:15 +08:00
|
|
|
|
2025-08-28 17:22:04 +08:00
|
|
|
/** 获取付费类型 */
|
|
|
|
|
public getGrilPriceType(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getGrilPriceType();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
2025-09-20 15:52:38 +08:00
|
|
|
/** 技师是否免费类型 */
|
|
|
|
|
public isGirlFreeType(categoryId: string, girlId: number): boolean {
|
|
|
|
|
let priceType = this.getGrilPriceType(categoryId, girlId);
|
|
|
|
|
return priceType == PriceType.free;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-20 15:52:38 +08:00
|
|
|
|
|
|
|
|
/** 技师是否付费类型 */
|
|
|
|
|
public isGirlPayType(categoryId: string, girlId: number): boolean {
|
|
|
|
|
let priceType = this.getGrilPriceType(categoryId, girlId);
|
|
|
|
|
return priceType == PriceType.pay;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-20 15:52:38 +08:00
|
|
|
|
2025-09-09 19:16:46 +08:00
|
|
|
/** 获取原来的价格,除100 */
|
|
|
|
|
public getGrilOriginalPrice(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
let price = oneData.getGrilPrice();
|
2025-09-09 19:24:04 +08:00
|
|
|
return price / 100;
|
|
|
|
|
}
|
2025-09-09 19:16:46 +08:00
|
|
|
|
2025-08-28 17:22:04 +08:00
|
|
|
/** 获取价格 */
|
|
|
|
|
public getGrilPrice(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getGrilPrice();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 获取VIP能否解锁 */
|
|
|
|
|
public getGrilVipUnlock(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
return oneData.getGrilVipUnlock();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取头像路径 */
|
2025-08-28 17:22:04 +08:00
|
|
|
public getGrilAvatar(categoryId: string, girlId: number): string {
|
|
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getGrilAvatar();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取list头像路径 */
|
|
|
|
|
public getGrilListAvatar(categoryId: string, girlId: number): string {
|
2025-08-28 17:22:04 +08:00
|
|
|
let oneData = this.getGrilBrief(categoryId, girlId);
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!oneData) return "";
|
|
|
|
|
return oneData.getGrilListAvatar();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-03 17:35:27 +08:00
|
|
|
|
2025-09-05 09:42:22 +08:00
|
|
|
/** 获取主题枚举,根据 id */
|
|
|
|
|
public getGrilCategoryById(girlId: number): number {
|
|
|
|
|
const cats = this.ensureCategories();
|
2025-09-08 15:10:51 +08:00
|
|
|
// 遍历
|
2025-09-05 09:42:22 +08:00
|
|
|
for (const bucket of cats.values()) {
|
|
|
|
|
// 先查简要信息
|
|
|
|
|
const brief = bucket.briefs.get(girlId);
|
2025-09-08 15:10:51 +08:00
|
|
|
if (brief) {
|
|
|
|
|
return brief.getGrilCategory();
|
2025-09-05 09:42:22 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 未找到
|
|
|
|
|
return 0;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-05 09:42:22 +08:00
|
|
|
|
2025-08-28 17:22:04 +08:00
|
|
|
/** --------------------------------------------------------- 技师的详细数据 --------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
// 解析技师详细数据,一个
|
2025-09-09 19:21:05 +08:00
|
|
|
private parseOneGirlDetail(
|
|
|
|
|
data: proto.cs.IGirlsDetail
|
|
|
|
|
): GirlDetailData | null {
|
2025-08-28 17:22:04 +08:00
|
|
|
if (!data) return null;
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = new GirlDetailData();
|
|
|
|
|
oneData.init?.(DataId.GirlDetail);
|
|
|
|
|
oneData.setData(data);
|
2025-08-28 17:22:04 +08:00
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 保存技师的详细数据 */
|
2025-09-08 15:10:51 +08:00
|
|
|
private setGirlDetail(categoryId: string, data: proto.cs.IGirlData[]): void {
|
|
|
|
|
if (!data) return;
|
2025-08-28 17:22:04 +08:00
|
|
|
const bucket = this.ensureBucket(categoryId);
|
2025-09-08 15:10:51 +08:00
|
|
|
for (const g of data) {
|
|
|
|
|
const one = this.parseOneGirlDetail(g.detail);
|
|
|
|
|
if (!one) continue;
|
|
|
|
|
bucket.details.set(g.id, one);
|
|
|
|
|
}
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
2025-09-15 16:22:31 +08:00
|
|
|
/** 技师的详细信息是否存在 */
|
|
|
|
|
public isGirlDetailIn(categoryId: string, girlId: number): boolean {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return false;
|
|
|
|
|
return b.details.has(girlId);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-15 16:22:31 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 取某分类 + girlId 的详细数据 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilDetail(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number
|
|
|
|
|
): GirlDetailData | null {
|
2025-08-28 17:22:04 +08:00
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return null;
|
|
|
|
|
return b.details.get(girlId) ?? null;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
|
|
|
|
/** 获取技师描述 */
|
|
|
|
|
public getGrilDesc(categoryId: string, girlId: number): string {
|
|
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getGirlDesc();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
2025-09-03 17:35:27 +08:00
|
|
|
/** 获取所有技师图片数据的数量 */
|
|
|
|
|
public getAllGrilPhotoDataCount(categoryId: string, girlId: number): number {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getAllGrilPhotoDataCount();
|
|
|
|
|
}
|
2025-09-03 17:35:27 +08:00
|
|
|
|
2025-09-09 15:15:28 +08:00
|
|
|
/** 获取所有技师图片的id */
|
|
|
|
|
public getAllGrilPhotoId(categoryId: string, girlId: number): number[] {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return [];
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getAllGrilPhotoId();
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-10 01:00:27 +08:00
|
|
|
/** 获取所有用来展示在列表的技师图片的id,可展示的有以下几种情况
|
|
|
|
|
* 1,图片类型为在详情页展示的(不管免费,付费,是否解锁)
|
|
|
|
|
* 2,图片类型为在聊天触发的,并且已经达到了触发次数的(不管是否已经解锁)
|
2025-09-23 11:23:17 +08:00
|
|
|
*/
|
2025-09-09 19:21:05 +08:00
|
|
|
public getAllDisplayGrilPhotoId(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number
|
|
|
|
|
): number[] {
|
2025-09-09 15:15:28 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return [];
|
|
|
|
|
// 所有id
|
2025-09-09 19:21:05 +08:00
|
|
|
let allId = oneData.getAllGrilPhotoId();
|
2025-09-09 15:15:28 +08:00
|
|
|
// 总聊天次数
|
|
|
|
|
let chatTotalCount = this.getChatTotalCount(categoryId, girlId);
|
|
|
|
|
// 用来展示的id
|
|
|
|
|
let displayIds = [];
|
|
|
|
|
for (let id of allId) {
|
2025-09-10 01:00:27 +08:00
|
|
|
const unlockCounts = oneData.getGrilPhotoUnlockCounts(id);
|
|
|
|
|
// 免费
|
|
|
|
|
const isFreeType = this.isGirlPhotoFreeType(categoryId, girlId, id);
|
|
|
|
|
// 付费
|
|
|
|
|
const isPayType = this.isGirlPhotoPayType(categoryId, girlId, id);
|
|
|
|
|
// 在详情页展示
|
|
|
|
|
const isShowInList = this.isGirlPhotoShowInList(categoryId, girlId, id);
|
|
|
|
|
// 在聊天触发
|
|
|
|
|
const isShowInChat = this.isGirlPhotoShowInChat(categoryId, girlId, id);
|
|
|
|
|
|
|
|
|
|
if (isShowInList) {
|
2025-09-23 11:23:17 +08:00
|
|
|
displayIds.push(id);
|
2025-09-10 01:00:27 +08:00
|
|
|
} else if (isShowInChat) {
|
|
|
|
|
// 总聊天次数 大于等于 触发次数
|
|
|
|
|
if (chatTotalCount >= unlockCounts) {
|
2025-09-09 22:05:26 +08:00
|
|
|
displayIds.push(id);
|
2025-09-09 15:15:28 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return displayIds;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-03 17:35:27 +08:00
|
|
|
|
2025-09-10 01:00:27 +08:00
|
|
|
/** 用来展示在列表的技师图片是否可见 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlPhotoVisible(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
// 免费
|
|
|
|
|
const isFreeType = this.isGirlPhotoFreeType(categoryId, girlId, id);
|
|
|
|
|
// 付费
|
|
|
|
|
const isPayType = this.isGirlPhotoPayType(categoryId, girlId, id);
|
|
|
|
|
// 在详情页展示
|
|
|
|
|
const isShowInList = this.isGirlPhotoShowInList(categoryId, girlId, id);
|
|
|
|
|
// 在聊天触发
|
|
|
|
|
const isShowInChat = this.isGirlPhotoShowInChat(categoryId, girlId, id);
|
|
|
|
|
|
|
|
|
|
if (isShowInList) {
|
|
|
|
|
if (isFreeType) {
|
|
|
|
|
// 免费,可见
|
|
|
|
|
return true;
|
|
|
|
|
} else if (isPayType) {
|
|
|
|
|
// 付费,并且已经解锁,可见
|
|
|
|
|
const isUnlock = this.isImageUnlock(categoryId, girlId, id);
|
|
|
|
|
if (isUnlock) return true;
|
|
|
|
|
}
|
|
|
|
|
} else if (isShowInChat) {
|
|
|
|
|
// 总聊天次数 大于等于 触发次数
|
|
|
|
|
const isUnlock = this.isImageUnlock(categoryId, girlId, id);
|
|
|
|
|
// 已经解锁,可见
|
2025-09-23 11:23:17 +08:00
|
|
|
if (isUnlock) return true;
|
2025-09-10 01:00:27 +08:00
|
|
|
}
|
|
|
|
|
// 其他情况,不可见
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-10 20:58:43 +08:00
|
|
|
/** 获取 在聊天中,触发技师图片的id */
|
|
|
|
|
public getTriggerGrilPhotoId(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
// 所有图片 id,展示类型属于在聊天中触发
|
|
|
|
|
let allId = oneData.getAllTriggerGrilPhotoId();
|
|
|
|
|
// 总聊天次数
|
|
|
|
|
let chatTotalCount = this.getChatTotalCount(categoryId, girlId);
|
|
|
|
|
// 遍历
|
|
|
|
|
for (let id of allId) {
|
|
|
|
|
let count = this.getGrilPhotoUnlockCounts(categoryId, girlId, id);
|
2025-09-23 11:23:17 +08:00
|
|
|
if (chatTotalCount == count) return id;
|
2025-09-10 20:58:43 +08:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-08 16:12:40 +08:00
|
|
|
/** 获取第一个技师图片的资源路径 */
|
|
|
|
|
public getFirstGrilPhotoPath(categoryId: string, girlId: number): string {
|
|
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
|
|
|
|
// 第一个 id
|
2025-09-09 15:15:28 +08:00
|
|
|
const ids = this.getAllGrilPhotoId(categoryId, girlId);
|
2025-09-08 16:12:40 +08:00
|
|
|
const length = ids.length;
|
|
|
|
|
if (length <= 0) return "";
|
|
|
|
|
// 返回数据
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilPhotoPath(ids[0]);
|
|
|
|
|
}
|
2025-09-08 16:12:40 +08:00
|
|
|
|
2025-09-10 01:00:27 +08:00
|
|
|
/** 图片展示类型:在详情页展示 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlPhotoShowInList(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
2025-09-10 21:30:08 +08:00
|
|
|
return oneData.isGirlPhotoShowInList(id);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 01:00:27 +08:00
|
|
|
/** 图片展示类型:在聊天触发 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlPhotoShowInChat(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
2025-09-10 21:30:08 +08:00
|
|
|
return oneData.isGirlPhotoShowInChat(id);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 01:00:27 +08:00
|
|
|
|
|
|
|
|
/** 图片是否免费 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlPhotoFreeType(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
|
|
|
|
// 价格
|
|
|
|
|
const price = oneData.getGrilPhotoPrice(id);
|
|
|
|
|
return price <= 0;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 01:00:27 +08:00
|
|
|
|
|
|
|
|
/** 图片是否需要付费 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlPhotoPayType(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return true;
|
|
|
|
|
// 价格
|
|
|
|
|
const price = oneData.getGrilPhotoPrice(id);
|
|
|
|
|
return price > 0;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 01:00:27 +08:00
|
|
|
|
2025-09-03 17:35:27 +08:00
|
|
|
/** 获取技师图片的类型 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilPhotoType(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): number {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
2025-09-03 17:35:27 +08:00
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilPhotoType(id);
|
|
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 获取技师图片的聊天触发次数 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilPhotoUnlockCounts(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): number {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:24:04 +08:00
|
|
|
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilPhotoUnlockCounts(id);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-09 19:16:46 +08:00
|
|
|
/** 获取技师图片的原来价格,除100 */
|
2025-09-09 19:24:04 +08:00
|
|
|
public getGrilPhotoOriginalPrice(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): number {
|
2025-09-09 19:16:46 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:24:04 +08:00
|
|
|
let price = oneData.getGrilPhotoPrice(id);
|
|
|
|
|
return price / 100;
|
|
|
|
|
}
|
2025-09-10 01:00:27 +08:00
|
|
|
|
2025-09-03 17:35:27 +08:00
|
|
|
/** 获取技师图片的价格 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilPhotoPrice(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): number {
|
2025-09-03 17:35:27 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilPhotoPrice(id);
|
|
|
|
|
}
|
2025-09-03 17:35:27 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取技师图片的资源路径 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilPhotoPic(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): string {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilPhotoPath(id);
|
|
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
2025-09-03 17:35:27 +08:00
|
|
|
/** 获取所有技师视频数据的数量 */
|
|
|
|
|
public getAllGrilVideoDataCount(categoryId: string, girlId: number): number {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getAllGrilVideoDataCount();
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-09 15:15:28 +08:00
|
|
|
/** 获取所有技师视频的id */
|
|
|
|
|
public getAllGrilVideoId(categoryId: string, girlId: number): number[] {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return [];
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getAllGrilVideoId();
|
|
|
|
|
}
|
2025-09-09 15:15:28 +08:00
|
|
|
|
|
|
|
|
/** 获取所有用来展示在列表的技师视频的id */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getAllDisplayGrilVideoId(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number
|
|
|
|
|
): number[] {
|
2025-09-09 20:33:43 +08:00
|
|
|
return this.getAllGrilVideoId(categoryId, girlId);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 01:00:27 +08:00
|
|
|
/** 用来展示在列表的技师视频是否可见 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlVideoVisible(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
// 免费
|
|
|
|
|
const isFreeType = this.isGirlVideoFreeType(categoryId, girlId, id);
|
|
|
|
|
// 付费
|
|
|
|
|
const isPayType = this.isGirlVideoPayType(categoryId, girlId, id);
|
|
|
|
|
|
|
|
|
|
if (isFreeType) {
|
|
|
|
|
// 免费,可见
|
|
|
|
|
return true;
|
|
|
|
|
} else if (isPayType) {
|
|
|
|
|
// 付费,并且已经解锁,可见
|
|
|
|
|
const isUnlock = this.isVideoUnlock(categoryId, girlId, id);
|
2025-09-23 11:23:17 +08:00
|
|
|
if (isUnlock) return true;
|
2025-09-10 01:00:27 +08:00
|
|
|
}
|
|
|
|
|
// 其他情况,不可见
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 视频是否免费 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlVideoFreeType(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
|
|
|
|
// 价格
|
|
|
|
|
const price = oneData.getGrilVideoPrice(id);
|
|
|
|
|
return price <= 0;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 01:00:27 +08:00
|
|
|
|
|
|
|
|
/** 视频是否需要付费 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public isGirlVideoPayType(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 01:00:27 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return true;
|
|
|
|
|
// 价格
|
|
|
|
|
const price = oneData.getGrilVideoPrice(id);
|
|
|
|
|
return price > 0;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 01:00:27 +08:00
|
|
|
|
2025-09-08 16:12:40 +08:00
|
|
|
/** 获取第一个技师视频的资源路径 */
|
|
|
|
|
public getFirstGrilVideoPath(categoryId: string, girlId: number): string {
|
|
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
|
|
|
|
// 第一个 id
|
2025-09-09 15:15:28 +08:00
|
|
|
const ids = this.getAllGrilVideoId(categoryId, girlId);
|
2025-09-08 16:12:40 +08:00
|
|
|
const length = ids.length;
|
|
|
|
|
if (length <= 0) return "";
|
|
|
|
|
// 返回数据
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilVideoPath(ids[0]);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取技师视频的资源路径 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilVideoPath(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): string {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
2025-09-03 17:35:27 +08:00
|
|
|
if (!oneData) return "";
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilVideoPath(id);
|
|
|
|
|
}
|
2025-09-03 17:35:27 +08:00
|
|
|
|
|
|
|
|
/** 获取技师视频的关联情绪 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilVideoEmotion(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): number {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
2025-08-28 17:22:04 +08:00
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilVideoEmotion(id);
|
|
|
|
|
}
|
2025-09-03 17:35:27 +08:00
|
|
|
|
2025-09-09 19:16:46 +08:00
|
|
|
/** 获取技师视频的原来价格,除100 */
|
2025-09-09 19:24:04 +08:00
|
|
|
public getGrilVideoOriginalPrice(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): number {
|
2025-09-09 19:16:46 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:24:04 +08:00
|
|
|
let price = oneData.getGrilVideoPrice(id);
|
|
|
|
|
return price / 100;
|
|
|
|
|
}
|
2025-09-09 19:16:46 +08:00
|
|
|
|
2025-09-03 17:35:27 +08:00
|
|
|
/** 获取技师视频的价格 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public getGrilVideoPrice(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): number {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilDetail(categoryId, girlId);
|
2025-09-03 17:35:27 +08:00
|
|
|
if (!oneData) return 0;
|
2025-09-09 19:21:05 +08:00
|
|
|
return oneData.getGrilVideoPrice(id);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** --------------------------------------------------------- 技师的解锁数据 --------------------------------------------------------- */
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
// 创建一个技师解锁数据
|
2025-09-23 11:23:17 +08:00
|
|
|
private createOneGirlUnlock(
|
|
|
|
|
id: number,
|
|
|
|
|
isRelease: boolean,
|
|
|
|
|
unlockTime: number,
|
|
|
|
|
unlockedImageIds: number[],
|
|
|
|
|
unlockedVideoIds: number[]
|
|
|
|
|
): GirlUnlockData {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = new GirlUnlockData();
|
|
|
|
|
oneData.init?.(DataId.GirlUnlock);
|
2025-09-22 17:54:33 +08:00
|
|
|
oneData.setId(id);
|
|
|
|
|
oneData.setIsRelease(isRelease);
|
|
|
|
|
oneData.setUnlockTime(unlockTime);
|
|
|
|
|
if (unlockedImageIds) {
|
|
|
|
|
oneData.setUnlockedImageIds(unlockedImageIds);
|
2025-09-08 15:10:51 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
if (unlockedVideoIds) {
|
|
|
|
|
oneData.setUnlockedVideoIds(unlockedVideoIds);
|
2025-09-08 15:10:51 +08:00
|
|
|
}
|
|
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
// 解析技师解锁数据,一个
|
|
|
|
|
private parseOneGirlUnlock(data: proto.cs.IGirlData): GirlUnlockData | null {
|
|
|
|
|
if (!data) return null;
|
|
|
|
|
let unlockedImageIds = [];
|
|
|
|
|
if (data.images) {
|
|
|
|
|
for (let one of data.images) {
|
|
|
|
|
unlockedImageIds.push(one.resId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let unlockedVideoIds = [];
|
|
|
|
|
if (data.videos) {
|
|
|
|
|
for (let one of data.videos) {
|
|
|
|
|
unlockedVideoIds.push(one.resId);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-23 11:23:17 +08:00
|
|
|
let oneData = this.createOneGirlUnlock(
|
|
|
|
|
data.id,
|
|
|
|
|
data.isRelease,
|
|
|
|
|
Number(data.unlockTime),
|
|
|
|
|
unlockedImageIds,
|
|
|
|
|
unlockedVideoIds
|
|
|
|
|
);
|
2025-09-22 17:54:33 +08:00
|
|
|
return oneData;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 保存技师的解锁数据 */
|
|
|
|
|
private setGirlUnlock(categoryId: string, data: proto.cs.IGirlData[]): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
const bucket = this.ensureBucket(categoryId);
|
|
|
|
|
for (const g of data) {
|
|
|
|
|
const one = this.parseOneGirlUnlock(g);
|
|
|
|
|
if (!one) continue;
|
|
|
|
|
bucket.unlocks.set(g.id, one);
|
|
|
|
|
}
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 刷新技师的解锁数据 */
|
|
|
|
|
private refreshGirlUnlock(data: proto.cs.ILastChatData): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
let briefData = data.girl;
|
|
|
|
|
let categoryId = briefData.category;
|
|
|
|
|
let girlId = briefData.id;
|
|
|
|
|
let unlockData = this.getGrilUnlock(categoryId.toString(), girlId);
|
|
|
|
|
if (unlockData) {
|
|
|
|
|
// 已存在数据,刷新
|
|
|
|
|
unlockData.setIsRelease(data.isRelease);
|
|
|
|
|
unlockData.setUnlockTime(Number(data.unlockTime));
|
|
|
|
|
} else {
|
|
|
|
|
// 不存在数据,创建
|
|
|
|
|
const bucket = this.ensureBucket(categoryId.toString());
|
2025-09-23 11:23:17 +08:00
|
|
|
let oneData = this.createOneGirlUnlock(
|
|
|
|
|
data.id,
|
|
|
|
|
data.isRelease,
|
|
|
|
|
Number(data.unlockTime),
|
|
|
|
|
[],
|
|
|
|
|
[]
|
|
|
|
|
);
|
2025-09-22 17:54:33 +08:00
|
|
|
if (oneData) {
|
|
|
|
|
bucket.unlocks.set(data.id, oneData);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 取某分类 + girlId 的解锁数据 */
|
2025-09-09 19:21:05 +08:00
|
|
|
private getGrilUnlock(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number
|
|
|
|
|
): GirlUnlockData | null {
|
2025-09-08 15:10:51 +08:00
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return null;
|
|
|
|
|
return b.unlocks.get(girlId) ?? null;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
2025-09-15 16:22:31 +08:00
|
|
|
/** 技师的解锁数据是否存在 */
|
|
|
|
|
public isGirlUnlockIn(categoryId: string, girlId: number): boolean {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return false;
|
|
|
|
|
return b.unlocks.has(girlId);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-15 16:22:31 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取 付费技师是否已经解锁 */
|
|
|
|
|
public getIsRelease(categoryId: string, girlId: number): boolean {
|
|
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
2025-09-03 17:35:27 +08:00
|
|
|
if (!oneData) return false;
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData.getIsRelease();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
2025-09-09 18:16:13 +08:00
|
|
|
/** 保存 付费技师是否已经解锁 */
|
2025-09-09 19:24:04 +08:00
|
|
|
public setIsRelease(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
value: boolean
|
|
|
|
|
): void {
|
2025-09-09 18:16:13 +08:00
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
oneData.setIsRelease(value);
|
2025-09-09 19:24:04 +08:00
|
|
|
}
|
2025-09-09 18:16:13 +08:00
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 获取 角色解锁时间,时间戳,秒 */
|
|
|
|
|
public getUnlockTime(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
return oneData.getUnlockTime();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 保存 角色解锁时间,时间戳,秒 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public setUnlockTime(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
value: number
|
|
|
|
|
): void {
|
2025-09-22 17:54:33 +08:00
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
oneData.setUnlockTime(value);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 判断图片是否解锁 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public isImageUnlock(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
|
|
|
|
return oneData.isImageUnlock(id);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 解锁图片 */
|
|
|
|
|
public unlockImage(categoryId: string, girlId: number, id: number): void {
|
|
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
return oneData.unlockImage(id);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 获取所有解锁图片的 id */
|
|
|
|
|
public getUnlockedImageIds(categoryId: string, girlId: number): number[] {
|
|
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return [];
|
|
|
|
|
return oneData.getUnlockedImageIds();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 判断视频是否解锁 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public isVideoUnlock(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
|
|
|
|
return oneData.isVideoUnlock(id);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 解锁视频 */
|
|
|
|
|
public unlockVideo(categoryId: string, girlId: number, id: number): void {
|
|
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
return oneData.unlockVideo(id);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取所有解锁视频的 id */
|
|
|
|
|
public getUnlockedVideoIds(categoryId: string, girlId: number): number[] {
|
|
|
|
|
let oneData = this.getGrilUnlock(categoryId, girlId);
|
|
|
|
|
if (!oneData) return [];
|
|
|
|
|
return oneData.getUnlockedVideoIds();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
2025-09-20 15:52:38 +08:00
|
|
|
/** 获取所有已经解锁技师的 id,不区分技师的付费类型 */
|
|
|
|
|
public getAllReleaseGirlIds(): number[] {
|
|
|
|
|
const result: number[] = [];
|
2025-09-23 10:28:50 +08:00
|
|
|
const seen = new Set<number>(); // 用来去重
|
2025-09-20 15:52:38 +08:00
|
|
|
const cats = this.ensureCategories();
|
2025-09-23 10:28:50 +08:00
|
|
|
// 遍历
|
2025-09-20 15:52:38 +08:00
|
|
|
for (const [categoryId, bucket] of cats.entries()) {
|
|
|
|
|
for (const girlId of bucket.girlIds) {
|
2025-09-23 10:28:50 +08:00
|
|
|
if (this.getIsRelease(categoryId, girlId) && !seen.has(girlId)) {
|
|
|
|
|
seen.add(girlId); // 标记已加入
|
2025-09-20 15:52:38 +08:00
|
|
|
result.push(girlId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 返回结果
|
|
|
|
|
return result;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-20 15:52:38 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** --------------------------------------------------------- 技师的聊天数据 --------------------------------------------------------- */
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
// 创建一个技师聊天数据
|
2025-09-23 11:23:17 +08:00
|
|
|
private createOneGirlChat(
|
|
|
|
|
id: number,
|
|
|
|
|
chatTotalCount: number,
|
|
|
|
|
chatRemainCount: number
|
|
|
|
|
): GirlChatData {
|
2025-09-22 17:54:33 +08:00
|
|
|
let oneData = new GirlChatData();
|
|
|
|
|
oneData.init?.(DataId.GirlChat);
|
|
|
|
|
oneData.setId(id);
|
|
|
|
|
oneData.setChatTotalCount(chatTotalCount);
|
|
|
|
|
oneData.setChatRemainCount(chatRemainCount);
|
|
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
// 解析技师聊天数据,一个
|
|
|
|
|
private parseOneGirlChat(data: proto.cs.IGirlData): GirlChatData | null {
|
|
|
|
|
if (!data) return null;
|
2025-09-23 11:23:17 +08:00
|
|
|
let oneData = this.createOneGirlChat(
|
|
|
|
|
data.id,
|
|
|
|
|
data.chatTotalCount,
|
|
|
|
|
data.chatRemainCount
|
|
|
|
|
);
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 保存技师的聊天数据 */
|
|
|
|
|
private setGirlChat(categoryId: string, data: proto.cs.IGirlData[]): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
const bucket = this.ensureBucket(categoryId);
|
|
|
|
|
for (const g of data) {
|
|
|
|
|
const one = this.parseOneGirlChat(g);
|
|
|
|
|
if (!one) continue;
|
|
|
|
|
bucket.chats.set(g.id, one);
|
|
|
|
|
}
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 刷新技师的聊天数据 */
|
|
|
|
|
private refreshGirlChat(data: proto.cs.ILastChatData): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
let briefData = data.girl;
|
|
|
|
|
let categoryId = briefData.category;
|
|
|
|
|
let girlId = briefData.id;
|
|
|
|
|
let chatData = this.getGrilChat(categoryId.toString(), girlId);
|
|
|
|
|
if (chatData) {
|
|
|
|
|
// 已存在数据,刷新
|
|
|
|
|
chatData.setChatTotalCount(data.chatTotalCount);
|
|
|
|
|
chatData.setChatRemainCount(data.chatRemainCount);
|
|
|
|
|
chatData.setChatRecord(data.msgs);
|
|
|
|
|
} else {
|
|
|
|
|
// 不存在数据,创建
|
|
|
|
|
const bucket = this.ensureBucket(categoryId.toString());
|
2025-09-23 11:23:17 +08:00
|
|
|
let oneData = this.createOneGirlChat(
|
|
|
|
|
data.id,
|
|
|
|
|
data.chatTotalCount,
|
|
|
|
|
data.chatRemainCount
|
|
|
|
|
);
|
2025-09-22 17:54:33 +08:00
|
|
|
if (oneData) {
|
|
|
|
|
oneData.setChatRecord(data.msgs);
|
|
|
|
|
bucket.chats.set(data.id, oneData);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 取某分类 + girlId 的聊天数据 */
|
|
|
|
|
private getGrilChat(categoryId: string, girlId: number): GirlChatData | null {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return null;
|
|
|
|
|
return b.chats.get(girlId) ?? null;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
2025-09-15 16:22:31 +08:00
|
|
|
/** 技师的聊天数据是否存在 */
|
|
|
|
|
public isGirlChatIn(categoryId: string, girlId: number): boolean {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return false;
|
|
|
|
|
return b.chats.has(girlId);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-15 16:22:31 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取总聊天次数 */
|
|
|
|
|
public getChatTotalCount(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
return oneData.getChatTotalCount();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 保存总聊天次数 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public setChatTotalCount(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
value: number
|
|
|
|
|
): void {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
return oneData.setChatTotalCount(value);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取剩余聊天次数 */
|
|
|
|
|
public getChatRemainCount(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
return oneData.getChatRemainCount();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 保存剩余聊天次数 */
|
2025-09-09 19:21:05 +08:00
|
|
|
public setChatRemainCount(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
value: number
|
|
|
|
|
): void {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
return oneData.setChatRemainCount(value);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 更新剩余聊天次数 */
|
|
|
|
|
public useChat(categoryId: string, girlId: number, times: number = 1): void {
|
|
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
return oneData.useChat(times);
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 17:59:47 +08:00
|
|
|
/** 是否可聊天 */
|
|
|
|
|
public isCanChat(categoryId: string, girlId: number): boolean {
|
2025-09-22 17:54:33 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
|
|
|
|
return oneData.isCanChat();
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 19:15:01 +08:00
|
|
|
/** 保存聊天记录 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public setChatRecord(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
data: proto.cs.IChatMsg[]
|
|
|
|
|
): void {
|
2025-09-10 19:15:01 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
oneData.setChatRecord(data);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 19:15:01 +08:00
|
|
|
|
|
|
|
|
/** 获取聊天记录的所有 id */
|
|
|
|
|
public getChatRecordIds(categoryId: string, girlId: number): number[] {
|
|
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return [];
|
|
|
|
|
return oneData.getChatRecordIds();
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 19:15:01 +08:00
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 获取最新的聊天记录的id */
|
2025-09-23 11:23:17 +08:00
|
|
|
public getLatestChatRecordId(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number
|
|
|
|
|
): number | null {
|
2025-09-22 17:54:33 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return null;
|
|
|
|
|
return oneData.getLatestChatRecordId();
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 获取最新的聊天记录的时间戳(毫秒) */
|
2025-09-23 11:23:17 +08:00
|
|
|
public getLatestChatRecordTimestamp(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number
|
|
|
|
|
): number | null {
|
2025-09-22 17:54:33 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return null;
|
|
|
|
|
return oneData.getLatestChatRecordTimestamp();
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
|
2025-09-10 19:15:01 +08:00
|
|
|
/** 获取聊天记录,根据 id,是否是 ai 聊天数据 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public getChatRecordIsAi(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): boolean {
|
2025-09-10 19:15:01 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
|
|
|
|
return oneData.getChatRecordIsAi(id);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 19:15:01 +08:00
|
|
|
/** 获取聊天记录,根据 id,聊天内容 */
|
2025-09-23 11:23:17 +08:00
|
|
|
public getChatRecordMsg(
|
|
|
|
|
categoryId: string,
|
|
|
|
|
girlId: number,
|
|
|
|
|
id: number
|
|
|
|
|
): string {
|
2025-09-10 19:15:01 +08:00
|
|
|
let oneData = this.getGrilChat(categoryId, girlId);
|
|
|
|
|
if (!oneData) return "";
|
|
|
|
|
return oneData.getChatRecordMsg(id);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 获取所有可聊天的技师 id */
|
|
|
|
|
public getAllCanChatGirlIds(): number[] {
|
|
|
|
|
const result: number[] = [];
|
2025-09-22 19:49:26 +08:00
|
|
|
const seen = new Set<number>(); // 用来去重
|
2025-09-22 17:54:33 +08:00
|
|
|
const cats = this.ensureCategories();
|
2025-09-22 19:49:26 +08:00
|
|
|
// 遍历
|
2025-09-22 17:54:33 +08:00
|
|
|
for (const [categoryId, bucket] of cats.entries()) {
|
|
|
|
|
for (const girlId of bucket.girlIds) {
|
2025-09-22 19:49:26 +08:00
|
|
|
if (this.isCanChat(categoryId, girlId) && !seen.has(girlId)) {
|
|
|
|
|
seen.add(girlId); // 标记已加入
|
2025-09-22 17:54:33 +08:00
|
|
|
result.push(girlId);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 18:41:59 +08:00
|
|
|
// 排序
|
|
|
|
|
// 1,都存在聊天记录,按照聊天时间从近到远,否则,有聊天记录的排在前面
|
|
|
|
|
// 2,都没有聊天记录
|
|
|
|
|
// 2.1,付费类型角色排在前面,免费类型角色排在后面
|
|
|
|
|
// 2.2,如果角色都是付费类型,则角色id越大,排在前面
|
|
|
|
|
// 2.3,如果角色都是免费类型,则角色id越大,排在前面
|
|
|
|
|
result.sort((a, b) => {
|
|
|
|
|
const categoryIdA = this.getGrilCategoryById(a);
|
|
|
|
|
const categoryIdB = this.getGrilCategoryById(b);
|
|
|
|
|
// 先取最新聊天时间戳
|
|
|
|
|
const tsA = this.getLatestChatRecordTimestamp(categoryIdA.toString(), a);
|
|
|
|
|
const tsB = this.getLatestChatRecordTimestamp(categoryIdB.toString(), b);
|
|
|
|
|
|
|
|
|
|
if (tsA && tsB) {
|
|
|
|
|
// 都有聊天记录,按时间倒序
|
|
|
|
|
return tsB - tsA;
|
|
|
|
|
} else if (tsA && !tsB) {
|
|
|
|
|
// a 有聊天记录,优先
|
|
|
|
|
return -1;
|
|
|
|
|
} else if (!tsA && tsB) {
|
|
|
|
|
// b 有聊天记录,优先
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
// 都没有聊天记录 → 解锁排前,最后是免费类型
|
|
|
|
|
const isPayTypeA = this.isGirlPayType(categoryIdA.toString(), a);
|
|
|
|
|
const isFreeTypeA = this.isGirlFreeType(categoryIdA.toString(), a);
|
|
|
|
|
const isPayTypeB = this.isGirlPayType(categoryIdB.toString(), b);
|
|
|
|
|
const isFreeTypeB = this.isGirlFreeType(categoryIdB.toString(), b);
|
|
|
|
|
if (isPayTypeA && isFreeTypeB) {
|
|
|
|
|
// A 付费,B 免费 → A 前
|
|
|
|
|
return -1;
|
|
|
|
|
} else if (isFreeTypeA && isPayTypeB) {
|
|
|
|
|
// B 付费,A 免费 → B 前
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
// 都是付费 or 都是免费 → 按 id 倒序
|
|
|
|
|
return b - a;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
// 返回结果
|
|
|
|
|
return result;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-10 17:59:47 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** --------------------------------------------------------- 技师的好感度数据 --------------------------------------------------------- */
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
// 创建一个技师好感度数据
|
2025-10-08 13:38:45 +08:00
|
|
|
private createOneGirlFavorability(id: number, star: number, bookmarkTime: number): GirlFavorabilityData {
|
2025-09-08 15:10:51 +08:00
|
|
|
let oneData = new GirlFavorabilityData();
|
|
|
|
|
oneData.init?.(DataId.GirlFavorability);
|
2025-09-22 17:54:33 +08:00
|
|
|
oneData.setId(id);
|
|
|
|
|
oneData.setStar(star);
|
2025-10-08 13:38:45 +08:00
|
|
|
oneData.setBookmarkTime(bookmarkTime);
|
2025-09-22 17:54:33 +08:00
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析技师好感度数据,一个
|
2025-10-08 13:38:45 +08:00
|
|
|
private parseOneGirlFavorability(data: proto.cs.IGirlData): GirlFavorabilityData | null {
|
2025-09-22 17:54:33 +08:00
|
|
|
if (!data) return null;
|
2025-10-08 13:38:45 +08:00
|
|
|
let oneData = this.createOneGirlFavorability(data.id, data.star, Number(data.bookmarkTime));
|
2025-09-08 15:10:51 +08:00
|
|
|
return oneData;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
|
|
|
|
/** 保存技师的好感度数据 */
|
2025-10-08 13:38:45 +08:00
|
|
|
private setGirlFavorability(categoryId: string,data: proto.cs.IGirlData[]): void {
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!data) return;
|
|
|
|
|
const bucket = this.ensureBucket(categoryId);
|
|
|
|
|
for (const g of data) {
|
|
|
|
|
const one = this.parseOneGirlFavorability(g);
|
|
|
|
|
if (!one) continue;
|
|
|
|
|
bucket.favorability.set(g.id, one);
|
|
|
|
|
}
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-22 17:54:33 +08:00
|
|
|
/** 刷新技师的好感度数据 */
|
|
|
|
|
private refreshGirlFavorability(data: proto.cs.ILastChatData): void {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
let briefData = data.girl;
|
|
|
|
|
let categoryId = briefData.category;
|
|
|
|
|
let girlId = briefData.id;
|
2025-10-08 13:38:45 +08:00
|
|
|
let favData = this.getGirlFavorability(categoryId.toString(), girlId);
|
2025-09-22 17:54:33 +08:00
|
|
|
if (favData) {
|
|
|
|
|
// 已存在数据,刷新
|
|
|
|
|
favData.setStar(data.star);
|
|
|
|
|
} else {
|
|
|
|
|
// 不存在数据,创建
|
|
|
|
|
const bucket = this.ensureBucket(categoryId.toString());
|
2025-10-08 13:38:45 +08:00
|
|
|
let oneData = this.createOneGirlFavorability(data.id, data.star, 0);
|
2025-09-22 17:54:33 +08:00
|
|
|
if (oneData) {
|
|
|
|
|
bucket.favorability.set(data.id, oneData);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-22 17:54:33 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 取某分类 + girlId 的好感度数据 */
|
2025-10-08 13:38:45 +08:00
|
|
|
private getGirlFavorability(categoryId: string, girlId: number): GirlFavorabilityData | null {
|
2025-09-08 15:10:51 +08:00
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return null;
|
|
|
|
|
return b.favorability.get(girlId) ?? null;
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-15 16:22:31 +08:00
|
|
|
/** 技师的好感度数据是否存在 */
|
|
|
|
|
public isGirlFavorabilityIn(categoryId: string, girlId: number): boolean {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return false;
|
|
|
|
|
return b.favorability.has(girlId);
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-15 16:22:31 +08:00
|
|
|
|
2025-09-08 15:10:51 +08:00
|
|
|
/** 获取星级 */
|
|
|
|
|
public getStar(categoryId: string, girlId: number): number {
|
2025-10-08 13:38:45 +08:00
|
|
|
let oneData = this.getGirlFavorability(categoryId, girlId);
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!oneData) return 0;
|
|
|
|
|
return oneData.getStar();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
2025-10-08 13:38:45 +08:00
|
|
|
/** 获取收藏时间,时间戳,秒 */
|
|
|
|
|
public getBookmarkTime(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGirlFavorability(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
return oneData.getBookmarkTime();
|
|
|
|
|
}
|
2025-08-28 17:22:04 +08:00
|
|
|
|
2025-10-09 16:46:57 +08:00
|
|
|
/** 保存 收藏时间,时间戳,秒 */
|
|
|
|
|
public setBookmarkTime(categoryId: string, girlId: number, value: number): void {
|
|
|
|
|
let oneData = this.getGirlFavorability(categoryId, girlId);
|
|
|
|
|
if (!oneData) return;
|
|
|
|
|
oneData.setBookmarkTime(value);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-08 13:38:45 +08:00
|
|
|
/** 是否已经收藏 */
|
|
|
|
|
public isBookmarkGirl(categoryId: string, girlId: number): boolean {
|
|
|
|
|
let oneData = this.getGirlFavorability(categoryId, girlId);
|
|
|
|
|
if (!oneData) return false;
|
|
|
|
|
return oneData.isBookmarkGirl();
|
2025-10-09 16:46:57 +08:00
|
|
|
}
|
2025-10-08 13:38:45 +08:00
|
|
|
|
|
|
|
|
/** 获取所有已经收藏技师的 id */
|
|
|
|
|
public getAllBookmarkGirlIds(): number[] {
|
|
|
|
|
const result: number[] = [];
|
|
|
|
|
const seen = new Set<number>(); // 用来去重
|
|
|
|
|
const cats = this.ensureCategories();
|
|
|
|
|
// 遍历
|
|
|
|
|
for (const [categoryId, bucket] of cats.entries()) {
|
|
|
|
|
for (const girlId of bucket.girlIds) {
|
|
|
|
|
if (this.isBookmarkGirl(categoryId, girlId) && !seen.has(girlId)) {
|
|
|
|
|
seen.add(girlId); // 标记已加入
|
|
|
|
|
result.push(girlId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 返回结果
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** --------------------------------------------------------- 技师的其他数据 --------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
// 创建一个技师其他数据
|
|
|
|
|
private createOneGirlOther(heatValue: number): GirlOtherData {
|
|
|
|
|
let oneData = new GirlOtherData();
|
|
|
|
|
oneData.init?.(DataId.GirlOther);
|
|
|
|
|
oneData.setHeatValue(heatValue);
|
|
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析技师其他数据,一个
|
|
|
|
|
private parseOneGirlOther(data: proto.cs.IGirlData): GirlOtherData | null {
|
|
|
|
|
if (!data) return null;
|
|
|
|
|
let oneData = this.createOneGirlOther(Number(data.score));
|
|
|
|
|
return oneData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 保存技师的其他数据 */
|
|
|
|
|
private setGirlOther(categoryId: string, data: proto.cs.IGirlData[]): void {
|
2025-09-08 15:10:51 +08:00
|
|
|
if (!data) return;
|
2025-10-08 13:38:45 +08:00
|
|
|
const bucket = this.ensureBucket(categoryId);
|
|
|
|
|
for (const g of data) {
|
|
|
|
|
const one = this.parseOneGirlOther(g);
|
|
|
|
|
if (!one) continue;
|
|
|
|
|
bucket.other.set(g.id, one);
|
|
|
|
|
}
|
2025-08-26 11:10:15 +08:00
|
|
|
}
|
|
|
|
|
|
2025-10-08 13:38:45 +08:00
|
|
|
/** 取某分类 + girlId 的其他数据 */
|
|
|
|
|
private getGirlOther(categoryId: string, girlId: number): GirlOtherData | null {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return null;
|
|
|
|
|
return b.other.get(girlId) ?? null;
|
2025-09-23 11:23:17 +08:00
|
|
|
}
|
2025-09-15 16:22:31 +08:00
|
|
|
|
2025-10-08 13:38:45 +08:00
|
|
|
/** 技师的其他数据是否存在 */
|
|
|
|
|
public isGirlOtherIn(categoryId: string, girlId: number): boolean {
|
|
|
|
|
const b = this.ensureCategories().get(categoryId);
|
|
|
|
|
if (!b) return false;
|
|
|
|
|
return b.other.has(girlId);
|
|
|
|
|
}
|
2025-09-08 15:10:51 +08:00
|
|
|
|
2025-10-08 13:38:45 +08:00
|
|
|
/** 获取热度值 */
|
|
|
|
|
public getHeatValue(categoryId: string, girlId: number): number {
|
|
|
|
|
let oneData = this.getGirlOther(categoryId, girlId);
|
|
|
|
|
if (!oneData) return 0;
|
|
|
|
|
return oneData.getHeatValue();
|
2025-09-09 19:21:05 +08:00
|
|
|
}
|
2025-08-26 11:10:15 +08:00
|
|
|
}
|