order-detail.ts 18 KB

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