price.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. //超级订阅价格计算
  2. class Buyset {
  3. constructor(areacount, cityArr = [], buyerCount, upgrade) {
  4. this.areacount = areacount; //省份数量 -1 全国
  5. this.citys = cityArr; //购买的城市数组
  6. this.buyerclasscount = buyerCount; //行业数量
  7. this.upgrade = upgrade; //是否是升级版的超级订阅
  8. }
  9. }
  10. var Calculation = {
  11. PriceRule: {
  12. "old": {
  13. "month": {
  14. "oneCity_oneBuyerClass": 580,
  15. "oneCity_allBuyerClass": 1800,
  16. "oneProvince_oneBuyerClass": 1180,
  17. "oneProvince_allBuyerClass": 3800,
  18. "allProvince_oneBuyerClass": 11800,
  19. "allProvince_allBuyerClass": 38800
  20. },
  21. "year": {
  22. "oneCity_oneBuyerClass": 5800,
  23. "oneCity_allBuyerClass": 18000,
  24. "oneProvince_oneBuyerClass": 11800,
  25. "oneProvince_allBuyerClass": 38000,
  26. "allProvince_oneBuyerClass": 118000,
  27. "allProvince_allBuyerClass": 388000
  28. },
  29. "cityPrice": 580,
  30. "provincePrice": 1180,
  31. "buyerClassPrice": 580,
  32. "cityMaxCount": 2,
  33. "provinceMaxCount": 9,
  34. "buyerClassMaxCount": 3,
  35. "monthMaxCount": 10
  36. },
  37. "new": {
  38. "month": {
  39. "oneProvince_allBuyerClass": 3800,
  40. "allProvince_allBuyerClass": 59900
  41. },
  42. "quarter": {"oneProvince_allBuyerClass": 9900, "allProvince_allBuyerClass": 149900},
  43. "year": {
  44. "oneProvince_allBuyerClass": 38000,
  45. "allProvince_allBuyerClass": 599900
  46. },
  47. "provincePrice": 3800,
  48. "provinceMaxCount": 15,
  49. "monthMaxCount": 10
  50. },
  51. "discount": 1
  52. }
  53. , //套餐价格表
  54. IsTrial: true, //是否时试用用户
  55. OldBuyset: new Buyset(),//用户之前套餐
  56. EndTime: 0, //会员到期时间
  57. RenewList: [],
  58. Init: function (isTrial, oldBuyset, renewList, price, endTime) { //首次购买时oldBuyset传入undefined
  59. this.IsTrial = isTrial;
  60. this.OldBuyset = oldBuyset;
  61. this.RenewList = renewList;
  62. this.EndTime = endTime;
  63. if (price) this.PriceRule = price;
  64. },
  65. Check: function (tmpBuyset, oldBuyset) { //校验是否合法
  66. if (!oldBuyset) {
  67. oldBuyset = this.OldBuyset;
  68. }
  69. if (!oldBuyset) {
  70. return true
  71. }
  72. if (oldBuyset.upgrade === 1) { //升级后省份数量必须大于升级前的
  73. return (tmpBuyset.areacount === -1 && oldBuyset.areacount !== -1) || tmpBuyset.areacount >= oldBuyset.areacount;
  74. } else {
  75. return tmpBuyset.areacount === -1 || tmpBuyset.areacount >= oldBuyset.areacount + oldBuyset.citys.length;
  76. }
  77. },
  78. /*
  79. 首次购买 或 单独续费
  80. param newBuyset 选择套餐 [*续费时传入undefined]
  81. buyTime [数量,单位(1:年,2月)]
  82. return 价格
  83. */
  84. GetTotal: function (newBuyset, buyTime = [1, 2]) { //newBuyset 用户选择的套餐;
  85. if (newBuyset) {//首次购买
  86. return this.getBuysetPrice(newBuyset, buyTime)
  87. }
  88. return this.getBuysetPrice(this.OldBuyset, buyTime) //续费
  89. },
  90. /*
  91. 套餐升级
  92. param newBuyset 选择套餐
  93. buyTime [数量,单位(1:年,2月)]
  94. return 价格、计价清单
  95. */
  96. GetUpgradeDetail: function (newBuyset = new Buyset(), buyTime = []) { //升级计价 time[数量,单位(1:年,2月)]
  97. let subtotail = []; //计价清单
  98. let final_price = 0; //最终计算价格
  99. let nowEndTime = this.EndTime;
  100. //续费升级价格
  101. if (this.RenewList.length > 0) {
  102. for (var i = this.RenewList.length - 1; i >= 0; i--) {
  103. let thisBuyset = this.RenewList[i].o_buyset;
  104. let thisStartTime = this.RenewList[i].l_validtime;
  105. let old = new Buyset(thisBuyset.areacount, thisBuyset.newcitys, thisBuyset.buyerclasscount, this.upgrade || 0)
  106. var this_price = this.GetSubPrice(old, newBuyset, thisStartTime, nowEndTime);
  107. if (this_price < 0) {
  108. return [-2, []] //已续费升级异常
  109. }
  110. //清单数组
  111. subtotail.push({
  112. "buyset": old,
  113. "startTime": thisStartTime,
  114. "endTime": nowEndTime,
  115. "price": this_price,
  116. "type": 1
  117. });
  118. final_price = this.numAdd(final_price, this_price);
  119. nowEndTime = thisStartTime;
  120. }
  121. }
  122. //现在使用升级价格
  123. let now_price = this.GetSubPrice(this.OldBuyset, newBuyset, new Date().getTime() / 1000, nowEndTime);
  124. if (now_price < 0) {
  125. return [-2, []] //当前套餐升级异常
  126. }
  127. subtotail.push({ //清单数组
  128. "buyset": this.OldBuyset,
  129. "startTime": new Date().getTime() / 1000,
  130. "endTime": nowEndTime,
  131. "price": now_price,
  132. "type": 0
  133. });
  134. final_price = this.numAdd(final_price, now_price);
  135. //新增续费升级价格
  136. if (buyTime.length === 2) {
  137. let thisPrice = this.getBuysetPrice(newBuyset, buyTime);
  138. if (thisPrice < 0) {
  139. return [-2, []] //本次升级中续费时间异常
  140. }
  141. console.log(newBuyset, buyTime, "额外升级费用", thisPrice);
  142. final_price = this.numAdd(final_price, thisPrice);
  143. subtotail.push({//清单数组
  144. "buyset": newBuyset,
  145. "startTime": this.EndTime,
  146. "endTime": this.getVipEndDate(buyTime[1], buyTime[0]),
  147. "price": thisPrice,
  148. "type": 2
  149. });
  150. }
  151. return [final_price, subtotail]
  152. },
  153. GetSubPrice: function (oldBuyset, newBuyset, start, end) { //升级-计算套餐差价
  154. if (!this.Check(newBuyset, oldBuyset)) {
  155. console.error("当前所选套餐等级低于已购买套餐")
  156. return -1
  157. }
  158. let beforePrice = 0;
  159. let newPrice = 0;
  160. let t = this.getDateSub(start, end);
  161. if (t[1] !== 0) {//月
  162. beforePrice = this.numAdd(beforePrice, this.getBuysetPrice(oldBuyset, [t[1], 2]))
  163. newPrice = this.numAdd(newPrice, this.getBuysetPrice(newBuyset, [t[1], 2]))
  164. }
  165. if (t[0] !== 0) {//年
  166. beforePrice = this.numAdd(beforePrice, this.getBuysetPrice(oldBuyset, [t[0], 1]))
  167. newPrice = this.numAdd(newPrice, this.getBuysetPrice(newBuyset, [t[0], 1]))
  168. }
  169. console.log("old ", oldBuyset, " \n new ", newBuyset, " \n 相差", t[0], "年 ", t[1], "个月\n price:", newPrice, "-", beforePrice, "=", (newPrice * 10000 - beforePrice * 10000) / 10000);
  170. return (newPrice * 10000 - beforePrice * 10000) / 10000
  171. },
  172. getBuysetPrice: function (vipbuyset = new Buyset(), t) { //获取套餐价格
  173. if (t.length !== 2) {
  174. console.error("选择时间格式异常")
  175. return -1
  176. }
  177. if (vipbuyset.upgrade === 0) { //旧版大会员价格计算
  178. if (t[0] > this.PriceRule.old.monthMaxCount && t[1] === 2) t[0] = 10;//月份十个月以上价格一样
  179. if (vipbuyset.areacount === -1) {//计算全国套餐价格
  180. if (vipbuyset.buyerclasscount === 1) return this.getSetMealPrice_old(0, 1, t[1]) * t[0]; //全国1行业套餐
  181. if (vipbuyset.buyerclasscount === 0) return this.getSetMealPrice_old(0, 0, t[1]) * t[0]; //全国全行业套餐
  182. return this.getSetMealPrice_old(0, vipbuyset.buyerclasscount, t[1]) * t[0] //全国多行业套餐
  183. }
  184. let final_price = 0;//计算省份价格
  185. for (var i in vipbuyset.citys) {
  186. var thisPrice = 0;
  187. if (vipbuyset.citys[i] === 1) {//单城市
  188. thisPrice = this.getSetMealPrice_old(2, vipbuyset.buyerclasscount, t[1]) * t[0];
  189. } else {//多城市
  190. if (vipbuyset.buyerclasscount === 0 || vipbuyset.buyerclasscount === 1) {//多城市 单行业
  191. if (vipbuyset.citys[i] > this.PriceRule.old.cityMaxCount) {
  192. vipbuyset.areacount++;
  193. } else {
  194. thisPrice = vipbuyset.citys[i] * this.getSetMealPrice_old(2, vipbuyset.buyerclasscount, t[1]) * t[0];
  195. }
  196. } else {//多城市 多行业
  197. if (vipbuyset.citys[i] > this.PriceRule.old.cityMaxCount) {
  198. vipbuyset.areacount++;
  199. } else {
  200. thisPrice = this.getSetMealPrice_old(2, vipbuyset.buyerclasscount, t[1]) * vipbuyset.citys[i] * t[0];
  201. }
  202. }
  203. }
  204. final_price += thisPrice;
  205. }
  206. final_price += vipbuyset.areacount * this.getSetMealPrice_old(1, vipbuyset.buyerclasscount, t[1]) * t[0];
  207. return final_price
  208. } else {//新版大会员价格计算
  209. let pCount = vipbuyset.areacount
  210. let count = t[0]
  211. let unit = t[1]
  212. if (pCount > this.PriceRule.new.provinceMaxCount) {
  213. pCount = -1
  214. }
  215. if (pCount === -1) {
  216. pCount = 0
  217. }
  218. if (pCount !== 0) { //购买省份计算 省份10个月价格和11个月价格一样
  219. //当选择月份大于 按照全年计算
  220. if (t[0] > this.PriceRule.new.monthMaxCount && t[1] === 2) count = 10//月份十个月以上价格一样
  221. } else { //购买全国计算 全国10个月价格和11个月价格不一样
  222. //当选择月份大于 按照全年计算
  223. if (t[0] > this.PriceRule.new.monthMaxCount && unit === 2) { //月份十个月以上价格一样
  224. count = 1
  225. unit = 1
  226. }
  227. }
  228. return this.getSetMealPrice_new(pCount, unit) * count //全国1行业套餐
  229. }
  230. },
  231. getSetMealPrice_old: function (c, iCount, u) { //旧套餐价格计算
  232. var t = u === 2; //是否是月单位
  233. switch (c) {
  234. case 0:
  235. if (iCount === -1) {
  236. if (t) return this.PriceRule.old.month.allProvince_allBuyerClass; //1月全国全行业
  237. return this.PriceRule.old.year.allProvince_allBuyerClass; //1年全国全行业
  238. } else {
  239. if (t) return this.PriceRule.old.month.allProvince_oneBuyerClass * iCount; //1月全国icount个行业
  240. return this.PriceRule.old.year.allProvince_oneBuyerClass * iCount; //1年全国icount个行业
  241. }
  242. case 1:
  243. if (iCount === -1) {
  244. if (t) return this.PriceRule.old.month.oneProvince_allBuyerClass; //1月1省全行业
  245. return this.PriceRule.old.year.oneProvince_allBuyerClass //1年1省全行业
  246. } else {
  247. if (t) return this.PriceRule.old.month.oneProvince_oneBuyerClass * iCount; //1月1省icount个行业
  248. return this.PriceRule.old.year.oneProvince_oneBuyerClass * iCount //1年1省icount个行业
  249. }
  250. default:
  251. if (iCount === -1) {
  252. if (t) return this.PriceRule.old.month.oneCity_allBuyerClass; //1月1市全行业
  253. return this.PriceRule.old.year.oneCity_allBuyerClass //1年1市全行业
  254. } else {
  255. if (t) return this.PriceRule.old.month.oneCity_oneBuyerClass * iCount; //1月1市icount个行业
  256. return this.PriceRule.old.year.oneCity_oneBuyerClass * iCount //1年1市icount个行业
  257. }
  258. }
  259. },
  260. getSetMealPrice_new: function (p, u) { //新套餐价格计算 p省份格式,u时间单位
  261. let t = u === 2 //是否是月单位
  262. switch (p) {
  263. case 0:
  264. if (t) {
  265. return this.PriceRule.new.month.allProvince_allBuyerClass // 1月全国全行业
  266. }
  267. return this.PriceRule.new.year.allProvince_allBuyerClass //1年全国全行业
  268. default :
  269. if (t) {
  270. return this.PriceRule.new.month.oneProvince_allBuyerClass * p //1月p省全行业
  271. }
  272. return this.PriceRule.new.year.oneProvince_allBuyerClass * p //1年p省全行业
  273. }
  274. },
  275. getDateSub: function (start, end) { //计算时间间隔差 [年个数, 月个数]
  276. let startTime = new Date(start * 1000);
  277. let endTime = new Date(end * 1000);
  278. let startYear = startTime.getFullYear();
  279. let startMonth = startTime.getMonth();
  280. let startDay = startTime.getDate();
  281. let endYear = endTime.getFullYear();
  282. let endMonth = endTime.getMonth();
  283. let endDay = endTime.getDate();
  284. let finalMonthNum = 0;
  285. let finalYearNum = 0;
  286. if (startYear === endYear) {
  287. if (startMonth === endMonth) {
  288. finalMonthNum = 1;
  289. } else {
  290. if (endDay > startDay) {
  291. finalMonthNum = endMonth - startMonth + 1;
  292. } else {
  293. finalMonthNum = endMonth - startMonth;
  294. }
  295. }
  296. } else {
  297. if (startMonth === endMonth) {
  298. if (endDay <= startDay) {
  299. finalMonthNum = (endYear - startYear) * 12;
  300. } else {
  301. finalMonthNum = (endYear - startYear) * 12 + 1;
  302. }
  303. } else if (endMonth > startMonth) {
  304. if (endDay <= startDay) {
  305. finalMonthNum = (endYear - startYear) * 12 + (endMonth - startMonth);
  306. } else {
  307. finalMonthNum = (endYear - startYear) * 12 + (endMonth - startMonth) + 1;
  308. }
  309. } else {
  310. if (endDay <= startDay) {
  311. finalMonthNum = (endYear - startYear - 1) * 12 + (12 - startMonth + endMonth);
  312. } else {
  313. finalMonthNum = (endYear - startYear - 1) * 12 + (12 - startMonth + endMonth) + 1;
  314. }
  315. }
  316. finalYearNum = Math.floor(finalMonthNum / 12);
  317. if (finalYearNum > 0) {
  318. finalMonthNum = finalMonthNum - finalYearNum * 12
  319. }
  320. }
  321. return [finalYearNum, finalMonthNum]
  322. },
  323. getVipEndDate: function (flag, value) {
  324. let EndTime = new Date(this.EndTime * 1000);
  325. let startDay = EndTime.getDate();
  326. let yearNum = EndTime.getFullYear();
  327. let monthNum = EndTime.getMonth();
  328. if (flag === 1) {//将年转换成月
  329. //年
  330. yearNum += value;
  331. } else {
  332. //月
  333. if (monthNum + value > 11) {
  334. monthNum = monthNum + value - 12;
  335. yearNum++
  336. } else {
  337. monthNum += value
  338. }
  339. }
  340. //获取当月最后一天
  341. let lastDay = new Date(yearNum, monthNum + 1, 0).getDate();
  342. if (startDay < lastDay) {
  343. return new Date(yearNum, monthNum, startDay, 23, 59, 59).getTime() / 1000;
  344. } else {
  345. return new Date(yearNum, monthNum, lastDay, 23, 59, 59).getTime() / 1000;
  346. }
  347. },
  348. numAdd: function (num1, num2) {
  349. return (num1 * 10000 + num2 * 10000) / 10000
  350. }
  351. }
  352. /*
  353. //首次购买
  354. Calculation.Init(false, undefined, [], 0)
  355. Calculation.GetTotal(new Buyset(15, [], -1, 1), [1, 2]) //首次购买
  356. //续费
  357. Calculation.Init(false, new Buyset(1, [1, 2], 3, 0))
  358. Calculation.GetTotal(undefined, [1, 2])
  359. //升级
  360. //初始化 非试用用户 已经购买了 1个省份 两个省份【1个城市、两个城市】 3个行业 非升级版超级订阅
  361. Calculation.Init(false, new Buyset(1, [1, 2], 3, 0),
  362. [{
  363. "l_validtime": 1622476799,
  364. "o_buyset": {
  365. "areacount": 3,
  366. "buyerclasscount": -1,
  367. "newcitys": []
  368. }
  369. }], undefined, 1625068799)
  370. //计算价格 升级为 15个省份 并续费一个月价格
  371. Calculation.GetUpgradeDetail(new Buyset(15, [], -1, 1), [1, 2])
  372. */