orderConfirm.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  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.msg || '创建订单失败', icon: "error" });
  257. }
  258. },
  259. fail: (err) => {
  260. uni.hideLoading();
  261. this.isSubmitting = false;
  262. uni.showToast({ title: '网络错误,请稍后重试', icon: "error" });
  263. }
  264. });
  265. },
  266. // 轮询查支付状态
  267. checkPayStatus() {
  268. uni.request({
  269. url: this.$apiHost + "/Order/getstatus",
  270. data: {
  271. uuid: getApp().globalData.uuid,
  272. linkid: this.linkid,
  273. },
  274. header: {
  275. "content-type": "application/json",
  276. sign: getApp().globalData.headerSign
  277. },
  278. success: (res) => {
  279. if (res.data.success == "yes") {
  280. uni.hideLoading();
  281. uni.showToast({ title: "支付成功", icon: "none" });
  282. // 跳转到订单详情或列表
  283. uni.redirectTo({ url: '/pages/crowdFunding/orderList' });
  284. } else {
  285. setTimeout(() => { this.checkPayStatus(); }, 1000);
  286. }
  287. },
  288. fail: (err) => {
  289. uni.hideLoading();
  290. uni.showToast({ title: "网络错误,请重试", icon: "none" });
  291. }
  292. });
  293. }
  294. },
  295. };
  296. </script>
  297. <style lang="scss">
  298. page {
  299. background: #f6faf6;
  300. }
  301. .order-confirm-page {
  302. min-height: 100vh;
  303. background: #f6faf6;
  304. padding: 0 10rpx;
  305. box-sizing: border-box;
  306. .nav-bar {
  307. display: flex;
  308. align-items: center;
  309. padding: 0 32rpx;
  310. height: 100rpx;
  311. background: #fff;
  312. .back {
  313. font-size: 44rpx;
  314. }
  315. .title {
  316. font-size: 36rpx;
  317. font-weight: bold;
  318. margin-left: 32rpx;
  319. }
  320. }
  321. .address-card {
  322. background: #fff;
  323. border-radius: 18rpx;
  324. margin: 10rpx;
  325. padding: 32rpx;
  326. display: flex;
  327. align-items: center;
  328. justify-content: space-between;
  329. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
  330. .address-content {
  331. flex: 1;
  332. min-width: 0;
  333. .row {
  334. display: flex;
  335. align-items: center;
  336. margin-bottom: 12rpx;
  337. .name {
  338. font-size: 32rpx;
  339. font-weight: bold;
  340. margin-right: 18rpx;
  341. color: #222;
  342. }
  343. .mobile {
  344. font-size: 32rpx;
  345. margin-right: 18rpx;
  346. color: #222;
  347. }
  348. .default {
  349. font-size: 22rpx;
  350. color: #fff;
  351. background: #1f1f1f;
  352. border-radius: 8rpx;
  353. padding: 2rpx 12rpx;
  354. margin-right: 12rpx;
  355. margin-left: 4rpx;
  356. vertical-align: middle;
  357. font-weight: 500;
  358. background: #1f1f1f;
  359. color: #acf934;
  360. }
  361. }
  362. .address {
  363. font-size: 26rpx;
  364. color: #666;
  365. white-space: nowrap;
  366. text-overflow: ellipsis;
  367. overflow: hidden;
  368. width: 90vw; // 防止溢出
  369. max-width: 600rpx;
  370. }
  371. }
  372. .arrow {
  373. width: 32rpx;
  374. height: 32rpx;
  375. flex-shrink: 0;
  376. }
  377. }
  378. .order-section {
  379. background: #fff;
  380. border-radius: 18rpx;
  381. margin: 10rpx;
  382. padding: 0 32rpx;
  383. .order-row {
  384. display: flex;
  385. align-items: center;
  386. justify-content: space-between;
  387. height: 88rpx;
  388. font-size: 30rpx;
  389. .right {
  390. display: flex;
  391. align-items: center;
  392. }
  393. .minus,
  394. .plus {
  395. width: 40rpx;
  396. height: 40rpx;
  397. border-radius: 50%;
  398. background: #1f1f1f;
  399. color: #acf934;
  400. text-align: center;
  401. // line-height: 48rpx;
  402. // font-size: 36rpx;
  403. // margin: 0 12rpx;
  404. }
  405. .num {
  406. width: 80rpx;
  407. text-align: center;
  408. }
  409. }
  410. .order-row:last-child {
  411. border-bottom: none;
  412. }
  413. }
  414. .remark-section {
  415. background: #fff;
  416. border-radius: 18rpx;
  417. margin: 10rpx;
  418. padding: 0 32rpx;
  419. display: flex;
  420. align-items: center;
  421. height: 88rpx;
  422. .remark-input {
  423. flex: 1;
  424. border: none;
  425. background: transparent;
  426. font-size: 28rpx;
  427. color: #1f1f1f;
  428. margin-left: 24rpx;
  429. }
  430. }
  431. .pay-section {
  432. background: #fff;
  433. border-radius: 18rpx;
  434. margin: 10rpx;
  435. padding: 0 32rpx;
  436. .pay-item {
  437. display: flex;
  438. align-items: center;
  439. height: 88rpx;
  440. font-size: 30rpx;
  441. position: relative;
  442. .pay-icon {
  443. width: 48rpx;
  444. height: 48rpx;
  445. margin-right: 18rpx;
  446. border-radius: 50%;
  447. }
  448. .check {
  449. position: absolute;
  450. right: 0;
  451. width: 32rpx;
  452. height: 32rpx;
  453. border-radius: 50%;
  454. }
  455. }
  456. .pay-item:last-child {
  457. border-bottom: none;
  458. }
  459. }
  460. .protocol-section {
  461. background: #fff;
  462. border-radius: 18rpx;
  463. margin: 10rpx;
  464. padding: 32rpx;
  465. .title {
  466. font-size: 28rpx;
  467. font-weight: bold;
  468. margin-bottom: 12rpx;
  469. display: block;
  470. }
  471. .content {
  472. font-size: 24rpx;
  473. color: #888;
  474. line-height: 1.7;
  475. }
  476. }
  477. .order-bottom {
  478. position: fixed;
  479. left: 0;
  480. right: 0;
  481. bottom: 0;
  482. background: #fff;
  483. display: flex;
  484. align-items: center;
  485. justify-content: flex-end;
  486. background: #fff;
  487. height: 88rpx;
  488. padding: 0 32rpx;
  489. box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.04);
  490. padding-bottom: var(--window-bottom);
  491. box-sizing: content-box;
  492. .total-wrap {
  493. display: flex;
  494. align-items: baseline;
  495. margin-right: 32rpx;
  496. .label {
  497. color: #b2b2b2;
  498. font-size: 28rpx;
  499. margin-right: 8rpx;
  500. }
  501. .price {
  502. color: #222;
  503. font-size: 32rpx;
  504. font-weight: bold;
  505. }
  506. }
  507. .submit-btn {
  508. background: #1f1f1f;
  509. color: #acf934;
  510. border-radius: 44rpx;
  511. font-size: 32rpx;
  512. font-weight: bold;
  513. width: 240rpx;
  514. height: 72rpx;
  515. text-align: center;
  516. line-height: 72rpx;
  517. margin-left: 12rpx;
  518. box-shadow: none;
  519. display: flex;
  520. align-items: center;
  521. justify-content: center;
  522. }
  523. }
  524. }
  525. .bom-reserveASeat {
  526. width: 100%;
  527. height: calc(var(--window-bottom) + 100rpx);
  528. }
  529. </style>