|
@@ -0,0 +1,373 @@
|
|
|
+//超级订阅价格计算
|
|
|
+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": 9
|
|
|
+ },
|
|
|
+ "new": {
|
|
|
+ "month": {
|
|
|
+ "oneProvince_allBuyerClass": 3800,
|
|
|
+ "allProvince_allBuyerClass": 59900
|
|
|
+ },
|
|
|
+ "year": {
|
|
|
+ "oneProvince_allBuyerClass": 38800,
|
|
|
+ "allProvince_allBuyerClass": 599900
|
|
|
+ },
|
|
|
+ "provincePrice": 3800,
|
|
|
+ "provinceMaxCount": 15,
|
|
|
+ "monthMaxCount": 9
|
|
|
+ },
|
|
|
+ "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;
|
|
|
+ //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 = [1, 2]) { //升级计价 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] / 100; //全国1行业套餐
|
|
|
+ if (vipbuyset.buyerclasscount === 0) return this.getSetMealPrice_old(0, 0, t[1]) * t[0] / 100; //全国全行业套餐
|
|
|
+ return this.getSetMealPrice_old(0, vipbuyset.buyerclasscount, t[1]) * t[0] / 100 //全国多行业套餐
|
|
|
+ }
|
|
|
+ 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 / 100
|
|
|
+ } else {//新版大会员价格计算
|
|
|
+ let pCount = vipbuyset.areacount
|
|
|
+ let count = t[0]
|
|
|
+ if (pCount > this.PriceRule.new.provinceMaxCount) {
|
|
|
+ pCount = -1
|
|
|
+ }
|
|
|
+ if (pCount === -1) {
|
|
|
+ pCount = 0
|
|
|
+ }
|
|
|
+ //当选择月份大于 按照全年计算
|
|
|
+ if (t[0] > this.PriceRule.new.monthMaxCount && t[1] === 2) { //月份十个月以上价格一样
|
|
|
+ count = 10
|
|
|
+ }
|
|
|
+ return this.getSetMealPrice_new(pCount, t[1]) * 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])
|
|
|
+ */
|
|
|
+
|
|
|
+
|