index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import { Button, Cell, Icon, Image, showConfirmDialog } from 'vant';
  2. import { defineComponent } from 'vue';
  3. import styles from './index.module.less';
  4. import request from '@/helpers/request';
  5. import iconStudent from '@common/images/icon-student.png';
  6. import iconMemberLogo from './images/member_logo.png';
  7. import iconGift from '../student-register/images/icon-gift.png';
  8. import { moneyFormat } from '@/helpers/utils';
  9. import OHeader from '@/components/m-header';
  10. import member1 from './images/member-1.png';
  11. import member2 from './images/member-2.png';
  12. import ODialog from '@/components/m-dialog';
  13. import { useEventListener, useWindowScroll } from '@vueuse/core';
  14. import dayjs from 'dayjs';
  15. export default defineComponent({
  16. name: 'MemberCenter',
  17. data() {
  18. return {
  19. functionList: [] as any,
  20. selectMember: {} as any,
  21. users: {} as any,
  22. memberStatus: false,
  23. background: 'transparent',
  24. color: '#fff',
  25. showTips: false,
  26. showMessage: ''
  27. };
  28. },
  29. computed: {
  30. userInfo() {
  31. const users: any = this.users;
  32. return {
  33. username: users?.nickname || '',
  34. phone: users?.phone || '',
  35. avatar: users?.avatar,
  36. id: users?.id,
  37. isVip: users?.vipMember,
  38. membershipGiftDays: users?.membershipGiftDays,
  39. membershipDays: users?.membershipDays,
  40. membershipEndTime: dayjs(users?.membershipEndTime).format('YYYY-MM-DD')
  41. };
  42. }
  43. },
  44. async mounted() {
  45. useEventListener(document, 'scroll', () => {
  46. const { y } = useWindowScroll();
  47. if (y.value > 15) {
  48. this.background = '#fff';
  49. this.color = '#323333';
  50. } else {
  51. this.background = 'transparent';
  52. this.color = '#fff';
  53. }
  54. });
  55. //
  56. this.__init();
  57. },
  58. methods: {
  59. async __init() {
  60. try {
  61. const userInfo = await request.get('/edu-app/student/member');
  62. this.users = userInfo.data || {};
  63. const { data } = await request.post(`/edu-app/cityFeeSetting/member`);
  64. this.selectMember = data;
  65. this.paymentOrderUnpaid();
  66. } catch {
  67. //
  68. }
  69. },
  70. // 查询未支付订单
  71. async paymentOrderUnpaid() {
  72. try {
  73. const { data } = await request.get('/edu-app/userPaymentOrder/unpaid', {
  74. requestType: 'form',
  75. params: {
  76. paymentType: 'VIP'
  77. }
  78. });
  79. // 判断是否有待支付订单
  80. if (data.id) {
  81. showConfirmDialog({
  82. message: '您有待支付的订单,是否继续支付',
  83. cancelButtonText: '取消订单',
  84. confirmButtonText: '继续支付'
  85. })
  86. .then(() => {
  87. const paymentConfig = data.paymentConfig;
  88. this.$router.push({
  89. path: '/order-detail',
  90. query: {
  91. config: JSON.stringify(paymentConfig.paymentConfig),
  92. orderNo: paymentConfig.orderNo
  93. }
  94. });
  95. })
  96. .catch(async () => {
  97. try {
  98. await request.post(
  99. '/edu-app/userPaymentOrder/cancelPayment/' + data.orderNo
  100. );
  101. } catch {
  102. //
  103. }
  104. });
  105. }
  106. } catch {
  107. //
  108. }
  109. },
  110. calcSalePrice(item: any) {
  111. // discount
  112. if (item.discount === 1) {
  113. const tempPrice = Number(
  114. (item.salePrice - item.discountPrice).toFixed(2)
  115. );
  116. return tempPrice >= 0 ? tempPrice : 0;
  117. }
  118. return item.salePrice;
  119. },
  120. // 购买
  121. async onSubmit() {
  122. try {
  123. const selectMember = this.selectMember;
  124. const params: any = [
  125. {
  126. giftVipDay: this.users.membershipGiftDays,
  127. goodsId: selectMember.id,
  128. goodsNum: 1,
  129. goodsType: 'VIP',
  130. paymentCashAmount: selectMember.salePrice, // 现金支付金额
  131. paymentCouponAmount: 0 // 优惠券金额
  132. }
  133. ]; // 支付参数
  134. // 创建订单
  135. const result = await request.post(
  136. '/edu-app/userPaymentOrder/executeOrder',
  137. {
  138. data: {
  139. orderType: 'VIP',
  140. paymentCashAmount: this.selectMember.salePrice || 0,
  141. paymentCouponAmount: 0,
  142. goodsInfos: params,
  143. orderName: '乐器AI学练工具',
  144. orderDesc: '乐器AI学练工具'
  145. }
  146. }
  147. );
  148. if (result.code === 5435) {
  149. this.showTips = true;
  150. this.showMessage = result.message;
  151. return;
  152. }
  153. const data = result.data;
  154. const res = await request.get(
  155. '/edu-app/userPaymentOrder/detail/' + data.orderNo
  156. );
  157. if (res.data.status !== 'WAIT_PAY' && res.data.status !== 'PAYING') {
  158. this.$router.push({
  159. path: '/payment-result',
  160. query: {
  161. orderNo: data.orderNo
  162. }
  163. });
  164. } else {
  165. this.$router.push({
  166. path: '/order-detail',
  167. query: {
  168. config: JSON.stringify({
  169. ...data.paymentConfig,
  170. paymentType: data.paymentType
  171. }),
  172. orderNo: data.orderNo
  173. }
  174. });
  175. }
  176. } catch (e: any) {
  177. //
  178. console.log(e);
  179. }
  180. }
  181. },
  182. render() {
  183. return (
  184. <div class={styles['member-center']}>
  185. <OHeader
  186. background={this.background}
  187. color={this.color}
  188. border={false}
  189. />
  190. <div class={styles.member_container}>
  191. <Cell
  192. class={[styles.userMember]}
  193. labelClass={styles.timeRemaining}
  194. center
  195. v-slots={{
  196. icon: () => (
  197. <div class={styles.userImgSection}>
  198. <Image
  199. class={styles.userImg}
  200. src={this.userInfo.avatar || iconStudent}
  201. fit="cover"
  202. />
  203. </div>
  204. ),
  205. title: () => (
  206. <div class={styles.userInfo}>
  207. <span class={styles.name}>{this.userInfo.username}</span>
  208. {!!this.userInfo.isVip && (
  209. <Image class={styles.level} src={iconMemberLogo} />
  210. )}
  211. {this.userInfo.phone && (
  212. <span
  213. class={styles.phone}
  214. v-html={`(${this.userInfo.phone})`}></span>
  215. )}
  216. </div>
  217. ),
  218. label: () => (
  219. <div class={styles.member_time}>
  220. <>
  221. {this.userInfo.isVip ? (
  222. <div>
  223. {/* 使用有效期剩余
  224. <span class={styles.remaining}>
  225. {this.userInfo.membershipDays}
  226. </span>
  227. 天 */}
  228. 有效期至
  229. <span class={styles.remaining}>
  230. {this.userInfo.membershipEndTime}
  231. </span>
  232. </div>
  233. ) : (
  234. <div>您还未领取器乐学练工具哟</div>
  235. )}
  236. </>
  237. </div>
  238. )
  239. }}></Cell>
  240. </div>
  241. <div class={[styles.memberContainer]}>
  242. <div
  243. class={[
  244. styles.memberItem,
  245. this.users.membershipGiftDays > 0 ? styles.memberGift : ''
  246. ]}>
  247. <p class={[styles.title]}>
  248. 乐器AI学练工具
  249. <span>12个月</span>
  250. </p>
  251. <div class={styles.priceGroup}>
  252. <p class={styles.price}>
  253. <span>¥</span>
  254. {moneyFormat(this.selectMember.salePrice)}
  255. </p>
  256. {this.selectMember.salePrice <
  257. this.selectMember.originalPrice && (
  258. <del class={styles.originalPrice}>
  259. ¥{moneyFormat(this.selectMember.originalPrice)}
  260. </del>
  261. )}
  262. </div>
  263. {this.users.membershipGiftDays > 0 && (
  264. <Cell border={false} class={styles.giftCell}>
  265. {{
  266. title: () => (
  267. <div class={styles.gift}>
  268. <img src={iconGift} class={styles.iconGift} />
  269. 现在领取赠送{' '}
  270. <span>{this.users.membershipGiftDays || 0}</span>
  271. 天有效期
  272. </div>
  273. )
  274. }}
  275. </Cell>
  276. )}
  277. </div>
  278. <div class={styles.memberImgs}>
  279. <img src={member1} />
  280. <img src={member2} />
  281. </div>
  282. </div>
  283. <div class={styles.btnGroup}>
  284. <div class={styles.priceSection}>
  285. <div class={styles.price}>
  286. <span class={styles.priceUnit}>¥</span>
  287. <span class={styles.priceNum}>
  288. {moneyFormat(this.calcSalePrice(this.selectMember) || 0)}
  289. </span>
  290. </div>
  291. {this.selectMember.originalPrice >
  292. this.calcSalePrice(this.selectMember) || 0 ? (
  293. <del class={styles.allPrice}>
  294. ¥ {moneyFormat(this.selectMember.originalPrice)}
  295. </del>
  296. ) : (
  297. ''
  298. )}
  299. </div>
  300. {this.userInfo.id ? (
  301. <Button round class={styles.btn} onClick={this.onSubmit}>
  302. 立即领取
  303. </Button>
  304. ) : (
  305. ''
  306. )}
  307. </div>
  308. <ODialog
  309. v-model:show={this.memberStatus}
  310. title="待激活团练宝"
  311. message="为让团员有效使用乐团学习工具,首次加入乐团且购买团练宝的团员,团练宝的生效时间为乐团首次训练之日,具体训练时间可查看课表。"
  312. messageAlign="left"
  313. dialogMarginTop="env(safe-area-inset-top)"
  314. confirmButtonText="我知道了"
  315. />
  316. <ODialog
  317. v-model:show={this.showTips}
  318. title="温馨提示"
  319. message={this.showMessage}
  320. messageAlign="center"
  321. dialogMarginTop="env(safe-area-inset-top)"
  322. confirmButtonText="刷新"
  323. onConfirm={async () => {
  324. // window.location.reload();
  325. window.scrollTo({
  326. top: 0,
  327. behavior: 'smooth'
  328. });
  329. this.__init();
  330. }}
  331. />
  332. </div>
  333. );
  334. }
  335. });