orderConfirm.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. <template>
  2. <view class="order-confirm-page">
  3. <view class="address-card scale-tap" @click="selectAddress()">
  4. <view class="address-content" v-if="address.id != 0">
  5. <view class="row">
  6. <text class="name">{{ address.realname }}</text>
  7. <text class="mobile">{{ address.mobile }}</text>
  8. <text class="default" v-if="address.is_default == 'yse'">默认</text>
  9. </view>
  10. <view class="address">收获地址:{{ address.area + address.address }}</view>
  11. </view>
  12. <view class="address-content" v-else>
  13. <view class="row">
  14. <text class="name" style="color: red;">请选择地址</text>
  15. </view>
  16. </view>
  17. <image class="arrow" src="@/static/crowdFunding/right.png" />
  18. </view>
  19. <view class="order-section">
  20. <view class="order-row">
  21. <text>回报内容</text>
  22. <text class="right">({{ selectedSpec && selectedSpec.selectedReward && selectedSpec.selectedReward.title }}) ¥{{
  23. price }}</text>
  24. </view>
  25. <view class="order-row">
  26. <text>众筹数量</text>
  27. <view class="right">
  28. <image src="@/static/icon/stepping_minus.png" @click="minus" class="minus" />
  29. <text class="num">{{ count }}</text>
  30. <image src="@/static/icon/stepping_add.png" @click="plus" class="plus" />
  31. </view>
  32. </view>
  33. <view class="order-row">
  34. <text>运费</text>
  35. <text class="right">{{ !shippingFee ? '包邮' : shippingFee }}</text>
  36. </view>
  37. </view>
  38. <view class="remark-section">
  39. <text>填写备注</text>
  40. <input class="remark-input" placeholder="选填" v-model="remark" />
  41. </view>
  42. <view class="pay-section">
  43. <view class="pay-item" :class="{ checked: payType === 'wx' }" @click="payType = 'wx'">
  44. <image src="@/static/icon/weixin_logo.png" class="pay-icon" />
  45. <text>微信支付</text>
  46. <image :src="payType === 'wx'
  47. ? '/static/icon/wd_icon_gouxuan05.png'
  48. : '/static/icon/wd_icon_gouxuan04.png'
  49. " class="check" />
  50. </view>
  51. <view class="pay-item" :class="{ checked: payType === 'alipay' }" @click="payType = 'alipay'">
  52. <image src="@/static/icon/zhifubao_logon.png" class="pay-icon" />
  53. <text>支付宝</text>
  54. <image :src="payType === 'alipay'
  55. ? '/static/icon/wd_icon_gouxuan05.png'
  56. : '/static/icon/wd_icon_gouxuan04.png'
  57. " class="check" />
  58. </view>
  59. </view>
  60. <view class="protocol-section">
  61. <text class="title">免责协议:</text>
  62. <text class="content">
  63. 免责协议:
  64. 1.点击"提交订单",即表明您已阅读并同意《支持者协议》及《隐私政策》,并自愿承担众筹相应风险。
  65. 2.您参与众筹是支持将创意变为现实的过程,而不是直接的商品交易,因此存在一定风险。请您根据自己的判断选择、支持众筹项目自。众筹存在于发起人与支持者之间,摩点网作为第三方平台,只只提供网络空间、技术支持等服务。众筹的回报产品和承诺由发起人是供和作出,发起者和支持者应依法承担使用萌创星球产品产生的法律后来果。
  66. 3.众筹项目的回报发放及其他后续服务事项均由发起人负责。如果发生发起人无法发放回报、延迟发放回报、不提供回报后续服务务等情形,您需要直接和发起人协商解决。
  67. 4.众筹结束前最后1小时及众筹结束后未超过预计发货时间期间无法申请退款,具体退款规则参见《退款说明》。
  68. 5.由于发起人能力和经验不足、市场风险、法律风险等各种因素,众筹可能失败。对于在众筹期限届满前失败的项目,您支持项目的款项会全部原路退还给您;对于众筹成功的项目,支持者不能通过萌创星球平台申请退款,若此时支持者因任何原因希望退款,需直接与发起者者协商,若发起者同意退款,需直接向支持者退回款项,萌创星球不会从可可结算款项中扣除该部分退款金额。您对项目发起人的无偿支持!以及额外打赏,一旦众筹成功将不予退款,但众筹失败的情况除外。
  69. </text>
  70. </view>
  71. <view class="bom-reserveASeat"></view>
  72. <view class="order-bottom">
  73. <view class="total-wrap">
  74. <text class="label">总金额</text>
  75. <text class="price">¥{{ (price * count).toFixed(2) }}</text>
  76. </view>
  77. <view class="submit-btn blick-btn-animation" @click="submit">提交订单</view>
  78. </view>
  79. </view>
  80. </template>
  81. <script>
  82. export default {
  83. data() {
  84. return {
  85. address: {
  86. id: 0
  87. },
  88. price: 0,
  89. count: 1,
  90. remark: "",
  91. payType: "wx",
  92. isSubmitting: false,
  93. lastClickTime: 0,
  94. linkid: '',
  95. selectedSpec: null,
  96. detail: null,
  97. shippingFee: 0,
  98. };
  99. },
  100. onLoad(options) {
  101. console.log('options', options);
  102. if (options.orderId) {
  103. } else {
  104. const eventChannel = this.getOpenerEventChannel();
  105. eventChannel.on('acceptDataFromOpener', (data) => {
  106. this.selectedSpec = data.selectedSpec;
  107. this.detail = data.detail;
  108. this.price = this.selectedSpec && this.selectedSpec.selectedReward && this.selectedSpec.selectedReward.price || 0
  109. console.log('接收到的数据:', this.selectedSpec, this.detail);
  110. });
  111. eventChannel.on('acceptAddress', (address) => {
  112. this.address = address;
  113. console.log('接收到的地址:', this.address);
  114. });
  115. if (this.address.id == 0) {
  116. this.getAddress();
  117. }
  118. this.getPostage();
  119. }
  120. },
  121. onShow() {
  122. },
  123. methods: {
  124. goBack() {
  125. uni.navigateBack();
  126. },
  127. goPage(url) {
  128. uni.navigateTo({ url });
  129. },
  130. minus() {
  131. if (this.count > 1) this.count--;
  132. this.getPostage()
  133. },
  134. plus() {
  135. this.count++;
  136. this.getPostage()
  137. },
  138. getAddress() {
  139. // 获取默认地址
  140. uni.request({
  141. url: this.$apiHost + '/Address/getdefault',
  142. method: 'GET',
  143. data: {
  144. uuid: getApp().globalData.uuid,
  145. skey: getApp().globalData.skey
  146. },
  147. success: (res) => {
  148. if (res.data && res.data.info) {
  149. this.address = res.data.info;
  150. console.log(res.data.info, '获取到的默认地址');
  151. }
  152. }
  153. });
  154. },
  155. getPostage() {
  156. // 获取默认地址
  157. uni.request({
  158. url: this.$apiHost + '/crowdfund/calculate-shipping',
  159. method: 'GET',
  160. data: {
  161. uuid: getApp().globalData.uuid,
  162. skey: getApp().globalData.skey,
  163. num: this.count,
  164. area: this.address.area,
  165. reward_id: this.selectedSpec && this.selectedSpec.selectedReward && this.selectedSpec.selectedReward.id
  166. },
  167. success: (res) => {
  168. if (res.data && res.data.success == 'yes') {
  169. console.log(res.data.data, '获取到邮费');
  170. this.shippingFee = res.data.data.shipping_fee
  171. }
  172. }
  173. });
  174. },
  175. selectAddress() {
  176. uni.navigateTo({
  177. url: '/pages/crowdFunding/receivingAddress?isSelectAddress=true',
  178. success: function (res) {
  179. // 通过 eventChannel 向被打开页面传送数据
  180. res.eventChannel.emit('acceptDataFromOpener', { selectedSpec: this.selectedSpec, detail: this.detail });
  181. }.bind(this)
  182. });
  183. },
  184. async submit() {
  185. const now = Date.now();
  186. if (now - this.lastClickTime < 3000) {
  187. uni.showToast({ title: "请勿频繁点击", icon: "none" });
  188. return;
  189. }
  190. this.lastClickTime = now;
  191. if (this.isSubmitting) return;
  192. this.isSubmitting = true;
  193. uni.showLoading({ title: '创建订单中...' });
  194. // 创建订单
  195. uni.request({
  196. url: this.$apiHost + '/Order/submit',
  197. method: 'GET',
  198. data: {
  199. uuid: getApp().globalData.uuid,
  200. // 这里根据你的业务传递商品、数量、备注、支付方式等
  201. type: 'buyCrowdfund',
  202. reward_id: this.selectedSpec.selectedReward.id,
  203. num: this.count,
  204. beizu: this.remark,
  205. payType: this.payType,
  206. address_id: this.address.id
  207. },
  208. header: {
  209. 'content-type': 'application/json',
  210. sign: getApp().globalData.headerSign
  211. },
  212. success: (res) => {
  213. if (res.data.success == 'yes') {
  214. this.linkid = res.data.linkid;
  215. // 微信支付
  216. if (this.payType === 'wx') {
  217. uni.requestPayment({
  218. provider: "wxpay",
  219. orderInfo: {
  220. appid: res.data.wepay.appid,
  221. partnerid: res.data.wepay.partnerid,
  222. prepayid: res.data.wepay.prepayid,
  223. package: "Sign=WXPay",
  224. noncestr: res.data.wepay.noncestr,
  225. timestamp: res.data.wepay.timestamp,
  226. sign: res.data.wepay.sign
  227. },
  228. success: (payRes) => {
  229. this.checkPayStatus();
  230. },
  231. fail: (err) => {
  232. uni.hideLoading();
  233. this.isSubmitting = false;
  234. uni.showToast({ title: '支付取消', icon: 'none' });
  235. }
  236. });
  237. }
  238. // 支付宝支付
  239. else if (this.payType === 'alipay') {
  240. uni.requestPayment({
  241. provider: "alipay",
  242. orderInfo: res.data.ali_pay,
  243. success: (payRes) => {
  244. this.checkPayStatus();
  245. },
  246. fail: (err) => {
  247. uni.hideLoading();
  248. this.isSubmitting = false;
  249. uni.showToast({ title: '支付取消', icon: 'none' });
  250. }
  251. });
  252. }
  253. } else {
  254. uni.hideLoading();
  255. this.isSubmitting = false;
  256. uni.showToast({ title: res.data.str || '创建订单失败', icon: "none" });
  257. }
  258. },
  259. fail: (err) => {
  260. uni.hideLoading();
  261. this.isSubmitting = false;
  262. uni.showToast({ title: '网络错误,请稍后重试', icon: "none" });
  263. }
  264. });
  265. },
  266. // 轮询查支付状态
  267. checkPayStatus() {
  268. console.log(this.linkid, "支付订单号");
  269. uni.request({
  270. url: this.$apiHost + "/Order/getstatus",
  271. data: {
  272. uuid: getApp().globalData.uuid,
  273. linkid: this.linkid,
  274. },
  275. header: {
  276. "content-type": "application/json",
  277. sign: getApp().globalData.headerSign
  278. },
  279. success: (res) => {
  280. console.log(res.data, "支付状态");
  281. if (res.data.success == "yes") {
  282. uni.hideLoading();
  283. uni.showToast({ title: "支付成功", icon: "none" });
  284. // 跳转到订单详情或列表
  285. uni.redirectTo({ url: '/pages/crowdFunding/orderList' });
  286. } else {
  287. setTimeout(() => { this.checkPayStatus(); }, 1000);
  288. }
  289. },
  290. fail: (err) => {
  291. uni.hideLoading();
  292. uni.showToast({ title: "网络错误,请重试", icon: "none" });
  293. }
  294. });
  295. }
  296. },
  297. };
  298. </script>
  299. <style lang="scss">
  300. page {
  301. background: #f6faf6;
  302. }
  303. .order-confirm-page {
  304. min-height: 100vh;
  305. background: #f6faf6;
  306. padding: 0 10rpx;
  307. box-sizing: border-box;
  308. .nav-bar {
  309. display: flex;
  310. align-items: center;
  311. padding: 0 32rpx;
  312. height: 100rpx;
  313. background: #fff;
  314. .back {
  315. font-size: 44rpx;
  316. }
  317. .title {
  318. font-size: 36rpx;
  319. font-weight: bold;
  320. margin-left: 32rpx;
  321. }
  322. }
  323. .address-card {
  324. background: #fff;
  325. border-radius: 18rpx;
  326. margin: 10rpx;
  327. padding: 32rpx;
  328. display: flex;
  329. align-items: center;
  330. justify-content: space-between;
  331. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
  332. .address-content {
  333. flex: 1;
  334. min-width: 0;
  335. .row {
  336. display: flex;
  337. align-items: center;
  338. margin-bottom: 12rpx;
  339. .name {
  340. font-size: 32rpx;
  341. font-weight: bold;
  342. margin-right: 18rpx;
  343. color: #222;
  344. }
  345. .mobile {
  346. font-size: 32rpx;
  347. margin-right: 18rpx;
  348. color: #222;
  349. }
  350. .default {
  351. font-size: 22rpx;
  352. color: #fff;
  353. background: #1f1f1f;
  354. border-radius: 8rpx;
  355. padding: 2rpx 12rpx;
  356. margin-right: 12rpx;
  357. margin-left: 4rpx;
  358. vertical-align: middle;
  359. font-weight: 500;
  360. background: #1f1f1f;
  361. color: #acf934;
  362. }
  363. }
  364. .address {
  365. font-size: 26rpx;
  366. color: #666;
  367. white-space: nowrap;
  368. text-overflow: ellipsis;
  369. overflow: hidden;
  370. width: 90vw; // 防止溢出
  371. max-width: 600rpx;
  372. }
  373. }
  374. .arrow {
  375. width: 32rpx;
  376. height: 32rpx;
  377. flex-shrink: 0;
  378. }
  379. }
  380. .order-section {
  381. background: #fff;
  382. border-radius: 18rpx;
  383. margin: 10rpx;
  384. padding: 0 32rpx;
  385. .order-row {
  386. display: flex;
  387. align-items: center;
  388. justify-content: space-between;
  389. height: 88rpx;
  390. font-size: 30rpx;
  391. .right {
  392. display: flex;
  393. align-items: center;
  394. }
  395. .minus,
  396. .plus {
  397. width: 40rpx;
  398. height: 40rpx;
  399. border-radius: 50%;
  400. background: #1f1f1f;
  401. color: #acf934;
  402. text-align: center;
  403. // line-height: 48rpx;
  404. // font-size: 36rpx;
  405. // margin: 0 12rpx;
  406. }
  407. .num {
  408. width: 80rpx;
  409. text-align: center;
  410. }
  411. }
  412. .order-row:last-child {
  413. border-bottom: none;
  414. }
  415. }
  416. .remark-section {
  417. background: #fff;
  418. border-radius: 18rpx;
  419. margin: 10rpx;
  420. padding: 0 32rpx;
  421. display: flex;
  422. align-items: center;
  423. height: 88rpx;
  424. .remark-input {
  425. flex: 1;
  426. border: none;
  427. background: transparent;
  428. font-size: 28rpx;
  429. color: #1f1f1f;
  430. margin-left: 24rpx;
  431. }
  432. }
  433. .pay-section {
  434. background: #fff;
  435. border-radius: 18rpx;
  436. margin: 10rpx;
  437. padding: 0 32rpx;
  438. .pay-item {
  439. display: flex;
  440. align-items: center;
  441. height: 88rpx;
  442. font-size: 30rpx;
  443. position: relative;
  444. .pay-icon {
  445. width: 48rpx;
  446. height: 48rpx;
  447. margin-right: 18rpx;
  448. border-radius: 50%;
  449. }
  450. .check {
  451. position: absolute;
  452. right: 0;
  453. width: 32rpx;
  454. height: 32rpx;
  455. border-radius: 50%;
  456. }
  457. }
  458. .pay-item:last-child {
  459. border-bottom: none;
  460. }
  461. }
  462. .protocol-section {
  463. background: #fff;
  464. border-radius: 18rpx;
  465. margin: 10rpx;
  466. padding: 32rpx;
  467. .title {
  468. font-size: 28rpx;
  469. font-weight: bold;
  470. margin-bottom: 12rpx;
  471. display: block;
  472. }
  473. .content {
  474. font-size: 24rpx;
  475. color: #888;
  476. line-height: 1.7;
  477. }
  478. }
  479. .order-bottom {
  480. position: fixed;
  481. left: 0;
  482. right: 0;
  483. bottom: 0;
  484. background: #fff;
  485. display: flex;
  486. align-items: center;
  487. justify-content: flex-end;
  488. background: #fff;
  489. height: 88rpx;
  490. padding: 0 32rpx;
  491. box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.04);
  492. padding-bottom: var(--window-bottom);
  493. box-sizing: content-box;
  494. .total-wrap {
  495. display: flex;
  496. align-items: baseline;
  497. margin-right: 32rpx;
  498. .label {
  499. color: #b2b2b2;
  500. font-size: 28rpx;
  501. margin-right: 8rpx;
  502. }
  503. .price {
  504. color: #222;
  505. font-size: 32rpx;
  506. font-weight: bold;
  507. }
  508. }
  509. .submit-btn {
  510. background: #1f1f1f;
  511. color: #acf934;
  512. border-radius: 44rpx;
  513. font-size: 32rpx;
  514. font-weight: bold;
  515. width: 240rpx;
  516. height: 72rpx;
  517. text-align: center;
  518. line-height: 72rpx;
  519. margin-left: 12rpx;
  520. box-shadow: none;
  521. display: flex;
  522. align-items: center;
  523. justify-content: center;
  524. }
  525. }
  526. }
  527. .bom-reserveASeat {
  528. width: 100%;
  529. height: calc(var(--window-bottom) + 100rpx);
  530. }
  531. </style>