M_purchase.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <template>
  2. <view class="page">
  3. <view class="topBody">
  4. <PageHeader title="会员" class="PageHeader">
  5. <template v-slot:right>
  6. <DropdownMenu
  7. :options="dropdownOptions"
  8. @select="handleDropdownSelect"
  9. />
  10. </template>
  11. </PageHeader>
  12. <view class="reserveASeat"></view>
  13. <view class="myGoldCoin-box">
  14. <view>我的M币</view>
  15. <view class="myGoldCoin-box-content">
  16. <image src="../../static/icon/coin_m.png" mode="widthFix" />
  17. <text>{{ myGoldCoin }}</text>
  18. </view>
  19. </view>
  20. <view class="myinfo">
  21. <view class="purchaseList" style="margin-top: 60rpx">
  22. <view
  23. class="item"
  24. :class="index == sel ? 'itemSel' : ''"
  25. v-for="(item, index) in list"
  26. @click="selTA(item, index)"
  27. :key="index"
  28. >
  29. <view class="num1">
  30. <image src="../../static/icon/coin_m.png" mode="widthFix" />
  31. <view class="name">{{ item.num_gmm| formatNumberToK }} </view>
  32. </view>
  33. <view class="num2">
  34. <view class="name">{{ item.money }}{{ $t("txt.¥") }}</view>
  35. </view>
  36. </view>
  37. </view>
  38. <view class="jinchu">
  39. <text>{{ $t("txt.支付方式") }}</text>
  40. </view>
  41. <view v-if="isWeChatPay" class="mingxiList" @click="selPay('wechat')">
  42. <view class="left">
  43. <image
  44. class="icon"
  45. src="../../static/me/icon_wechat.png"
  46. mode="widthFix"
  47. />
  48. <text style="font-size: 28rpx; margin-left: 20rpx">{{
  49. $t("txt.微信支付")
  50. }}</text>
  51. </view>
  52. <view class="right">
  53. <image
  54. class="icon"
  55. :src="
  56. payType != 'wechat'
  57. ? '../../static/icon/wd_icon_gouxuan04.png'
  58. : '../../static/icon/wd_icon_gouxuan05.png'
  59. "
  60. mode="heightFix"
  61. />
  62. </view>
  63. </view>
  64. <!-- <view class="line"></view> -->
  65. <view class="mingxiList" @click="selPay('alipay')">
  66. <view class="left">
  67. <image
  68. class="icon"
  69. src="../../static/me/icon_alipay.png"
  70. mode="widthFix"
  71. />
  72. <text style="font-size: 28rpx; margin-left: 20rpx">{{
  73. $t("txt.支付宝支付")
  74. }}</text>
  75. </view>
  76. <view class="right">
  77. <image
  78. class="icon"
  79. :src="
  80. payType != 'alipay'
  81. ? '../../static/icon/wd_icon_gouxuan04.png'
  82. : '../../static/icon/wd_icon_gouxuan05.png'
  83. "
  84. mode="heightFix"
  85. />
  86. </view>
  87. </view>
  88. <!-- <view class="line"></view> -->
  89. <view class="agree">
  90. <view class="agree2" @click="agreeChk()">
  91. <image
  92. mode="widthFix"
  93. src="../../static/icon/wd_icon_gouxuan04.png"
  94. v-if="is_agree == 0"
  95. ></image>
  96. <image
  97. mode="widthFix"
  98. src="../../static/icon/wd_icon_gouxuan05.png"
  99. v-if="is_agree == 1"
  100. ></image>
  101. </view>
  102. <view>
  103. 同意
  104. <text class="xy" @click="goPage('/pages/AboutUs/pay_xy')">
  105. 《充值服务协议》 </text
  106. >,充值M币仅【萌创星球】使用点击查看
  107. <text class="xy" @click="goPage('yszc')"> 充值记录 </text>
  108. </view>
  109. </view>
  110. <view class="btn_submit" :class="{'btn-loading': isSubmitting}" @click="submitData">
  111. <text v-if="!isSubmitting">¥{{ money }}</text>
  112. <text v-if="!isSubmitting">确认充值</text>
  113. <view v-if="isSubmitting" class="loading-spinner"></view>
  114. </view>
  115. </view>
  116. <view class="blankHeight"></view>
  117. </view>
  118. <!-- 提示框 -->
  119. <DialogBox ref="DialogBox"></DialogBox>
  120. </view>
  121. </template>
  122. <script>
  123. import DropdownMenu from '@/components/DropdownMenu.vue'
  124. import { mapState } from 'vuex'
  125. export default {
  126. components: {
  127. DropdownMenu
  128. },
  129. computed: {
  130. ...mapState('hideModule', ['isWeChatPay'])
  131. },
  132. data() {
  133. return {
  134. title: "",
  135. sel: 1,
  136. payType: "wechat",
  137. list: [],
  138. money: 0,
  139. tid: 0,
  140. linkid: "",
  141. is_agree: 0,
  142. myGoldCoin: 0,
  143. dropdownOptions: [
  144. { label: '购买记录', type: 'vipRecord' }
  145. ],
  146. isSubmitting: false,
  147. lastClickTime: 0
  148. };
  149. },
  150. onLoad() {
  151. // setTimeout(function() {
  152. // uni.setNavigationBarColor({
  153. // frontColor: '#ffffff',
  154. // backgroundColor: '#00000000',
  155. // animation: {
  156. // duration: 400,
  157. // timingFunc: 'easeIn'
  158. // }
  159. // })
  160. // }, 200);
  161. },
  162. onShow() {
  163. this.loadData();
  164. let that = this;
  165. },
  166. methods: {
  167. onBack() {},
  168. goPage(page) {
  169. uni.navigateTo({
  170. url: page,
  171. });
  172. },
  173. selTA(item, se) {
  174. this.tid = item.id;
  175. this.sel = se;
  176. if (this.list != null && this.list != undefined) {
  177. this.money = this.list[se]["money"];
  178. }
  179. },
  180. selPay(se) {
  181. this.payType = se;
  182. },
  183. chkSel() {
  184. if (this.sel == 1) {
  185. this.sel = 0;
  186. } else {
  187. this.sel = 1;
  188. }
  189. },
  190. submitData() {
  191. const now = Date.now();
  192. if (now - this.lastClickTime < 3000) {
  193. uni.showToast({
  194. title: "请勿频繁点击",
  195. icon: "none"
  196. });
  197. return;
  198. }
  199. this.lastClickTime = now;
  200. if (this.isSubmitting) return;
  201. if (this.is_agree == 0) {
  202. uni.showToast({
  203. title: "请确认并选择协议",
  204. icon: "none",
  205. });
  206. return;
  207. }
  208. this.isSubmitting = true;
  209. let that = this;
  210. uni.request({
  211. url: this.$apiHost + "/Order/submit",
  212. data: {
  213. uuid: getApp().globalData.uuid,
  214. product_id: this.tid,
  215. type: "buyM",
  216. payType: this.payType,
  217. },
  218. header: {
  219. "content-type": "application/json",
  220. },
  221. success: (res) => {
  222. console.log("res-pay", res.data);
  223. if (res.data.success == "yes") {
  224. this.linkid = res.data.linkid;
  225. // 微信支付逻辑
  226. if (this.payType === "wechat") {
  227. uni.requestPayment({
  228. provider: "wxpay",
  229. orderInfo: {
  230. appid: res.data.wepay.appid,
  231. partnerid: res.data.wepay.partnerid,
  232. prepayid: res.data.wepay.prepayid,
  233. package: "Sign=WXPay",
  234. noncestr: res.data.wepay.noncestr,
  235. timestamp: res.data.wepay.timestamp,
  236. sign: res.data.wepay.sign
  237. },
  238. success(res) {
  239. console.log("微信支付成功:", res);
  240. setTimeout(function () {
  241. that.showPayCall();
  242. }, 1000);
  243. },
  244. fail(e) {
  245. console.log("微信支付失败:", e);
  246. uni.showToast({
  247. title: "支付失败,请重试",
  248. icon: "none"
  249. });
  250. }
  251. });
  252. }
  253. // 支付宝支付逻辑
  254. else if (this.payType === "alipay") {
  255. uni.requestPayment({
  256. provider: "alipay",
  257. orderInfo: res.data.ali_pay, // 直接使用后端返回的支付宝支付参数
  258. success(res) {
  259. console.log("支付宝支付成功:", res);
  260. setTimeout(function () {
  261. that.showPayCall();
  262. }, 1000);
  263. },
  264. fail(e) {
  265. console.log("支付宝支付失败:", e);
  266. uni.showToast({
  267. title: "支付失败,请重试",
  268. icon: "none"
  269. });
  270. }
  271. });
  272. }
  273. } else {
  274. uni.showToast({
  275. title: "创建订单失败,请联系客服",
  276. icon: "none",
  277. });
  278. }
  279. },
  280. fail: (err) => {
  281. console.log("请求失败:", err);
  282. uni.showToast({
  283. title: "网络错误,请重试",
  284. icon: "none"
  285. });
  286. },
  287. complete: () => {
  288. that.isSubmitting = false;
  289. }
  290. });
  291. },
  292. showPayCall() {
  293. let that = this;
  294. this.$refs["DialogBox"]
  295. .confirm({
  296. title: "提示",
  297. content: "我已经支付完成",
  298. DialogType: "inquiry",
  299. btn1: "否",
  300. btn2: "是",
  301. animation: 0,
  302. })
  303. .then((res) => {
  304. uni.request({
  305. url: this.$apiHost + "/Order/getstatus",
  306. data: {
  307. uuid: getApp().globalData.uuid,
  308. linkid: that.linkid,
  309. },
  310. header: {
  311. "content-type": "application/json",
  312. },
  313. success: (res) => {
  314. if (res.data.success == "yes") {
  315. uni.showToast({
  316. title: "充值成功",
  317. icon: "none",
  318. });
  319. } else {
  320. uni.showToast({
  321. title: "还未检测到充值状态,请稍后再试",
  322. icon: "none",
  323. });
  324. setTimeout(function () {
  325. that.showPayCall();
  326. }, 1000);
  327. }
  328. },
  329. complete: (com) => {},
  330. });
  331. });
  332. },
  333. loadData() {
  334. // 获取M币数量
  335. uni.request({
  336. url: this.$apiHost + '/My/getnum',
  337. method: 'GET',
  338. header: {
  339. 'content-type': 'application/json',
  340. 'sign': getApp().globalData.headerSign
  341. },
  342. data: {
  343. uuid: getApp().globalData.uuid
  344. },
  345. success: (res) => {
  346. console.log("获取用户M币数量:", res.data);
  347. if (res.data && res.data.num_gmm) {
  348. this.myGoldCoin = res.data.num_gmm;
  349. }
  350. }
  351. });
  352. // 获取充值列表
  353. uni.request({
  354. url: this.$apiHost + "/User/getCzList",
  355. data: {
  356. uuid: getApp().globalData.uuid,
  357. },
  358. header: {
  359. "content-type": "application/json",
  360. },
  361. success: (res) => {
  362. console.log("res", res.data);
  363. this.num = res.data.num;
  364. if (res.data.list != null && res.data.list != undefined) {
  365. this.list = res.data.list;
  366. this.tid = this.list[1]["id"];
  367. this.sel = 1;
  368. this.money = this.list[1]["money"];
  369. }
  370. },
  371. });
  372. },
  373. handleDropdownSelect(item) {
  374. switch (item.type) {
  375. case "vipRecord":
  376. uni.navigateTo({
  377. url: "/pages/vip/record?type=coin",
  378. });
  379. break;
  380. }
  381. },
  382. agreeChk() {
  383. if (this.is_agree == 0) {
  384. this.is_agree = 1;
  385. } else {
  386. this.is_agree = 0;
  387. }
  388. },
  389. },
  390. };
  391. </script>
  392. <style scoped lang="scss">
  393. @import "M_purchase.scss";
  394. .agree {
  395. width: 90%;
  396. margin: 0 auto;
  397. color: #666666;
  398. font-size: 24rpx;
  399. margin-top: 40rpx;
  400. display: flex;
  401. align-items: center;
  402. text-align: left;
  403. line-height: 32rpx;
  404. .agree2 {
  405. display: flex;
  406. flex-direction: row;
  407. justify-content: flex-start;
  408. align-items: center;
  409. padding-right: 8rpx;
  410. flex-shrink: 0;
  411. }
  412. .xy {
  413. color: #0084ff;
  414. display: inline;
  415. }
  416. image {
  417. width: 32rpx;
  418. height: 32rpx;
  419. }
  420. }
  421. .btn_submit {
  422. width: 626rpx;
  423. height: 88rpx;
  424. background: linear-gradient(90deg, #1f1f1f 0%, #444444 100%);
  425. border-radius: 76rpx;
  426. margin: 0 auto;
  427. margin-top: 70rpx;
  428. color: #acf934;
  429. display: flex;
  430. align-items: center;
  431. justify-content: center;
  432. font-size: 32rpx;
  433. line-height: 0;
  434. position: relative;
  435. overflow: hidden;
  436. transition: all 0.3s ease;
  437. &.btn-loading {
  438. opacity: 0.7;
  439. pointer-events: none;
  440. }
  441. .loading-spinner {
  442. width: 40rpx;
  443. height: 40rpx;
  444. border: 4rpx solid rgba(255, 255, 255, 0.3);
  445. border-radius: 50%;
  446. border-top-color: #fff;
  447. animation: spin 1s linear infinite;
  448. }
  449. text {
  450. font-size: 44rpx;
  451. display: inline-block;
  452. margin-right: 10rpx;
  453. }
  454. }
  455. @keyframes spin {
  456. to {
  457. transform: rotate(360deg);
  458. }
  459. }
  460. </style>