//超级订阅价格计算 class Buyset { constructor(areacount, cityArr = [], buyerCount, upgrade) { this.areacount = areacount; //省份数量 -1 全国 this.citys = cityArr; //购买的城市数组 this.buyerclasscount = buyerCount; //行业数量 this.upgrade = upgrade; //是否是升级版的超级订阅 } } var Calculation = { PriceRule: { "old": { "month": { "oneCity_oneBuyerClass": 580, "oneCity_allBuyerClass": 1800, "oneProvince_oneBuyerClass": 1180, "oneProvince_allBuyerClass": 3800, "allProvince_oneBuyerClass": 11800, "allProvince_allBuyerClass": 38800 }, "year": { "oneCity_oneBuyerClass": 5800, "oneCity_allBuyerClass": 18000, "oneProvince_oneBuyerClass": 11800, "oneProvince_allBuyerClass": 38000, "allProvince_oneBuyerClass": 118000, "allProvince_allBuyerClass": 388000 }, "cityPrice": 580, "provincePrice": 1180, "buyerClassPrice": 580, "cityMaxCount": 2, "provinceMaxCount": 9, "buyerClassMaxCount": 3, "monthMaxCount": 10 }, "new": { "month": { "oneProvince_allBuyerClass": 3800, "allProvince_allBuyerClass": 59900 }, "quarter": {"oneProvince_allBuyerClass": 9900, "allProvince_allBuyerClass": 149900}, "year": { "oneProvince_allBuyerClass": 38000, "allProvince_allBuyerClass": 599900 }, "provincePrice": 3800, "provinceMaxCount": 15, "monthMaxCount": 10 }, "discount": 1 } , //套餐价格表 IsTrial: true, //是否时试用用户 OldBuyset: new Buyset(),//用户之前套餐 EndTime: 0, //会员到期时间 RenewList: [], Init: function (isTrial, oldBuyset, renewList, price, endTime) { //首次购买时oldBuyset传入undefined this.IsTrial = isTrial; this.OldBuyset = oldBuyset; this.RenewList = renewList; this.EndTime = endTime; if (price) this.PriceRule = price; }, Check: function (tmpBuyset, oldBuyset) { //校验是否合法 if (!oldBuyset) { oldBuyset = this.OldBuyset; } if (!oldBuyset) { return true } if (oldBuyset.upgrade === 1) { //升级后省份数量必须大于升级前的 return (tmpBuyset.areacount === -1 && oldBuyset.areacount !== -1) || tmpBuyset.areacount >= oldBuyset.areacount; } else { return tmpBuyset.areacount === -1 || tmpBuyset.areacount >= oldBuyset.areacount + oldBuyset.citys.length; } }, /* 首次购买 或 单独续费 param newBuyset 选择套餐 [*续费时传入undefined] buyTime [数量,单位(1:年,2月)] return 价格 */ GetTotal: function (newBuyset, buyTime = [1, 2]) { //newBuyset 用户选择的套餐; if (newBuyset) {//首次购买 return this.getBuysetPrice(newBuyset, buyTime) } return this.getBuysetPrice(this.OldBuyset, buyTime) //续费 }, /* 套餐升级 param newBuyset 选择套餐 buyTime [数量,单位(1:年,2月)] return 价格、计价清单 */ GetUpgradeDetail: function (newBuyset = new Buyset(), buyTime = []) { //升级计价 time[数量,单位(1:年,2月)] let subtotail = []; //计价清单 let final_price = 0; //最终计算价格 let nowEndTime = this.EndTime; //续费升级价格 if (this.RenewList.length > 0) { for (var i = this.RenewList.length - 1; i >= 0; i--) { let thisBuyset = this.RenewList[i].o_buyset; let thisStartTime = this.RenewList[i].l_validtime; let old = new Buyset(thisBuyset.areacount, thisBuyset.newcitys, thisBuyset.buyerclasscount, this.upgrade || 0) var this_price = this.GetSubPrice(old, newBuyset, thisStartTime, nowEndTime); if (this_price < 0) { return [-2, []] //已续费升级异常 } //清单数组 subtotail.push({ "buyset": old, "startTime": thisStartTime, "endTime": nowEndTime, "price": this_price, "type": 1 }); final_price = this.numAdd(final_price, this_price); nowEndTime = thisStartTime; } } //现在使用升级价格 let now_price = this.GetSubPrice(this.OldBuyset, newBuyset, new Date().getTime() / 1000, nowEndTime); if (now_price < 0) { return [-2, []] //当前套餐升级异常 } subtotail.push({ //清单数组 "buyset": this.OldBuyset, "startTime": new Date().getTime() / 1000, "endTime": nowEndTime, "price": now_price, "type": 0 }); final_price = this.numAdd(final_price, now_price); //新增续费升级价格 if (buyTime.length === 2) { let thisPrice = this.getBuysetPrice(newBuyset, buyTime); if (thisPrice < 0) { return [-2, []] //本次升级中续费时间异常 } console.log(newBuyset, buyTime, "额外升级费用", thisPrice); final_price = this.numAdd(final_price, thisPrice); subtotail.push({//清单数组 "buyset": newBuyset, "startTime": this.EndTime, "endTime": this.getVipEndDate(buyTime[1], buyTime[0]), "price": thisPrice, "type": 2 }); } return [final_price, subtotail] }, GetSubPrice: function (oldBuyset, newBuyset, start, end) { //升级-计算套餐差价 if (!this.Check(newBuyset, oldBuyset)) { console.error("当前所选套餐等级低于已购买套餐") return -1 } let beforePrice = 0; let newPrice = 0; let t = this.getDateSub(start, end); if (t[1] !== 0) {//月 beforePrice = this.numAdd(beforePrice, this.getBuysetPrice(oldBuyset, [t[1], 2])) newPrice = this.numAdd(newPrice, this.getBuysetPrice(newBuyset, [t[1], 2])) } if (t[0] !== 0) {//年 beforePrice = this.numAdd(beforePrice, this.getBuysetPrice(oldBuyset, [t[0], 1])) newPrice = this.numAdd(newPrice, this.getBuysetPrice(newBuyset, [t[0], 1])) } console.log("old ", oldBuyset, " \n new ", newBuyset, " \n 相差", t[0], "年 ", t[1], "个月\n price:", newPrice, "-", beforePrice, "=", (newPrice * 10000 - beforePrice * 10000) / 10000); return (newPrice * 10000 - beforePrice * 10000) / 10000 }, getBuysetPrice: function (vipbuyset = new Buyset(), t) { //获取套餐价格 if (t.length !== 2) { console.error("选择时间格式异常") return -1 } if (vipbuyset.upgrade === 0) { //旧版大会员价格计算 if (t[0] > this.PriceRule.old.monthMaxCount && t[1] === 2) t[0] = 10;//月份十个月以上价格一样 if (vipbuyset.areacount === -1) {//计算全国套餐价格 if (vipbuyset.buyerclasscount === 1) return this.getSetMealPrice_old(0, 1, t[1]) * t[0]; //全国1行业套餐 if (vipbuyset.buyerclasscount === 0) return this.getSetMealPrice_old(0, 0, t[1]) * t[0]; //全国全行业套餐 return this.getSetMealPrice_old(0, vipbuyset.buyerclasscount, t[1]) * t[0] //全国多行业套餐 } let final_price = 0;//计算省份价格 for (var i in vipbuyset.citys) { var thisPrice = 0; if (vipbuyset.citys[i] === 1) {//单城市 thisPrice = this.getSetMealPrice_old(2, vipbuyset.buyerclasscount, t[1]) * t[0]; } else {//多城市 if (vipbuyset.buyerclasscount === 0 || vipbuyset.buyerclasscount === 1) {//多城市 单行业 if (vipbuyset.citys[i] > this.PriceRule.old.cityMaxCount) { vipbuyset.areacount++; } else { thisPrice = vipbuyset.citys[i] * this.getSetMealPrice_old(2, vipbuyset.buyerclasscount, t[1]) * t[0]; } } else {//多城市 多行业 if (vipbuyset.citys[i] > this.PriceRule.old.cityMaxCount) { vipbuyset.areacount++; } else { thisPrice = this.getSetMealPrice_old(2, vipbuyset.buyerclasscount, t[1]) * vipbuyset.citys[i] * t[0]; } } } final_price += thisPrice; } final_price += vipbuyset.areacount * this.getSetMealPrice_old(1, vipbuyset.buyerclasscount, t[1]) * t[0]; return final_price } else {//新版大会员价格计算 let pCount = vipbuyset.areacount let count = t[0] let unit = t[1] if (pCount > this.PriceRule.new.provinceMaxCount) { pCount = -1 } if (pCount === -1) { pCount = 0 } if (pCount !== 0) { //购买省份计算 省份10个月价格和11个月价格一样 //当选择月份大于 按照全年计算 if (t[0] > this.PriceRule.new.monthMaxCount && t[1] === 2) count = 10//月份十个月以上价格一样 } else { //购买全国计算 全国10个月价格和11个月价格不一样 //当选择月份大于 按照全年计算 if (t[0] > this.PriceRule.new.monthMaxCount && unit === 2) { //月份十个月以上价格一样 count = 1 unit = 1 } } return this.getSetMealPrice_new(pCount, unit) * count //全国1行业套餐 } }, getSetMealPrice_old: function (c, iCount, u) { //旧套餐价格计算 var t = u === 2; //是否是月单位 switch (c) { case 0: if (iCount === -1) { if (t) return this.PriceRule.old.month.allProvince_allBuyerClass; //1月全国全行业 return this.PriceRule.old.year.allProvince_allBuyerClass; //1年全国全行业 } else { if (t) return this.PriceRule.old.month.allProvince_oneBuyerClass * iCount; //1月全国icount个行业 return this.PriceRule.old.year.allProvince_oneBuyerClass * iCount; //1年全国icount个行业 } case 1: if (iCount === -1) { if (t) return this.PriceRule.old.month.oneProvince_allBuyerClass; //1月1省全行业 return this.PriceRule.old.year.oneProvince_allBuyerClass //1年1省全行业 } else { if (t) return this.PriceRule.old.month.oneProvince_oneBuyerClass * iCount; //1月1省icount个行业 return this.PriceRule.old.year.oneProvince_oneBuyerClass * iCount //1年1省icount个行业 } default: if (iCount === -1) { if (t) return this.PriceRule.old.month.oneCity_allBuyerClass; //1月1市全行业 return this.PriceRule.old.year.oneCity_allBuyerClass //1年1市全行业 } else { if (t) return this.PriceRule.old.month.oneCity_oneBuyerClass * iCount; //1月1市icount个行业 return this.PriceRule.old.year.oneCity_oneBuyerClass * iCount //1年1市icount个行业 } } }, getSetMealPrice_new: function (p, u) { //新套餐价格计算 p省份格式,u时间单位 let t = u === 2 //是否是月单位 switch (p) { case 0: if (t) { return this.PriceRule.new.month.allProvince_allBuyerClass // 1月全国全行业 } return this.PriceRule.new.year.allProvince_allBuyerClass //1年全国全行业 default : if (t) { return this.PriceRule.new.month.oneProvince_allBuyerClass * p //1月p省全行业 } return this.PriceRule.new.year.oneProvince_allBuyerClass * p //1年p省全行业 } }, getDateSub: function (start, end) { //计算时间间隔差 [年个数, 月个数] let startTime = new Date(start * 1000); let endTime = new Date(end * 1000); let startYear = startTime.getFullYear(); let startMonth = startTime.getMonth(); let startDay = startTime.getDate(); let endYear = endTime.getFullYear(); let endMonth = endTime.getMonth(); let endDay = endTime.getDate(); let finalMonthNum = 0; let finalYearNum = 0; if (startYear === endYear) { if (startMonth === endMonth) { finalMonthNum = 1; } else { if (endDay > startDay) { finalMonthNum = endMonth - startMonth + 1; } else { finalMonthNum = endMonth - startMonth; } } } else { if (startMonth === endMonth) { if (endDay <= startDay) { finalMonthNum = (endYear - startYear) * 12; } else { finalMonthNum = (endYear - startYear) * 12 + 1; } } else if (endMonth > startMonth) { if (endDay <= startDay) { finalMonthNum = (endYear - startYear) * 12 + (endMonth - startMonth); } else { finalMonthNum = (endYear - startYear) * 12 + (endMonth - startMonth) + 1; } } else { if (endDay <= startDay) { finalMonthNum = (endYear - startYear - 1) * 12 + (12 - startMonth + endMonth); } else { finalMonthNum = (endYear - startYear - 1) * 12 + (12 - startMonth + endMonth) + 1; } } finalYearNum = Math.floor(finalMonthNum / 12); if (finalYearNum > 0) { finalMonthNum = finalMonthNum - finalYearNum * 12 } } return [finalYearNum, finalMonthNum] }, getVipEndDate: function (flag, value) { let EndTime = new Date(this.EndTime * 1000); let startDay = EndTime.getDate(); let yearNum = EndTime.getFullYear(); let monthNum = EndTime.getMonth(); if (flag === 1) {//将年转换成月 //年 yearNum += value; } else { //月 if (monthNum + value > 11) { monthNum = monthNum + value - 12; yearNum++ } else { monthNum += value } } //获取当月最后一天 let lastDay = new Date(yearNum, monthNum + 1, 0).getDate(); if (startDay < lastDay) { return new Date(yearNum, monthNum, startDay, 23, 59, 59).getTime() / 1000; } else { return new Date(yearNum, monthNum, lastDay, 23, 59, 59).getTime() / 1000; } }, numAdd: function (num1, num2) { return (num1 * 10000 + num2 * 10000) / 10000 } } /* //首次购买 Calculation.Init(false, undefined, [], 0) Calculation.GetTotal(new Buyset(15, [], -1, 1), [1, 2]) //首次购买 //续费 Calculation.Init(false, new Buyset(1, [1, 2], 3, 0)) Calculation.GetTotal(undefined, [1, 2]) //升级 //初始化 非试用用户 已经购买了 1个省份 两个省份【1个城市、两个城市】 3个行业 非升级版超级订阅 Calculation.Init(false, new Buyset(1, [1, 2], 3, 0), [{ "l_validtime": 1622476799, "o_buyset": { "areacount": 3, "buyerclasscount": -1, "newcitys": [] } }], undefined, 1625068799) //计算价格 升级为 15个省份 并续费一个月价格 Calculation.GetUpgradeDetail(new Buyset(15, [], -1, 1), [1, 2]) */