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

This commit is contained in:
2025-09-02 17:07:49 +08:00
21 changed files with 194 additions and 88 deletions
+1 -17
View File
@@ -29,9 +29,6 @@ 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 { WalletData } from "../../chat18x/data/WalletData"; import { WalletData } from "../../chat18x/data/WalletData";
import { AccountData } from "../../chat18x/data/AccountData";
import { MetaData } from "../../chat18x/data/MetaData";
import { NetTimeData } from "../../chat18x/data/NetTimeData";
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";
@@ -280,20 +277,7 @@ export class PreloadUI extends Component {
loginData.expire = resData.expire; loginData.expire = 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.identifier = resData.Identifier;
// accountData.identityType = resData.IdentityType;
// accountData.uid = resData.Uid;
// accountData.isNewGuide = resData.IsNewGuide;
// accountData.isNewRegist = resData.IsNewRegist;
// const metaData = DataManager.I.getDataById<MetaData>(DataId.Meta);
// metaData.gameName = resData.GameName;
// const netTimeData = DataManager.I.getDataById<NetTimeData>(DataId.NetTime);
// netTimeData.serverTime = resData.ServerTime;
// netTimeData.timezoneOffset = resData.TimezoneOffset;
this.loginFinish = true; this.loginFinish = true;
// this.reqMyInfo(); // this.reqMyInfo();
@@ -25,6 +25,20 @@ export class GirlConfig extends BaseConfig {
return ConfigManager.tables.TbGirls; return ConfigManager.tables.TbGirls;
} }
/**
* 获取所有配置 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
*/ */
@@ -12,6 +12,7 @@ import { ThemeData } from "./ThemeData";
import { WalletData } from "./WalletData"; import { WalletData } from "./WalletData";
import { ShopData } from "./ShopData"; import { ShopData } from "./ShopData";
import { OrderData } from "./OrderData"; import { OrderData } from "./OrderData";
import { GirlData } from "./GirlData";
/** /**
* 集中定义数据ID,避免写错字符串 * 集中定义数据ID,避免写错字符串
@@ -26,6 +27,7 @@ export enum DataId {
Wallet = "wallet", // 钱包数据 Wallet = "wallet", // 钱包数据
Shop = "shop", // 商城数据 Shop = "shop", // 商城数据
Order = "order", // 订单数据 Order = "order", // 订单数据
Girl = "girl", // 技师数据
} }
/** 构造器类型 */ /** 构造器类型 */
@@ -67,6 +69,7 @@ export class DataManager {
this.register(DataId.Wallet, WalletData); this.register(DataId.Wallet, WalletData);
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);
} }
/** /**
+15
View File
@@ -309,6 +309,7 @@ export class GirlData extends BaseData {
public setDailyRecommend(res: proto.cs.ICSDailyRecommendRes): void { public setDailyRecommend(res: proto.cs.ICSDailyRecommendRes): void {
this.mergeBriefs(DAILY_BUCKET, res.girls); this.mergeBriefs(DAILY_BUCKET, res.girls);
this._dailyRecommendIds = res.girls.map(g => g.id ?? 0); this._dailyRecommendIds = res.girls.map(g => g.id ?? 0);
console.log("保存每日推荐: ", this._dailyRecommendIds);
} }
/** 获取每日推荐的简要信息 */ /** 获取每日推荐的简要信息 */
@@ -319,10 +320,24 @@ export class GirlData extends BaseData {
return b.briefs.get(b.girlIds[index]) ?? null; return b.briefs.get(b.girlIds[index]) ?? null;
} }
/** 获取 id */
public getRecommendGrilId(index: number): number {
let oneData = this.getRecommendGrilBrief(DAILY_BUCKET, index);
if (!oneData) return 0;
return oneData.id;
}
/** 获取名字 */ /** 获取名字 */
public getRecommendGrilName(index: number): string { public getRecommendGrilName(index: number): string {
let oneData = this.getRecommendGrilBrief(DAILY_BUCKET, index); let oneData = this.getRecommendGrilBrief(DAILY_BUCKET, index);
if (!oneData) return ""; if (!oneData) return "";
return oneData.name; return oneData.name;
} }
/** 获取头像 */
public getRecommendGrilAvatar(index: number): string {
let oneData = this.getRecommendGrilBrief(DAILY_BUCKET, index);
if (!oneData) return "";
return oneData.avatar;
}
} }
@@ -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 = false; const USE_MOCK = true;
export class GirlService implements IGirlService { export class GirlService implements IGirlService {
private static _I: GirlService | null = null; private static _I: GirlService | null = null;
@@ -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 { IGirlService } from "./IGirlService"; import type { IGirlService } from "./IGirlService";
import { ConfigManager, ConfigId } from "../../manager/ConfigManager";
import { GirlConfig } from "../../config/GirlConfig";
export class MockGirlService implements IGirlService { export class MockGirlService implements IGirlService {
private delay(ms = 180) { return new Promise<void>(r => setTimeout(r, ms)); } private delay(ms = 180) { return new Promise<void>(r => setTimeout(r, ms)); }
@@ -8,23 +10,22 @@ export class MockGirlService implements IGirlService {
private pick<T>(arr: T[]) { return arr[this.randInt(0, arr.length - 1)]; } private pick<T>(arr: T[]) { return arr[this.randInt(0, arr.length - 1)]; }
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 error"): ApiResponse<T> { private err<T = unknown>(message = "mock error"): ApiResponse<T> {
return ({ ok: false, error: { message } } as unknown) as ApiResponse<T>; return ({ code: 100, error: { message } } as unknown) as ApiResponse<T>;
} }
private genBrief(id: number): proto.cs.IGirlBrief { private genBrief(id: number, name: string, age: number, tagKey: string, priceType: number, price: number, avatar: string, star: number): proto.cs.IGirlBrief {
const tags = ["cute", "cool", "elegant", "sporty", "sweet"];
return { return {
id, id,
name: `Girl-${id}`, name,
age: this.randInt(18, 28), age,
tagKey: this.pick(tags), tagKey,
priceType: (id % 2) + 1, priceType,
price: 50 + (id % 6) * 10, price,
avatar: `https://dummy.local/avatar/${id}.png`, avatar,
star: (id % 5) + 1, star,
}; };
} }
@@ -34,23 +35,72 @@ export class MockGirlService implements IGirlService {
private genDetail(id: number): proto.cs.IGirlDetail { private genDetail(id: number): proto.cs.IGirlDetail {
const photos = Array.from({ length: 4 }, (_, i) => this.genPhoto(id * 10 + i)); const photos = Array.from({ length: 4 }, (_, i) => this.genPhoto(id * 10 + i));
return { brief: this.genBrief(id), desc: `Mock detail for ${id}`, photos, isRelease: Math.random() < 0.4, chatCount: this.randInt(0, 5) }; return { brief: this.genBrief(id, "", 1, "", 2, 3, "", 4), desc: `Mock detail for ${id}`, photos, isRelease: Math.random() < 0.4, chatCount: this.randInt(0, 5) };
} }
// 每日推荐 // 每日推荐
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 count = this.randInt(4, 8);
const girls = Array.from({ length: count }, (_, i) => this.genBrief(100 + i)); const configData = ConfigManager.I.getDataById<GirlConfig>(ConfigId.Girl);
const allId = configData.getAllId();
const recId = allId[0];
let name = configData.getNameById(recId);
let age = Number(configData.getAgeById(recId));
let tagKey = configData.getTagKeyById(recId);
let priceType = configData.getPriceTypeById(recId);
let price = 9.9;
let avatar = configData.getAvatarPathById(recId);
let star = 3;
let oneData = this.genBrief(recId, name, age, tagKey, priceType, price, avatar, star);
// 返回数据
const girls = [oneData];
return this.ok({ girls }); return this.ok({ girls });
} }
// 获取技师列表 // 获取技师列表
async reqGetGirlList(req: proto.cs.ICSGetGirlListReq): Promise<ApiResponse<proto.cs.ICSGetGirlListRes>> { async reqGetGirlList(req: proto.cs.ICSGetGirlListReq): Promise<ApiResponse<proto.cs.ICSGetGirlListRes>> {
// 延时
await this.delay(200); await this.delay(200);
const base = (req?.category ?? 0) * 1000 + (req?.page ?? 1) * 100;
const limit = Math.max(1, Math.min(req?.limit ?? 10, 50)); const configData = ConfigManager.I.getDataById<GirlConfig>(ConfigId.Girl);
const girls = Array.from({ length: limit }, (_, i) => this.genBrief(base + i)); const allId = configData.getAllId();
// 按 category 精确匹配
const category = Number(req?.category ?? -1);
const filteredIds = category >= 0
? allId.filter((id: number) => {
const cat = Number(configData.getCategoryById(id) ?? -1);
return cat === category;
})
: allId;
// 分页
const page = Math.max(1, Number(req?.page ?? 1));
const limit = Math.max(1, Math.min(Number(req?.limit ?? 10), 50));
const start = (page - 1) * limit;
const pageIds = filteredIds.slice(start, start + limit);
// 映射为 IGirlBrief
const girls: proto.cs.IGirlBrief[] = pageIds.map((id: number) => {
const name = configData.getNameById(id);
const age = Number(configData.getAgeById(id));
const tagKey = configData.getTagKeyById(id);
const priceType = Number(configData.getPriceTypeById(id));
const avatar = 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;
return this.genBrief(id, name, age, tagKey, priceType, price, avatar, star);
});
return this.ok({ girls }); return this.ok({ girls });
} }
@@ -38,6 +38,7 @@ export class MockThemeService implements IThemeService {
let oneData = this.makeTheme(oneId, key, name, category, isRelease, path); let oneData = this.makeTheme(oneId, key, name, category, isRelease, path);
themes.push(oneData); themes.push(oneData);
} }
// 返回数据
const res: proto.cs.ICSHallThemeRes = { themes }; const res: proto.cs.ICSHallThemeRes = { themes };
return this.ok(res); return this.ok(res);
} }
@@ -4,6 +4,11 @@ import Utils from "db://assets/Scripts/Main/Common/Utils";
import { GButton } from "db://assets/Scripts/Main/Common/GButton"; import { GButton } from "db://assets/Scripts/Main/Common/GButton";
import { GirlListItem } from "../../uiitems/GirlListItem"; import { GirlListItem } from "../../uiitems/GirlListItem";
import { ConfigManager } from "../../manager/ConfigManager"; import { ConfigManager } from "../../manager/ConfigManager";
import { GirlService } from "db://assets/Scripts/chat18x/network/services/GirlService";
import { DataManager, DataId } from "../../data/DataManager";
import { GirlData } from "../../data/GirlData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@ccclass("GirlListPanel") @ccclass("GirlListPanel")
@@ -28,22 +33,34 @@ export class GirlListPanel extends li_BaseView {
this.refresh(this.category); this.refresh(this.category);
} }
refresh(category: number) { async refresh(category: number) {
if (this.cache) { if (this.cache) {
for (let i = this.cache.length - 1; i >= 0; i--) { for (let i = this.cache.length - 1; i >= 0; i--) {
this.cache[i].node.destroy(); this.cache[i].node.destroy();
} }
} }
const GirlsData = ConfigManager.tables.TbGirls.getDataList();
const config = GirlsData.filter((value) => value.category == category); // 请求列表
for (let i = 0; i < config.length; i++) { const reqData = {
const cfg = config[i]; category,
let newNode = instantiate(this.itemInst.node); page: 1,
let item = newNode.getComponent(GirlListItem); limit: 10,
item.refreshData(cfg, this.node); };
newNode.active = true; let res = await GirlService.I.reqGetGirlList(reqData);
this.cache.push(item); if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
this.content.addChild(newNode); // 保存数据
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
girlData.setGirlBriefs(category.toString(), res.data);
// 根据数据,刷新界面
const allId = girlData.getGirlIds(category.toString());
for (let id of allId) {
let newNode = instantiate(this.itemInst.node);
let item = newNode.getComponent(GirlListItem);
item.refreshData(category, id, this.node);
newNode.active = true;
this.cache.push(item);
this.content.addChild(newNode);
}
} }
} }
+45 -31
View File
@@ -14,13 +14,15 @@ import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
import { ThemeItem } from "../../uiitems/ThemeItem"; import { ThemeItem } from "../../uiitems/ThemeItem";
import { NavigationManager } from "../../manager/NavigationManager"; import { NavigationManager } from "../../manager/NavigationManager";
import { GirlListItem } from "../../uiitems/GirlListItem"; import { GirlListItem } from "../../uiitems/GirlListItem";
import { ConfigManager } from "../../manager/ConfigManager";
import LanguageUtils from "../../../Main/Common/LanguageUtils"; import LanguageUtils from "../../../Main/Common/LanguageUtils";
import { ViewManager } from "../../../Main/Manager/ViewManager"; import { ViewManager } from "../../../Main/Manager/ViewManager";
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode"; import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
import { ThemeService } from "db://assets/Scripts/chat18x/network/services/ThemeService"; import { ThemeService } from "db://assets/Scripts/chat18x/network/services/ThemeService";
import { GirlService } from "db://assets/Scripts/chat18x/network/services/GirlService";
import { DataManager, DataId } from "../../data/DataManager"; import { DataManager, DataId } from "../../data/DataManager";
import { ThemeData } from "../../data/ThemeData"; import { ThemeData } from "../../data/ThemeData";
import { GirlData } from "../../data/GirlData";
import proto from 'db://assets/Scripts/proto/proto.pb.js';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@@ -68,37 +70,49 @@ export class ThemePanel extends li_BaseView {
}; };
let res = await ThemeService.I.reqHallTheme(reqData); let res = await ThemeService.I.reqHallTheme(reqData);
// 保存数据 if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme); // 保存数据
themeData.themes = res.data; const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
// 根据数据,构建界面显示 themeData.themes = res.data;
const themeIds = themeData.themeIds; // 根据数据,刷新界面
for (let id of themeIds) { const themeIds = themeData.themeIds;
let newNode = instantiate(this.itemInst.node); for (let id of themeIds) {
let item = newNode.getComponent(ThemeItem); let newNode = instantiate(this.itemInst.node);
item.refresh(id); let item = newNode.getComponent(ThemeItem);
newNode.active = true; item.refresh(id);
this.cache.push(item); newNode.active = true;
this.content.addChild(newNode); this.cache.push(item);
} this.content.addChild(newNode);
const rectInfo = ConfigManager.tables.TbGirls.get(10001);
this.recId = rectInfo.id;
this.rectNameKey = rectInfo.nameKey;
//this.recName.string = LanguageUtils.getText(this.rectNameKey);
ResManager.I.changeBundleSpriteFrame(
this.recSprite,
rectInfo.avatarPath,
"Chat18x",
() => {
let sizeTran = this.recSprite.node.parent.getComponent(UITransform);
Utils.adjustBgPixelRatioToSize(
sizeTran.contentSize,
this.recSprite.node,
1
);
} }
); }
// 请求每日推荐
const reqData2 = {
};
let res2 = await GirlService.I.reqDailyRecommend(reqData2);
if (res2 && res2.code === proto.cs.EnmRetCode.SUCCESS) {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
girlData.setDailyRecommend(res2.data);
// 根据数据,刷新界面
this.recId = girlData.getRecommendGrilId(0);
this.rectNameKey = girlData.getRecommendGrilName(0);
let avatarPath = girlData.getRecommendGrilAvatar(0);
//this.recName.string = LanguageUtils.getText(this.rectNameKey);
ResManager.I.changeBundleSpriteFrame(
this.recSprite,
avatarPath,
"Chat18x",
() => {
let sizeTran = this.recSprite.node.parent.getComponent(UITransform);
Utils.adjustBgPixelRatioToSize(
sizeTran.contentSize,
this.recSprite.node,
1
);
}
);
}
} }
private registerListener() { private registerListener() {
+19 -11
View File
@@ -7,6 +7,8 @@ import { NavigationManager } from "../manager/NavigationManager";
import { Girl, PriceType } from "../../schema/schema"; import { Girl, PriceType } from "../../schema/schema";
import LanguageUtils from "../../Main/Common/LanguageUtils"; import LanguageUtils from "../../Main/Common/LanguageUtils";
import { InnerMsgCode } from "../../Main/Config/InnerMsgCode"; import { InnerMsgCode } from "../../Main/Config/InnerMsgCode";
import { DataManager, DataId } from "../data/DataManager";
import { GirlData } from "../data/GirlData";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@@ -33,6 +35,7 @@ export class GirlListItem extends Component {
nameKey: string; nameKey: string;
tagKey: string; tagKey: string;
category: number;
private onLanguageChangeCallback = () => { private onLanguageChangeCallback = () => {
if (!this.girlName || !this.tags) return; if (!this.girlName || !this.tags) return;
@@ -64,26 +67,31 @@ export class GirlListItem extends Component {
} }
baseNode: Node; baseNode: Node;
refreshData(data: Girl, baseNode: Node) { refreshData(category: number, girlId: number, baseNode: Node) {
this.category = category;
this.baseNode = baseNode; this.baseNode = baseNode;
this.id = data.id; this.id = girlId;
this.nameKey = data.nameKey; // 数据
this.girlName.string = LanguageUtils.getText(data.nameKey); const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
this.tagKey = data.tagKey; this.nameKey = girlData.getGrilName(this.category.toString(), this.id);
this.girlName.string = LanguageUtils.getText(this.nameKey);
this.tagKey = girlData.getGrilTagKey(this.category.toString(), this.id);
let desc = ""; let desc = "";
const tags = LanguageUtils.getText(data.tagKey).split("|"); const tags = LanguageUtils.getText(this.tagKey).split("|");
for (let i = 0; i < tags.length; i++) { for (let i = 0; i < tags.length; i++) {
if (i != 0) desc += "|"; if (i != 0) desc += "|";
desc += tags[i]; desc += tags[i];
} }
this.tags.string = desc; this.tags.string = desc;
this.price.node.active = data.priceType == PriceType.pay; let priceType = girlData.getGrilPriceType(this.category.toString(), this.id);
this.freeNode.active = data.priceType == PriceType.free; this.price.node.active = priceType == PriceType.pay;
this.tryNode.active = data.priceType == PriceType.first_time_free; this.freeNode.active = priceType == PriceType.free;
this.tryNode.active = priceType == PriceType.first_time_free;
// TODO,先用 AvatarPath 代替着 listAvatarPath
let listAvatarPath = girlData.getGrilAvatar(this.category.toString(), this.id);
ResManager.I.changeBundleSpriteFrame( ResManager.I.changeBundleSpriteFrame(
this.avatar, this.avatar,
data.listAvatarPath, listAvatarPath,
"Chat18x", "Chat18x",
() => { () => {
let sizeTran = this.avatar.node.parent.getComponent(UITransform); let sizeTran = this.avatar.node.parent.getComponent(UITransform);