You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
598 lines
24 KiB
598 lines
24 KiB
|
|
export default class CySDK {
|
|
//sdk 0.4.1
|
|
//1、增加A/B测功能(增加是否开启AB处理)
|
|
//2、关卡埋点
|
|
//3、时长分析面板
|
|
//4、抖跳微
|
|
//5、首日次日用户,新老用户
|
|
//6、快手跳微信接入
|
|
//7、iaa2.0插件接入
|
|
|
|
|
|
static isABTest: boolean = false;//如果用不到AB测功能则关掉
|
|
static appKey: string = "";//后台策略appKey
|
|
static version: string = "GameName1.0.3-cy0.4.1"; //若不使用ab测试时的本地版本号(同一个版本号,每一个关卡序号需要跟每一个关卡名称一致)
|
|
|
|
//#region 其他参数
|
|
static logUrl = "https://log.liehujt.com/game_log"
|
|
static openId: string = ""; //用户唯一标识
|
|
static scene: number = -1; //场景值
|
|
static gameName: string = "";
|
|
static companyName: string = "";
|
|
static code: string = "";
|
|
static shareTitle: string = "分享游戏";
|
|
static shareImageUrl: string = "";
|
|
static launchRes: Object = {};//launch的参数
|
|
//#endregion
|
|
|
|
private static storageData: cyStoreData;//sdk存档数据
|
|
|
|
|
|
|
|
static init(cb: Function) {
|
|
console.log("=========创游SDK版本:0.4.1");
|
|
const self = this;
|
|
//=========创游SDK初始化
|
|
let finishCb = (data: any) => {
|
|
setInterval(() => {
|
|
self.storageData.playTime++;
|
|
self.saveCyStoreData();
|
|
}, 1000);//每秒更新一次时间
|
|
|
|
if (data?.shareTitle) {
|
|
this.shareTitle = data.shareTitle;
|
|
}
|
|
if (data?.shareImageUrl) {
|
|
this.shareImageUrl = data.shareImageUrl;
|
|
}
|
|
cb(data);
|
|
}
|
|
if (this.appKey == "") {
|
|
console.warn("=========创游SDK appkey 未设置,跳过sdk初始化");
|
|
this.cyStoreDataDeal();
|
|
finishCb(null);
|
|
if (window["wx"]) {
|
|
self.launchRes = window["wx"].getLaunchOptionsSync();
|
|
self.trackEvent_uma("launch", { res: JSON.stringify(self.launchRes) });
|
|
}
|
|
self.trackEvent({ event: "login", level_type: "normal" });
|
|
} else {
|
|
this.login((data: any) => {
|
|
finishCb(data);
|
|
self.trackEvent({ event: "login", level_type: "normal" });
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
//#region 埋点接口
|
|
/**友盟打点 */
|
|
static trackEvent_uma(event, obj = {}) {
|
|
obj["playTime"] = this.storageData.playTime;
|
|
obj["version"] = this.version;
|
|
obj["fisrtLoginDateStr"] = this.storageData.firstLoginDateStr;
|
|
for (let key in this.iaaData) {
|
|
const umaKey = "IAA" + key;
|
|
obj[umaKey] = this.iaaData[key];
|
|
}
|
|
|
|
console.log("友盟尝试打点", event, obj);
|
|
if (window["wx"] && window['wx'].uma) {
|
|
window['wx'].uma.trackEvent(event, obj);
|
|
console.log("wx友盟打点发送", event, obj);
|
|
}
|
|
}
|
|
/**游戏内埋点统一接口(主要减少一些通用参数的传输) */
|
|
private static trackEvent(data: object, cb?: Function) {
|
|
if (this.appKey == "") {
|
|
console.warn("=========创游SDKappKey缺失,无法发送埋点数据");
|
|
return;
|
|
}
|
|
if (this.openId == "") {
|
|
console.warn("=========创游SDKopenId缺失,无法发送埋点数据");
|
|
return;
|
|
}
|
|
if (this.scene == -1) {
|
|
console.warn("=========创游SDKscene缺失,无法发送埋点数据");
|
|
return;
|
|
}
|
|
const self = this;
|
|
let sendData = {
|
|
appkey: self.appKey,
|
|
scene: self.scene,
|
|
version: self.version,
|
|
isNew: self.storageData.isNew,//true 是新用户,false是老用户,此处信息前端会给到,用于判定新老用户
|
|
hasPlayDay: (self.getNowDay() - self.storageData.firstLoginDay),//用户已玩天数,此处信息前端传入,用户首次日筛选,(若没有则后端自行处理成0,给之前的版本做兼容)
|
|
gameTime: self.storageData.playTime,//游玩时长(秒),此处信息前端传入,用于后续制作用户时长分布面板
|
|
firstLoginDateStr: self.storageData.firstLoginDateStr,//用户首次登录日期字符串,格式yyyy-MM-dd,用于记录筛选对应日期进来用户的后续行为数据
|
|
data: {
|
|
event: "", // login, level_start, level_success, level_fail, ad_request, ad_cancel, ad_finish,encrypted_data
|
|
openid: "",
|
|
level_type: "",
|
|
level_name: "",
|
|
level_index: -1,
|
|
dur: -1,
|
|
mode: "",
|
|
mode_type: "",
|
|
mode_index: -1,
|
|
why: "",
|
|
encryptedData: "",
|
|
iv: "",
|
|
}
|
|
}
|
|
sendData.data["openid"] = self.openId;
|
|
sendData.data["dur"] = Math.ceil(sendData.data["dur"] || -1); // 确保dur为整数
|
|
for (let key in data) {
|
|
if (sendData.data.hasOwnProperty(key)) {
|
|
sendData.data[key] = data[key];
|
|
}
|
|
}
|
|
const sendStr = JSON.stringify(sendData);
|
|
console.log("=========创游SDK埋点数据发送", sendStr);
|
|
if (!window["wx"]) {
|
|
fetch(self.logUrl, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
body: sendStr
|
|
})
|
|
.then((value) => {
|
|
console.log("=========创游SDK埋点数据发送返回", sendStr);
|
|
cb && cb(value)
|
|
})
|
|
.catch(err => {
|
|
console.log("=========创游SDK埋点数据发送失败", sendStr, err);
|
|
});
|
|
|
|
} else {
|
|
window["wx"].request(
|
|
{
|
|
url: self.logUrl,
|
|
method: "POST",
|
|
data: JSON.stringify(sendData),
|
|
success(res) {
|
|
console.log("=========创游SDK埋点数据发送成功", sendData);
|
|
cb && cb(res);
|
|
},
|
|
fail(err) {
|
|
console.log("=========创游SDK埋点数据发送失败", sendData, err)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
//#endregion
|
|
|
|
//#region 登录初始化
|
|
/** SDK登录
|
|
* @param version 版本(用来分辨不同版本的数据)
|
|
* @param cb 回调函数(data) =>{} data为后台策略返回数据
|
|
*/
|
|
private static login(cb: Function) {
|
|
const self = this;
|
|
if (this.appKey == "") {
|
|
cb(null);
|
|
return;
|
|
}
|
|
if (window["wx"]) {
|
|
let count = 2;
|
|
let loginCode = -1;
|
|
let scene = -1;
|
|
|
|
let clue_token = "";
|
|
let req_id = "";
|
|
let ad_id = "";
|
|
let clickid = "";
|
|
|
|
let callback = "";
|
|
let ksCampaignId = "";
|
|
let ksUnitId = "";
|
|
let ksCreativeId = "";
|
|
let ksChannel = "";
|
|
let ksSiteAccountId = "";
|
|
let ksPageId = "";
|
|
|
|
//拿登录
|
|
const loginCb = (backCb: Function) => {
|
|
window['wx'].login({
|
|
success: (res) => {
|
|
backCb(res.code);
|
|
},
|
|
fail: (err) => {
|
|
console.log("wx登录失败", err);
|
|
backCb(-1);
|
|
}
|
|
})
|
|
};
|
|
//拿场景值
|
|
const getSceneCb = (backCb: Function) => {
|
|
console.log("=========创游SDK获取场景值");
|
|
const res = window["wx"].getLaunchOptionsSync();
|
|
self.launchRes = res;
|
|
|
|
console.log("=========创游SDK冷启动成功", res, JSON.stringify(res));
|
|
const sceneGet = res.scene || -1;
|
|
if (sceneGet == 1069) {//如果是从外部app导入的用户
|
|
//抖音
|
|
clue_token = res.query["clue_token"] || "";
|
|
req_id = res.query["req_id"] || "";
|
|
ad_id = res.query["ad_id"] || "";
|
|
clickid = res.query["clickid"] || "";
|
|
//快手
|
|
callback = res.query["callback"] || "";
|
|
ksCampaignId = res.query["ksCampaignId"] || "";
|
|
ksUnitId = res.query["ksUnitId"] || "";
|
|
ksCreativeId = res.query["ksCreativeId"] || "";
|
|
ksChannel = res.query["ksChannel"] || "";
|
|
ksSiteAccountId = res.query["ksSiteAccountId"] || "";
|
|
ksPageId = res.query["ksPageId"] || "";
|
|
}
|
|
console.log("=========创游SDK场景值获取成功1", sceneGet);
|
|
backCb(sceneGet);
|
|
}
|
|
const finishCb = () => {
|
|
count--;
|
|
console.log("=========创游SDKFinishCb", count);
|
|
if (count > 0)
|
|
return;
|
|
//一些sdk的存档数据
|
|
self.cyStoreDataDeal();
|
|
//拿配置
|
|
window["wx"].request(
|
|
{
|
|
url: "https://liehujt.com//api/campaign/strategy-new-info/" + self.appKey + "/" + self.version,
|
|
success(res) {
|
|
cb(res.data);
|
|
},
|
|
fail(err) {
|
|
console.log("=========创游SDK策略参数获取失败", err)
|
|
cb(null);
|
|
}
|
|
}
|
|
)
|
|
|
|
}
|
|
loginCb((code:any) => {
|
|
loginCode = code;
|
|
let url = "https://log.liehujt.com/login?appkey=" + self.appKey + "&code=" + loginCode;
|
|
if (clue_token != "") {//抖音跳转微信
|
|
url = url + "&clue_token=" + clue_token + "&project_id=___&promotion_id=___&mid1=___&mid2=___&mid3=___&mid4=___&mid5=___" + "&req_id=" + req_id + "&advertiser_id=" + ad_id + "&clickid=" + clickid;
|
|
}
|
|
if (ksCampaignId != "")//快手跳转微信
|
|
{
|
|
url = url + "&callback=" + callback + "&ksCampaignId=" + ksCampaignId + "&ksUnitId=" + ksUnitId + "&ksCreativeId=" + ksCreativeId + "&ksChannel=" + ksChannel + "&ksSiteAccountId=" + ksSiteAccountId + "&ksPageId=" + ksPageId;
|
|
}
|
|
//登录
|
|
window["wx"].request(
|
|
{
|
|
method: "GET",
|
|
url: url,
|
|
success(res) {
|
|
console.log("=========创游SDK登录返回", res);
|
|
self.openId = res.data.openid || "";
|
|
if (self.isABTest) {
|
|
self.version = res.data.version || self.version;
|
|
} else {
|
|
self.version = self.version;
|
|
}
|
|
console.log("=========创游SDK登录成功", self.openId, self.version);
|
|
finishCb();
|
|
},
|
|
fail(err:any) {
|
|
console.log("=========创游SDK登录失败", err)
|
|
self.openId = "";
|
|
self.version = self.version;
|
|
finishCb();
|
|
}
|
|
}
|
|
)
|
|
})
|
|
getSceneCb((sceneGet:any) => {
|
|
scene = sceneGet;
|
|
self.scene = scene;
|
|
console.log("=========创游SDK场景值获取成功2", self.scene);
|
|
finishCb();
|
|
})
|
|
} else {
|
|
this.scene = 0; //默认场景值为0,等于web端
|
|
this.openId = localStorage.getItem("cy_sdk_web_openid") as string || "";
|
|
if (this.openId == null || this.openId == "") {
|
|
this.openId = "web_" + Date.now(); //web端默认openId为当前时间戳
|
|
localStorage.setItem("cy_sdk_web_openid", this.openId);
|
|
console.log("=========创游SDK web端登录成功(新用户)", this.openId);
|
|
} else {
|
|
console.log("=========创游SDK web端登录成功(老用户)", this.openId);
|
|
}
|
|
this.cyStoreDataDeal();
|
|
if (window["wx"]) {
|
|
self.trackEvent_uma("launch", { res: self.launchRes });
|
|
}
|
|
console.log("获取策略", this.appKey, this.version);
|
|
//拿配置
|
|
fetch("https://liehujt.com//api/campaign/strategy-new-info/" + this.appKey + "/" + this.version).then((response: Response) => {
|
|
// fetch("https://liehujt.com//api/campaign/strategy-info/" + this.appKey).then((response: Response) => {
|
|
return response.text()
|
|
}).then((value) => {
|
|
cb(JSON.parse(value))
|
|
}).catch((err) => {
|
|
console.log("创游策略参数获取失败", err)
|
|
cb(null);
|
|
})
|
|
}
|
|
}
|
|
|
|
//#endregion
|
|
|
|
//#region sdk存档
|
|
/**cySDK存档数据处理 */
|
|
private static cyStoreDataDeal() {
|
|
console.log("=========创游SDK存档数据处理");
|
|
const customData = new cyStoreData(this.version, this.getNowDay())
|
|
const localData = localStorage.getItem("cy_sdk_data");
|
|
this.storageData = localData ? JSON.parse(localData) : null;
|
|
if (!this.storageData) {
|
|
this.storageData = customData;
|
|
this.saveCyStoreData();
|
|
} else {
|
|
this.storageData.isNew = false;
|
|
for (let key in customData) {
|
|
if (!this.storageData.hasOwnProperty(key)) {
|
|
this.storageData[key] = customData[key];
|
|
}
|
|
}
|
|
this.saveCyStoreData();
|
|
}
|
|
}
|
|
private static saveCyStoreData() {
|
|
localStorage.setItem("cy_sdk_data", JSON.stringify(this.storageData));
|
|
}
|
|
//#endregion
|
|
|
|
//#region 关卡埋点
|
|
static levelStartTime = 0; //关卡开始时间
|
|
/**关卡开始
|
|
* @param level_type 关卡入口("normal"表示普通关卡,为后续拓展预留位置)
|
|
* @param level_name 关卡名称(全局唯一)
|
|
* @param level_index 关卡索引(全局唯一,与level_name一一对应)
|
|
*/
|
|
static onLevelStart(level_type: string, level_name: string, level_index: number) {
|
|
this.trackEvent({
|
|
event: "level_start",
|
|
level_type: level_type,
|
|
level_name: level_name,
|
|
level_index: level_index,
|
|
})
|
|
this.levelStartTime = new Date().getTime();
|
|
this.trackEvent_uma("startStage", { type: level_type, level: level_index });
|
|
|
|
}
|
|
/**关卡成功
|
|
* @param level_type 关卡入口("normal"表示普通关卡,为后续拓展预留位置)
|
|
* @param level_name 关卡名称(全局唯一)
|
|
* @param level_index 关卡索引(全局唯一,与level_name一一对应)
|
|
* @param dur 关卡耗时(单位:秒)
|
|
*/
|
|
static onLevelSuccess(level_type: string, level_name: string, level_index: number) {
|
|
let dur = Math.ceil((new Date().getTime() - this.levelStartTime) / 1000);
|
|
this.trackEvent({
|
|
event: "level_success",
|
|
level_type: level_type,
|
|
level_name: level_name,
|
|
level_index: level_index,
|
|
dur: dur
|
|
});
|
|
this.trackEvent_uma("passStage", { type: level_type, level: level_index });
|
|
|
|
}
|
|
/**关卡失败
|
|
* @param level_type 关卡类型("normal"表示普通关卡)
|
|
* @param level_name 关卡名称(全局唯一)
|
|
* @param level_index 关卡索引(全局唯一,与level_name一一对应)
|
|
* @param dur 关卡耗时(单位:秒)
|
|
*/
|
|
static onLevelFail(level_type: string, level_name: string, level_index: number) {
|
|
let dur = Math.ceil((new Date().getTime() - this.levelStartTime) / 1000);
|
|
this.trackEvent({
|
|
event: "level_fail",
|
|
level_type: level_type,
|
|
level_name: level_name,
|
|
level_index: level_index,
|
|
dur: dur
|
|
});
|
|
this.trackEvent_uma("failStage", { type: level_type, level: level_index });
|
|
|
|
}
|
|
/**广告请求
|
|
* @param mode 游戏模式("level"表示关卡模式,为后续拓展预留位置)
|
|
* @param mode_type 对应模式的类型(例如"normal"表示普通关卡)
|
|
* @param mode_index 对应模式的索引(例如:mode= "level" ,mode_type ="normal"时,等于关卡游戏模式,normal类型,的level_index,方便做关卡分析看板用)
|
|
* @param why 广告原因(例如:"tips")
|
|
*/
|
|
static onAdRequest(mode: string, mode_type: string, mode_index: number, why: string) {
|
|
this.trackEvent({
|
|
event: "ad_request",
|
|
mode: mode,
|
|
mode_type: mode_type,
|
|
mode_index: mode_index,
|
|
why: why,
|
|
});
|
|
this.trackEvent_uma("videoAdRequest", { type: why, mode: mode_type, level: mode_index });
|
|
this.getIaaInfo(mode_type, why, false);
|
|
|
|
}
|
|
/**广告取消
|
|
* @param mode 游戏模式("level"表示关卡模式,为后续拓展预留位置)
|
|
* @param mode_type 对应模式的类型(例如"normal"表示普通关卡)
|
|
* @param mode_index 对应模式的索引(例如:mode= "level" ,mode_type ="normal"时,等于关卡游戏模式,normal类型,的level_index,方便做关卡分析看板用)
|
|
* @param why 广告原因(例如:"tips")
|
|
*/
|
|
static onAdCancel(mode: string, mode_type: string, mode_index: number, why: string) {
|
|
this.trackEvent({
|
|
event: "ad_cancel",
|
|
mode: mode,
|
|
mode_type: mode_type,
|
|
mode_index: mode_index,
|
|
why: why,
|
|
});
|
|
this.trackEvent_uma("videoAdCancel", { type: why, mode: mode_type, level: mode_index });
|
|
|
|
}
|
|
/**广告完成
|
|
* @param mode 游戏模式("level"表示关卡模式,为后续拓展预留位置)
|
|
* @param mode_type 对应模式的类型(例如"normal"表示普通关卡)
|
|
* @param mode_index 对应模式的索引(例如:mode= "level" ,mode_type ="normal"时,等于关卡游戏模式,normal类型,的level_index,方便做关卡分析看板用)
|
|
* @param why 广告原因(例如:"tips")
|
|
*/
|
|
static onAdFinish(mode: string, mode_type: string, mode_index: number, why: string) {
|
|
this.trackEvent({
|
|
event: "ad_finish",
|
|
mode: mode,
|
|
mode_type: mode_type,
|
|
mode_index: mode_index,
|
|
why: why,
|
|
});
|
|
this.trackEvent_uma("videoAd", { type: why, mode: mode_type, level: mode_index });
|
|
this.getIaaInfo(mode_type, why, true);
|
|
|
|
}
|
|
//#endregion
|
|
|
|
//#region 时间获取接口
|
|
static getNowTime() {
|
|
return new Date().getTime() - new Date().getTimezoneOffset() * 60000;
|
|
}
|
|
static getNowDay() {
|
|
return Math.floor(this.getNowTime() / 86400000);
|
|
}
|
|
static getNowDateStr() {
|
|
const now = new Date(this.getNowTime());
|
|
const year = now.getFullYear();
|
|
const month = now.getMonth() + 1;
|
|
const day = now.getDate();
|
|
return year + "-" + (month < 10 ? "0" + month : month) + "-" + (day < 10 ? "0" + day : day);
|
|
}
|
|
//#endregion
|
|
|
|
//#region 加密接口
|
|
static encrypted(encryptedData, iv, cb) {
|
|
console.log("=========创游SDK上传用户加密数据");
|
|
this.trackEvent({ event: "encrypted_data", encryptedData: encryptedData, iv: iv },
|
|
(res) => {
|
|
console.log("=========创游SDK用户加密数据返回", res);
|
|
if (res.data) {
|
|
cb(res.data);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
//#endregion
|
|
//#region iaa插件
|
|
static iaaData = {
|
|
isOn: false,
|
|
value: -1,
|
|
today_play_duration: -1,
|
|
weekly_login_cnt: -1,
|
|
continuous_login_days: -1,
|
|
value_exposure: -1, // 新增,本周期曝光次数,仅'labelId=='iaa_feature_v2'返回
|
|
};
|
|
static getIaaInfo(scene: string, type: string, isSuccess: boolean) {
|
|
let value: number;
|
|
let successCount: number;
|
|
for (let i = 0; i < this.storageData.videoCount.length; i++) {
|
|
let info = this.storageData.videoCount[i];
|
|
if (info.scene == scene && info.type == type) {
|
|
if (isSuccess) {
|
|
info.successTime++;
|
|
} else {
|
|
info.requestTime++;
|
|
}
|
|
value = info.requestTime;
|
|
successCount = info.successTime;
|
|
break;
|
|
}
|
|
}
|
|
if (!value) {
|
|
let info = new VideoCountInfo(scene, type);
|
|
if (isSuccess) {
|
|
info.successTime = 1;
|
|
info.requestTime = 1;
|
|
} else {
|
|
info.successTime = 0;
|
|
info.requestTime = 1;
|
|
}
|
|
value = info.requestTime;
|
|
successCount = info.successTime;
|
|
this.storageData.videoCount.push(info);
|
|
}
|
|
console.log("iaa广告次数计算,scene:", scene, "type:", type, "value:", value, "successCount:", successCount);
|
|
this.saveCyStoreData();
|
|
if (!isSuccess) return;
|
|
if (!window["miniGameCommon"] || !window["miniGameCommon"].getUserLabel) {
|
|
console.warn("=========创游SDK iaa插件未接入,无法获取iaa信息");
|
|
return;
|
|
}
|
|
const data = {
|
|
gift_scene: scene,//广告触发场景(如玩法单局内,局外签到,局外数值养成等)
|
|
gift_name: type,//广告设计点(如单局内的复活卡、刷新卡,单局外养成资源等)
|
|
gift_value: value,//游戏内用户点击该广告位的次数(指点击按钮的次数、无论用户是否成功拉起广告,都视为1次点击)
|
|
gift_value_success: successCount//游戏内用户成功看完广告的次数
|
|
}
|
|
const self = this;
|
|
//30秒后执行
|
|
setTimeout(() => {
|
|
window["miniGameCommon"].getUserLabel({
|
|
reportData: JSON.stringify(data),// reportdata是字符串,注意不要传入object
|
|
labelId: 'iaa_feature_v2' // 注意labelid必填 iaa_feature,若传入其他labelId会报错
|
|
}).then((res) => {
|
|
console.log("=========创游SDK iaa2.0插件获取信息成功", res);
|
|
self.trackEvent_uma("iaa2First", { res: res });
|
|
if (res.encryptedData) {
|
|
self.encrypted(res.encryptedData, res.iv, (data) => {
|
|
self.iaaData.isOn = true;
|
|
self.iaaData.value = data.value;
|
|
self.iaaData.today_play_duration = data.today_play_duration;
|
|
self.iaaData.weekly_login_cnt = data.weekly_login_cnt;
|
|
self.iaaData.continuous_login_days = data.continuous_login_days;
|
|
self.iaaData.value_exposure = data.value_exposure;
|
|
self.trackEvent_uma("iaa2Second");
|
|
});
|
|
}
|
|
}).catch((err) => {
|
|
console.log("=========创游SDK iaa2.0插件获取失败", err);
|
|
});
|
|
}, 30 * 1000);
|
|
|
|
}
|
|
//#endregion
|
|
}
|
|
|
|
class VideoCountInfo {
|
|
scene: string;
|
|
type: string;
|
|
requestTime: number = 0;
|
|
successTime: number = 0;
|
|
constructor(scene, type) {
|
|
this.scene = scene;
|
|
this.type = type;
|
|
this.requestTime = 0;
|
|
this.successTime = 0;
|
|
}
|
|
}
|
|
class cyStoreData {
|
|
version: string;
|
|
playTime: number;
|
|
isNew: boolean;
|
|
firstLoginDay: number;
|
|
videoCount: VideoCountInfo[];
|
|
firstLoginDateStr: string;
|
|
constructor(version, firstDay) {
|
|
this.version = version;
|
|
this.playTime = 0;
|
|
this.isNew = true;
|
|
this.firstLoginDay = firstDay;
|
|
this.videoCount = [];
|
|
this.firstLoginDateStr = CySDK.getNowDateStr();
|
|
}
|
|
}
|