327 lines
12 KiB
TypeScript
327 lines
12 KiB
TypeScript
import type { ApiResponse } from "../client/types";
|
|
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
|
import type { IGirlService } from "./IGirlService";
|
|
import { ConfigManager, ConfigId } from "../../manager/ConfigManager";
|
|
import { GirlConfig } from "../../config/GirlConfig";
|
|
import { GirlDetailConfig } from "../../config/GirlDetailConfig";
|
|
import { DataManager, DataId } from "../../data/DataManager";
|
|
import { GirlData } from "../../data/GirlData";
|
|
import { WalletData } from "../../data/WalletData";
|
|
|
|
export class MockGirlService implements IGirlService {
|
|
private delay(ms = 180) { return new Promise<void>(r => setTimeout(r, ms)); }
|
|
private randInt(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min; }
|
|
|
|
private ok<T>(data: T): ApiResponse<T> {
|
|
return ({ code: proto.cs.EnmRetCode.SUCCESS, data } as unknown) as ApiResponse<T>;
|
|
}
|
|
private err<T = unknown>(message = "mock error"): ApiResponse<T> {
|
|
return ({ code: 100, error: { message } } as unknown) as ApiResponse<T>;
|
|
}
|
|
|
|
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 {
|
|
id,
|
|
nameKey,
|
|
age,
|
|
category,
|
|
tagKey,
|
|
priceType,
|
|
price,
|
|
vipUnlock,
|
|
avatarPath,
|
|
listAvatarPath,
|
|
};
|
|
}
|
|
|
|
private genPhoto(id: number, imageType: number, unlockCounts: number, imagePrice: number, path: string): proto.cs.IPurchaseCommercialImage {
|
|
return {
|
|
id,
|
|
imageType,
|
|
unlockCounts,
|
|
imagePrice,
|
|
path,
|
|
};
|
|
}
|
|
|
|
private genVideo(id: number, path: string, emotion: number, videoPrice: number): proto.cs.IPurchaseCommercialVideo {
|
|
return {
|
|
id,
|
|
path,
|
|
emotion,
|
|
videoPrice,
|
|
};
|
|
}
|
|
|
|
private genDetail(id: number, detailDesc: string, commercialImages: proto.cs.IPurchaseCommercialImage[], commercialVideos: proto.cs.IPurchaseCommercialVideo[]): proto.cs.IGirlsDetail {
|
|
return {
|
|
id,
|
|
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,
|
|
videos,
|
|
chatTotalCount,
|
|
chatRemainCount,
|
|
};
|
|
}
|
|
|
|
// 每日推荐
|
|
async reqDailyRecommend(req: proto.cs.ICSDailyRecommendReq): Promise<ApiResponse<proto.cs.ICSDailyRecommendRes>> {
|
|
// 延时
|
|
await this.delay(180);
|
|
// 配置数据
|
|
const configData = ConfigManager.I.getDataById<GirlConfig>(ConfigId.Girl);
|
|
const allId = configData.getAllId();
|
|
const recId = allId[0];
|
|
let nameKey = configData.getNameById(recId);
|
|
let age = configData.getAgeById(recId);
|
|
let tagKey = configData.getTagKeyById(recId);
|
|
let priceType = configData.getPriceTypeById(recId);
|
|
let price = configData.getPriceById(recId);
|
|
let vipUnlock = configData.getVipUnlockById(recId);
|
|
let avatarPath = configData.getAvatarPathById(recId);
|
|
let category = configData.getCategoryById(recId);
|
|
let listAvatarPath = configData.getListAvatarPathPathById(recId);
|
|
let oneData = this.genBrief(recId, nameKey, age, category, tagKey, priceType, price, vipUnlock, avatarPath, listAvatarPath);
|
|
// 返回数据
|
|
const res: proto.cs.ICSDailyRecommendRes = {girl: oneData};
|
|
return this.ok(res);
|
|
}
|
|
|
|
// 获取技师列表
|
|
async reqGetGirlList(req: proto.cs.ICSGetGirlListReq): Promise<ApiResponse<proto.cs.ICSGetGirlListRes>> {
|
|
// 延时
|
|
await this.delay(200);
|
|
// 配置数据
|
|
const configData = ConfigManager.I.getDataById<GirlConfig>(ConfigId.Girl);
|
|
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);
|
|
|
|
// 映射数据
|
|
const girls: proto.cs.IGirlData[] = pageIds.map((id: number) => {
|
|
// 简要数据
|
|
const nameKey = configData.getNameById(id);
|
|
const age = configData.getAgeById(id);
|
|
const tagKey = configData.getTagKeyById(id);
|
|
const priceType = configData.getPriceTypeById(id);
|
|
const price = configData.getPriceById(id);
|
|
const vipUnlock = configData.getVipUnlockById(id);
|
|
const avatarPath = configData.getAvatarPathById(id);
|
|
const category = configData.getCategoryById(id);
|
|
const listAvatarPath = configData.getListAvatarPathPathById(id);
|
|
const briefData = this.genBrief(id, nameKey, age, category, tagKey, priceType, price, vipUnlock, avatarPath, 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;
|
|
});
|
|
// 返回数据
|
|
const res: proto.cs.ICSGetGirlListRes = {girls};
|
|
return this.ok(res);
|
|
}
|
|
|
|
// 获取技师详细信息
|
|
async reqGetGirlDetail(req: proto.cs.ICSGetGirlDetailReq): Promise<ApiResponse<proto.cs.ICSGetGirlDetailRes>> {
|
|
// 延时
|
|
await this.delay(160);
|
|
// 配置数据
|
|
const girlConfig = ConfigManager.I.getDataById<GirlConfig>(ConfigId.Girl);
|
|
const girlDetailConfig = ConfigManager.I.getDataById<GirlDetailConfig>(ConfigId.GirlDetail);
|
|
// id
|
|
const girlId = req.id;
|
|
// 简要数据
|
|
let nameKey = girlConfig.getNameById(girlId);
|
|
let age = girlConfig.getAgeById(girlId);
|
|
let tagKey = girlConfig.getTagKeyById(girlId);
|
|
let priceType = girlConfig.getPriceTypeById(girlId);
|
|
let price = girlConfig.getPriceById(girlId);
|
|
let vipUnlock = girlConfig.getVipUnlockById(girlId);
|
|
let avatarPath = girlConfig.getAvatarPathById(girlId);
|
|
let category = girlConfig.getCategoryById(girlId);
|
|
let listAvatarPath = girlConfig.getListAvatarPathPathById(girlId);
|
|
let briefData = this.genBrief(girlId, nameKey, age, category, tagKey, priceType, price, vipUnlock, avatarPath, listAvatarPath);
|
|
|
|
let isRelease = Math.random() < 0.4;
|
|
let detailDesc = girlDetailConfig.getDetailDescById(girlId);
|
|
// 图片
|
|
let photoData = [];
|
|
let photoIds = girlDetailConfig.getCommercialImagesIds(girlId);
|
|
for (let id of photoIds) {
|
|
let imageType = girlDetailConfig.getImageTypeById(girlId, id);
|
|
let unlockCounts = girlDetailConfig.getImageUnlockCountsById(girlId, id);
|
|
let imagePrice = girlDetailConfig.getImagePriceById(girlId, id);
|
|
let imagePath = girlDetailConfig.getImagePathById(girlId, id);
|
|
let oneData = this.genPhoto(id, imageType, unlockCounts, imagePrice, imagePath);
|
|
photoData.push(oneData);
|
|
}
|
|
// 视频
|
|
let videoData = [];
|
|
let videoIds = girlDetailConfig.getCommercialVideosIds(girlId);
|
|
for (let id of videoIds) {
|
|
let videoPath = girlDetailConfig.getVideoPathById(girlId, id);
|
|
let videoEmotion = girlDetailConfig.getVideoEmotionById(girlId, id);
|
|
let videoPrice = girlDetailConfig.getVideoPriceById(girlId, id);
|
|
let oneData = this.genVideo(id, videoPath, videoEmotion, videoPrice);
|
|
videoData.push(oneData);
|
|
}
|
|
// 详细数据
|
|
let detail = this.genDetail(girlId, detailDesc, photoData, videoData);
|
|
// 付费图片解锁数据
|
|
let unlockImageData: proto.cs.IResourceUnlock[] = [];
|
|
for (let id of photoIds) {
|
|
// 价格大于0才为付费
|
|
let imagePrice = girlDetailConfig.getImagePriceById(girlId, id);
|
|
// 偶数才解锁
|
|
let isUnlock = (id % 2 === 0);
|
|
if (imagePrice > 0 && isUnlock) {
|
|
let oneData = {
|
|
girlId: girlId,
|
|
resId: id,
|
|
};
|
|
unlockImageData.push(oneData);
|
|
}
|
|
}
|
|
// 付费视频解锁数据
|
|
let unlockVideoData: proto.cs.IResourceUnlock[] = [];
|
|
for (let id of videoIds) {
|
|
// 价格大于0才为付费
|
|
let videoPrice = girlDetailConfig.getVideoPriceById(girlId, id);
|
|
// 偶数才解锁
|
|
let isUnlock = (id % 2 === 0);
|
|
if (videoPrice > 0 && 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);
|
|
// 返回数据
|
|
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 reqGirlId = req.id;
|
|
// 数据层的数据
|
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
|
const category = girlData.getGrilCategoryById(reqGirlId);
|
|
const price = girlData.getGrilPrice(category.toString(), reqGirlId);
|
|
const walletData = DataManager.I.getDataById<WalletData>(DataId.Wallet);
|
|
// 余额
|
|
let balanceNumber = Number(walletData.balance) - Number(price);
|
|
let balance = balanceNumber.toString();
|
|
// vip 30天后过期
|
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
let vipExpire = nowSeconds + 30 * 24 * 3600;
|
|
// 返回数据
|
|
const res: proto.cs.ICSUnlockGirlRes = {
|
|
balance,
|
|
vipExpire,
|
|
};
|
|
return this.ok(res);
|
|
}
|
|
|
|
// 解锁资源
|
|
async reqUnlockGirlRes(req: proto.cs.ICSUnlockResourceReq): Promise<ApiResponse<proto.cs.ICSUnlockResourceRes>> {
|
|
// 延时
|
|
await this.delay(180);
|
|
// 请求数据
|
|
const reqGirlId = req.girlId;
|
|
const resId = req.resId;
|
|
const resType = req.type;
|
|
// 数据层的数据
|
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
|
const category = girlData.getGrilCategoryById(reqGirlId);
|
|
let price = 0;
|
|
if (resType === proto.cs.EnmResType.ERT_Image) {
|
|
// 图片
|
|
price = girlData.getGrilPhotoPrice(category.toString(), reqGirlId, resId);
|
|
} else if (resType === proto.cs.EnmResType.ERT_Video) {
|
|
// 视频
|
|
price = girlData.getGrilVideoPrice(category.toString(), reqGirlId, resId);
|
|
}
|
|
const walletData = DataManager.I.getDataById<WalletData>(DataId.Wallet);
|
|
// 余额
|
|
let balanceNumber = Number(walletData.balance) - Number(price);
|
|
let balance = balanceNumber.toString();
|
|
// vip 30天后过期
|
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
let vipExpire = nowSeconds + 30 * 24 * 3600;
|
|
// 返回数据
|
|
const res: proto.cs.ICSUnlockResourceRes = {
|
|
balance,
|
|
vipExpire,
|
|
};
|
|
return this.ok(res);
|
|
}
|
|
|
|
// 获取可聊天的技师数据
|
|
async reqCanChatGirlData(req: proto.cs.ICSGetLastChatListReq): Promise<ApiResponse<proto.cs.ICSGetLastChatListRes>> {
|
|
// TODO
|
|
|
|
// 返回数据
|
|
const res: proto.cs.ICSGetLastChatListRes = {
|
|
LastChatList: [],
|
|
};
|
|
return this.ok(res);
|
|
}
|
|
|
|
// 获取排行榜列表
|
|
async reqGirlRankData(req: proto.cs.ICSGetRankReq): Promise<ApiResponse<proto.cs.ICSGetRankRes>> {
|
|
// TODO
|
|
|
|
// 返回数据
|
|
const res: proto.cs.ICSGetRankRes = {
|
|
girls: [],
|
|
};
|
|
return this.ok(res);
|
|
}
|
|
}
|