index.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. import {
  2. Image,
  3. Cell,
  4. CellGroup,
  5. Tag,
  6. Button,
  7. Stepper,
  8. Icon,
  9. Popup,
  10. showConfirmDialog,
  11. showToast
  12. } from 'vant';
  13. import { computed, defineComponent, onMounted, reactive } from 'vue';
  14. import styles from './index.module.less';
  15. import iconGift from './images/icon-gift.png';
  16. import shopEmpty from './images/shop-empty.png';
  17. import MSticky from '@/components/m-sticky';
  18. import MVideo from '@/components/m-video';
  19. import { useRoute, useRouter } from 'vue-router';
  20. import RegisterModal from './register-modal';
  21. import { useStudentRegisterStore } from '@/store/modules/student-register-store';
  22. import request from '@/helpers/request';
  23. import { moneyFormat } from '@/helpers/utils';
  24. import deepClone from '@/helpers/deep-clone';
  25. import { storage } from '@/helpers/storage';
  26. import { ACCESS_TOKEN } from '@/store/mutation-types';
  27. import OWxTip from '@/components/m-wx-tip';
  28. export default defineComponent({
  29. name: 'student-register',
  30. setup() {
  31. const route = useRoute();
  32. const studentRegisterStore = useStudentRegisterStore();
  33. const router = useRouter();
  34. // 初始化学校编号
  35. studentRegisterStore.setShoolId(route.query.sId as any);
  36. const forms = reactive({
  37. schoolId: route.query.sId as any,
  38. popupShow: false,
  39. popupRegister: false,
  40. details: [] as any[],
  41. schoolType: '', // 学校类型
  42. gradeYear: '', // 学制
  43. bugGoods: false, // 是否购买AI
  44. submitLoading: false
  45. });
  46. // 查询未支付订单
  47. const paymentOrderUnpaid = async () => {
  48. try {
  49. const { data } = await request.get('/edu-app/userPaymentOrder/unpaid');
  50. // 判断是否有待支付订单
  51. if (data.id) {
  52. await request.post(
  53. '/edu-app/userPaymentOrder/cancelPayment/' + data.orderNo
  54. );
  55. }
  56. } catch {
  57. //
  58. }
  59. };
  60. const getRegisterGoods = async () => {
  61. try {
  62. const { data } = await request.get(
  63. '/edu-app/open/userOrder/registerGoods/' + forms.schoolId,
  64. {
  65. noAuthorization: true // 是否请求接口的时候添加toekn
  66. }
  67. );
  68. // 默认选中商品
  69. studentRegisterStore.setVip(data.details || []);
  70. forms.details = deepClone(data.details || []);
  71. forms.bugGoods = data.bugGoods;
  72. forms.schoolType = data.schoolType;
  73. forms.gradeYear = data.gradeYear;
  74. } catch {}
  75. };
  76. // 计算金额
  77. const calcPrice = computed(() => {
  78. let amount: number = 0; //现价
  79. let originAmount: number = 0; // 原价
  80. const vipList: any[] = studentRegisterStore.getVip;
  81. vipList.forEach((vip: any) => {
  82. amount += Number(vip.currentPrice);
  83. originAmount += Number(vip.originalPrice);
  84. });
  85. const goodsList: any[] = studentRegisterStore.getGoods;
  86. goodsList.forEach((good: any) => {
  87. amount += Number(good.price) * good.quantity;
  88. originAmount += Number(good.originalPrice) * good.quantity;
  89. });
  90. return {
  91. amount,
  92. originAmount
  93. };
  94. });
  95. // 删除商品
  96. const onGoodsRemove = (item: any) => {
  97. showConfirmDialog({
  98. message: '是否删除该商品',
  99. confirmButtonColor: '#FF8633'
  100. }).then(() => {
  101. console.log(item, 'item');
  102. studentRegisterStore.deleteGoods(item.productSkuId);
  103. });
  104. };
  105. // 登记成功之后购买
  106. const onRegisterSubmit = async () => {
  107. try {
  108. forms.submitLoading = true;
  109. // 检测token是否失效
  110. const Authorization = storage.get(ACCESS_TOKEN) || '';
  111. const authInfo = await request.post('/edu-app/open/user/verification', {
  112. noAuthorization: true,
  113. data: { token: Authorization }
  114. });
  115. // 判断当前token是否失效
  116. if (!authInfo.data) {
  117. storage.remove(ACCESS_TOKEN);
  118. studentRegisterStore.deleteToken();
  119. forms.popupRegister = true;
  120. return;
  121. }
  122. // 请求是否有待支付订单,如果有则自动关闭
  123. await paymentOrderUnpaid();
  124. const schoolInfo = await request.get(
  125. '/edu-app/userPaymentOrder/registerStatus/' + forms.schoolId
  126. );
  127. const vipList = studentRegisterStore.getVip;
  128. const goodsList = studentRegisterStore.getGoods;
  129. if (schoolInfo.data.hasBuyCourse && vipList.length > 0) {
  130. setTimeout(() => {
  131. showToast('您已购买数字化器乐学练工具,请勿重复购买');
  132. }, 100);
  133. return;
  134. }
  135. const params: any[] = [];
  136. vipList.forEach((vip: any) => {
  137. params.push({
  138. goodsId: vip.goodsId,
  139. goodsNum: 1,
  140. goodsType: vip.goodsType,
  141. paymentCashAmount: vip.currentPrice, // 现金支付金额
  142. paymentCouponAmount: 0 // 优惠券金额
  143. });
  144. });
  145. goodsList.forEach((goods: any) => {
  146. params.push({
  147. goodsId: goods.productId,
  148. goodsNum: goods.quantity,
  149. goodsType: 'INSTRUMENTS',
  150. paymentCashAmount: goods.price, // 现金支付金额
  151. paymentCouponAmount: 0, // 优惠券金额
  152. goodsSkuId: goods.productSkuId
  153. });
  154. });
  155. // 创建订单
  156. const { data } = await request.post(
  157. '/edu-app/userPaymentOrder/executeOrder',
  158. {
  159. hideLoading: false,
  160. data: {
  161. paymentType: 'adapay',
  162. bizId: forms.schoolId, // 乐团编号
  163. orderType: 'SCHOOL_REGISTER',
  164. paymentCashAmount: calcPrice.value.amount || 0,
  165. paymentCouponAmount: 0,
  166. goodsInfos: params,
  167. orderName: '学生登记',
  168. orderDesc: '学生登记'
  169. }
  170. }
  171. );
  172. router.push({
  173. path: '/order-detail',
  174. query: {
  175. pm: 1, // h5乐团报名
  176. config: JSON.stringify({
  177. ...data.paymentConfig,
  178. paymentType: data.paymentType
  179. }),
  180. orderNo: data.orderNo
  181. }
  182. });
  183. } finally {
  184. forms.submitLoading = false;
  185. }
  186. };
  187. onMounted(() => {
  188. getRegisterGoods();
  189. });
  190. return () => (
  191. <div class={styles['student-register']}>
  192. <div class={styles.studentSection} style={{ marginTop: '18px' }}>
  193. <div class={styles.titleTool}></div>
  194. {forms.details.map((item: any) => (
  195. <CellGroup
  196. class={styles.goodsSection}
  197. onClick={() => {
  198. if (studentRegisterStore.selectedVip(item.goodsId)) {
  199. studentRegisterStore.deleteVip(item.goodsId);
  200. } else {
  201. studentRegisterStore.setVip([item]);
  202. }
  203. }}>
  204. <Cell border={false} class={styles.goodsCell}>
  205. {{
  206. icon: () => <Image class={styles.img} src={item.goodsUrl} />,
  207. title: () => (
  208. <div class={styles.section}>
  209. <div class={styles.sectionContent}>
  210. <h2>
  211. {item.goodsName}
  212. <Tag class={styles.brandName}>12个月</Tag>
  213. </h2>
  214. <p class={[styles.model]}>{item.description}</p>
  215. <div class={styles.sbtnGroup}>
  216. <span
  217. class={styles.btnDetail}
  218. onClick={(e: MouseEvent) => {
  219. e.stopPropagation();
  220. router.push('/student-digital-tools');
  221. }}>
  222. 查看详情
  223. </span>
  224. <span
  225. class={styles.btnVideo}
  226. onClick={(e: MouseEvent) => {
  227. e.stopPropagation();
  228. forms.popupShow = true;
  229. }}>
  230. 介绍视频
  231. </span>
  232. </div>
  233. </div>
  234. <i
  235. class={
  236. studentRegisterStore.selectedVip(item.goodsId)
  237. ? styles.selected
  238. : styles.noSelected
  239. }></i>
  240. </div>
  241. )
  242. }}
  243. </Cell>
  244. <Cell border={false} class={styles.priceCell}>
  245. {{
  246. title: () => (
  247. <div class={styles.sPriceGroup}>
  248. <div class={styles.tg}>
  249. 团购价:
  250. <span>
  251. <i>¥ </i>
  252. {moneyFormat(item.currentPrice)}
  253. </span>
  254. </div>
  255. {item.currentPrice < item.originalPrice && (
  256. <del>¥{moneyFormat(item.originalPrice)}</del>
  257. )}
  258. </div>
  259. )
  260. }}
  261. </Cell>
  262. <Cell border={false} class={styles.giftCell}>
  263. {{
  264. title: () => (
  265. <div class={styles.gift}>
  266. <img src={iconGift} class={styles.iconGift} />
  267. 现在购买赠送 <span>{item.membershipDays || 0}</span>
  268. 天有效期
  269. </div>
  270. )
  271. }}
  272. </Cell>
  273. </CellGroup>
  274. ))}
  275. </div>
  276. {forms.bugGoods && (
  277. <>
  278. <div class={styles.studentSection}>
  279. <div class={styles.titleBuy}></div>
  280. {studentRegisterStore.getGoods &&
  281. studentRegisterStore.getGoods.length <= 0 ? (
  282. <div class={styles.goodsEmpty}>
  283. <img src={shopEmpty} class={styles.shopImg} />
  284. <div class={styles.goodsContainer}>
  285. <h2>
  286. 为你的<span>音乐之旅</span>做好准备
  287. </h2>
  288. <p class={styles.tips}>快去选购乐器吧~</p>
  289. <Button
  290. class={styles.goSelect}
  291. type="primary"
  292. onClick={() => {
  293. router.push('/goods-list');
  294. }}>
  295. 进入商城选购
  296. <Icon name="arrow" />
  297. </Button>
  298. </div>
  299. </div>
  300. ) : (
  301. studentRegisterStore.getGoods.map(
  302. (goods: any, index: number) => (
  303. <CellGroup class={styles.goodsSection}>
  304. <Cell border={false} class={styles.goodsCell}>
  305. {{
  306. icon: () => (
  307. <Image class={styles.img} src={goods.pic} />
  308. ),
  309. title: () => (
  310. <div class={styles.section}>
  311. <div class={styles.sectionContent}>
  312. <h2>
  313. {goods.name}
  314. <Tag class={styles.brandName}>
  315. {goods.brandName}
  316. </Tag>
  317. </h2>
  318. <p class={[styles.model]}>
  319. 规格:{goods.spDataJson}
  320. </p>
  321. <p class={[styles.model]}>{goods.productSn}</p>
  322. <Stepper
  323. min={1}
  324. max={99}
  325. v-model={goods.quantity}
  326. />
  327. </div>
  328. <i
  329. class={styles.delete}
  330. onClick={() => onGoodsRemove(goods)}></i>
  331. </div>
  332. )
  333. }}
  334. </Cell>
  335. <Cell border={false} class={styles.priceCell}>
  336. {{
  337. title: () => (
  338. <div class={styles.sPriceGroup}>
  339. <div class={styles.tg}>
  340. 团购价:
  341. <span>
  342. <i>¥ </i>
  343. {moneyFormat(goods.price)}
  344. </span>
  345. </div>
  346. {goods.price < goods.originalPrice && (
  347. <del>¥{moneyFormat(goods.originalPrice)}</del>
  348. )}
  349. </div>
  350. )
  351. }}
  352. </Cell>
  353. </CellGroup>
  354. )
  355. )
  356. )}
  357. </div>
  358. {studentRegisterStore.getGoods &&
  359. studentRegisterStore.getGoods.length > 0 && (
  360. <Button
  361. class={styles.addButton}
  362. block
  363. onClick={() => {
  364. router.push('/goods-list');
  365. }}>
  366. <Icon name="add-o" />
  367. 进入商城选购
  368. </Button>
  369. )}
  370. </>
  371. )}
  372. <MSticky position="bottom">
  373. <div class={styles.paymentContainer}>
  374. <div class={styles.payemntPrice}>
  375. <span class={styles.needPrice}>
  376. <i style="font-style: normal">¥ </i>
  377. <span>{moneyFormat(calcPrice.value.amount)}</span>
  378. </span>
  379. <del class={styles.allPrice}>
  380. ¥ {moneyFormat(calcPrice.value.originAmount)}
  381. </del>
  382. </div>
  383. <div
  384. class={styles.paymentBtn}
  385. onClick={() => {
  386. const vipList = studentRegisterStore.getVip;
  387. const goodsList = studentRegisterStore.getGoods;
  388. if (vipList.length <= 0 && goodsList.length <= 0) {
  389. setTimeout(() => {
  390. showToast('请选择需要购买的商品');
  391. }, 100);
  392. return;
  393. }
  394. if (!studentRegisterStore.getToken) {
  395. forms.popupRegister = true;
  396. } else {
  397. onRegisterSubmit();
  398. }
  399. }}>
  400. <Button
  401. disabled={forms.submitLoading}
  402. loading={forms.submitLoading}>
  403. 确认购买
  404. </Button>
  405. </div>
  406. </div>
  407. </MSticky>
  408. <Popup v-model:show={forms.popupShow} class={styles.videoPopup}>
  409. {forms.popupShow && (
  410. <MVideo
  411. src={'https://daya.ks3-cn-beijing.ksyun.com/202105/SWmqmvW.mp4'}
  412. />
  413. )}
  414. </Popup>
  415. <Popup
  416. v-model:show={forms.popupRegister}
  417. class={styles.registerPopup}
  418. position="bottom"
  419. round>
  420. <RegisterModal
  421. schoolId={forms.schoolId}
  422. schoolType={forms.schoolType}
  423. gradeYear={forms.gradeYear}
  424. onClose={() => (forms.popupRegister = false)}
  425. onSubmit={onRegisterSubmit}
  426. />
  427. </Popup>
  428. {/* 是否在微信中打开 */}
  429. {/* <OWxTip /> */}
  430. </div>
  431. );
  432. }
  433. });