order-detail.ts 17 KB

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