2
0

order.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. import memberService from '../../utils/member.js';
  2. import passengerService from '../../utils/passenger.js';
  3. Page({
  4. data:{
  5. schedule: {
  6. price: 88,
  7. left: 12,
  8. time: '09:00',
  9. model: '宇通大巴',
  10. fromLoc: '东直门地铁站A口',
  11. toLoc: '上海体育馆',
  12. type: 'bus',
  13. duration: '约5小时',
  14. refundPolicy: '行程前72小时之前退票无手续费'
  15. },
  16. passengers: [],
  17. phoneNumber: '',
  18. hasPhoneNumber: false,
  19. activityName: '',
  20. totalPrice: 0,
  21. isCharter: false,
  22. memberInfo: {},
  23. memberLevel: {},
  24. originalPrice: 0,
  25. memberDiscount: 0,
  26. availableCoupons: [],
  27. selectedCoupon: null,
  28. couponDiscount: 0,
  29. savedPassengers: [],
  30. showPassengerSelector: false
  31. },
  32. onLoad(options){
  33. const { scheduleId, activityName, type } = options;
  34. const isCharter = type === 'business-charter';
  35. // 模拟根据scheduleId获取班次详情
  36. let schedule = {
  37. price: isCharter ? 1200 : 88,
  38. left: isCharter ? 6 : 12,
  39. time: isCharter ? '任意时间' : '09:00',
  40. model: isCharter ? '奔驰V级商务车' : '宇通大巴',
  41. fromLoc: isCharter ? '指定地点接送' : '东直门地铁站A口',
  42. toLoc: isCharter ? '活动现场' : '上海体育馆',
  43. type: type,
  44. duration: isCharter ? '约4小时' : '约5小时',
  45. refundPolicy: isCharter ? '预约后可协商退改' : '行程前72小时之前退票无手续费'
  46. };
  47. this.setData({
  48. schedule,
  49. activityName: activityName || '活动',
  50. isCharter
  51. });
  52. this.loadMemberInfo();
  53. this.loadSavedPassengers();
  54. this.calculateTotalPrice();
  55. },
  56. onShow() {
  57. this.loadMemberInfo();
  58. this.loadSavedPassengers();
  59. this.calculateTotalPrice();
  60. },
  61. // 加载会员信息
  62. loadMemberInfo() {
  63. const memberInfo = memberService.getUserMemberInfo();
  64. const memberLevel = memberService.getMemberLevelInfo(memberInfo.level);
  65. const availableCoupons = memberService.getAvailableCoupons();
  66. this.setData({
  67. memberInfo,
  68. memberLevel,
  69. availableCoupons
  70. });
  71. },
  72. // 加载已保存的乘车人
  73. loadSavedPassengers() {
  74. const savedPassengers = passengerService.getAllPassengers();
  75. this.setData({ savedPassengers });
  76. },
  77. // 选择优惠券
  78. selectCoupon() {
  79. const { availableCoupons } = this.data;
  80. if (availableCoupons.length === 0) {
  81. wx.showToast({
  82. title: '暂无可用优惠券',
  83. icon: 'none'
  84. });
  85. return;
  86. }
  87. const items = ['不使用优惠券', ...availableCoupons.map(c => `${c.name} (¥${c.value})`)];
  88. wx.showActionSheet({
  89. itemList: items,
  90. success: (res) => {
  91. if (res.tapIndex === 0) {
  92. // 不使用优惠券
  93. this.setData({
  94. selectedCoupon: null,
  95. couponDiscount: 0
  96. });
  97. } else {
  98. // 选择优惠券
  99. const coupon = availableCoupons[res.tapIndex - 1];
  100. this.setData({
  101. selectedCoupon: coupon,
  102. couponDiscount: coupon.value
  103. });
  104. }
  105. this.calculateTotalPrice();
  106. }
  107. });
  108. },
  109. calculateTotalPrice() {
  110. const { schedule, passengers, isCharter, memberLevel, couponDiscount } = this.data;
  111. let originalPrice = 0;
  112. if (isCharter) {
  113. // 包车按车计费
  114. originalPrice = schedule.price;
  115. } else {
  116. // 拼车按人计费
  117. originalPrice = passengers.length * schedule.price;
  118. }
  119. // 应用会员折扣
  120. const memberDiscount = memberLevel.discount || 1.0;
  121. let totalPrice = originalPrice * memberDiscount;
  122. // 应用优惠券折扣
  123. totalPrice = Math.max(0, totalPrice - (couponDiscount || 0));
  124. // 保留两位小数
  125. totalPrice = Math.round(totalPrice * 100) / 100;
  126. const memberDiscountAmount = originalPrice - (originalPrice * memberDiscount);
  127. this.setData({
  128. originalPrice,
  129. totalPrice,
  130. memberDiscount: memberDiscountAmount
  131. });
  132. },
  133. onGetPhoneNumber(e){
  134. if (e.detail.errMsg === 'getPhoneNumber:ok') {
  135. // 实际项目中需要发送code到后端获取手机号
  136. this.setData({
  137. phoneNumber: '138****8888', // 模拟获取到的手机号
  138. hasPhoneNumber: true
  139. });
  140. wx.showToast({title:'获取手机号成功',icon:'success'});
  141. } else {
  142. wx.showToast({title:'获取手机号失败',icon:'none'});
  143. }
  144. },
  145. addPassenger(){
  146. if (!this.data.hasPhoneNumber) {
  147. wx.showToast({title:'请先获取手机号',icon:'none'});
  148. return;
  149. }
  150. const { savedPassengers } = this.data;
  151. if (savedPassengers.length > 0) {
  152. // 如果有已保存的乘车人,显示选择器
  153. this.setData({ showPassengerSelector: true });
  154. } else {
  155. // 没有已保存的乘车人,直接跳转到添加页面
  156. wx.navigateTo({
  157. url:'/pages/add-passenger/add-passenger'
  158. });
  159. }
  160. },
  161. // 显示乘车人选择器
  162. showPassengerSelector() {
  163. this.setData({ showPassengerSelector: true });
  164. },
  165. // 关闭乘车人选择器
  166. closePassengerSelector() {
  167. this.setData({ showPassengerSelector: false });
  168. },
  169. // 选择已有乘车人
  170. selectSavedPassenger(e) {
  171. const { id } = e.currentTarget.dataset;
  172. const passenger = passengerService.getPassengerById(id);
  173. if (passenger) {
  174. // 检查是否已经添加过这个乘车人
  175. const existingPassenger = this.data.passengers.find(p => p.idcard === passenger.idcard);
  176. if (existingPassenger) {
  177. wx.showToast({title:'该乘车人已添加',icon:'none'});
  178. return;
  179. }
  180. // 添加到当前订单的乘车人列表
  181. const passengers = [...this.data.passengers, passenger];
  182. this.setData({
  183. passengers,
  184. showPassengerSelector: false
  185. });
  186. this.calculateTotalPrice();
  187. wx.showToast({title:'添加成功',icon:'success'});
  188. }
  189. },
  190. // 添加新乘车人
  191. addNewPassenger() {
  192. this.setData({ showPassengerSelector: false });
  193. wx.navigateTo({
  194. url:'/pages/add-passenger/add-passenger'
  195. });
  196. },
  197. // 管理乘车人
  198. managePassengers() {
  199. this.setData({ showPassengerSelector: false });
  200. wx.navigateTo({
  201. url:'/pages/passenger-management/passenger-management'
  202. });
  203. },
  204. deletePassenger(e) {
  205. const index = e.currentTarget.dataset.index;
  206. const passengers = this.data.passengers;
  207. passengers.splice(index, 1);
  208. this.setData({ passengers });
  209. this.calculateTotalPrice();
  210. },
  211. pay(){
  212. if (!this.data.hasPhoneNumber) {
  213. wx.showToast({title:'请先获取手机号',icon:'none'});
  214. return;
  215. }
  216. if (this.data.passengers.length === 0) {
  217. wx.showToast({title:'请添加乘车人信息',icon:'none'});
  218. return;
  219. }
  220. if (!this.data.isCharter && this.data.passengers.length > this.data.schedule.left) {
  221. wx.showToast({title:`最多只能购买${this.data.schedule.left}张票`,icon:'none'});
  222. return;
  223. }
  224. // 发起微信支付
  225. this.requestPayment();
  226. },
  227. requestPayment() {
  228. // 模拟微信支付
  229. wx.showLoading({title: '发起支付...'});
  230. setTimeout(() => {
  231. wx.hideLoading();
  232. wx.requestPayment({
  233. timeStamp: String(Date.now()),
  234. nonceStr: 'randomstring',
  235. package: 'prepay_id=mock_prepay_id',
  236. signType: 'MD5',
  237. paySign: 'mock_pay_sign',
  238. success: (res) => {
  239. // 支付成功,添加会员值和积分
  240. const { totalPrice, selectedCoupon, schedule } = this.data;
  241. // 使用优惠券
  242. if (selectedCoupon) {
  243. memberService.useCoupon(selectedCoupon.id);
  244. }
  245. // 添加会员值和积分
  246. const result = memberService.addMemberValueAndPoints(totalPrice);
  247. // 生成订单ID
  248. const orderId = this.generateOrderId();
  249. const orderType = schedule.type || 'bus';
  250. let successUrl = `/pages/pay-success/pay-success?totalPrice=${totalPrice}&passengerCount=${this.data.passengers.length}&orderId=${orderId}&orderType=${orderType}`;
  251. // 如果有等级升级,添加升级信息
  252. if (result.levelUpgraded) {
  253. successUrl += `&levelUpgraded=true&newLevel=${result.newLevel}&addedPoints=${result.addedPoints}&addedValue=${result.addedValue}`;
  254. } else {
  255. successUrl += `&addedPoints=${result.addedPoints}&addedValue=${result.addedValue}`;
  256. }
  257. wx.navigateTo({
  258. url: successUrl
  259. });
  260. },
  261. fail: (res) => {
  262. wx.showToast({title:'支付失败',icon:'none'});
  263. }
  264. });
  265. }, 1000);
  266. },
  267. // 生成订单ID
  268. generateOrderId() {
  269. const now = new Date();
  270. const timestamp = now.getTime();
  271. const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
  272. return `ORDER_${timestamp}_${random}`;
  273. }
  274. });