Merge branch 'main' of 47.107.44.202:xionglijia/18xchat

# Conflicts:
#	assets/Scripts/Sub/UI/PreloadUI.ts
#	assets/Scripts/chat18x/ui/panels/GirlDetailPanel.ts
#	assets/Scripts/chat18x/uiitems/DetailImageItem.ts
This commit is contained in:
2025-09-09 14:50:51 +08:00
70 changed files with 15763 additions and 6106 deletions
+16 -11
View File
@@ -28,7 +28,9 @@ import LanguageUtils, { LanguageType } from "../../Main/Common/LanguageUtils";
import { DataManager, DataId } from "../../chat18x/data/DataManager"; import { DataManager, DataId } from "../../chat18x/data/DataManager";
import { LoginData } from "../../chat18x/data/LoginData"; import { LoginData } from "../../chat18x/data/LoginData";
import { PlayerData } from "../../chat18x/data/PlayerData"; import { PlayerData } from "../../chat18x/data/PlayerData";
import { AccountData } from "../../chat18x/data/AccountData";
import { WalletData } from "../../chat18x/data/WalletData"; import { WalletData } from "../../chat18x/data/WalletData";
import { EnvData } from "../../chat18x/data/EnvData";
import { ConfigManager } from "../../chat18x/manager/ConfigManager"; import { ConfigManager } from "../../chat18x/manager/ConfigManager";
import { AppConfig } from "db://assets/Scripts/chat18x/config/env/appConfig"; import { AppConfig } from "db://assets/Scripts/chat18x/config/env/appConfig";
import DeviceIdService from "db://assets/Scripts/chat18x/foundation/identity/DeviceIdService"; import DeviceIdService from "db://assets/Scripts/chat18x/foundation/identity/DeviceIdService";
@@ -59,9 +61,7 @@ export class PreloadUI extends Component {
this.jinduFilled = this.jinduBar this.jinduFilled = this.jinduBar
.getChildByName("jinduFilled") .getChildByName("jinduFilled")
.getComponent(Sprite); .getComponent(Sprite);
// this.LabProgress = this.node
// .getChildByName("LabProgress")
// .getComponent(Label);
this.loginNode = this.node.getChildByName("loginNode"); this.loginNode = this.node.getChildByName("loginNode");
this.btnLogin = this.loginNode.getChildByName("btnLogin"); this.btnLogin = this.loginNode.getChildByName("btnLogin");
@@ -258,12 +258,12 @@ export class PreloadUI extends Component {
// 游客登录 // 游客登录
const deviceId = DeviceIdService.I.id; const deviceId = DeviceIdService.I.id;
const machineIdentifier = MachineInfoService.I.getMachineIdentifier(); const os = MachineInfoService.I.getMachineOs();
const reqData = { const reqData = {
platType: "guset", platType: "guset",
userId: deviceId, userId: deviceId,
device: deviceId, device: deviceId,
os: 3, os,
}; };
console.log("登录请求数据:", reqData); console.log("登录请求数据:", reqData);
let res = await AuthService.I.login(reqData); let res = await AuthService.I.login(reqData);
@@ -274,28 +274,33 @@ export class PreloadUI extends Component {
const loginData = DataManager.I.getDataById<LoginData>(DataId.Login); const loginData = DataManager.I.getDataById<LoginData>(DataId.Login);
loginData.token = resData.token; loginData.token = resData.token;
loginData.refreshToken = resData.refreshToken; loginData.refreshToken = resData.refreshToken;
loginData.expire = resData.expire; loginData.expire = Number(resData.expire);
const playerData = DataManager.I.getDataById<PlayerData>(DataId.Player); const playerData = DataManager.I.getDataById<PlayerData>(DataId.Player);
playerData.name = resData.name; playerData.name = resData.name;
const accountData = DataManager.I.getDataById<AccountData>(
DataId.Account
);
accountData.accId = resData.accId;
const envData = DataManager.I.getDataById<EnvData>(DataId.Env);
envData.cdn = resData.cdn;
this.loginFinish = true; this.loginFinish = true;
// 请求个人信息
// this.reqMyInfo(); this.reqMyInfo();
} }
} }
// 请求个人信息 // 请求个人信息
private async reqMyInfo() { private async reqMyInfo() {
const reqData = {}; const reqData = {};
console.log("个人信息请求数据:", reqData);
let res = await PlayerDataService.I.reqMyInfo(reqData); let res = await PlayerDataService.I.reqMyInfo(reqData);
console.log("个人信息响应数据:", res); console.log("个人信息响应数据:", res);
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) { if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
const resData = res.data; const resData = res.data;
// 保存数据 // 保存数据
const walletData = DataManager.I.getDataById<WalletData>(DataId.Wallet); const walletData = DataManager.I.getDataById<WalletData>(DataId.Wallet);
walletData.diamond = resData.diamond; walletData.balance = Number(resData.balance);
walletData.vipExpire = resData.vipExpire; walletData.vipExpire = Number(resData.vipExpire);
} }
} }
@@ -25,6 +25,20 @@ export class AiCharacterConfig extends BaseConfig {
return ConfigManager.tables.TbAiCharacters; return ConfigManager.tables.TbAiCharacters;
} }
/**
* 获取所有配置 id,如果存在
*/
public getAllId(): any | null {
let allData = this.getAllConfig();
if (!allData) return null;
const dataArr = allData.getDataList();
let allId = [];
for (let oneData of dataArr) {
allId.push(oneData.id);
}
return allId;
}
/** /**
* 获取配置,根据 id * 获取配置,根据 id
*/ */
@@ -83,6 +83,20 @@ export class GirlConfig extends BaseConfig {
return oneData.priceType; return oneData.priceType;
} }
/** 根据 id 获取购买价格 */
public getPriceById(id: number): number | null {
let oneData = this.getConfigById(id);
if (!oneData) return null;
return oneData.price;
}
/** 根据 id 获取VIP能否解锁 */
public getVipUnlockById(id: number): number | null {
let oneData = this.getConfigById(id);
if (!oneData) return null;
return oneData.vipUnlock;
}
/** 根据 id 获取头像路径 */ /** 根据 id 获取头像路径 */
public getAvatarPathById(id: number): string | null { public getAvatarPathById(id: number): string | null {
let oneData = this.getConfigById(id); let oneData = this.getConfigById(id);
@@ -55,28 +55,57 @@ export class GirlDetailConfig extends BaseConfig {
return oneData.length; return oneData.length;
} }
/** 根据 id 和 index 获取图片类型 */ /** 根据 id 获取 commercialImages的id数组 */
public getImageTypeById(id: number, index: number): number | null { public getCommercialImagesIds(id: number): number[] {
let oneData = this.getCommercialImagesById(id); let oneData = this.getCommercialImagesById(id);
if (!oneData) return null; if (!oneData) return [];
if (index < 0 || index >= oneData.length) return null; // 获取所有 id
return oneData[index].imageType; let allId = [];
for (let one of oneData) {
allId.push(one.id);
}
return allId;
} }
/** 根据 id 和 index 获取图片价格 */ /** 根据 id 获取 某一个commercialImage */
public getImagePriceById(id: number, index: number): number | null { private getOneCommercialImageById(id: number, resId: number): any | null {
let oneData = this.getCommercialImagesById(id); let oneData = this.getCommercialImagesById(id);
if (!oneData) return null; if (!oneData) return null;
if (index < 0 || index >= oneData.length) return null; // 遍历数组找到匹配的资源
return oneData[index].imagePrice; for (let one of oneData) {
if (one.id === resId) {
return one;
}
}
return null;
} }
/** 根据 id 和 index 获取图片路径 */ /** 根据 id 获取图片类型 */
public getImagePathById(id: number, index: number): string | null { public getImageTypeById(id: number, resId: number): number | null {
let oneData = this.getCommercialImagesById(id); let oneData = this.getOneCommercialImageById(id, resId);
if (!oneData) return null; if (!oneData) return null;
if (index < 0 || index >= oneData.length) return null; return oneData.imageType;
return oneData[index].path; }
/** 根据 id 获取聊天触发次数 */
public getImageUnlockCountsById(id: number, resId: number): number | null {
let oneData = this.getOneCommercialImageById(id, resId);
if (!oneData) return null;
return oneData.unlockCounts;
}
/** 根据 id 获取图片价格 */
public getImagePriceById(id: number, resId: number): number | null {
let oneData = this.getOneCommercialImageById(id, resId);
if (!oneData) return null;
return oneData.imagePrice;
}
/** 根据 id 获取图片路径 */
public getImagePathById(id: number, resId: number): string | null {
let oneData = this.getOneCommercialImageById(id, resId);
if (!oneData) return null;
return oneData.path;
} }
/** 根据 id 获取 commercialVideos */ /** 根据 id 获取 commercialVideos */
@@ -93,27 +122,49 @@ export class GirlDetailConfig extends BaseConfig {
return oneData.length; return oneData.length;
} }
/** 根据 id 和 index 获取视频路径 */ /** 根据 id 获取 commercialVideo的id数组 */
public getVideoPathById(id: number, index: number): string | null { public getCommercialVideosIds(id: number): number[] {
let oneData = this.getCommercialVideosById(id); let oneData = this.getCommercialVideosById(id);
if (!oneData) return null; if (!oneData) return [];
if (index < 0 || index >= oneData.length) return null; // 获取所有 id
return oneData[index].path; let allId = [];
for (let one of oneData) {
allId.push(one.id);
}
return allId;
} }
/** 根据 id 和 index 获取关联情绪 */ /** 根据 id 获取 某一个commercialVideo */
public getVideoEmotionById(id: number, index: number): number | null { private getOneCommercialVideoById(id: number, resId: number): any | null {
let oneData = this.getCommercialVideosById(id); let oneData = this.getCommercialVideosById(id);
if (!oneData) return null; if (!oneData) return null;
if (index < 0 || index >= oneData.length) return null; // 遍历数组找到匹配的资源
return oneData[index].emotion; for (let one of oneData) {
if (one.id === resId) {
return one;
}
}
return null;
} }
/** 根据 id 和 index 获取视频价格 */ /** 根据 id 获取视频路径 */
public getVideoPriceById(id: number, index: number): number | null { public getVideoPathById(id: number, resId: number): string | null {
let oneData = this.getCommercialVideosById(id); let oneData = this.getOneCommercialVideoById(id, resId);
if (!oneData) return null; if (!oneData) return null;
if (index < 0 || index >= oneData.length) return null; return oneData.path;
return oneData[index].videoPrice; }
/** 根据 id 获取关联情绪 */
public getVideoEmotionById(id: number, resId: number): number | null {
let oneData = this.getOneCommercialVideoById(id, resId);
if (!oneData) return null;
return oneData.emotion;
}
/** 根据 id 获取视频价格 */
public getVideoPriceById(id: number, resId: number): number | null {
let oneData = this.getOneCommercialVideoById(id, resId);
if (!oneData) return null;
return oneData.videoPrice;
} }
} }
@@ -74,6 +74,20 @@ export class GlobalConfig extends BaseConfig {
return oneData.FreeChatTimes; return oneData.FreeChatTimes;
} }
/** 单次对话增长好感度 */
public getOnceChatAddScore(): number | null {
let oneData = this.getAllConfig();
if (!oneData) return null;
return oneData.OnceChatAddScore;
}
/** 好感度等级兑换比例 */
public getScoreExchangeStarLevel(): number | null {
let oneData = this.getAllConfig();
if (!oneData) return null;
return oneData.ScoreExchangeStarLevel;
}
/** 游戏名 */ /** 游戏名 */
public getGameName(): string | null { public getGameName(): string | null {
let oneData = this.getAllConfig(); let oneData = this.getAllConfig();
@@ -25,6 +25,65 @@ export class PurchaseConfig extends BaseConfig {
return ConfigManager.tables.TbPurchaseConfig; return ConfigManager.tables.TbPurchaseConfig;
} }
/**
* 获取所有配置 id,如果存在
*/
public getAllId(): any | null {
let allData = this.getAllConfig();
if (!allData) return null;
const dataArr = allData.getDataList();
let allId = [];
for (let oneData of dataArr) {
allId.push(oneData.id);
}
return allId;
}
/** 获取 充值商品的id数组,首位数字为 1 */
public getRechargeIds(): number[] {
let allId = this.getAllId();
if (!allId) return [];
// 获取所有 id
let resultId = [];
for (let one of allId) {
const firstDigit = one.toString()[0]; // 取首位字符
if (firstDigit === "1") {
resultId.push(one);
}
}
return resultId;
}
/** 获取 会员商品的id数组,首位数字为 2 */
public getMemberIds(): number[] {
let allId = this.getAllId();
if (!allId) return [];
// 获取所有 id
let resultId = [];
for (let one of allId) {
const firstDigit = one.toString()[0]; // 取首位字符
if (firstDigit === "2") {
resultId.push(one);
}
}
return resultId;
}
/** 获取 聊天商品的id数组,首位数字为 3 */
public getChatIds(): number[] {
let allId = this.getAllId();
if (!allId) return [];
// 获取所有 id
let resultId = [];
for (let one of allId) {
const firstDigit = one.toString()[0]; // 取首位字符
if (firstDigit === "3") {
resultId.push(one);
}
}
return resultId;
}
/** /**
* 获取配置,根据 id * 获取配置,根据 id
*/ */
@@ -47,4 +106,11 @@ export class PurchaseConfig extends BaseConfig {
if (!oneData) return null; if (!oneData) return null;
return oneData.count; return oneData.count;
} }
/** 根据商品 id 获取商品价格 */
public getPriceById(id: number): number | null {
let oneData = this.getConfigById(id);
if (!oneData) return null;
return oneData.price;
}
} }
+11 -11
View File
@@ -8,8 +8,8 @@ export class AccountData extends BaseData {
private _identifier = ""; private _identifier = "";
// 身份类型,1:游客;2:微信;3googleplay // 身份类型,1:游客;2:微信;3googleplay
private _identityType = 1; private _identityType = 1;
// 玩家Uid // 用户id
private _uid = ""; private _accId: string = "";
// 是否新手 // 是否新手
private _isNewGuide = true; private _isNewGuide = true;
// 是否刚注册 // 是否刚注册
@@ -18,7 +18,7 @@ export class AccountData extends BaseData {
public reset(): void { public reset(): void {
this._identifier = ""; this._identifier = "";
this._identityType = 1; this._identityType = 1;
this._uid = ""; this._accId = "";
this._isNewGuide = true; this._isNewGuide = true;
this._isNewRegist = true; this._isNewRegist = true;
} }
@@ -26,7 +26,7 @@ export class AccountData extends BaseData {
public clear(): void { public clear(): void {
this._identifier = ""; this._identifier = "";
this._identityType = 1; this._identityType = 1;
this._uid = ""; this._accId = "";
this._isNewGuide = true; this._isNewGuide = true;
this._isNewRegist = true; this._isNewRegist = true;
} }
@@ -35,7 +35,7 @@ export class AccountData extends BaseData {
super.destroy(); super.destroy();
this._identifier = null; this._identifier = null;
this._identityType = null; this._identityType = null;
this._uid = null; this._accId = null;
this._isNewGuide = null; this._isNewGuide = null;
this._isNewRegist = null; this._isNewRegist = null;
} }
@@ -60,14 +60,14 @@ export class AccountData extends BaseData {
return this._identityType; return this._identityType;
} }
/** 设置玩家Uid */ /** 设置用户id */
public set uid(value: string) { public set accId(value: string) {
this._uid = value; this._accId = value;
} }
/** 获取玩家Uid */ /** 获取用户id */
public get uid(): string { public get accId(): string {
return this._uid; return this._accId;
} }
/** 设置是否新手 */ /** 设置是否新手 */
+7
View File
@@ -13,6 +13,13 @@ export class BaseData {
/** 数据ID */ /** 数据ID */
protected _dataId: string = ''; protected _dataId: string = '';
/**
* 构造方法
*/
constructor() {
}
/** /**
* 初始化数据 * 初始化数据
* @param dataId 数据ID * @param dataId 数据ID
+11 -6
View File
@@ -13,6 +13,8 @@ import { WalletData } from "./WalletData";
import { ShopData } from "./ShopData"; import { ShopData } from "./ShopData";
import { OrderData } from "./OrderData"; import { OrderData } from "./OrderData";
import { GirlData } from "./GirlData"; import { GirlData } from "./GirlData";
import { EnvData } from "./EnvData";
import { GlobalData } from "./GlobalData";
/** /**
* 集中定义数据ID,避免写错字符串 * 集中定义数据ID,避免写错字符串
@@ -28,6 +30,13 @@ export enum DataId {
Shop = "shop", // 商城数据 Shop = "shop", // 商城数据
Order = "order", // 订单数据 Order = "order", // 订单数据
Girl = "girl", // 技师数据 Girl = "girl", // 技师数据
GirlBrief = "girlBrief", // 技师的简要数据
GirlDetail = "girlDetail", // 技师的详细数据
GirlUnlock = "girlUnlock", // 技师的解锁数据
GirlChat = "girlChat", // 技师的聊天数据
GirlFavorability = "girlFavorability", // 技师的好感度数据
Env = "env", // 环境数据
Global = "global", // 全局数据
} }
/** 构造器类型 */ /** 构造器类型 */
@@ -70,6 +79,8 @@ export class DataManager {
this.register(DataId.Shop, ShopData); this.register(DataId.Shop, ShopData);
this.register(DataId.Order, OrderData); this.register(DataId.Order, OrderData);
this.register(DataId.Girl, GirlData); this.register(DataId.Girl, GirlData);
this.register(DataId.Env, EnvData);
this.register(DataId.Global, GlobalData);
} }
/** /**
@@ -102,8 +113,6 @@ export class DataManager {
// 若你的 BaseData.init 接受 dataId,可传入 // 若你的 BaseData.init 接受 dataId,可传入
instance.init?.(dataId); instance.init?.(dataId);
this._dataMap.set(dataId, instance); this._dataMap.set(dataId, instance);
console.log(`[DataManager] 实例化并缓存数据: ${dataId}`);
return instance; return instance;
} }
@@ -115,7 +124,6 @@ export class DataManager {
if (data) { if (data) {
data.destroy?.(); data.destroy?.();
this._dataMap.delete(dataId); this._dataMap.delete(dataId);
console.log(`[DataManager] 移除数据: ${dataId}`);
return true; return true;
} }
return false; return false;
@@ -125,7 +133,6 @@ export class DataManager {
* 重置所有数据 * 重置所有数据
*/ */
public resetAllData(): void { public resetAllData(): void {
console.log("[DataManager] 重置所有数据");
this._dataMap.forEach((data) => data.reset?.()); this._dataMap.forEach((data) => data.reset?.());
} }
@@ -133,7 +140,6 @@ export class DataManager {
* 清空所有数据 * 清空所有数据
*/ */
public clearAllData(): void { public clearAllData(): void {
console.log("[DataManager] 清空所有数据");
this._dataMap.forEach((data) => data.clear?.()); this._dataMap.forEach((data) => data.clear?.());
} }
@@ -141,7 +147,6 @@ export class DataManager {
* 销毁所有数据 * 销毁所有数据
*/ */
public destroyAllData(): void { public destroyAllData(): void {
console.log("[DataManager] 销毁所有数据");
this._dataMap.forEach((data) => data.destroy?.()); this._dataMap.forEach((data) => data.destroy?.());
this._dataMap.clear(); this._dataMap.clear();
} }
+32
View File
@@ -0,0 +1,32 @@
/**
* 环境数据
*/
import { BaseData } from "./BaseData";
export class EnvData extends BaseData {
// cdn地址
private _cdn: string = '';
public reset(): void {
this._cdn = '';
}
public clear(): void {
this._cdn = '';
}
public destroy(): void {
super.destroy();
this._cdn = null;
}
/** 设置cdn地址 */
public set cdn(value: string) {
this._cdn = value;
}
/** 获取cdn地址 */
public get cdn(): string {
return this._cdn;
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "cf8c891f-8726-42be-918b-4f101118dae3",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,147 @@
/**
* 技师的简要数据
*/
import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class GirlBriefData extends BaseData {
// id
private id: number;
// 名字键
private nameKey: string;
// 年龄
private age: string;
// 主题枚举
private category: number;
// 标签键
private tagKey: string;
// 付费类型
private priceType: number;
// 购买价格
private price: number;
// VIP能否解锁
private vipUnlock: number;
// 头像路径
private avatarPath: string;
// list头像路径
private listAvatarPath: string;
constructor() {
super();
this.id = 0;
this.nameKey = "";
this.age = "";
this.category = 0;
this.tagKey = "";
this.priceType = 0;
this.price = 0;
this.vipUnlock = 0;
this.avatarPath = "";
this.listAvatarPath = "";
}
public reset(): void {
this.id = 0;
this.nameKey = "";
this.age = "";
this.category = 0;
this.tagKey = "";
this.priceType = 0;
this.price = 0;
this.vipUnlock = 0;
this.avatarPath = "";
this.listAvatarPath = "";
}
public clear(): void {
this.id = 0;
this.nameKey = "";
this.age = "";
this.category = 0;
this.tagKey = "";
this.priceType = 0;
this.price = 0;
this.vipUnlock = 0;
this.avatarPath = "";
this.listAvatarPath = "";
}
public destroy(): void {
super.destroy();
this.id = null;
this.nameKey = null;
this.age = null;
this.category = null;
this.tagKey = null;
this.priceType = null;
this.price = null;
this.vipUnlock = null;
this.avatarPath = null;
this.listAvatarPath = null;
}
/** 保存数据 */
public setData(data: proto.cs.IGirls): void {
if (!data) return;
this.id = data.id;
this.nameKey = data.nameKey;
this.age = data.age;
this.category = data.category;
this.tagKey = data.tagKey;
this.priceType = data.priceType;
this.price = data.price;
this.vipUnlock = data.vipUnlock;
this.avatarPath = data.avatarPath;
this.listAvatarPath = data.listAvatarPath;
}
/** 获取 id */
public getId(): number {
return this.id;
}
/** 获取名字键 */
public getGrilName(): string {
return this.nameKey;
}
/** 获取年龄 */
public getGrilAge(): string {
return this.age;
}
/** 获取主题枚举 */
public getGrilCategory(): number {
return this.category;
}
/** 获取标签键 */
public getGrilTagKey(): string {
return this.tagKey;
}
/** 获取付费类型 */
public getGrilPriceType(): number {
return this.priceType;
}
/** 获取价格 */
public getGrilPrice(): number {
return this.price;
}
/** 获取VIP能否解锁 */
public getGrilVipUnlock(): number {
return this.vipUnlock;
}
/** 获取头像路径 */
public getGrilAvatar(): string {
return this.avatarPath;
}
/** 获取list头像路径 */
public getGrilListAvatar(): string {
return this.listAvatarPath;
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "35c42c32-997a-40f3-b689-6de7e53cdf3b",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,79 @@
/**
* 技师的聊天数据
*/
import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class GirlChatData extends BaseData {
// id
private id: number;
// 总聊天次数
private chatTotalCount: number;
// 剩余聊天次数, < 0: 不限制; = 0 聊天次数已经用完; > 0 还剩余多少次聊天次数
private chatRemainCount: number;
constructor() {
super();
this.id = 0;
this.chatTotalCount = 0;
this.chatRemainCount = 0;
}
public reset(): void {
this.id = 0;
this.chatTotalCount = 0;
this.chatRemainCount = 0;
}
public clear(): void {
this.id = 0;
this.chatTotalCount = 0;
this.chatRemainCount = 0;
}
public destroy(): void {
super.destroy();
this.id = null;
this.chatTotalCount = null;
this.chatRemainCount = null;
}
/** 获取 id */
public getId(): number {
return this.id;
}
/** 保存 id */
public setId(value: number): void {
this.id = value;
}
/** 获取总聊天次数 */
public getChatTotalCount(): number {
return this.chatTotalCount;
}
/** 保存总聊天次数 */
public setChatTotalCount(value: number): void {
this.chatTotalCount = value;
console.log("当前技师 ", this.id, " ,总聊天次数:", this.chatTotalCount);
}
/** 获取剩余聊天次数 */
public getChatRemainCount(): number {
return this.chatRemainCount;
}
/** 保存剩余聊天次数 */
public setChatRemainCount(value: number): void {
this.chatRemainCount = value;
console.log("当前技师 ", this.id, " ,剩余聊天次数:", this.chatRemainCount);
}
/** 更新剩余聊天次数 */
public useChat(times: number = 1) {
if (this.chatRemainCount > 0) {
this.setChatRemainCount(Math.max(0, this.chatRemainCount - times));
}
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "40a2e0a1-fce2-4812-97b5-f96153800c52",
"files": [],
"subMetas": {},
"userData": {}
}
+445 -313
View File
@@ -1,15 +1,27 @@
/** /**
* 技师数据 * 技师数据,统一访问入口
*/ */
import { BaseData } from "./BaseData"; import { BaseData } from "./BaseData";
import { GirlBriefData } from "./GirlBriefData";
import { GirlDetailData } from "./GirlDetailData";
import { GirlUnlockData } from "./GirlUnlockData";
import { GirlChatData } from "./GirlChatData";
import { GirlFavorabilityData } from "./GirlFavorabilityData";
import { DataId } from "./DataManager";
import proto from 'db://assets/Scripts/proto/proto.pb.js'; import proto from 'db://assets/Scripts/proto/proto.pb.js';
// 分类的数据结构 // 分类的数据结构
interface CategoryBucket { interface CategoryBucket {
// 技师的简要数据 // 技师的简要数据
briefs: Map<number, proto.cs.IGirlBrief>; briefs: Map<number, GirlBriefData>;
// 技师的详细数据 // 技师的详细数据
details: Map<number, proto.cs.IGirlDetail>; details: Map<number, GirlDetailData>;
// 技师的解锁数据
unlocks: Map<number, GirlUnlockData>;
// 技师的聊天数据
chats: Map<number, GirlChatData>;
// 技师的好感度数据
favorability: Map<number, GirlFavorabilityData>;
// 技师的id // 技师的id
girlIds: number[]; girlIds: number[];
} }
@@ -20,8 +32,6 @@ const DAILY_BUCKET = "__daily__";
export class GirlData extends BaseData { export class GirlData extends BaseData {
// 大分类 // 大分类
private _categories = new Map<string, CategoryBucket>(); private _categories = new Map<string, CategoryBucket>();
// 每日推荐(存放在 DAILY_BUCKET 中,同时保留 id 索引便于 UI 使用)
private _dailyRecommendIds: number[] = [];
public reset(): void { public reset(): void {
this._categories.clear(); this._categories.clear();
@@ -50,8 +60,11 @@ export class GirlData extends BaseData {
let bucket = cats.get(categoryId); let bucket = cats.get(categoryId);
if (!bucket) { if (!bucket) {
bucket = { bucket = {
briefs: new Map<number, proto.cs.IGirlBrief>(), briefs: new Map<number, GirlBriefData>(),
details: new Map<number, proto.cs.IGirlDetail>(), details: new Map<number, GirlDetailData>(),
unlocks: new Map<number, GirlUnlockData>(),
chats: new Map<number, GirlChatData>(),
favorability: new Map<number, GirlFavorabilityData>(),
girlIds: [], girlIds: [],
}; };
cats.set(categoryId, bucket); cats.set(categoryId, bucket);
@@ -59,262 +72,200 @@ export class GirlData extends BaseData {
return bucket; return bucket;
} }
/**
* 合并一批简要信息到指定分类;并维护 girlIds 顺序(去重追加)
*/
public mergeBriefs(categoryId: string, respOrList: proto.cs.IGirlBrief[]): void {
if (!respOrList) return;
let allData = this.parseAllGirlBrief(respOrList);
if (!allData) return;
const bucket = this.ensureBucket(categoryId);
// 用一个临时 Set 保存已有的 id,加速去重
const existed = new Set<number>(bucket.girlIds);
for (const g of allData) {
const id = g.id;
bucket.briefs.set(id, g);
// 去重
if (!existed.has(id)) {
bucket.girlIds.push(id);
existed.add(id);
}
}
console.log("保存技师的简要数据: ", bucket);
}
/** 取分类下的全部 girlIds(若分类不存在返回空数组) */ /** 取分类下的全部 girlIds(若分类不存在返回空数组) */
public getGirlIds(categoryId: string): number[] { public getGirlIds(categoryId: string): number[] {
const b = this.ensureCategories().get(categoryId); const b = this.ensureCategories().get(categoryId);
return b ? b.girlIds : []; return b ? b.girlIds : [];
} }
/** 保存技师列表 */
public setGirlList(categoryId: string, data: proto.cs.ICSGetGirlListRes): void {
if (!data) return;
this.setGirlBrief(categoryId, data.girls);
this.setGirlUnlock(categoryId, data.girls);
this.setGirlFavorability(categoryId, data.girls);
const bucket = this.ensureBucket(categoryId);
console.log("保存类别 ", categoryId, " 的技师列表: ", bucket);
}
/** 保存技师详细数据 */
public setGirlDetailData(categoryId: string, data: proto.cs.ICSGetGirlDetailRes): void {
if (!data) return;
let details = []
details.push(data.girl);
this.setGirlBrief(categoryId, details);
this.setGirlDetail(categoryId, details);
this.setGirlUnlock(categoryId, details);
this.setGirlChat(categoryId, details);
this.setGirlFavorability(categoryId, details);
const bucket = this.ensureBucket(categoryId);
console.log("保存类别 ", categoryId, " 的详细数据: ", bucket);
}
/** --------------------------------------------------------- 技师的简要数据 --------------------------------------------------------- */ /** --------------------------------------------------------- 技师的简要数据 --------------------------------------------------------- */
// 解析技师简要数据,一个 /**
private parseOneGirlBrief(data: proto.cs.IGirlBrief): proto.cs.IGirlBrief | null { * 合并一个简要数据到指定分类;并维护 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);
}
}
/**
* 合并一批简要数据到指定分类;并维护 girlIds 顺序(去重追加)
*/
private mergeBriefs(categoryId: string, respOrList: proto.cs.IGirlData[]): void {
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);
}
}
}
private parseOneGirlBrief(data: proto.cs.IGirls): GirlBriefData | null {
if (!data) return null; if (!data) return null;
const oneData: proto.cs.IGirlBrief = { let oneData = new GirlBriefData();
id: data.id, // id oneData.init?.(DataId.GirlBrief);
name: data.name, // 名字 oneData.setData(data);
age: data.age, // 年龄
tagKey: data.tagKey, // 标签
priceType: data.priceType, // 付费类型
price: data.price, // 价格
avatar: data.avatar, // 头像
star: data.star, // 星级
category: data.category, // 主题枚举
listAvatarPath: data.listAvatarPath, // list头像路径
};
return oneData; 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 { private setGirlBrief(categoryId: string, data: proto.cs.IGirlData[]): void {
this.mergeBriefs(categoryId, data.girls); this.mergeBriefs(categoryId, data);
} }
/** 取某分类 + girlId 的简要信息 */ /** 取某分类 + girlId 的简要数据 */
private getGrilBrief(categoryId: string, girlId: number): proto.cs.IGirlBrief | null { private getGrilBrief(categoryId: string, girlId: number): GirlBriefData | null {
const b = this.ensureCategories().get(categoryId); const b = this.ensureCategories().get(categoryId);
if (!b) return null; if (!b) return null;
return b.briefs.get(girlId) ?? null; return b.briefs.get(girlId) ?? null;
} }
/** 获取名字 */ /** 获取名字 */
public getGrilName(categoryId: string, girlId: number): string { public getGrilName(categoryId: string, girlId: number): string {
let oneData = this.getGrilBrief(categoryId, girlId); let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return ""; if (!oneData) return "";
return oneData.name; return oneData.getGrilName();
} }
/** 获取年龄 */ /** 获取年龄 */
public getGrilAge(categoryId: string, girlId: number): number { public getGrilAge(categoryId: string, girlId: number): string {
let oneData = this.getGrilBrief(categoryId, girlId); let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0; if (!oneData) return "0";
return oneData.age; return oneData.getGrilAge();
}
/** 获取标签 */
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;
} }
/** 获取主题枚举 */ /** 获取主题枚举 */
public getGrilCategory(categoryId: string, girlId: number): number { public getGrilCategory(categoryId: string, girlId: number): number {
let oneData = this.getGrilBrief(categoryId, girlId); let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0; if (!oneData) return 0;
return oneData.category; return oneData.getGrilCategory();
} }
/** 获取主题枚举,根据 id */ /** 获取标签键 */
public getGrilCategoryById(girlId: number): number { public getGrilTagKey(categoryId: string, girlId: number): string {
const cats = this.ensureCategories(); let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return "";
return oneData.getGrilTagKey();
}
for (const bucket of cats.values()) { /** 获取付费类型 */
// 先查简要信息 public getGrilPriceType(categoryId: string, girlId: number): number {
const brief = bucket.briefs.get(girlId); let oneData = this.getGrilBrief(categoryId, girlId);
if (brief && brief.category) { if (!oneData) return 0;
return brief.category; return oneData.getGrilPriceType();
} }
// 兜底:若只缓存了详情,也从详情里的 brief 取
const detail = bucket.details.get(girlId);
if (detail?.brief && typeof detail.brief.category) {
return detail.brief.category;
}
}
// 未找到 /** 获取价格 */
return 0; public getGrilPrice(categoryId: string, girlId: number): number {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0;
return oneData.getGrilPrice();
}
/** 获取VIP能否解锁 */
public getGrilVipUnlock(categoryId: string, girlId: number): number {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return 0;
return oneData.getGrilVipUnlock();
}
/** 获取头像路径 */
public getGrilAvatar(categoryId: string, girlId: number): string {
let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return "";
return oneData.getGrilAvatar();
} }
/** 获取list头像路径 */ /** 获取list头像路径 */
public getGrilListAvatar(categoryId: string, girlId: number): string { public getGrilListAvatar(categoryId: string, girlId: number): string {
let oneData = this.getGrilBrief(categoryId, girlId); let oneData = this.getGrilBrief(categoryId, girlId);
if (!oneData) return ""; if (!oneData) return "";
return oneData.listAvatarPath; return oneData.getGrilListAvatar();
}
/** 获取主题枚举,根据 id */
public getGrilCategoryById(girlId: number): number {
const cats = this.ensureCategories();
// 遍历
for (const bucket of cats.values()) {
// 先查简要信息
const brief = bucket.briefs.get(girlId);
if (brief) {
return brief.getGrilCategory();
}
}
// 未找到
return 0;
} }
/** --------------------------------------------------------- 技师的详细数据 --------------------------------------------------------- */ /** --------------------------------------------------------- 技师的详细数据 --------------------------------------------------------- */
// 解析技师图片数据,一个
private parseOneGirlPhoto(data: proto.cs.IPurchaseCommercialImage): proto.cs.IPurchaseCommercialImage | null {
if (!data) return null;
const oneData: proto.cs.IPurchaseCommercialImage = {
imageType: data.imageType, // 图片类型
imagePrice: data.imagePrice, // 图片价格
path: data.path, // 图片资源路径
isRelease: data.isRelease, // 是否解锁
};
return oneData;
}
// 解析技师图片数据,多个
private parseAllGirlPhoto(data: proto.cs.IPurchaseCommercialImage[]): proto.cs.IPurchaseCommercialImage[] | null {
if (!data) return null;
let allData = [];
for (const value of data) {
const oneData: proto.cs.IPurchaseCommercialImage = this.parseOneGirlPhoto(value);
if (oneData) {
allData.push(oneData);
}
}
return allData;
}
// 解析技师视频数据,一个
private parseOneGirlVideo(data: proto.cs.IPurchaseCommercialVideo): proto.cs.IPurchaseCommercialVideo | null {
if (!data) return null;
const oneData: proto.cs.IPurchaseCommercialVideo = {
path: data.path, // 视频资源路径
emotion: data.emotion, // 关联情绪
videoPrice: data.videoPrice, // 价格
isRelease: data.isRelease, // 是否解锁
};
return oneData;
}
// 解析技师视频数据,多个
private parseAllGirlVideo(data: proto.cs.IPurchaseCommercialVideo[]): proto.cs.IPurchaseCommercialVideo[] | null {
if (!data) return null;
let allData = [];
for (const value of data) {
const oneData: proto.cs.IPurchaseCommercialVideo = this.parseOneGirlVideo(value);
if (oneData) {
allData.push(oneData);
}
}
return allData;
}
// 解析技师详细数据,一个 // 解析技师详细数据,一个
private parseOneGirlDetail(data: proto.cs.IGirlDetail): proto.cs.IGirlDetail | null { private parseOneGirlDetail(data: proto.cs.IGirlsDetail): GirlDetailData | null {
if (!data) return null; if (!data) return null;
const photoData = this.parseAllGirlPhoto(data.images); let oneData = new GirlDetailData();
const videoData = this.parseAllGirlVideo(data.videos); oneData.init?.(DataId.GirlDetail);
const briefData = this.parseOneGirlBrief(data.brief); oneData.setData(data);
const oneData: proto.cs.IGirlDetail = {
brief: briefData, // 技师简要数据
desc: data.desc, // 技师描述
isRelease: data.isRelease, // 技师是否解锁
chatCount: data.chatCount, // 剩余聊天次数
images: photoData, // 技师图片列表
videos: videoData, // 技师视频列表
};
return oneData; 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 { private setGirlDetail(categoryId: string, data: proto.cs.IGirlData[]): void {
const d = data?.detail; if (!data) return;
if (!d) return;
// 合并简要信息
if (d.brief) this.mergeBriefs(categoryId, [d.brief]);
const oneDetail = this.parseOneGirlDetail(d);
const bucket = this.ensureBucket(categoryId); const bucket = this.ensureBucket(categoryId);
// id for (const g of data) {
const id = d.brief?.id ?? 0; const one = this.parseOneGirlDetail(g.detail);
// 写入详情 if (!one) continue;
bucket.details.set(id, oneDetail); bucket.details.set(g.id, one);
console.log("保存技师的详细数据: ", bucket); }
} }
/** 取某分类 + girlId 的详细信息 */ /** 取某分类 + girlId 的详细数据 */
public getGrilDetail(categoryId: string, girlId: number): proto.cs.IGirlDetail | null { public getGrilDetail(categoryId: string, girlId: number): GirlDetailData | null {
const b = this.ensureCategories().get(categoryId); const b = this.ensureCategories().get(categoryId);
if (!b) return null; if (!b) return null;
return b.details.get(girlId) ?? null; return b.details.get(girlId) ?? null;
@@ -324,163 +275,344 @@ export class GirlData extends BaseData {
public getGrilDesc(categoryId: string, girlId: number): string { public getGrilDesc(categoryId: string, girlId: number): string {
let oneData = this.getGrilDetail(categoryId, girlId); let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return ""; if (!oneData) return "";
return oneData.desc; return oneData.getGirlDesc();
}
/** 获取技师是否解锁 */
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;
}
/** 获取所有技师图片数据 */
private getAllGrilPhotoData(categoryId: string, girlId: number): proto.cs.IPurchaseCommercialImage[] | null {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData || !oneData.images) return null;
return oneData.images;
} }
/** 获取所有技师图片数据的数量 */ /** 获取所有技师图片数据的数量 */
public getAllGrilPhotoDataCount(categoryId: string, girlId: number): number { public getAllGrilPhotoDataCount(categoryId: string, girlId: number): number {
let allData = this.getAllGrilPhotoData(categoryId, girlId); let oneData = this.getGrilDetail(categoryId, girlId);
if (!allData) return 0; if (!oneData) return 0;
return allData.length; return oneData.getAllGrilPhotoDataCount();
} }
/** 获取技师图片数据,通过 index */ /** 获取所有技师图片数据的id */
private getGrilPhotoData(categoryId: string, girlId: number, index: number): proto.cs.IPurchaseCommercialImage | null { public getAllGrilPhotoDataId(categoryId: string, girlId: number): number[] {
let allData = this.getAllGrilPhotoData(categoryId, girlId); let oneData = this.getGrilDetail(categoryId, girlId);
if (!allData) return null; if (!oneData) return [];
// 下标越界保护 return oneData.getAllGrilPhotoDataId();
if (index < 0 || index >= allData.length) return null; }
return allData[index] ?? null; /** 获取第一个技师图片的资源路径 */
public getFirstGrilPhotoPath(categoryId: string, girlId: number): string {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return "";
// 第一个 id
const ids = this.getAllGrilPhotoDataId(categoryId, girlId);
const length = ids.length;
if (length <= 0) return "";
// 返回数据
return oneData.getGrilPhotoPath(ids[0]);
} }
/** 获取技师图片的类型 */ /** 获取技师图片的类型 */
public getGrilPhotoType(categoryId: string, girlId: number, index: number): number { public getGrilPhotoType(categoryId: string, girlId: number, id: number): number {
let oneData = this.getGrilPhotoData(categoryId, girlId, index); let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return 0; if (!oneData) return 0;
return oneData.imageType; return oneData.getGrilPhotoType(id);
}
/** 获取技师图片的聊天触发次数 */
public getGrilPhotoUnlockCounts(categoryId: string, girlId: number, id: number): number {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return 0;
return oneData.getGrilPhotoUnlockCounts(id);
} }
/** 获取技师图片的价格 */ /** 获取技师图片的价格 */
public getGrilPhotoPrice(categoryId: string, girlId: number, index: number): number { public getGrilPhotoPrice(categoryId: string, girlId: number, id: number): number {
let oneData = this.getGrilPhotoData(categoryId, girlId, index);
if (!oneData) return 0;
return oneData.imagePrice;
}
/** 获取技师图片的路径 */
public getGrilPhotoPic(categoryId: string, girlId: number, index: number): string {
let oneData = this.getGrilPhotoData(categoryId, girlId, index);
if (!oneData) return "";
return oneData.path;
}
/** 获取技师图片是否解锁 */
public getGrilPhotoIsRelease(categoryId: string, girlId: number, index: number): boolean {
let oneData = this.getGrilPhotoData(categoryId, girlId, index);
if (!oneData) return false;
return oneData.isRelease;
}
/** 获取所有技师视频数据 */
private getAllGrilVideoData(categoryId: string, girlId: number): proto.cs.IPurchaseCommercialVideo[] | null {
let oneData = this.getGrilDetail(categoryId, girlId); let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData || !oneData.videos) return null; if (!oneData) return 0;
return oneData.getGrilPhotoPrice(id);
}
return oneData.videos ?? null; /** 获取技师图片的资源路径 */
public getGrilPhotoPic(categoryId: string, girlId: number, id: number): string {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return "";
return oneData.getGrilPhotoPath(id);
} }
/** 获取所有技师视频数据的数量 */ /** 获取所有技师视频数据的数量 */
public getAllGrilVideoDataCount(categoryId: string, girlId: number): number { public getAllGrilVideoDataCount(categoryId: string, girlId: number): number {
let allData = this.getAllGrilVideoData(categoryId, girlId); let oneData = this.getGrilDetail(categoryId, girlId);
if (!allData) return 0; if (!oneData) return 0;
return allData.length; return oneData.getAllGrilVideoDataCount();
} }
/** 获取技师视频数据,通过 index */ /** 获取所有技师视频数据的id */
private getGrilVideoData(categoryId: string, girlId: number, index: number): proto.cs.IPurchaseCommercialVideo | null { public getAllGrilVideoDataId(categoryId: string, girlId: number): number[] {
let allData = this.getAllGrilVideoData(categoryId, girlId); let oneData = this.getGrilDetail(categoryId, girlId);
if (!allData) return null; if (!oneData) return [];
// 下标越界保护 return oneData.getAllGrilVideoDataId();
if (index < 0 || index >= allData.length) return null;
return allData[index] ?? null;
} }
/** 获取技师视频的路径 */ /** 获取第一个技师视频的资源路径 */
public getGrilVideoPath(categoryId: string, girlId: number, index: number): string { public getFirstGrilVideoPath(categoryId: string, girlId: number): string {
let oneData = this.getGrilVideoData(categoryId, girlId, index); let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return ""; if (!oneData) return "";
return oneData.path; // 第一个 id
const ids = this.getAllGrilVideoDataId(categoryId, girlId);
const length = ids.length;
if (length <= 0) return "";
// 返回数据
return oneData.getGrilVideoPath(ids[0]);
}
/** 获取技师视频的资源路径 */
public getGrilVideoPath(categoryId: string, girlId: number, id: number): string {
let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return "";
return oneData.getGrilVideoPath(id);
} }
/** 获取技师视频的关联情绪 */ /** 获取技师视频的关联情绪 */
public getGrilVideoEmotion(categoryId: string, girlId: number, index: number): number { public getGrilVideoEmotion(categoryId: string, girlId: number, id: number): number {
let oneData = this.getGrilVideoData(categoryId, girlId, index); let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return 0; if (!oneData) return 0;
return oneData.emotion; return oneData.getGrilVideoEmotion(id);
} }
/** 获取技师视频的价格 */ /** 获取技师视频的价格 */
public getGrilVideoPrice(categoryId: string, girlId: number, index: number): number { public getGrilVideoPrice(categoryId: string, girlId: number, id: number): number {
let oneData = this.getGrilVideoData(categoryId, girlId, index); let oneData = this.getGrilDetail(categoryId, girlId);
if (!oneData) return 0; if (!oneData) return 0;
return oneData.videoPrice; return oneData.getGrilVideoPrice(id);
} }
/** 获取技师视频是否解锁 */ /** --------------------------------------------------------- 技师的解锁数据 --------------------------------------------------------- */
public getGrilVideoIsRelease(categoryId: string, girlId: number, index: number): boolean {
let oneData = this.getGrilVideoData(categoryId, girlId, index); // 解析技师解锁数据,一个
private parseOneGirlUnlock(data: proto.cs.IGirlData): GirlUnlockData | null {
if (!data) return null;
let oneData = new GirlUnlockData();
oneData.init?.(DataId.GirlUnlock);
oneData.setId(data.id);
oneData.setIsRelease(data.isRelease);
if (data.images) {
let ids = [];
for (let one of data.images) {
ids.push(one.resId);
}
oneData.setUnlockedImageIds(ids);
}
if (data.videos) {
let ids = [];
for (let one of data.videos) {
ids.push(one.resId);
}
oneData.setUnlockedVideoIds(ids);
}
return oneData;
}
/** 保存技师的解锁数据 */
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);
}
}
/** 取某分类 + girlId 的解锁数据 */
private getGrilUnlock(categoryId: string, girlId: number): GirlUnlockData | null {
const b = this.ensureCategories().get(categoryId);
if (!b) return null;
return b.unlocks.get(girlId) ?? null;
}
/** 获取 付费技师是否已经解锁 */
public getIsRelease(categoryId: string, girlId: number): boolean {
let oneData = this.getGrilUnlock(categoryId, girlId);
if (!oneData) return false; if (!oneData) return false;
return oneData.isRelease; return oneData.getIsRelease();
}
/** 判断图片是否解锁 */
public isImageUnlock(categoryId: string, girlId: number, id: number): boolean {
let oneData = this.getGrilUnlock(categoryId, girlId);
if (!oneData) return false;
return oneData.isImageUnlock(id);
}
/** 解锁图片 */
public unlockImage(categoryId: string, girlId: number, id: number): void {
let oneData = this.getGrilUnlock(categoryId, girlId);
if (!oneData) return;
return oneData.unlockImage(id);
}
/** 获取所有解锁图片的 id */
public getUnlockedImageIds(categoryId: string, girlId: number): number[] {
let oneData = this.getGrilUnlock(categoryId, girlId);
if (!oneData) return [];
return oneData.getUnlockedImageIds();
}
/** 判断视频是否解锁 */
public isVideoUnlock(categoryId: string, girlId: number, id: number): boolean {
let oneData = this.getGrilUnlock(categoryId, girlId);
if (!oneData) return false;
return oneData.isVideoUnlock(id);
}
/** 解锁视频 */
public unlockVideo(categoryId: string, girlId: number, id: number): void {
let oneData = this.getGrilUnlock(categoryId, girlId);
if (!oneData) return;
return oneData.unlockVideo(id);
}
/** 获取所有解锁视频的 id */
public getUnlockedVideoIds(categoryId: string, girlId: number): number[] {
let oneData = this.getGrilUnlock(categoryId, girlId);
if (!oneData) return [];
return oneData.getUnlockedVideoIds();
}
/** --------------------------------------------------------- 技师的聊天数据 --------------------------------------------------------- */
// 解析技师聊天数据,一个
private parseOneGirlChat(data: proto.cs.IGirlData): GirlChatData | null {
if (!data) return null;
let oneData = new GirlChatData();
oneData.init?.(DataId.GirlChat);
oneData.setId(data.id);
oneData.setChatTotalCount(data.chatTotalCount);
oneData.setChatRemainCount(data.chatRemainCount);
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);
}
}
/** 取某分类 + 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;
}
/** 获取总聊天次数 */
public getChatTotalCount(categoryId: string, girlId: number): number {
let oneData = this.getGrilChat(categoryId, girlId);
if (!oneData) return 0;
return oneData.getChatTotalCount();
}
/** 保存总聊天次数 */
public setChatTotalCount(categoryId: string, girlId: number, value: number): void {
let oneData = this.getGrilChat(categoryId, girlId);
if (!oneData) return;
return oneData.setChatTotalCount(value);
}
/** 获取剩余聊天次数 */
public getChatRemainCount(categoryId: string, girlId: number): number {
let oneData = this.getGrilChat(categoryId, girlId);
if (!oneData) return 0;
return oneData.getChatRemainCount();
}
/** 保存剩余聊天次数 */
public setChatRemainCount(categoryId: string, girlId: number, value: number): void {
let oneData = this.getGrilChat(categoryId, girlId);
if (!oneData) return;
return oneData.setChatRemainCount(value);
}
/** 更新剩余聊天次数 */
public useChat(categoryId: string, girlId: number, times: number = 1): void {
let oneData = this.getGrilChat(categoryId, girlId);
if (!oneData) return;
return oneData.useChat(times);
}
/** --------------------------------------------------------- 技师的好感度数据 --------------------------------------------------------- */
// 解析技师好感度数据,一个
private parseOneGirlFavorability(data: proto.cs.IGirlData): GirlFavorabilityData | null {
if (!data) return null;
let oneData = new GirlFavorabilityData();
oneData.init?.(DataId.GirlFavorability);
oneData.setId(data.id);
oneData.setStar(data.star);
return oneData;
}
/** 保存技师的好感度数据 */
private setGirlFavorability(categoryId: string, data: proto.cs.IGirlData[]): void {
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);
}
}
/** 取某分类 + girlId 的好感度数据 */
private getGrilFavorability(categoryId: string, girlId: number): GirlFavorabilityData | null {
const b = this.ensureCategories().get(categoryId);
if (!b) return null;
return b.favorability.get(girlId) ?? null;
}
/** 获取星级 */
public getStar(categoryId: string, girlId: number): number {
let oneData = this.getGrilFavorability(categoryId, girlId);
if (!oneData) return 0;
return oneData.getStar();
} }
/** --------------------------------------------------------- 每日推荐 --------------------------------------------------------- */ /** --------------------------------------------------------- 每日推荐 --------------------------------------------------------- */
/** 保存每日推荐:放入特殊分类 DAILY_BUCKET,并维护 id 索引 */ /** 保存每日推荐:放入特殊分类 DAILY_BUCKET,并维护 id 索引 */
public setDailyRecommend(res: proto.cs.ICSDailyRecommendRes): void { public setDailyRecommend(data: proto.cs.ICSDailyRecommendRes): void {
this.mergeBriefs(DAILY_BUCKET, res.girls); if (!data) return;
this._dailyRecommendIds = res.girls.map(g => g.id ?? 0); this.mergeOneBrief(DAILY_BUCKET, data.girl);
console.log("保存每日推荐: ", this._dailyRecommendIds); const bucket = this.ensureBucket(DAILY_BUCKET);
console.log("保存每日推荐: ", bucket);
} }
/** 获取每日推荐的简要信息 */ /** 获取推荐id */
private getRecommendGrilBrief(categoryId: string, index: number): proto.cs.IGirlBrief | null { public getRecommendGirlId(): number {
const b = this.ensureCategories().get(categoryId); const bucket = this.ensureBucket(DAILY_BUCKET);
if (!b) return null; const girlIds = bucket.girlIds;
if (index < 0 || index >= b.girlIds.length) return null; const length = girlIds.length;
return b.briefs.get(b.girlIds[index]) ?? null; if (length <= 0) return 0;
return girlIds[length-1];
} }
/** 获取 id */ /** 获取每日推荐的简要数据 */
public getRecommendGrilId(index: number): number { private getRecommendGrilBrief(): GirlBriefData | null {
let oneData = this.getRecommendGrilBrief(DAILY_BUCKET, index); const recId = this.getRecommendGirlId();
if (!oneData) return 0; if (recId <= 0) return null;
return oneData.id; const data = this.getGrilBrief(DAILY_BUCKET, recId);
return data;
} }
/** 获取名字 */ /** 获取名字 */
public getRecommendGrilName(index: number): string { public getRecommendGrilName(): string {
let oneData = this.getRecommendGrilBrief(DAILY_BUCKET, index); let oneData = this.getRecommendGrilBrief();
if (!oneData) return ""; if (!oneData) return "";
return oneData.name; return oneData.getGrilName();
} }
/** 获取头像 */ /** 获取头像路径 */
public getRecommendGrilAvatar(index: number): string { public getRecommendGrilAvatar(): string {
let oneData = this.getRecommendGrilBrief(DAILY_BUCKET, index); let oneData = this.getRecommendGrilBrief();
if (!oneData) return ""; if (!oneData) return "";
return oneData.avatar; return oneData.getGrilAvatar();
} }
} }
@@ -0,0 +1,227 @@
/**
* 技师的详细数据
*/
import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class GirlDetailData extends BaseData {
// id
private id: number;
// 自我介绍
private detailDesc: string;
// 图片数据
private photoData: proto.cs.IPurchaseCommercialImage[];
// 视频数据
private videoData: proto.cs.IPurchaseCommercialVideo[];
constructor() {
super();
this.id = 0;
this.detailDesc = "";
this.photoData = [];
this.videoData = [];
}
public reset(): void {
this.id = 0;
this.detailDesc = "";
this.photoData = [];
this.videoData = [];
}
public clear(): void {
this.id = 0;
this.detailDesc = "";
this.photoData = [];
this.videoData = [];
}
public destroy(): void {
super.destroy();
this.id = null;
this.detailDesc = null;
this.photoData = null;
this.videoData = null;
}
/** 保存数据 */
public setData(data: proto.cs.IGirlsDetail): void {
if (!data) return;
this.id = data.id;
this.detailDesc = data.detailDesc;
this.photoData = this.parseAllGirlPhoto(data.commercialImages);
this.videoData = this.parseAllGirlVideo(data.commercialVideos);
}
/** 获取 id */
public getId(): number {
return this.id;
}
/** 获取自我介绍 */
public getGirlDesc(): string {
return this.detailDesc;
}
/** --------------------------------------------------------- 图片数据 --------------------------------------------------------- */
// 解析技师图片数据,一个
private parseOneGirlPhoto(data: proto.cs.IPurchaseCommercialImage): proto.cs.IPurchaseCommercialImage | null {
if (!data) return null;
const oneData: proto.cs.IPurchaseCommercialImage = {
id: data.id, // 图片 id
imageType: data.imageType, // 图片类型
unlockCounts: data.unlockCounts, // 聊天触发次数
imagePrice: data.imagePrice, // 图片价格
path: data.path, // 图片资源路径
};
return oneData;
}
// 解析技师图片数据,多个
private parseAllGirlPhoto(data: proto.cs.IPurchaseCommercialImage[]): proto.cs.IPurchaseCommercialImage[] {
if (!data) return [];
let allData = [];
for (const value of data) {
const oneData: proto.cs.IPurchaseCommercialImage = this.parseOneGirlPhoto(value);
if (oneData) {
allData.push(oneData);
}
}
return allData;
}
/** 获取所有技师图片数据的数量 */
public getAllGrilPhotoDataCount(): number {
if (!this.photoData) return 0;
return this.photoData.length;
}
/** 获取所有技师图片数据的id */
public getAllGrilPhotoDataId(): number[] {
if (!this.photoData) return [];
// 获取所有 id
let allId = [];
for (let one of this.photoData) {
allId.push(one.id);
}
return allId;
}
/** 获取技师图片数据,通过 id */
private getGrilPhotoData(id: number): proto.cs.IPurchaseCommercialImage | null {
if (!this.photoData) return null;
// 遍历数组找到匹配的资源
for (let oneData of this.photoData) {
if (oneData.id === id) {
return oneData;
}
}
return null;
}
/** 获取技师图片的类型 */
public getGrilPhotoType(id: number): number {
let oneData = this.getGrilPhotoData(id);
if (!oneData) return 0;
return oneData.imageType;
}
/** 获取技师图片的聊天触发次数 */
public getGrilPhotoUnlockCounts(id: number): number {
let oneData = this.getGrilPhotoData(id);
if (!oneData) return 0;
return oneData.unlockCounts;
}
/** 获取技师图片的价格 */
public getGrilPhotoPrice(id: number): number {
let oneData = this.getGrilPhotoData(id);
if (!oneData) return 0;
return oneData.imagePrice;
}
/** 获取技师图片的资源路径 */
public getGrilPhotoPath(id: number): string {
let oneData = this.getGrilPhotoData(id);
if (!oneData) return "";
return oneData.path;
}
/** --------------------------------------------------------- 视频数据 --------------------------------------------------------- */
// 解析技师视频数据,一个
private parseOneGirlVideo(data: proto.cs.IPurchaseCommercialVideo): proto.cs.IPurchaseCommercialVideo | null {
if (!data) return null;
const oneData: proto.cs.IPurchaseCommercialVideo = {
id: data.id, // 视频 id
path: data.path, // 视频资源路径
emotion: data.emotion, // 关联情绪
videoPrice: data.videoPrice, // 价格
};
return oneData;
}
// 解析技师视频数据,多个
private parseAllGirlVideo(data: proto.cs.IPurchaseCommercialVideo[]): proto.cs.IPurchaseCommercialVideo[] {
if (!data) return [];
let allData = [];
for (const value of data) {
const oneData: proto.cs.IPurchaseCommercialVideo = this.parseOneGirlVideo(value);
if (oneData) {
allData.push(oneData);
}
}
return allData;
}
/** 获取所有技师视频数据的数量 */
public getAllGrilVideoDataCount(): number {
if (!this.videoData) return 0;
return this.videoData.length;
}
/** 获取所有技师视频数据的id */
public getAllGrilVideoDataId(): number[] {
if (!this.videoData) return [];
// 获取所有 id
let allId = [];
for (let one of this.videoData) {
allId.push(one.id);
}
return allId;
}
/** 获取技师视频数据,通过 id */
private getGrilVideoData(id: number): proto.cs.IPurchaseCommercialVideo | null {
if (!this.videoData) return null;
// 遍历数组找到匹配的资源
for (let oneData of this.videoData) {
if (oneData.id === id) {
return oneData;
}
}
return null;
}
/** 获取技师视频的资源路径 */
public getGrilVideoPath(id: number): string {
let oneData = this.getGrilVideoData(id);
if (!oneData) return "";
return oneData.path;
}
/** 获取技师视频的关联情绪 */
public getGrilVideoEmotion(id: number): number {
let oneData = this.getGrilVideoData(id);
if (!oneData) return 0;
return oneData.emotion;
}
/** 获取技师视频的价格 */
public getGrilVideoPrice(id: number): number {
let oneData = this.getGrilVideoData(id);
if (!oneData) return 0;
return oneData.videoPrice;
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "f10268c6-f575-4249-9175-499a07aeb2d8",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,54 @@
/**
* 技师的好感度数据
*/
import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class GirlFavorabilityData extends BaseData {
// id
private id: number;
// 星级
private star: number;
constructor() {
super();
this.id = 0;
this.star = 0;
}
public reset(): void {
this.id = 0;
this.star = 0;
}
public clear(): void {
this.id = 0;
this.star = 0;
}
public destroy(): void {
super.destroy();
this.id = null;
this.star = null;
}
/** 获取 id */
public getId(): number {
return this.id;
}
/** 保存 id */
public setId(value: number): void {
this.id = value;
}
/** 获取星级 */
public getStar(): number {
return this.star;
}
/** 保存星级 */
public setStar(value: number): void {
this.star = value;
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "fc838010-523c-4f4a-bff4-8c83d0ce5618",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,130 @@
/**
* 技师的解锁数据
*/
import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class GirlUnlockData extends BaseData {
// id
private id: number;
// 付费技师是否已经解锁
private isRelease: boolean;
// 解锁图片 id
private unlockedImageIds: number[];
// 解锁视频 id
private unlockedVideoIds: number[];
constructor() {
super();
this.id = 0;
this.isRelease = false;
this.unlockedImageIds = [];
this.unlockedVideoIds = [];
}
public reset(): void {
this.id = 0;
this.isRelease = false;
this.unlockedImageIds = [];
this.unlockedVideoIds = [];
}
public clear(): void {
this.id = 0;
this.isRelease = false;
this.unlockedImageIds = [];
this.unlockedVideoIds = [];
}
public destroy(): void {
super.destroy();
this.id = null;
this.isRelease = null;
this.unlockedImageIds = null;
this.unlockedVideoIds = null;
}
/** 获取 id */
public getId(): number {
return this.id;
}
/** 保存 id */
public setId(value: number): void {
this.id = value;
}
/** 获取 付费技师是否已经解锁 */
public getIsRelease(): boolean {
return this.isRelease;
}
/** 保存 付费技师是否已经解锁 */
public setIsRelease(value: boolean): void {
this.isRelease = value;
}
/** 判断图片是否解锁,根据 id */
public isImageUnlock(id: number): boolean {
for (let i = 0; i < this.unlockedImageIds.length; i++) {
if (this.unlockedImageIds[i] === id) {
return true;
}
}
return false;
}
/** 解锁图片 */
public unlockImage(id: number) {
// 去重
let exists = this.isImageUnlock(id);
if (!exists) {
this.unlockedImageIds.push(id);
}
console.log("技师 ", this.id, " 当前解锁图片的所有id",this.unlockedImageIds);
}
/** 获取所有解锁图片的 id */
public getUnlockedImageIds(): number[] {
return this.unlockedImageIds;
}
/** 保存解锁图片 id */
public setUnlockedImageIds(value: number[]): void {
for(let one of value) {
this.unlockImage(one);
}
}
/** 判断视频是否解锁,根据 id */
public isVideoUnlock(id: number): boolean {
for (let i = 0; i < this.unlockedVideoIds.length; i++) {
if (this.unlockedVideoIds[i] === id) {
return true;
}
}
return false;
}
/** 解锁视频 */
public unlockVideo(id: number) {
// 去重
let exists = this.isVideoUnlock(id);;
if (!exists) {
this.unlockedVideoIds.push(id);
}
console.log("技师 ", this.id, " 当前解锁视频的所有id",this.unlockedVideoIds);
}
/** 获取所有解锁视频的 id */
public getUnlockedVideoIds(): number[] {
return this.unlockedVideoIds;
}
/** 保存解锁视频 id */
public setUnlockedVideoIds(value: number[]): void {
for(let one of value) {
this.unlockVideo(one);
}
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "9ae023d4-bad5-4afc-9418-34c70cc4cb08",
"files": [],
"subMetas": {},
"userData": {}
}
+28
View File
@@ -0,0 +1,28 @@
/**
* 全局数据
*/
import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class GlobalData extends BaseData {
public reset(): void {
}
public clear(): void {
}
public destroy(): void {
super.destroy();
}
/** 设置全局数据 */
public set globals(res: proto.cs.ICSGetResConfigRes) {
console.log("设置全局数据:");
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "cc12432f-6e2f-4190-94c6-084037af001f",
"files": [],
"subMetas": {},
"userData": {}
}
-1
View File
@@ -88,7 +88,6 @@ export class LoginData extends BaseData {
/** 设置登录refresh token */ /** 设置登录refresh token */
public set refreshToken(value: string) { public set refreshToken(value: string) {
this._refreshToken = value; this._refreshToken = value;
console.log("设置登录refresh token", this._refreshToken);
} }
/** 获取登录refresh token */ /** 获取登录refresh token */
-30
View File
@@ -6,28 +6,18 @@ import { BaseData } from "./BaseData";
export class PlayerData extends BaseData { export class PlayerData extends BaseData {
// 用户名 // 用户名
private _name: string = ''; private _name: string = '';
// 钻石数
private _diamond: number = 0;
// vip失效时间戳
private _vipExpire: number = 0;
public reset(): void { public reset(): void {
this._name = ''; this._name = '';
this._diamond = 0;
this._vipExpire = 0;
} }
public clear(): void { public clear(): void {
this._name = ''; this._name = '';
this._diamond = 0;
this._vipExpire = 0;
} }
public destroy(): void { public destroy(): void {
super.destroy(); super.destroy();
this._name = null; this._name = null;
this._diamond = null;
this._vipExpire = null;
} }
/** 设置用户名 */ /** 设置用户名 */
@@ -39,24 +29,4 @@ export class PlayerData extends BaseData {
public get name(): string { public get name(): string {
return this._name; return this._name;
} }
/** 设置钻石数 */
public set diamond(value: number) {
this._diamond = value;
}
/** 获取钻石数 */
public get diamond(): number {
return this._diamond;
}
/** 设置vip失效时间戳 */
public set vipExpire(value: number) {
this._vipExpire = value;
}
/** 获取vip失效时间戳 */
public get vipExpire(): number {
return this._vipExpire;
}
} }
+52 -25
View File
@@ -1,12 +1,12 @@
/** /**
* 商数据 * 商数据
*/ */
import { BaseData } from "./BaseData"; import { BaseData } from "./BaseData";
import proto from 'db://assets/Scripts/proto/proto.pb.js'; import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class ShopData extends BaseData { export class ShopData extends BaseData {
// 商品数据 // 商品数据
private _goods = new Map<number, proto.cs.IGood>(); private _goods = new Map<number, proto.cs.IPurchaseConfig>();
// 商品 id // 商品 id
private _goodIds: number[] = []; private _goodIds: number[] = [];
@@ -27,17 +27,16 @@ export class ShopData extends BaseData {
} }
/** 设置商品数据 */ /** 设置商品数据 */
public set goods(res: proto.cs.ICSGetShopRes) { public set goods(res: proto.cs.ICSGetPurchaseRes) {
const list = res.Goods ?? []; const list = res.items ?? [];
this._goods.clear(); this._goods.clear();
this._goodIds = []; this._goodIds = [];
for (const g of list) { for (const g of list) {
const vo: proto.cs.IGood = { const vo: proto.cs.IPurchaseConfig = {
id: g.id, // 商品 id id: g.id, // 商品 id
name: g.name || "", // 商品名字 name: g.name, // 商品名字
desc: g.desc || "", // 商品描述 count: g.count, // 商品数量
price: g.price || "0.00", // 商品价格 price: g.price, // 商品价格
count: g.count || 0, // 商品数量
}; };
this._goods.set(vo.id, vo); this._goods.set(vo.id, vo);
this._goodIds.push(vo.id); this._goodIds.push(vo.id);
@@ -46,7 +45,7 @@ export class ShopData extends BaseData {
} }
/** 获取所有商品数据 */ /** 获取所有商品数据 */
public get goods(): Map<number, proto.cs.IGood> { return this._goods; } public get goods(): Map<number, proto.cs.IPurchaseConfig> { return this._goods; }
/** 获取所有商品数据的数量 */ /** 获取所有商品数据的数量 */
public get goodsCount(): number { return this._goods ? this._goods.size : 0; } public get goodsCount(): number { return this._goods ? this._goods.size : 0; }
@@ -54,18 +53,53 @@ export class ShopData extends BaseData {
/** 获取所有商品 id */ /** 获取所有商品 id */
public get goodIds(): number[] { return this._goodIds; } public get goodIds(): number[] { return this._goodIds; }
/** 获取vip商品数据 */ /** 获取 充值商品的id数组,首位数字为 1 */
public get vipGoods(): proto.cs.IGood[] { private getRechargeIds(): number[] {
return this._goodIds.map(id => this._goods.get(id)!).filter(g => g.id > 2000); let allId = this._goodIds;
if (!allId) return [];
// 获取所有 id
let resultId = [];
for (let one of allId) {
const firstDigit = one.toString()[0]; // 取首位字符
if (firstDigit === "1") {
resultId.push(one);
}
}
return resultId;
} }
/** 获取普通商品数据 */ /** 获取 会员商品的id数组,首位数字为 2 */
public get normalGoods(): proto.cs.IGood[] { private getMemberIds(): number[] {
return this._goodIds.map(id => this._goods.get(id)!).filter(g => g.id <= 2000); let allId = this._goodIds;
if (!allId) return [];
// 获取所有 id
let resultId = [];
for (let one of allId) {
const firstDigit = one.toString()[0]; // 取首位字符
if (firstDigit === "2") {
resultId.push(one);
}
}
return resultId;
}
/** 获取 聊天商品的id数组,首位数字为 3 */
private getChatIds(): number[] {
let allId = this._goodIds;
if (!allId) return [];
// 获取所有 id
let resultId = [];
for (let one of allId) {
const firstDigit = one.toString()[0]; // 取首位字符
if (firstDigit === "3") {
resultId.push(one);
}
}
return resultId;
} }
/** 根据商品 id 获取商品数据 */ /** 根据商品 id 获取商品数据 */
private getGoodDataById(id: number): proto.cs.IGood | null { private getGoodDataById(id: number): proto.cs.IPurchaseConfig | null {
if (!this._goods) return null; if (!this._goods) return null;
return this._goods.get(id) ?? null; return this._goods.get(id) ?? null;
} }
@@ -77,15 +111,8 @@ export class ShopData extends BaseData {
return oneData.name; return oneData.name;
} }
/** 根据商品 id 获取商品描述 */
public getDescById(id: number): string | null {
let oneData = this.getGoodDataById(id);
if (!oneData) return null;
return oneData.desc;
}
/** 根据商品 id 获取商品价格 */ /** 根据商品 id 获取商品价格 */
public getPriceById(id: number): string | null { public getPriceById(id: number): number | null {
let oneData = this.getGoodDataById(id); let oneData = this.getGoodDataById(id);
if (!oneData) return null; if (!oneData) return null;
return oneData.price; return oneData.price;
+9 -9
View File
@@ -6,7 +6,7 @@ import proto from 'db://assets/Scripts/proto/proto.pb.js';
export class ThemeData extends BaseData { export class ThemeData extends BaseData {
// 主题数据 // 主题数据
private _themes = new Map<number, proto.cs.IHallTheme>(); private _themes = new Map<number, proto.cs.IThemes>();
// 主题 id // 主题 id
private _themeIds: number[] = []; private _themeIds: number[] = [];
@@ -32,13 +32,13 @@ export class ThemeData extends BaseData {
this._themes.clear(); this._themes.clear();
this._themeIds = []; this._themeIds = [];
for (const t of list) { for (const t of list) {
const vo: proto.cs.IHallTheme = { const vo: proto.cs.IThemes = {
id: t.id || 0, // 主题 id id: t.id, // 主题 id
key: t.key || "", // 多语言键 key: t.key, // 多语言键
name: t.name || "", // 主题名称 name: t.name, // 主题名称
category: t.category || 0, // 主题枚举 category: t.category, // 主题枚举
isRelease: t.isRelease, // 是否解锁 isRelease: t.isRelease, // 是否解锁
path: t.path || "", // 图片路径 path: t.path, // 图片路径
}; };
this._themes.set(vo.id, vo); this._themes.set(vo.id, vo);
this._themeIds.push(vo.id); this._themeIds.push(vo.id);
@@ -47,7 +47,7 @@ export class ThemeData extends BaseData {
} }
/** 获取所有主题数据 */ /** 获取所有主题数据 */
public get themes(): Map<number, proto.cs.IHallTheme> { return this._themes; } public get themes(): Map<number, proto.cs.IThemes> { return this._themes; }
/** 获取所有主题数据的数量 */ /** 获取所有主题数据的数量 */
public get themesCount(): number { return this._themes ? this._themes.size : 0; } public get themesCount(): number { return this._themes ? this._themes.size : 0; }
@@ -56,7 +56,7 @@ export class ThemeData extends BaseData {
public get themeIds(): number[] { return this._themeIds; } public get themeIds(): number[] { return this._themeIds; }
/** 根据主题 id 获取主题数据 */ /** 根据主题 id 获取主题数据 */
private getThemeDataById(id: number): proto.cs.IHallTheme | null { private getThemeDataById(id: number): proto.cs.IThemes | null {
if (!this._themes) return null; if (!this._themes) return null;
return this._themes.get(id) ?? null; return this._themes.get(id) ?? null;
} }
+12 -12
View File
@@ -4,35 +4,35 @@
import { BaseData } from "./BaseData"; import { BaseData } from "./BaseData";
export class WalletData extends BaseData { export class WalletData extends BaseData {
// 钻石数 // 余额
private _diamond = 0; private _balance: number = 0;
// vip失效时间戳 // vip失效时间戳
private _vipExpire = 0; private _vipExpire: number = 0;
public reset(): void { public reset(): void {
this._diamond = 0; this._balance = 0;
this._vipExpire = 0; this._vipExpire = 0;
} }
public clear(): void { public clear(): void {
this._diamond = 0; this._balance = 0;
this._vipExpire = 0; this._vipExpire = 0;
} }
public destroy(): void { public destroy(): void {
super.destroy(); super.destroy();
this._diamond = null; this._balance = null;
this._vipExpire = null; this._vipExpire = null;
} }
/** 设置钻石数 */ /** 设置余额 */
public set diamond(value: number) { public set balance(value: number) {
this._diamond = value; this._balance = value;
} }
/** 获取钻石数 */ /** 获取余额 */
public get diamond(): number { public get balance(): number {
return this._diamond; return this._balance;
} }
/** 设置vip失效时间戳 */ /** 设置vip失效时间戳 */
@@ -108,6 +108,24 @@ export class MachineInfoService {
if (s.length > 64) s = s.slice(0, 64); if (s.length > 64) s = s.slice(0, 64);
return s || "Unknown"; return s || "Unknown";
} }
/** 获取机器系统标识 1: android 2:ios; 3: windows */
public getMachineOs(): number {
if (EDITOR) {
return 3; // 在 Cocos Creator 编辑器里运行
}
if (sys.platform === sys.Platform.ANDROID) {
return 1;
}
if (sys.platform === sys.Platform.IOS) {
return 2;
}
if (sys.platform === sys.Platform.WIN32) {
return 3;
}
return 3;
}
} }
export default MachineInfoService; export default MachineInfoService;
@@ -156,8 +156,6 @@ export class ConfigManager {
// 若你的 BaseConfig.init 接受 configId,可传入 // 若你的 BaseConfig.init 接受 configId,可传入
instance.init?.(configId); instance.init?.(configId);
this._dataMap.set(configId, instance); this._dataMap.set(configId, instance);
console.log(`[ConfigManager] 实例化并缓存数据: ${configId}`);
return instance; return instance;
} }
@@ -169,7 +167,6 @@ export class ConfigManager {
if (data) { if (data) {
data.destroy?.(); data.destroy?.();
this._dataMap.delete(configId); this._dataMap.delete(configId);
console.log(`[ConfigManager] 移除数据: ${configId}`);
return true; return true;
} }
return false; return false;
@@ -179,7 +176,6 @@ export class ConfigManager {
* 重置所有数据 * 重置所有数据
*/ */
public resetAllData(): void { public resetAllData(): void {
console.log("[ConfigManager] 重置所有数据");
this._dataMap.forEach((data) => data.reset?.()); this._dataMap.forEach((data) => data.reset?.());
} }
@@ -187,7 +183,6 @@ export class ConfigManager {
* 清空所有数据 * 清空所有数据
*/ */
public clearAllData(): void { public clearAllData(): void {
console.log("[ConfigManager] 清空所有数据");
this._dataMap.forEach((data) => data.clear?.()); this._dataMap.forEach((data) => data.clear?.());
} }
@@ -195,7 +190,6 @@ export class ConfigManager {
* 销毁所有数据 * 销毁所有数据
*/ */
public destroyAllData(): void { public destroyAllData(): void {
console.log("[ConfigManager] 销毁所有数据");
this._dataMap.forEach((data) => data.destroy?.()); this._dataMap.forEach((data) => data.destroy?.());
this._dataMap.clear(); this._dataMap.clear();
} }
@@ -64,7 +64,7 @@ export class NavigationManager {
console.warn("Invalid role ID for chat navigation:", roleId); console.warn("Invalid role ID for chat navigation:", roleId);
return; return;
} }
GameRootUI.I.hideDefaultView();
console.log(`Navigating to chat with role ID: ${roleId}`); console.log(`Navigating to chat with role ID: ${roleId}`);
ViewManager.I.openBundlesView("ChatPanel", roleId); ViewManager.I.openBundlesView("ChatPanel", roleId);
} }
@@ -25,9 +25,8 @@ export class ApiClient {
let jsonData: any; let jsonData: any;
if (ep.needsAuth && this.token) { if (ep.needsAuth && this.token) {
headers["Authorization"] = `Bearer ${this.token}`; headers["Authorization"] = `${this.token}`;
} }
// 编码 // 编码
if (ep.codec === "json") { if (ep.codec === "json") {
jsonData = (ep.method === "GET") ? req : JsonCodec.encode(req); jsonData = (ep.method === "GET") ? req : JsonCodec.encode(req);
@@ -26,8 +26,18 @@ export class ChatService implements IChatService {
this.impl = useMock ? new MockChatService() : new HttpChatService(); this.impl = useMock ? new MockChatService() : new HttpChatService();
} }
// 对外 API 保持不变 // 上报聊天数据
public async reqBuyChat(req: proto.cs.ICSBuyChatReq): Promise<ApiResponse<proto.cs.ICSBuyChatRes>> { public async reqChatMsg(req: proto.cs.ICSChatMsgReq): Promise<ApiResponse<proto.cs.ICSChatMsgRes>> {
return this.impl.reqBuyChat(req); return this.impl.reqChatMsg(req);
}
// 获取聊天数据
public async reqGetChatMsg(req: proto.cs.ICSGetChatMsgReq): Promise<ApiResponse<proto.cs.ICSGetChatMsgRes>> {
return this.impl.reqGetChatMsg(req);
}
// 获取技师聊天次数
public async reqChatCountData(req: proto.cs.ICSGetChatRemainCountReq): Promise<ApiResponse<proto.cs.ICSGetChatRemainCountRes>> {
return this.impl.reqChatCountData(req);
} }
} }
@@ -0,0 +1,32 @@
import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js";
import type { ICommonService } from "./ICommonService";
import { HttpCommonService } from "./HttpCommonService";
import { MockCommonService } from "./MockCommonService";
// 模拟开关
const USE_MOCK = true;
export class CommonService implements ICommonService {
private static _I: CommonService | null = null;
public static get I(): CommonService {
if (!CommonService._I) CommonService._I = new CommonService();
return CommonService._I;
}
private impl: ICommonService;
private constructor() {
this.impl = USE_MOCK ? new MockCommonService() : new HttpCommonService();
}
/** 运行期切换 */
public switch(useMock: boolean) {
this.impl = useMock ? new MockCommonService() : new HttpCommonService();
}
// 获取配置
public async reqResConfig(req: proto.cs.ICSGetResConfigReq): Promise<ApiResponse<proto.cs.ICSGetResConfigRes>> {
return this.impl.reqResConfig(req);
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "c53fc890-4e39-4c5e-bf35-ab87a8359139",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -5,7 +5,7 @@ import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js"; import proto from "db://assets/Scripts/proto/proto.pb.js";
// 模拟开关 // 模拟开关
const USE_MOCK = true; const USE_MOCK = false;
export class GirlService implements IGirlService { export class GirlService implements IGirlService {
private static _I: GirlService | null = null; private static _I: GirlService | null = null;
@@ -38,4 +38,14 @@ export class GirlService implements IGirlService {
public async reqGetGirlDetail(req: proto.cs.ICSGetGirlDetailReq): Promise<ApiResponse<proto.cs.ICSGetGirlDetailRes>> { public async reqGetGirlDetail(req: proto.cs.ICSGetGirlDetailReq): Promise<ApiResponse<proto.cs.ICSGetGirlDetailRes>> {
return this.impl.reqGetGirlDetail(req); return this.impl.reqGetGirlDetail(req);
} }
// 解锁技师
public async reqUnlockGirl(req: proto.cs.ICSUnlockGirlReq): Promise<ApiResponse<proto.cs.ICSUnlockGirlRes>> {
return this.impl.reqUnlockGirl(req);
}
// 解锁资源
public async reqUnlockGirlRes(req: proto.cs.ICSUnlockResourceReq): Promise<ApiResponse<proto.cs.ICSUnlockResourceRes>> {
return this.impl.reqUnlockGirlRes(req);
}
} }
@@ -7,10 +7,32 @@ import type { IChatService } from "./IChatService";
export class HttpChatService implements IChatService { export class HttpChatService implements IChatService {
constructor(private api = ApiClient.I) {} constructor(private api = ApiClient.I) {}
// 购买聊天次数 // 上报聊天数据
async reqBuyChat(req: proto.cs.ICSBuyChatReq): Promise<ApiResponse<proto.cs.ICSBuyChatRes>> { async reqChatMsg(req: proto.cs.ICSChatMsgReq): Promise<ApiResponse<proto.cs.ICSChatMsgRes>> {
const ep: Endpoint<proto.cs.ICSBuyChatReq, proto.cs.ICSBuyChatRes> = { const ep: Endpoint<proto.cs.ICSChatMsgReq, proto.cs.ICSChatMsgRes> = {
path: "api/logic/buyChat", path: "api/logic/chatMsg",
method: "POST",
codec: "json",
needsAuth: true,
};
return this.api.call(ep, req);
}
// 获取聊天数据
async reqGetChatMsg(req: proto.cs.ICSGetChatMsgReq): Promise<ApiResponse<proto.cs.ICSGetChatMsgRes>> {
const ep: Endpoint<proto.cs.ICSGetChatMsgReq, proto.cs.ICSGetChatMsgRes> = {
path: "api/logic/getChatMsg",
method: "POST",
codec: "json",
needsAuth: true,
};
return this.api.call(ep, req);
}
// 获取技师聊天次数
async reqChatCountData(req: proto.cs.ICSGetChatRemainCountReq): Promise<ApiResponse<proto.cs.ICSGetChatRemainCountRes>> {
const ep: Endpoint<proto.cs.ICSGetChatRemainCountReq, proto.cs.ICSGetChatRemainCountRes> = {
path: "api/logic/getChatRemainCount",
method: "POST", method: "POST",
codec: "json", codec: "json",
needsAuth: true, needsAuth: true,
@@ -0,0 +1,20 @@
import { ApiClient } from "../client/ApiClient";
import type { Endpoint } from "../client/endpoints";
import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js";
import type { ICommonService } from "./ICommonService";
export class HttpCommonService implements ICommonService {
constructor(private api = ApiClient.I) {}
// 获取配置
async reqResConfig(req: proto.cs.ICSGetResConfigReq): Promise<ApiResponse<proto.cs.ICSGetResConfigRes>> {
const ep: Endpoint<proto.cs.ICSGetResConfigReq, proto.cs.ICSGetResConfigRes> = {
path: "api/logic/getResConfig",
method: "POST",
codec: "json",
needsAuth: true,
};
return this.api.call(ep, req);
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "612b35c8-b85f-4ac1-8cbb-e4fd58c5d3c1",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -39,4 +39,26 @@ export class HttpGirlService implements IGirlService {
}; };
return this.api.call(epData, req); return this.api.call(epData, req);
} }
// 解锁技师
async reqUnlockGirl(req: proto.cs.ICSUnlockGirlReq): Promise<ApiResponse<proto.cs.ICSUnlockGirlRes>> {
let epData: Endpoint<proto.cs.ICSUnlockGirlReq, proto.cs.ICSUnlockGirlRes> = {
path: "api/logic/unlockGirl",
method: "POST",
codec: "json",
needsAuth: true
};
return this.api.call(epData, req);
}
// 解锁资源
async reqUnlockGirlRes(req: proto.cs.ICSUnlockResourceReq): Promise<ApiResponse<proto.cs.ICSUnlockResourceRes>> {
let epData: Endpoint<proto.cs.ICSUnlockResourceReq, proto.cs.ICSUnlockResourceRes> = {
path: "api/logic/unlockResource",
method: "POST",
codec: "json",
needsAuth: true
};
return this.api.call(epData, req);
}
} }
@@ -8,9 +8,20 @@ export class HttpShopService implements IShopService {
constructor(private api = ApiClient.I) {} constructor(private api = ApiClient.I) {}
// 获取商品列表 // 获取商品列表
async reqShopList(req: proto.cs.ICSGetShopReq): Promise<ApiResponse<proto.cs.ICSGetShopRes>> { async reqShopList(req: proto.cs.ICSGetPurchaseReq): Promise<ApiResponse<proto.cs.ICSGetPurchaseRes>> {
const ep: Endpoint<proto.cs.ICSGetShopReq, proto.cs.ICSGetShopRes> = { const ep: Endpoint<proto.cs.ICSGetPurchaseReq, proto.cs.ICSGetPurchaseRes> = {
path: "api/logic/shop", path: "api/logic/getPurchase",
method: "POST",
codec: "json",
needsAuth: true,
};
return this.api.call(ep, req);
}
// 使用余额购买商品
async reqBuyGood(req: proto.cs.ICSBuyGoodReq): Promise<ApiResponse<proto.cs.ICSBuyGoodRes>> {
const ep: Endpoint<proto.cs.ICSBuyGoodReq, proto.cs.ICSBuyGoodRes> = {
path: "api/logic/buyGood",
method: "POST", method: "POST",
codec: "json", codec: "json",
needsAuth: true, needsAuth: true,
@@ -3,6 +3,10 @@ import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js"; import proto from "db://assets/Scripts/proto/proto.pb.js";
export interface IChatService { export interface IChatService {
// 购买聊天次数 // 上报聊天数据
reqBuyChat(req: proto.cs.ICSBuyChatReq): Promise<ApiResponse<proto.cs.ICSBuyChatRes>>; reqChatMsg(req: proto.cs.ICSChatMsgReq): Promise<ApiResponse<proto.cs.ICSChatMsgRes>>;
// 获取聊天数据
reqGetChatMsg(req: proto.cs.ICSGetChatMsgReq): Promise<ApiResponse<proto.cs.ICSGetChatMsgRes>>;
// 获取技师聊天次数
reqChatCountData(req: proto.cs.ICSGetChatRemainCountReq): Promise<ApiResponse<proto.cs.ICSGetChatRemainCountRes>>;
} }
@@ -0,0 +1,7 @@
import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js";
export interface ICommonService {
// 获取配置
reqResConfig(req: proto.cs.ICSGetResConfigReq): Promise<ApiResponse<proto.cs.ICSGetResConfigRes>>;
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "05ed90ec-18c9-42cd-ae17-4a7ea4b3875c",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -8,4 +8,8 @@ export interface IGirlService {
reqGetGirlList(req: proto.cs.ICSGetGirlListReq): Promise<ApiResponse<proto.cs.ICSGetGirlListRes>>; reqGetGirlList(req: proto.cs.ICSGetGirlListReq): Promise<ApiResponse<proto.cs.ICSGetGirlListRes>>;
// 获取技师详细信息 // 获取技师详细信息
reqGetGirlDetail(req: proto.cs.ICSGetGirlDetailReq): Promise<ApiResponse<proto.cs.ICSGetGirlDetailRes>>; reqGetGirlDetail(req: proto.cs.ICSGetGirlDetailReq): Promise<ApiResponse<proto.cs.ICSGetGirlDetailRes>>;
// 解锁技师
reqUnlockGirl(req: proto.cs.ICSUnlockGirlReq): Promise<ApiResponse<proto.cs.ICSUnlockGirlRes>>;
// 解锁资源
reqUnlockGirlRes(req: proto.cs.ICSUnlockResourceReq): Promise<ApiResponse<proto.cs.ICSUnlockResourceRes>>;
} }
@@ -3,5 +3,7 @@ import proto from "db://assets/Scripts/proto/proto.pb.js";
export interface IShopService { export interface IShopService {
// 获取商品列表 // 获取商品列表
reqShopList(req: proto.cs.ICSGetShopReq): Promise<ApiResponse<proto.cs.ICSGetShopRes>>; reqShopList(req: proto.cs.ICSGetPurchaseReq): Promise<ApiResponse<proto.cs.ICSGetPurchaseRes>>;
// 使用余额购买商品
reqBuyGood(req: proto.cs.ICSBuyGoodReq): Promise<ApiResponse<proto.cs.ICSBuyGoodRes>>;
} }
@@ -4,10 +4,8 @@ import type { IAuthService } from "./IAuthService";
export class MockAuthService implements IAuthService { export class MockAuthService implements IAuthService {
private delay(ms = 180) { return new Promise<void>(r => setTimeout(r, ms)); } private delay(ms = 180) { return new Promise<void>(r => setTimeout(r, ms)); }
// 项目里 ApiResponse 结构若固定(code/message 等),把 ok()/err() 调整为你的真实结构即可
private ok<T>(data: T): ApiResponse<T> { private ok<T>(data: T): ApiResponse<T> {
return ({ ok: true, data } as unknown) as ApiResponse<T>; return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>;
} }
// private err<T = unknown>(message = "mock login error"): ApiResponse<T> { // private err<T = unknown>(message = "mock login error"): ApiResponse<T> {
// return ({ ok: false, error: { message } } as unknown) as ApiResponse<T>; // return ({ ok: false, error: { message } } as unknown) as ApiResponse<T>;
@@ -15,18 +13,29 @@ export class MockAuthService implements IAuthService {
// 登录 // 登录
async login(req: proto.cs.ICSLoginReq): Promise<ApiResponse<proto.cs.ICSLoginRes>> { async login(req: proto.cs.ICSLoginReq): Promise<ApiResponse<proto.cs.ICSLoginRes>> {
// 延时
await this.delay(150); await this.delay(150);
const name = req?.platType === "guest" ? `guest_${(req?.userId ?? "uid").toString().slice(-6)}` : "tester"; const isGuest = req?.platType === "guest";
// 注意:protobufjs 会把 int64 表达为 number/Long。这里用「秒」级时间戳更常见 const userId = req?.userId ?? "uid";
const name = isGuest ? `guest_${userId.toString().slice(-6)}` : "tester";
// 过期时间(秒级时间戳,7天后过期)
const expireSeconds = Math.floor(Date.now() / 1000) + 7 * 24 * 3600; const expireSeconds = Math.floor(Date.now() / 1000) + 7 * 24 * 3600;
// 你的生成器通常会把 refresh_token 转成 refreshTokencamelCase // 模拟用户ID
const accId = (Math.floor(Math.random() * 1000000)).toString();
// 模拟 CDN 前缀
const cdn = "https://cdn.mockserver.com/";
const res: proto.cs.ICSLoginRes = { const res: proto.cs.ICSLoginRes = {
name, name,
token: `mock_token_${Date.now()}`, token: `mock_token_${Date.now()}`,
refreshToken: `mock_refresh_${Date.now()}`, refreshToken: `mock_refresh_${Date.now()}`,
expire: expireSeconds, expire: expireSeconds,
accId,
cdn,
}; };
return this.ok(res); return this.ok(res);
@@ -1,22 +1,91 @@
import type { ApiResponse } from "../client/types"; import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js"; import proto from "db://assets/Scripts/proto/proto.pb.js";
import type { IChatService } from "./IChatService"; import type { IChatService } from "./IChatService";
import { DataManager, DataId } from "../../data/DataManager";
import { GirlData } from "../../data/GirlData";
export class MockChatService implements IChatService { export class MockChatService implements IChatService {
private delay(ms = 160) { return new Promise<void>(r => setTimeout(r, ms)); } private delay(ms = 160) { return new Promise<void>(r => setTimeout(r, ms)); }
// 按你们项目的 ApiResponse 结构调整这里即可
private ok<T>(data: T): ApiResponse<T> { private ok<T>(data: T): ApiResponse<T> {
return ({ ok: true, data } as unknown) as ApiResponse<T>; return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>;
} }
// private err<T = unknown>(message = "mock buyChat error"): ApiResponse<T> {
// return ({ ok: false, error: { message } } as unknown) as ApiResponse<T>;
// }
async reqBuyChat(_req: proto.cs.ICSBuyChatReq): Promise<ApiResponse<proto.cs.ICSBuyChatRes>> { // 上报聊天数据
async reqChatMsg(req: proto.cs.ICSChatMsgReq): Promise<ApiResponse<proto.cs.ICSChatMsgRes>> {
// 延时
await this.delay(); await this.delay();
// CSBuyChatRes 在 proto 中为空消息,这里返回 {} // 请求数据
const res: proto.cs.ICSBuyChatRes = {}; const reqGirlId = req.girlId;
// 数据层的数据
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
const reqGirlCategory = girlData.getGrilCategoryById(reqGirlId);
const chatTotalCount = girlData.getChatTotalCount(reqGirlCategory.toString(), reqGirlId);
const chatRemainCount = girlData.getChatRemainCount(reqGirlCategory.toString(), reqGirlId);
// 计算
let resultTotalCount = chatTotalCount + 1;
let resultRemainCount = chatRemainCount;
if (chatRemainCount > 0) {
resultRemainCount = chatRemainCount - 1;
}
// 返回数据
const res: proto.cs.ICSChatMsgRes = {
chatRemainCount: resultRemainCount,
chatTotalCount: resultTotalCount,
};
return this.ok(res);
}
// 获取聊天数据
async reqGetChatMsg(req: proto.cs.ICSGetChatMsgReq): Promise<ApiResponse<proto.cs.ICSGetChatMsgRes>> {
// 延时
await this.delay();
// 请求数据
const reqGirlId = req.GirlId;
const page = req.page;
const limit = req.limit;
// 数据层的数据
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
const reqGirlCategory = girlData.getGrilCategoryById(reqGirlId);
const chatTotalCount = girlData.getChatTotalCount(reqGirlCategory.toString(), reqGirlId);
const chatRemainCount = girlData.getChatRemainCount(reqGirlCategory.toString(), reqGirlId);
// 模拟一个完整的聊天记录池
const allMsgs: proto.cs.IChatMsg[] = [];
for (let i = 0; i < 50; i++) {
allMsgs.push({
msg: `模拟消息 ${i + 1} 来自技师 ${reqGirlId}`,
isAi: i % 2 === 0, // 偶数条当成 AI 说的
});
}
// 分页计算
const start = (page - 1) * limit;
const end = start + limit;
const pageMsgs = allMsgs.slice(start, end);
// 返回数据
const res: proto.cs.ICSGetChatMsgRes = {
msgs: pageMsgs,
chatRemainCount,
chatTotalCount,
};
return this.ok(res);
}
// 获取技师聊天次数
async reqChatCountData(req: proto.cs.ICSGetChatRemainCountReq): Promise<ApiResponse<proto.cs.ICSGetChatRemainCountRes>> {
// 延时
await this.delay();
// 请求数据
const reqGirlId = req.id;
// 数据层的数据
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
const reqGirlCategory = girlData.getGrilCategoryById(reqGirlId);
const chatTotalCount = girlData.getChatTotalCount(reqGirlCategory.toString(), reqGirlId);
const chatRemainCount = girlData.getChatRemainCount(reqGirlCategory.toString(), reqGirlId);
// 返回数据
const res: proto.cs.ICSGetChatRemainCountRes = {
chatRemainCount,
chatTotalCount,
};
return this.ok(res); return this.ok(res);
} }
} }
@@ -0,0 +1,37 @@
import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js";
import type { ICommonService } from "./ICommonService";
import { ConfigManager, ConfigId } from "../../manager/ConfigManager";
import { GlobalConfig } from "../../config/GlobalConfig";
export class MockCommonService implements ICommonService {
private delay(ms = 160) { return new Promise<void>(r => setTimeout(r, ms)); }
private ok<T>(data: T): ApiResponse<T> {
return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>;
}
// 获取配置
async reqResConfig(req: proto.cs.ICSGetResConfigReq): Promise<ApiResponse<proto.cs.ICSGetResConfigRes>> {
// 延时
await this.delay();
let data = "";
const resName = req.resName;
if (resName === "TbGlobalConfig") {
// 全局配置
data = this.getGlobalConfig();
}
// 返回数据
const res: proto.cs.ICSGetResConfigRes = { data };
return this.ok(res);
}
// 全局配置
private getGlobalConfig(): string {
const configData = ConfigManager.I.getDataById<GlobalConfig>(ConfigId.Global);
return "";
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "8fd66f05-3289-4fa5-aed1-69f384223065",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -15,71 +15,87 @@ export class MockGirlService implements IGirlService {
return ({ code: 100, error: { message } } as unknown) as ApiResponse<T>; return ({ code: 100, error: { message } } as unknown) as ApiResponse<T>;
} }
private genBrief(id: number, name: string, age: number, tagKey: string, priceType: number, price: number, avatar: string, star: number, category: number, listAvatarPath: string): proto.cs.IGirlBrief { private genBrief(id: number, nameKey: string, age: string, category: number, tagKey: string, priceType: number, price: number, vipUnlock: number, avatarPath: string, listAvatarPath: string): proto.cs.IGirls {
return { return {
id, id,
name, nameKey,
age, age,
category,
tagKey, tagKey,
priceType, priceType,
price, price,
avatar, vipUnlock,
star, avatarPath,
category,
listAvatarPath, listAvatarPath,
}; };
} }
private genPhoto(imageType: number, imagePrice: number, path: string, isRelease: boolean, ): proto.cs.IPurchaseCommercialImage { private genPhoto(id: number, imageType: number, unlockCounts: number, imagePrice: number, path: string): proto.cs.IPurchaseCommercialImage {
return { return {
id,
imageType, imageType,
unlockCounts,
imagePrice, imagePrice,
path, path,
isRelease,
}; };
} }
private genVideo(path: string, emotion: number, videoPrice: number, isRelease: boolean): proto.cs.IPurchaseCommercialVideo { private genVideo(id: number, path: string, emotion: number, videoPrice: number): proto.cs.IPurchaseCommercialVideo {
return { return {
id,
path, path,
emotion, emotion,
videoPrice, videoPrice,
isRelease,
}; };
} }
private genDetail(brief: proto.cs.IGirlBrief, desc: string, images: proto.cs.IPurchaseCommercialImage[], videos: proto.cs.IPurchaseCommercialVideo[], isRelease: boolean, chatCount: number): proto.cs.IGirlDetail { private genDetail(id: number, detailDesc: string, commercialImages: proto.cs.IPurchaseCommercialImage[], commercialVideos: proto.cs.IPurchaseCommercialVideo[]): proto.cs.IGirlsDetail {
return { return {
brief, id,
desc, detailDesc,
commercialImages,
commercialVideos,
};
}
private genGirlData(
id: number, girl: proto.cs.IGirls, isRelease: boolean, star: number,
detail: proto.cs.IGirlsDetail, images: proto.cs.IResourceUnlock[], videos: proto.cs.IResourceUnlock[],
chatTotalCount: number, chatRemainCount: number): proto.cs.IGirlData {
return {
id,
girl,
isRelease,
star,
detail,
images, images,
videos, videos,
isRelease, chatTotalCount,
chatCount, chatRemainCount,
}; };
} }
// 每日推荐 // 每日推荐
async reqDailyRecommend(_req: proto.cs.ICSDailyRecommendReq): Promise<ApiResponse<proto.cs.ICSDailyRecommendRes>> { async reqDailyRecommend(req: proto.cs.ICSDailyRecommendReq): Promise<ApiResponse<proto.cs.ICSDailyRecommendRes>> {
// 延时 // 延时
await this.delay(180); await this.delay(180);
// 配置数据 // 配置数据
const configData = ConfigManager.I.getDataById<GirlConfig>(ConfigId.Girl); const configData = ConfigManager.I.getDataById<GirlConfig>(ConfigId.Girl);
const allId = configData.getAllId(); const allId = configData.getAllId();
const recId = allId[0]; const recId = allId[0];
let name = configData.getNameById(recId); let nameKey = configData.getNameById(recId);
let age = Number(configData.getAgeById(recId)); let age = configData.getAgeById(recId);
let tagKey = configData.getTagKeyById(recId); let tagKey = configData.getTagKeyById(recId);
let priceType = configData.getPriceTypeById(recId); let priceType = configData.getPriceTypeById(recId);
let price = 9.9; let price = configData.getPriceById(recId);
let avatar = configData.getAvatarPathById(recId); let vipUnlock = configData.getVipUnlockById(recId);
let star = 3; let avatarPath = configData.getAvatarPathById(recId);
let category = configData.getCategoryById(recId); let category = configData.getCategoryById(recId);
let listAvatarPath = configData.getListAvatarPathPathById(recId); let listAvatarPath = configData.getListAvatarPathPathById(recId);
let oneData = this.genBrief(recId, name, age, tagKey, priceType, price, avatar, star, category, listAvatarPath); let oneData = this.genBrief(recId, nameKey, age, category, tagKey, priceType, price, vipUnlock, avatarPath, listAvatarPath);
// 返回数据 // 返回数据
const girls = [oneData]; const res: proto.cs.ICSDailyRecommendRes = {girl: oneData};
return this.ok({ girls }); return this.ok(res);
} }
// 获取技师列表 // 获取技师列表
@@ -105,29 +121,35 @@ export class MockGirlService implements IGirlService {
const start = (page - 1) * limit; const start = (page - 1) * limit;
const pageIds = filteredIds.slice(start, start + limit); const pageIds = filteredIds.slice(start, start + limit);
// 映射为 IGirlBrief // 映射数据
const girls: proto.cs.IGirlBrief[] = pageIds.map((id: number) => { const girls: proto.cs.IGirlData[] = pageIds.map((id: number) => {
const name = configData.getNameById(id); // 简要数据
const age = Number(configData.getAgeById(id)); const nameKey = configData.getNameById(id);
const age = configData.getAgeById(id);
const tagKey = configData.getTagKeyById(id); const tagKey = configData.getTagKeyById(id);
const priceType = Number(configData.getPriceTypeById(id)); const priceType = configData.getPriceTypeById(id);
const avatar = configData.getAvatarPathById(id); const price = configData.getPriceById(id);
const vipUnlock = configData.getVipUnlockById(id);
// 如果有价格配置,就用配置里的,否则给个兜底值 const avatarPath = configData.getAvatarPathById(id);
const price = typeof (configData as any).getPriceById === "function"
? Number((configData as any).getPriceById(id) ?? 9.9)
: 9.9;
// 星级兜底:1~5
const star = (id % 5) + 1;
const category = configData.getCategoryById(id); const category = configData.getCategoryById(id);
const listAvatarPath = configData.getListAvatarPathPathById(id); const listAvatarPath = configData.getListAvatarPathPathById(id);
const briefData = this.genBrief(id, nameKey, age, category, tagKey, priceType, price, vipUnlock, avatarPath, listAvatarPath);
return this.genBrief(id, name, age, tagKey, priceType, price, avatar, star, category, listAvatarPath); const isRelease = true;
const star = 3;
// 详细数据
const detail = null;
const images = [];
const videos = [];
const chatTotalCount = 0;
const chatRemainCount = 0;
const girlData = this.genGirlData(id, briefData, isRelease, star, detail, images, videos, chatTotalCount, chatRemainCount);
return girlData;
}); });
// 返回数据 // 返回数据
return this.ok({ girls }); const res: proto.cs.ICSGetGirlListRes = {girls};
return this.ok(res);
} }
// 获取技师详细信息 // 获取技师详细信息
@@ -140,45 +162,94 @@ export class MockGirlService implements IGirlService {
// id // id
const girlId = req.id; const girlId = req.id;
// 简要数据 // 简要数据
let name = girlConfig.getNameById(girlId); let nameKey = girlConfig.getNameById(girlId);
let age = Number(girlConfig.getAgeById(girlId)); let age = girlConfig.getAgeById(girlId);
let tagKey = girlConfig.getTagKeyById(girlId); let tagKey = girlConfig.getTagKeyById(girlId);
let priceType = girlConfig.getPriceTypeById(girlId); let priceType = girlConfig.getPriceTypeById(girlId);
let price = 9.9; let price = girlConfig.getPriceById(girlId);
let avatar = girlConfig.getAvatarPathById(girlId); let vipUnlock = girlConfig.getVipUnlockById(girlId);
let star = 3; let avatarPath = girlConfig.getAvatarPathById(girlId);
let category = girlConfig.getCategoryById(girlId); let category = girlConfig.getCategoryById(girlId);
let listAvatarPath = girlConfig.getListAvatarPathPathById(girlId); let listAvatarPath = girlConfig.getListAvatarPathPathById(girlId);
let briefData = this.genBrief(girlId, name, age, tagKey, priceType, price, avatar, star, category, listAvatarPath); let briefData = this.genBrief(girlId, nameKey, age, category, tagKey, priceType, price, vipUnlock, avatarPath, listAvatarPath);
let desc = girlDetailConfig.getDetailDescById(girlId);
let isRelease = Math.random() < 0.4; let isRelease = Math.random() < 0.4;
let chatCount = 10; let detailDesc = girlDetailConfig.getDetailDescById(girlId);
// 图片 // 图片
let photoData = []; let photoData = [];
let photoCount = girlDetailConfig.getCommercialImagesCount(girlId); let photoIds = girlDetailConfig.getCommercialImagesIds(girlId);
for (let i = 0; i < photoCount; i++) { for (let id of photoIds) {
let imageType = girlDetailConfig.getImageTypeById(girlId, i); let imageType = girlDetailConfig.getImageTypeById(girlId, id);
let imagePath = girlDetailConfig.getImagePathById(girlId, i); let unlockCounts = girlDetailConfig.getImageUnlockCountsById(girlId, id);
let isRelease = Math.random() < 0.4; let imagePrice = girlDetailConfig.getImagePriceById(girlId, id);
let imagePrice = girlDetailConfig.getImagePriceById(girlId, i); let imagePath = girlDetailConfig.getImagePathById(girlId, id);
let oneData = this.genPhoto(imageType, imagePrice, imagePath, isRelease); let oneData = this.genPhoto(id, imageType, unlockCounts, imagePrice, imagePath);
photoData.push(oneData); photoData.push(oneData);
} }
// 视频 // 视频
let videoData = []; let videoData = [];
let videoCount = girlDetailConfig.getCommercialVideosCount(girlId); let videoIds = girlDetailConfig.getCommercialVideosIds(girlId);
for (let i = 0; i < videoCount; i++) { for (let id of videoIds) {
let videoPath = girlDetailConfig.getVideoPathById(girlId, i); let videoPath = girlDetailConfig.getVideoPathById(girlId, id);
let videoEmotion = girlDetailConfig.getVideoEmotionById(girlId, i); let videoEmotion = girlDetailConfig.getVideoEmotionById(girlId, id);
let videoPrice = girlDetailConfig.getVideoPriceById(girlId, i); let videoPrice = girlDetailConfig.getVideoPriceById(girlId, id);
let isRelease = Math.random() < 0.4; let oneData = this.genVideo(id, videoPath, videoEmotion, videoPrice);
let oneData = this.genVideo(videoPath, videoEmotion, videoPrice, isRelease);
videoData.push(oneData); videoData.push(oneData);
} }
// 详细数据 // 详细数据
let detail = this.genDetail(briefData, desc, photoData, videoData, isRelease, chatCount); let detail = this.genDetail(girlId, detailDesc, photoData, videoData);
// 图片解锁数据
let unlockImageData: proto.cs.IResourceUnlock[] = [];
for (let id of photoIds) {
// 偶数才解锁
let isUnlock = (id % 2 === 0);
if (isUnlock) {
let oneData = {
girlId: girlId,
resId: id,
};
unlockImageData.push(oneData);
}
}
// 视频解锁数据
let unlockVideoData: proto.cs.IResourceUnlock[] = [];
for (let id of videoIds) {
// 偶数才解锁
let isUnlock = (id % 2 === 0);
if (isUnlock) {
let oneData = {
girlId: girlId,
resId: id,
};
unlockVideoData.push(oneData);
}
}
const star = 3;
const chatTotalCount = 20;
const chatRemainCount = 20;
const girlData = this.genGirlData(girlId, briefData, isRelease, star, detail, unlockImageData, unlockVideoData, chatTotalCount, chatRemainCount);
// 返回数据 // 返回数据
return this.ok({ detail }); const res: proto.cs.ICSGetGirlDetailRes = {girl: girlData};
return this.ok(res);
}
// 解锁技师
async reqUnlockGirl(_req: proto.cs.ICSUnlockGirlReq): Promise<ApiResponse<proto.cs.ICSUnlockGirlRes>> {
// 延时
await this.delay(180);
// 返回数据
const res: proto.cs.ICSUnlockGirlRes = {};
return this.ok(res);
}
// 解锁资源
async reqUnlockGirlRes(_req: proto.cs.ICSUnlockResourceReq): Promise<ApiResponse<proto.cs.ICSUnlockResourceRes>> {
// 延时
await this.delay(180);
// 返回数据
const res: proto.cs.ICSUnlockResourceRes = {};
return this.ok(res);
} }
} }
@@ -3,26 +3,26 @@ import proto from "db://assets/Scripts/proto/proto.pb.js";
import type { IPlayerDataService } from "./IPlayerDataService"; import type { IPlayerDataService } from "./IPlayerDataService";
export class MockPlayerDataService implements IPlayerDataService { export class MockPlayerDataService implements IPlayerDataService {
private delay(ms = 160) { return new Promise<void>(r => setTimeout(r, ms)); } private delay(ms = 160) {
return new Promise<void>(r => setTimeout(r, ms));
}
// 按你项目的 ApiResponse 真实结构调整这里
private ok<T>(data: T): ApiResponse<T> { private ok<T>(data: T): ApiResponse<T> {
return ({ ok: true, data } as unknown) as ApiResponse<T>; return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>;
} }
// 如需模拟失败
// private err<T = unknown>(message = "mock myInfo error"): ApiResponse<T> {
// return ({ ok: false, error: { message } } as unknown) as ApiResponse<T>;
// }
// 获取个人信息 // 获取个人信息
async reqMyInfo(_req: proto.cs.ICSMyInfoReq): Promise<ApiResponse<proto.cs.ICSMyInfoRes>> { async reqMyInfo(_req: proto.cs.ICSMyInfoReq): Promise<ApiResponse<proto.cs.ICSMyInfoRes>> {
// 延时
await this.delay(); await this.delay();
// 由于我们并不知道 ICSMyInfoRes 的具体字段,这里提供一个“最安全”的空对象返回; const nowSeconds = Math.floor(Date.now() / 1000);
// 如果你有明确字段(例如 name/diamond/vipExpire 等),可在此构造并 as-cast:
// const res = { name: "Player-001", diamond: 123, vipExpire: Math.floor(Date.now()/1000) } as unknown as proto.cs.ICSMyInfoRes;
const res = ({} as unknown) as proto.cs.ICSMyInfoRes; const res: proto.cs.ICSMyInfoRes = {
balance: Math.floor(Math.random() * 100000), // 随机余额
vipExpire: nowSeconds + 30 * 24 * 3600, // vip 30天后过期
};
// 返回数据
return this.ok(res); return this.ok(res);
} }
} }
@@ -1,6 +1,8 @@
import type { ApiResponse } from "../client/types"; import type { ApiResponse } from "../client/types";
import proto from "db://assets/Scripts/proto/proto.pb.js"; import proto from "db://assets/Scripts/proto/proto.pb.js";
import type { IShopService } from "./IShopService"; import type { IShopService } from "./IShopService";
import { PurchaseConfig } from "../../config/PurchaseConfig";
import { ConfigManager, ConfigId } from "../../manager/ConfigManager";
export class MockShopService implements IShopService { export class MockShopService implements IShopService {
private delay(ms = 180) { return new Promise<void>(r => setTimeout(r, ms)); } private delay(ms = 180) { return new Promise<void>(r => setTimeout(r, ms)); }
@@ -11,29 +13,44 @@ export class MockShopService implements IShopService {
} }
private ok<T>(data: T): ApiResponse<T> { private ok<T>(data: T): ApiResponse<T> {
return ({ ok: true, data } as unknown) as ApiResponse<T>; return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>;
} }
private genGood(id: number, vip = false): proto.cs.IGood { private genGood(id: number, name: string, count: number, price: number): proto.cs.IPurchaseConfig {
return { return {
id, id,
name: vip ? `VIP-${id}` : `Diamond Pack ${id}`, name,
desc: vip ? `VIP access for ${this.randInt(24, 168)} hours` : `Diamonds x${this.randInt(60, 2000)}`, count,
price: this.priceUSD(vip ? 4.99 : 0.99, vip ? 49.99 : 29.99), price,
count: vip ? this.randInt(24, 168) : this.randInt(60, 2000), // VIP=小时,普通=数量
}; };
} }
// 获取商品列表 // 获取商品列表
async reqShopList(_req: proto.cs.ICSGetShopReq): Promise<ApiResponse<proto.cs.ICSGetShopRes>> { async reqShopList(_req: proto.cs.ICSGetPurchaseReq): Promise<ApiResponse<proto.cs.ICSGetPurchaseRes>> {
// 延时
await this.delay(); await this.delay();
// 配置数据
const configData = ConfigManager.I.getDataById<PurchaseConfig>(ConfigId.Purchase);
const allId = configData.getAllId();
let goodData: proto.cs.IPurchaseConfig[] = [];
for (let id of allId) {
let name = configData.getNameById(id);
let count = configData.getCountById(id);
let price = configData.getPriceById(id);
let oneData = this.genGood(id, name, count, price);
goodData.push(oneData);
}
// 返回数据
const res: proto.cs.ICSGetPurchaseRes = { items: goodData };
return this.ok(res);
}
// 普通商品(<=2000+ VIP 商品(>2000 // 使用余额购买商品
const normals: proto.cs.IGood[] = Array.from({ length: 5 }, (_, i) => this.genGood(1000 + i, false)); async reqBuyGood(_req: proto.cs.ICSBuyGoodReq): Promise<ApiResponse<proto.cs.ICSBuyGoodRes>> {
const vips: proto.cs.IGood[] = Array.from({ length: 3 }, (_, i) => this.genGood(2001 + i, true)); // 延时
await this.delay();
// 注意:你的 proto 定义中字段名为 "Goods"(大写 G // 返回数据
const res: proto.cs.ICSGetShopRes = { Goods: [...normals, ...vips] }; const res: proto.cs.ICSBuyGoodRes = {};
return this.ok(res); return this.ok(res);
} }
} }
@@ -10,7 +10,7 @@ export class MockThemeService implements IThemeService {
return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>; return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>;
} }
private makeTheme(id: number, key: string, name: string, category: number, isRelease: boolean, path: string): proto.cs.IHallTheme { private makeTheme(id: number, key: string, name: string, category: number, isRelease: boolean, path: string): proto.cs.IThemes {
return { return {
id, id,
key, key,
@@ -22,13 +22,13 @@ export class MockThemeService implements IThemeService {
} }
// 获取大厅分类列表 // 获取大厅分类列表
async reqHallTheme(_req: proto.cs.ICSHallThemeReq): Promise<ApiResponse<proto.cs.ICSHallThemeRes>> { async reqHallTheme(req: proto.cs.ICSHallThemeReq): Promise<ApiResponse<proto.cs.ICSHallThemeRes>> {
// 延时 // 延时
await this.delay(); await this.delay();
const configData = ConfigManager.I.getDataById<ThemeConfig>(ConfigId.Theme); const configData = ConfigManager.I.getDataById<ThemeConfig>(ConfigId.Theme);
const allId = configData.getAllId(); const allId = configData.getAllId();
let themes: proto.cs.IHallTheme[] = []; let themes: proto.cs.IThemes[] = [];
for (let oneId of allId) { for (let oneId of allId) {
let key = configData.getLanKeyById(oneId); let key = configData.getLanKeyById(oneId);
let name = configData.getNameById(oneId); let name = configData.getNameById(oneId);
@@ -5,7 +5,7 @@ import { HttpPlayerDataService } from "./HttpPlayerDataService";
import { MockPlayerDataService } from "./MockPlayerDataService"; import { MockPlayerDataService } from "./MockPlayerDataService";
// 模拟开关 // 模拟开关
const USE_MOCK = true; const USE_MOCK = false;
export class PlayerDataService implements IPlayerDataService { export class PlayerDataService implements IPlayerDataService {
private static _I: PlayerDataService | null = null; private static _I: PlayerDataService | null = null;
@@ -26,7 +26,12 @@ export class ShopService implements IShopService {
} }
// 获取商品列表 // 获取商品列表
public async reqShopList(req: proto.cs.ICSGetShopReq): Promise<ApiResponse<proto.cs.ICSGetShopRes>> { public async reqShopList(req: proto.cs.ICSGetPurchaseReq): Promise<ApiResponse<proto.cs.ICSGetPurchaseRes>> {
return this.impl.reqShopList(req); return this.impl.reqShopList(req);
} }
// 使用余额购买商品
public async reqBuyGood(req: proto.cs.ICSBuyGoodReq): Promise<ApiResponse<proto.cs.ICSBuyGoodRes>> {
return this.impl.reqBuyGood(req);
}
} }
@@ -5,7 +5,7 @@ import { HttpThemeService } from "./HttpThemeService";
import { MockThemeService } from "./MockThemeService"; import { MockThemeService } from "./MockThemeService";
// 模拟开关 // 模拟开关
const USE_MOCK = true; const USE_MOCK = false;
export class ThemeService implements IThemeService { export class ThemeService implements IThemeService {
private static _I: ThemeService | null = null; private static _I: ThemeService | null = null;
@@ -19,12 +19,14 @@ import { SimpleToggle } from "../components/SimpleToggle";
import { DataManager, DataId } from "../../data/DataManager"; import { DataManager, DataId } from "../../data/DataManager";
import { GirlData } from "../../data/GirlData"; import { GirlData } from "../../data/GirlData";
import { GirlService } from "db://assets/Scripts/chat18x/network/services/GirlService"; import { GirlService } from "db://assets/Scripts/chat18x/network/services/GirlService";
import proto from "db://assets/Scripts/proto/proto.pb.js"; import proto from 'db://assets/Scripts/proto/proto.pb.js';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@ccclass("GirlDetailPanel") @ccclass("GirlDetailPanel")
export class GirlDetailPanel extends li_BaseView { export class GirlDetailPanel extends li_BaseView {
@property(Sprite)
avatar: Sprite;
@property(VideoPlayer) @property(VideoPlayer)
avatarVideo: VideoPlayer; avatarVideo: VideoPlayer;
@property(Label) @property(Label)
@@ -107,7 +109,7 @@ export class GirlDetailPanel extends li_BaseView {
const videoTransform = this.avatarVideo.node.getComponent(UITransform); const videoTransform = this.avatarVideo.node.getComponent(UITransform);
if (parentTransform && videoTransform && videoTransform.height > 0) { if (parentTransform && videoTransform && videoTransform.height > 0) {
const scale = parentTransform.width / videoTransform.width; const scale = parentTransform.height / videoTransform.height;
this.avatarVideo.node.setScale(scale, scale, 1); this.avatarVideo.node.setScale(scale, scale, 1);
console.log( console.log(
`Video scaled to: ${scale}, parent height: ${parentTransform.height}, video height: ${videoTransform.height}` `Video scaled to: ${scale}, parent height: ${parentTransform.height}, video height: ${videoTransform.height}`
@@ -143,14 +145,11 @@ export class GirlDetailPanel extends li_BaseView {
let res = await GirlService.I.reqGetGirlDetail(reqData); let res = await GirlService.I.reqGetGirlDetail(reqData);
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) { if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
// 保存数据 // 保存数据
girlData.setGirlDetails(this.category.toString(), res.data); girlData.setGirlDetailData(this.category.toString(), res.data);
// 根据数据,刷新界面 // 根据数据,刷新界面
this.nameKey = girlData.getGrilName(this.category.toString(), this.id); this.nameKey = girlData.getGrilName(this.category.toString(), this.id);
this.girlName.string = LanguageUtils.getText(this.nameKey); this.girlName.string = LanguageUtils.getText(this.nameKey);
this.desc.string = girlData.getGrilDesc( this.desc.string = girlData.getGrilDesc(this.category.toString(), this.id);
this.category.toString(),
this.id
);
let desc = ""; let desc = "";
this.tagKey = girlData.getGrilTagKey(this.category.toString(), this.id); this.tagKey = girlData.getGrilTagKey(this.category.toString(), this.id);
@@ -167,50 +166,48 @@ export class GirlDetailPanel extends li_BaseView {
this.descAge.string = this.descAge.string =
LanguageUtils.getText("girldetailpanel.age") + age.toString(); LanguageUtils.getText("girldetailpanel.age") + age.toString();
const firstPath = girlData.getGrilVideoPath( const firstPath = girlData.getFirstGrilVideoPath(this.category.toString(), this.id);
this.category.toString(), ResManager.I.changeBundleVideo(
this.id, this.avatarVideo,
0 firstPath,
"Chat18x"
); );
ResManager.I.changeBundleVideo(this.avatarVideo, firstPath, "Chat18x");
let allPhotoDataCount = girlData.getAllGrilPhotoDataCount( let resIds = girlData.getAllGrilPhotoDataId(this.category.toString(), this.id);
this.category.toString(),
this.id
);
// 也立即尝试调整(以防已经加载完成) // 也立即尝试调整(以防已经加载完成)
this.adjustVideoScale(); this.adjustVideoScale();
this.refreshImgs(1, this.category, this.id, allPhotoDataCount); this.refreshImgs(1, this.category, this.id, resIds);
} }
} }
bindImgToggle() { bindImgToggle() {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl); const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
let allPhotoDataCount = girlData.getAllGrilPhotoDataCount( let resIds = girlData.getAllGrilPhotoDataId(this.category.toString(), this.id);
this.category.toString(), this.refreshImgs(1, this.category, this.id, resIds);
this.id
);
this.refreshImgs(1, this.category, this.id, allPhotoDataCount);
} }
bindVideoToggle() { bindVideoToggle() {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl); const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
let allVideoDataCount = girlData.getAllGrilVideoDataCount( let resIds = girlData.getAllGrilVideoDataId(this.category.toString(), this.id);
this.category.toString(), this.refreshImgs(2, this.category, this.id, resIds);
this.id
);
this.refreshImgs(2, this.category, this.id, allVideoDataCount);
} }
refreshImgs(type: number, category: number, id: number, count: number) { refreshImgs(
type: number,
category: number,
id: number,
resIds: number[]
) {
for (let i = this.imgsLayout.children.length - 1; i >= 0; i--) { for (let i = this.imgsLayout.children.length - 1; i >= 0; i--) {
this.imgsLayout.children[i].destroy(); this.imgsLayout.children[i].destroy();
} }
let count = resIds.length;
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
let newNode = instantiate(this.imgItemInst.node); let newNode = instantiate(this.imgItemInst.node);
let item = newNode.getComponent(DetailImageItem); let item = newNode.getComponent(DetailImageItem);
item.refresh(this, type, category, id, i); let resId = resIds[i];
item.refresh(this, type, category, id, resId);
newNode.active = true; newNode.active = true;
this.imgsLayout.addChild(newNode); this.imgsLayout.addChild(newNode);
} }
@@ -51,7 +51,7 @@ export class GirlListPanel extends li_BaseView {
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) { if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
// 保存数据 // 保存数据
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl); const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
girlData.setGirlBriefs(category.toString(), res.data); girlData.setGirlList(category.toString(), res.data);
// 根据数据,刷新界面 // 根据数据,刷新界面
const allId = girlData.getGirlIds(category.toString()); const allId = girlData.getGirlIds(category.toString());
for (let id of allId) { for (let id of allId) {
@@ -95,10 +95,10 @@ export class ThemePanel extends li_BaseView {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl); const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
girlData.setDailyRecommend(res2.data); girlData.setDailyRecommend(res2.data);
// 根据数据,刷新界面 // 根据数据,刷新界面
this.recId = girlData.getRecommendGrilId(0); this.recId = girlData.getRecommendGirlId();
this.rectNameKey = girlData.getRecommendGrilName(0); this.rectNameKey = girlData.getRecommendGrilName();
let avatarPath = girlData.getRecommendGrilAvatar(0); let avatarPath = girlData.getRecommendGrilAvatar();
//this.recName.string = LanguageUtils.getText(this.rectNameKey); this.recName.string = LanguageUtils.getText(this.rectNameKey);
ResManager.I.changeBundleSpriteFrame( ResManager.I.changeBundleSpriteFrame(
this.recSprite, this.recSprite,
avatarPath, avatarPath,
@@ -1,4 +1,12 @@
import { _decorator, Component, math, Node, Sprite, UITransform } from "cc"; import {
_decorator,
Component,
Label,
math,
Node,
Sprite,
UITransform,
} from "cc";
import { Config18x } from "db://assets/Scripts/Main/Config/Config18x"; import { Config18x } from "db://assets/Scripts/Main/Config/Config18x";
import ResManager from "db://assets/Scripts/Main/Manager/ResManager"; import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager"; import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
@@ -21,13 +29,19 @@ export class DetailImageItem extends Component {
@property(Sprite) @property(Sprite)
video: Sprite; video: Sprite;
@property(Node)
priceFrame: Node;
@property(Label)
videoPrice: Label;
base: GirlDetailPanel; base: GirlDetailPanel;
url: string; url: string;
isImage: boolean; isImage: boolean;
uitransform: UITransform; uitransform: UITransform;
category: number; category: number;
id: number;
index: number; girlId: number;
resId: number;
type: number; type: number;
onLoad() { onLoad() {
@@ -59,7 +73,8 @@ export class DetailImageItem extends Component {
doScaleToFill() { doScaleToFill() {
if (!this.img || !this.img.spriteFrame) return; if (!this.img || !this.img.spriteFrame) return;
if (!this.uitransform)
this.uitransform = this.node.getComponent(UITransform);
const itemSize = this.uitransform.contentSize; const itemSize = this.uitransform.contentSize;
const imageSize = this.img.spriteFrame.originalSize; const imageSize = this.img.spriteFrame.originalSize;
@@ -93,24 +108,26 @@ export class DetailImageItem extends Component {
type: number, type: number,
category: number, category: number,
id: number, id: number,
index: number resId: number
) { ) {
this.base = base; this.base = base;
this.type = type; this.type = type;
this.category = category; this.category = category;
this.id = id; this.girlId = id;
this.index = index;
this.resId = resId;
this.question.active = true; // 显示问号,表示加载中 this.question.active = true; // 显示问号,表示加载中
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl); const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
let imgPath = ""; let imgPath = "";
this.video.enabled = type === 2; this.video.enabled = type === 2;
this.priceFrame.active = type === 2;
if (type === 1) { if (type === 1) {
// 图片 // 图片
this.url = girlData.getGrilPhotoPic( this.url = girlData.getGrilPhotoPic(
this.category.toString(), this.category.toString(),
this.id, this.girlId,
this.index this.resId
); );
imgPath = this.url; imgPath = this.url;
this.isImage = true; this.isImage = true;
@@ -119,19 +136,28 @@ export class DetailImageItem extends Component {
this.isImage = false; this.isImage = false;
this.url = girlData.getGrilVideoPath( this.url = girlData.getGrilVideoPath(
this.category.toString(), this.category.toString(),
this.id, this.girlId,
this.index this.resId
); );
let videoPrice = girlData.getGrilVideoPrice( let videoPrice = girlData.getGrilVideoPrice(
this.category.toString(), this.category.toString(),
this.id, this.girlId,
this.index this.resId
); );
this.url = girlData.getGrilVideoPath(
this.category.toString(),
this.girlId,
this.resId
);
if (videoPrice > 0) { if (videoPrice > 0) {
imgPath = this.url + "_thumbnail_blur"; imgPath = this.url + "_thumbnail_blur";
} else { } else {
imgPath = this.url + "_thumbnail"; imgPath = this.url + "_thumbnail";
} }
this.priceFrame.active = videoPrice > 0;
this.videoPrice.string = videoPrice.toString();
} }
ResManager.I.changeBundleSpriteFrame(this.img, imgPath, "Chat18x", () => { ResManager.I.changeBundleSpriteFrame(this.img, imgPath, "Chat18x", () => {
+3410 -1015
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3 -13
View File
@@ -234,7 +234,6 @@ export class GlobalConfig {
this.GameName = _buf_.readString() this.GameName = _buf_.readString()
this.EmotionRating = _buf_.readString() this.EmotionRating = _buf_.readString()
this.girlBasePrompt = _buf_.readString() this.girlBasePrompt = _buf_.readString()
this.dailyRecommendGirl = _buf_.readInt()
} }
/** /**
@@ -282,10 +281,6 @@ export class GlobalConfig {
* ai机器人基础规则 * ai机器人基础规则
*/ */
readonly girlBasePrompt: string readonly girlBasePrompt: string
/**
* 每日推荐技师ID,参见:girls.id
*/
readonly dailyRecommendGirl: number
resolve(tables:Tables) { resolve(tables:Tables) {
@@ -300,7 +295,6 @@ export class GlobalConfig {
} }
} }
@@ -439,8 +433,8 @@ export class PurchaseConfig {
constructor(_buf_: ByteBuf) { constructor(_buf_: ByteBuf) {
this.id = _buf_.readInt() this.id = _buf_.readInt()
this.name = _buf_.readString() this.name = _buf_.readString()
this.desc = _buf_.readString()
this.count = _buf_.readInt() this.count = _buf_.readInt()
this.price = _buf_.readInt()
} }
/** /**
@@ -454,11 +448,11 @@ export class PurchaseConfig {
/** /**
* 数量 * 数量
*/ */
readonly desc: string readonly count: number
/** /**
* 价格 * 价格
*/ */
readonly count: number readonly price: number
resolve(tables:Tables) { resolve(tables:Tables) {
@@ -812,10 +806,6 @@ export class TbGlobalConfig {
* ai机器人基础规则 * ai机器人基础规则
*/ */
get girlBasePrompt(): string { return this._data.girlBasePrompt; } get girlBasePrompt(): string { return this._data.girlBasePrompt; }
/**
* 每日推荐技师ID,参见:girls.id
*/
get dailyRecommendGirl(): number { return this._data.dailyRecommendGirl; }
resolve(tables:Tables) { resolve(tables:Tables) {
this._data.resolve(tables) this._data.resolve(tables)
File diff suppressed because it is too large Load Diff
Binary file not shown.
@@ -1,2 +1,2 @@
ƒé␍充值挡ä½1999ƒçƒê␍充值挡ä½29999§ƒë␍充值挡ä½319999ÀNƒì␍充值挡ä½429999Àu/ƒí␍充值挡ä½569999Áoƒî␍充值挡ä½699999Á†Ÿ‡Ñ ƒé␍充值挡ä½1ƒçƒçƒê␍充值挡ä½2§§ƒë␍充值挡ä½3ÀNÀNƒì␍充值挡ä½4Àu/Àu/ƒí␍充值挡ä½5ÁoÁoƒî␍充值挡ä½6Á†ŸÁ†Ÿ‡Ñ
7天会员168ƒç‡Ò 30天会员7200‡Ï‹¹增加èŠå¤©æ¬¡æ•°20€Ç 7天会员€¨ƒç‡Ò 30天会员‚Їϋ¹增加èŠå¤©æ¬¡æ•°€Ç
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"__version__": "3.0.7", "__version__": "3.0.7",
"game": { "game": {
"name": "UNKNOW GAME", "name": "未知游戏",
"app_id": "UNKNOW", "app_id": "UNKNOW",
"c_id": "0" "c_id": "0"
}, },
+6 -6
View File
@@ -4,19 +4,19 @@
"customSplash": { "customSplash": {
"id": "customSplash", "id": "customSplash",
"label": "customSplash", "label": "customSplash",
"enable": false, "enable": true,
"customSplash": { "customSplash": {
"complete": false, "complete": true,
"form": "https://creator-api.cocos.com/api/form/show?" "form": "https://creator-api.cocos.com/api/form/show?sid=800ccf353f6eb54dc483510ce462e944"
} }
}, },
"removeSplash": { "removeSplash": {
"id": "removeSplash", "id": "removeSplash",
"label": "removeSplash", "label": "removeSplash",
"enable": false, "enable": true,
"removeSplash": { "removeSplash": {
"complete": false, "complete": true,
"form": "https://creator-api.cocos.com/api/form/show?" "form": "https://creator-api.cocos.com/api/form/show?sid=800ccf353f6eb54dc483510ce462e944"
} }
} }
} }