order-detail.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. // pages/orders/order-detail.ts
  2. import { api_executeOrder, api_executePayment, api_queryByParamName, api_userPaymentOrderDetail, api_userPaymentOrderUnpaid } from "../../api/login";
  3. import { api_sysAreaQueryAllProvince, api_userReceiveAddressPage, api_userReceiveAddressSave } from "../../api/new";
  4. import { formatPrice, GRADE_ENUM } from "../../utils/util";
  5. // 获取应用实例
  6. const app = getApp<IAppOption>()
  7. Page({
  8. /**
  9. * 页面的初始数据
  10. */
  11. data: {
  12. status: 'WAIT_PAY',
  13. statusList: {
  14. WAIT_PAY: {
  15. logo: './images/ing.png',
  16. title: '等待付款',
  17. content: '请尽快完成支付,以便我们为您处理订单'
  18. },
  19. },
  20. backParams: null,
  21. addressList: [] as any,
  22. goodsInfo: {} as any,
  23. hasInstrument: false, // 是否有乐器
  24. receiveAddress: '', // 选择的地址信息
  25. receiveAddressInfo: {
  26. addressDetail: '',
  27. name: '',
  28. phoneNumber: ''
  29. },
  30. userBeneficiaryId: '', // 添加购买人信息
  31. userBeneficiaryInfo: {
  32. name: '',
  33. phoneNumber: '',
  34. schoolInfo: ''
  35. },
  36. isExpanded: false,
  37. paymentType: null as any, // 支付类型
  38. paymentChannel: null as any,
  39. showService: false,
  40. showArea: false,
  41. areaList: [] as any,
  42. currentValues: [] as any,
  43. addressShow: false,
  44. addressAfterLeave: false,
  45. // 添加地址表单信息
  46. id: "",
  47. name: '',
  48. phoneNumber: '',
  49. detailAddress: '',
  50. cityCode: 0,
  51. cityName: "",
  52. provinceCode: 0,
  53. provinceName: "",
  54. regionCode: '',
  55. regionName: "",
  56. },
  57. /**
  58. * 生命周期函数--监听页面加载
  59. */
  60. onLoad(options: any) {
  61. this.queryPayType()
  62. if (options.orderInfo) {
  63. console.log('goods', options)
  64. const goods = JSON.parse(decodeURIComponent(options.orderInfo));
  65. console.log(goods, 'goods', options)
  66. const infos = {
  67. allSalePrice: 0,
  68. allOriginPrice: 0,
  69. originIntegerPart: '',
  70. originDecimalPart: '',
  71. allDiscountPrice: '',
  72. discountIntegerPart: '',
  73. discountDecimalPart: '',
  74. integerPart: '',
  75. decimalPart: '',
  76. name: '',
  77. shopId: '',
  78. orderNo: options.orderNo || '',
  79. goodsList: [] as any,
  80. createTime: '', // 订单时间
  81. }
  82. // 是否有乐器
  83. let hasInstrument = false
  84. for (let i in goods) {
  85. const item = goods[i]
  86. if (item.goodsType === "INSTRUMENTS") {
  87. hasInstrument = true
  88. }
  89. infos.name = infos.name ? infos.name + '+' + item.name : item.name
  90. infos.shopId = item.shopId
  91. const afterPrice: any = formatPrice(item.salePrice)
  92. // console.log(infos.goodsList, 'infos.goodsList')
  93. infos.goodsList.push({
  94. ...item,
  95. originalPrice: formatPrice(Number(item.originalPrice || 0), 'ALL'),
  96. typePeriod: this.formatPeriod(item.num, item.period),
  97. ...afterPrice
  98. })
  99. infos.allSalePrice += Number(item.salePrice)
  100. infos.allOriginPrice += Number(item.originalPrice)
  101. }
  102. const allAfterPrice: any = formatPrice(infos.allSalePrice)
  103. infos.allDiscountPrice = formatPrice(infos.allOriginPrice - infos.allSalePrice, 'ALL') as string
  104. const allDiscount: any = formatPrice(infos.allOriginPrice - infos.allSalePrice)
  105. infos.integerPart = allAfterPrice.integerPart
  106. infos.decimalPart = allAfterPrice.decimalPart
  107. infos.discountIntegerPart = allDiscount.integerPart
  108. infos.discountDecimalPart = allDiscount.decimalPart
  109. const allOriginPrices: any = formatPrice(infos.allOriginPrice)
  110. infos.originIntegerPart = allOriginPrices.integerPart
  111. infos.originDecimalPart = allOriginPrices.decimalPart
  112. this.setData({
  113. goodsInfo: infos,
  114. userBeneficiaryId: options.userBeneficiaryId,
  115. status: options.status || '',
  116. hasInstrument
  117. }, () => {
  118. this.getOrderDetail()
  119. });
  120. }
  121. },
  122. /** 获取订单详情 */
  123. async getOrderDetail() {
  124. try {
  125. if (!this.data.goodsInfo.orderNo) return
  126. const { data } = await api_userPaymentOrderDetail(this.data.goodsInfo.orderNo, {
  127. version: 'V2'
  128. });
  129. const result = data.data || {}
  130. const addresses: any = result.addresses
  131. const beneficiary: any = result.beneficiary
  132. const tempSchoolAddress = [beneficiary?.provinceName, beneficiary?.cityName || '', beneficiary?.regionName || '', beneficiary?.schoolAreaName, GRADE_ENUM[beneficiary?.currentGradeNum], beneficiary?.currentClass + '班']
  133. this.setData({
  134. receiveAddress: addresses?.id,
  135. receiveAddressInfo: {
  136. addressDetail: addresses?.detailAddress,
  137. name: addresses?.name,
  138. phoneNumber: addresses?.phoneNumber
  139. },
  140. userBeneficiaryId: beneficiary.schoolAreaId, // 添加购买人信息
  141. userBeneficiaryInfo: {
  142. name: beneficiary.name,
  143. phoneNumber: beneficiary.phone,
  144. schoolInfo: tempSchoolAddress.join('')
  145. },
  146. status: result.wechatStatus,
  147. 'goodsInfo.createTime': result.createTime
  148. }, () => {
  149. console.log(this.data)
  150. })
  151. } catch {
  152. //
  153. }
  154. },
  155. // 格式化类型
  156. formatPeriod(num: number, type: string) {
  157. if (!type) return ''
  158. const template: any = {
  159. DAY: "天",
  160. MONTH: "个月",
  161. YEAR: "年"
  162. }
  163. if (type === "YEAR" && num >= 99) {
  164. return '终身'
  165. }
  166. return num + (template[type] || '')
  167. },
  168. // 获取后台配置的支付方式
  169. async queryPayType() {
  170. try {
  171. // wxlite_payment_service_provider
  172. const { data } = await api_queryByParamName({
  173. paramName: app.globalData.appId
  174. });
  175. if (data.code == 200) {
  176. const paramValue = data.data.paramValue ? JSON.parse(data.data.paramValue) : {}
  177. this.setData({
  178. paymentType: paramValue.vendor,
  179. paymentChannel: paramValue.channel
  180. });
  181. }
  182. } catch (error) {
  183. console.log(error, "error");
  184. }
  185. },
  186. /** 添加收货地址 */
  187. onSelectAddress() {
  188. console.log(this.data.addressList.length > 0, this.data.receiveAddress)
  189. if (this.data.addressList.length > 0 || this.data.receiveAddress) {
  190. wx.navigateTo({
  191. url: `../address/index?receiveAddress=${this.data.receiveAddress}`,
  192. })
  193. } else {
  194. this.onShowAddress()
  195. }
  196. },
  197. onPayError(message?: string) {
  198. wx.hideLoading()
  199. wx.showToast({
  200. title: message || '支付取消',
  201. icon: 'none'
  202. })
  203. },
  204. // 购买
  205. async onSubmit() {
  206. if (!this.data.receiveAddress && this.data.hasInstrument) {
  207. wx.showToast({
  208. title: '请选择收货地址',
  209. icon: 'none'
  210. })
  211. return
  212. }
  213. wx.showLoading({
  214. mask: true,
  215. title: "订单提交中...",
  216. });
  217. try {
  218. const { allSalePrice, shopId, name, orderNo, goodsList } = this.data.goodsInfo
  219. const goodsInfos: any = []
  220. goodsList.forEach((item: any) => {
  221. goodsInfos.push({
  222. "goodsId": item.id,
  223. "goodsNum": 1,
  224. "goodsType": item.goodsType,
  225. "paymentCashAmount": item.salePrice,
  226. "paymentCouponAmount": 0
  227. })
  228. })
  229. if (orderNo) {
  230. const { data } = await api_userPaymentOrderUnpaid({
  231. orderNo: orderNo,
  232. paymentType: 'WECHAT_MINI'
  233. })
  234. if (data.code === 200) {
  235. const { paymentConfig, paymentType, orderNo } = data.data.paymentConfig
  236. this.onExecutePay(paymentConfig, paymentType, orderNo)
  237. } else {
  238. this.onPayError()
  239. }
  240. } else {
  241. const { data } = await api_executeOrder({
  242. orderType: "WECHAT_MINI",
  243. paymentType: this.data.paymentType,
  244. paymentCashAmount: allSalePrice,
  245. paymentCouponAmount: 0,
  246. shopId: shopId,
  247. openId: app.globalData.userInfo?.liteOpenid,
  248. goodsInfos: goodsInfos,
  249. receiveAddress: this.data.receiveAddress,
  250. userBeneficiaryId: this.data.userBeneficiaryId,
  251. orderName: name,
  252. orderDesc: name
  253. })
  254. if (data.code === 200) {
  255. const { paymentConfig, paymentType, orderNo } = data.data
  256. this.onExecutePay(paymentConfig, paymentType, orderNo)
  257. } else if (data.code === 5200) {
  258. wx.hideLoading()
  259. wx.showToast({
  260. title: data.message,
  261. icon: 'none'
  262. })
  263. } else if ([5435, 5436, 5437, 5439, 5442, 5443, 5408, 5427, 5432].includes(data.code)) {
  264. wx.hideLoading()
  265. wx.showToast({
  266. title: data.message,
  267. icon: 'none'
  268. })
  269. setTimeout(() => {
  270. wx.navigateBack()
  271. }, 1000);
  272. } else {
  273. this.onPayError()
  274. }
  275. }
  276. } catch {
  277. wx.hideLoading()
  278. }
  279. },
  280. async onExecutePay(paymentConfig: any, paymentType: string, orderNo: string) {
  281. wx.login({
  282. success: async (wxres: any) => {
  283. const res = await api_executePayment({
  284. merOrderNo: paymentConfig.merOrderNo,
  285. paymentChannel: this.data.paymentChannel || 'wx_lite', // 'wx_pub', //
  286. paymentType,
  287. userId: app.globalData.userInfo?.id,
  288. code: wxres.code,
  289. wxMiniAppId: app.globalData.appId
  290. // code: '011yjYkl289aye4q2zml24UEWT3yjYkn',
  291. // wxPubAppId: 'wxbde13f59d40cb4f2'
  292. })
  293. wx.hideLoading()
  294. if (res.data.code === 200) {
  295. this.onPay(paymentType, res.data.data.reqParams, orderNo)
  296. } else if ([5435, 5436, 5437, 5439, 5442, 5443, 5408, 5427, 5432].includes(res.data.code)) {
  297. wx.hideLoading()
  298. wx.showToast({
  299. title: res.data.message,
  300. icon: 'none'
  301. })
  302. setTimeout(() => {
  303. wx.navigateBack()
  304. }, 1000);
  305. } else {
  306. this.onPayError(res.data.message)
  307. }
  308. },
  309. fail: () => {
  310. this.onPayError()
  311. }
  312. })
  313. },
  314. onPay(paymentType: string, paymentConfig: any, orderNo: string) {
  315. const isYeePay = paymentType.indexOf('yeepay') !== -1
  316. const prePayInfo = isYeePay ? JSON.parse(paymentConfig.prePayTn)
  317. : paymentConfig?.expend
  318. ? JSON.parse(paymentConfig?.expend?.pay_info)
  319. : paymentConfig
  320. const that = this
  321. wx.requestPayment({
  322. timeStamp: prePayInfo.timeStamp,
  323. nonceStr: prePayInfo.nonceStr,
  324. package: prePayInfo.package ? prePayInfo.package : prePayInfo.packageValue,
  325. paySign: prePayInfo.paySign,
  326. signType: prePayInfo.signType ? prePayInfo.signType : 'MD5',
  327. success() {
  328. wx.showToast({ title: '支付成功', icon: 'success' });
  329. wx.redirectTo({
  330. url: '/pages/orders/order-result?orderNo=' + orderNo
  331. })
  332. },
  333. fail(ressonInfo) {
  334. console.log('支付失败', ressonInfo)
  335. that.onPayError()
  336. that.setData({
  337. 'goodsInfo.orderNo': orderNo
  338. }, () => {
  339. that.getOrderDetail()
  340. })
  341. }
  342. })
  343. },
  344. /** 客服 */
  345. onService() {
  346. console.log("showService")
  347. this.setData({
  348. showService: true
  349. })
  350. },
  351. changePop(event: { detail: any }) {
  352. this.setData({
  353. showService: event.detail
  354. })
  355. },
  356. /**
  357. * 生命周期函数--监听页面初次渲染完成
  358. */
  359. onReady() {
  360. },
  361. /**
  362. * 生命周期函数--监听页面显示
  363. */
  364. onShow() {
  365. if (this.data.backParams) {
  366. // console.log(this.data.backParams, 'backParams'); // { key: 'value' }
  367. const backParams: any = this.data.backParams || {};
  368. this.setData({
  369. receiveAddress: backParams.receiveAddress,
  370. receiveAddressInfo: backParams.receiveAddressInfo,
  371. backParams: null // 清空参数
  372. })
  373. }
  374. this.getAddress()
  375. },
  376. /** 地址列表 */
  377. async getAddress() {
  378. try {
  379. const { data } = await api_userReceiveAddressPage({ page: 1, rows: -1 })
  380. this.setData({
  381. addressList: data.data.rows || []
  382. }, () => {
  383. if (this.data.addressList.length <= 0) {
  384. this.getAreas()
  385. }
  386. })
  387. } catch {
  388. //
  389. }
  390. },
  391. /** 获取省市区 */
  392. async getAreas() {
  393. try {
  394. const { data } = await api_sysAreaQueryAllProvince({})
  395. const areaList: any = this.formateArea(data.data)
  396. const currentValues = []
  397. if (areaList?.province_list) {
  398. // 获取第一个键值对
  399. const firstKey = Object.keys(areaList?.province_list)[0];
  400. // 通过键获取值
  401. const firstValue = areaList?.province_list[firstKey];
  402. currentValues.push({
  403. code: firstKey,
  404. name: firstValue
  405. })
  406. }
  407. if (areaList?.city_list) {
  408. // 获取第一个键值对
  409. const firstKey = Object.keys(areaList?.city_list)[0];
  410. // 通过键获取值
  411. const firstValue = areaList?.city_list[firstKey];
  412. currentValues.push({
  413. code: firstKey,
  414. name: firstValue
  415. })
  416. }
  417. if (areaList?.county_list) {
  418. // 获取第一个键值对
  419. const firstKey = Object.keys(areaList?.county_list)[0];
  420. // 通过键获取值
  421. const firstValue = areaList?.county_list[firstKey];
  422. currentValues.push({
  423. code: firstKey,
  424. name: firstValue
  425. })
  426. }
  427. this.setData({
  428. areaList,
  429. currentValues
  430. })
  431. } catch {
  432. //
  433. }
  434. },
  435. formateArea(area: any[]) {
  436. const province_list: { [_: string]: string } = {};
  437. const city_list: { [_: string]: string } = {};
  438. const county_list: { [_: string]: string } = {};
  439. area.forEach((item: any) => {
  440. province_list[item.code] = item.name;
  441. });
  442. area.forEach((item: any) => {
  443. item.areas && item.areas.forEach((city: any) => {
  444. city_list[city.code] = city.name;
  445. });
  446. });
  447. area.forEach((item: any) => {
  448. item.areas && item.areas.forEach((city: any) => {
  449. city.areas && city.areas.forEach((county: any) => {
  450. county_list[county.code] = county.name;
  451. });
  452. });
  453. });
  454. return {
  455. province_list,
  456. city_list,
  457. county_list
  458. };
  459. },
  460. /** 显示选择地区 */
  461. async onShowAreaList() {
  462. this.setData({
  463. showArea: true
  464. })
  465. },
  466. /** 关闭选择地区 */
  467. onCloseAreaList() {
  468. this.setData({
  469. showArea: false
  470. })
  471. },
  472. /** 确定选择地区 */
  473. submitArea(e: any) {
  474. const selectedOptions: any = e.detail.values
  475. this.setData({
  476. provinceCode: selectedOptions[0].code,
  477. cityCode: selectedOptions[1].code,
  478. regionCode: selectedOptions[2].code,
  479. provinceName: selectedOptions[0].name,
  480. cityName: selectedOptions[1].name,
  481. regionName: selectedOptions[2].name,
  482. showArea: false,
  483. })
  484. },
  485. onShowAddress() {
  486. this.setData({
  487. addressAfterLeave: false,
  488. addressShow: true
  489. })
  490. },
  491. onCloseAddress() {
  492. this.setData({
  493. addressShow: false
  494. })
  495. },
  496. onAddressAfterLeave() {
  497. this.setData({
  498. addressAfterLeave: true,
  499. name: '',
  500. phoneNumber: '',
  501. detailAddress: '',
  502. cityCode: 0,
  503. cityName: "",
  504. provinceCode: 0,
  505. provinceName: "",
  506. regionCode: '',
  507. regionName: "",
  508. })
  509. },
  510. /** 创建/修改收货地址 */
  511. async onOperationAddress() {
  512. const addressForm = this.data
  513. try {
  514. if (!addressForm.name) {
  515. wx.showToast({
  516. title: '请输入收货人姓名',
  517. icon: "none"
  518. })
  519. return
  520. }
  521. if (!addressForm.phoneNumber || !/^1[3456789]\d{9}$/.test(addressForm.phoneNumber)) {
  522. wx.showToast({
  523. title: '请输入正确的手机号码',
  524. icon: "none"
  525. })
  526. return
  527. }
  528. if (!addressForm.provinceCode || !addressForm.cityCode || !addressForm.regionCode) {
  529. wx.showToast({
  530. title: '请选择地区',
  531. icon: "none"
  532. })
  533. return
  534. }
  535. if (!addressForm.detailAddress) {
  536. wx.showToast({
  537. title: '请输入详细地址',
  538. icon: "none"
  539. })
  540. return
  541. }
  542. const params = {
  543. name: addressForm.name,
  544. phoneNumber: addressForm.phoneNumber,
  545. province: addressForm.provinceCode,
  546. city: addressForm.cityCode,
  547. region: addressForm.regionCode,
  548. detailAddress: addressForm.detailAddress
  549. }
  550. const { data } = await api_userReceiveAddressSave({
  551. ...params
  552. })
  553. wx.showToast({
  554. title: '添加成功',
  555. icon: 'none'
  556. })
  557. this.setData({
  558. receiveAddress: data.data, // 选择的地址信息
  559. receiveAddressInfo: {
  560. addressDetail: (addressForm.provinceName || '') + (addressForm.cityName || '') + (addressForm.regionName || '') + addressForm.detailAddress,
  561. name: addressForm.name,
  562. phoneNumber: addressForm.phoneNumber
  563. }
  564. })
  565. this.onCloseAddress()
  566. } catch (e) {
  567. //
  568. console.log(e, '1212')
  569. }
  570. },
  571. onExpanded() {
  572. this.setData({
  573. isExpanded: !this.data.isExpanded
  574. })
  575. },
  576. onCopy(e: { currentTarget: any }) {
  577. wx.setClipboardData({
  578. data: e.currentTarget.dataset.orderno,
  579. success: () => {
  580. wx.showToast({title: '复制成功', icon: 'none'})
  581. },
  582. fail: () => {
  583. wx.showToast({title: '复制失败,请稍后再试', icon: 'none'})
  584. }
  585. })
  586. },
  587. /**
  588. * 用户点击右上角分享
  589. */
  590. onShareAppMessage() {
  591. return {
  592. title: '器乐数字AI工具',
  593. path: '/pages/index/index',
  594. imageUrl: 'https://oss.dayaedu.com/ktyq/1739764429916.png'
  595. }
  596. }
  597. })