index-apply.tsx 87 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433
  1. import {
  2. Image,
  3. Cell,
  4. Tag,
  5. Button,
  6. Popup,
  7. showToast,
  8. Form,
  9. Field,
  10. CountDown,
  11. RadioGroup,
  12. Radio,
  13. Picker,
  14. closeToast,
  15. Popover
  16. } from 'vant';
  17. import {
  18. computed,
  19. defineComponent,
  20. nextTick,
  21. onMounted,
  22. onUnmounted,
  23. reactive,
  24. ref
  25. } from 'vue';
  26. import qs from 'query-string';
  27. import {
  28. state as baseState,
  29. goWechatAuth,
  30. setLogin,
  31. setLoginInit
  32. } from '@/state';
  33. import styles from './index-apply.module.less';
  34. import MSticky from '@/components/m-sticky';
  35. // import MVideo from '@/components/m-video';
  36. import { useRoute, useRouter } from 'vue-router';
  37. import { useStudentRegisterStore } from '@/store/modules/student-register-store';
  38. import request from '@/helpers/request';
  39. import requestStudent from './request';
  40. import { browser, checkPhone, getHttpOrigin, getUrlCode, moneyFormat, convertToChineseNumber } from '@/helpers/utils';
  41. import deepClone from '@/helpers/deep-clone';
  42. import OWxTip from '@/components/m-wx-tip';
  43. import MDialog from '@/components/m-dialog';
  44. // import f1 from './images/new/f-1.png';
  45. // import f2 from './images/new/f-2.png';
  46. // import f3 from './images/new/f-3.png';
  47. // import iconTip2 from './images/new/icon-tip2.png';
  48. // import functionBg from './images/new/function-bg.png';
  49. import tuangou from './images/new/tuangou.png';
  50. import icon3 from './images/new/icon-3.png';
  51. import icon5 from './images/new/icon-5.png';
  52. import icon10 from './images/new/icon-10.png';
  53. import icon6 from './images/new/icon-6.png';
  54. import giftTip from './images/new/icon-9.png';
  55. import iconGift from './images/new/icon-gift.png';
  56. import vipGiftTIps from './images/new/vip_gift_tips.png';
  57. import dayjs from 'dayjs';
  58. // import MMessageTip from '@/components/m-message-tip';
  59. import { CurrentTime, useCountDown } from '@vant/use';
  60. import Payment from '../adapay/payment';
  61. import QrcodePayment from './qrcode-payment';
  62. import MImgCode from '@/components/m-img-code';
  63. import { beforeSubmit } from './order-state';
  64. import { useInterval, useIntervalFn } from '@vueuse/core';
  65. import MPopup from '@/components/m-popup';
  66. import UserAuth from './component/user-auth';
  67. import MMessageTip from '@/components/m-message-tip';
  68. import SelectStudent from './modal/select-student';
  69. import { vipGiftPeriodType } from '.';
  70. import tipTitleIcon from './images/tip-title-icon.png';
  71. import tipIcon1 from './images/tip1-icon.png';
  72. import tipIcon2 from './images/tip2-icon.png';
  73. import tipIcon3 from './images/tip3-icon.png';
  74. import tipBtnIcon from './images/tip-btn-icon.png';
  75. import giftBoxTitleIcon from './images/gift-box-title.png';
  76. import giftExtraTitleIcon from './images/gift-tip-icon.png';
  77. import giftExtraTitleIcon2 from './images/gift-tip-icon2.png';
  78. import giftCard1Icon from './images/gift_card1.png';
  79. import giftCard2Icon from './images/gift_card2.png';
  80. import giftZsIcon from './images/gift_zs_icon.png';
  81. import selectZsTip from './images/select_zs_tip.png';
  82. import useWeChatShare from '@/hooks/useWeChatShare';
  83. const classList: any = [];
  84. for (let i = 1; i <= 40; i++) {
  85. classList.push({ text: i + '班', value: i });
  86. }
  87. const GRADE_ENUM = {
  88. '1': '一年级',
  89. '2': '二年级',
  90. '3': '三年级',
  91. '4': '四年级',
  92. '5': '五年级',
  93. '6': '六年级',
  94. '7': '七年级',
  95. '8': '八年级',
  96. '9': '九年级'
  97. } as any;
  98. const getGradeList = (gradeYear: string, instrumentCode?: string) => {
  99. let tempList: any = [];
  100. const five = [
  101. { text: '一年级', value: 1, instrumentCode },
  102. { text: '二年级', value: 2, instrumentCode },
  103. { text: '三年级', value: 3, instrumentCode },
  104. { text: '四年级', value: 4, instrumentCode },
  105. { text: '五年级', value: 5, instrumentCode }
  106. ];
  107. const one = [{ text: '六年级', value: 6, instrumentCode }];
  108. const three = [
  109. { text: '七年级', value: 7, instrumentCode },
  110. { text: '八年级', value: 8, instrumentCode },
  111. { text: '九年级', value: 9, instrumentCode }
  112. ];
  113. if (gradeYear === 'FIVE_YEAR_SYSTEM') {
  114. tempList.push(...[...five]);
  115. } else if (gradeYear === 'SIX_YEAR_SYSTEM') {
  116. tempList.push(...[...five, ...one]);
  117. } else if (gradeYear === 'THREE_YEAR_SYSTEM') {
  118. tempList.push(...[...three]);
  119. } else if (gradeYear === 'FORE_YEAR_SYSTEM') {
  120. tempList.push(...[...one, ...three]);
  121. } else {
  122. tempList.push(...[...five, ...one, ...three]);
  123. }
  124. return tempList;
  125. };
  126. export default defineComponent({
  127. name: 'student-register',
  128. setup() {
  129. const weChatShare = useWeChatShare(
  130. '音乐(器乐)数字AI团购通道',
  131. '智慧旋律,告别枯燥练习。借助科技的光芒,我们让音乐跨越山海,抵达每一个角落,点亮每一颗童心',
  132. window.location.origin + '/classroom-app/shareImg/instrument-share.png'
  133. );
  134. const route = useRoute();
  135. const studentRegisterStore = useStudentRegisterStore();
  136. const router = useRouter();
  137. // document.title = route.query.rt === 'MUST_BUY_GOODS' ? '音乐(器乐)数字AI团购通道' : '报名通道';
  138. // 初始化学校编号
  139. studentRegisterStore.setShoolId(route.query.sId as any);
  140. const countDownRef = ref();
  141. const mstickyRef = ref();
  142. const forms = reactive({
  143. schoolId: route.query.sId as any,
  144. paymentType: '', // 支付类型
  145. paymentChannel: '',
  146. multi_user_limit: 1, // 限制注册学生数量
  147. // popupShow: false,
  148. registerDetails: {} as any,
  149. details: [] as any[],
  150. // schoolType: '', // 学校类型
  151. gradeYear: '', // 学制
  152. schoolInstrumentSetType: null as any,
  153. // bugGoods: false, // 是否购买AI
  154. isRegister: 'create' as 'create' | 'update' | '', // 是否注册学生
  155. isTipRegister: false, // 是否显示名字不一致 - 默认显示
  156. isChangeSchool: false, // 是否切换学校
  157. registerType: '', // 报名类型
  158. detailVip: {} as any,
  159. giftVipDay: 0, // 赠送天数
  160. submitLoading: false,
  161. // showMore: true,
  162. showTips: false,
  163. showButton: false,
  164. showMessage: '请使用微信扫描二维码',
  165. countDownStatus: true,
  166. countDownTime: 1000 * 120, // 倒计时时间
  167. // modelValue: false, // 是否选中协议
  168. imgCodeStatus: false,
  169. gradeNumText: '',
  170. currentClassText: '',
  171. gradeStatus: false,
  172. classStatus: false,
  173. loading: false,
  174. dialogStatus: false,
  175. dialogMessage: '',
  176. confirmButtonText: '确定',
  177. cancelButtonText: '取消',
  178. messageAlign: 'center' as 'left' | 'center' | 'right',
  179. tipStatus: true,
  180. dialogConfirmStatus: false,
  181. contract_sign: false, // 是否实名认证
  182. countDownTimePay: 60 * 1000,
  183. dialogConfig: {} as any,
  184. showSelectStudent: false, // 选择学生
  185. studentList: [], // 手机号关联学生列表
  186. studentItem: {} as any, // 选择的学生
  187. joinType: 'digitalize' as 'digitalize' | 'tradition',
  188. gradeList: [] as any,
  189. classList: [] as any,
  190. saveUserId: null as any,
  191. saveId: null as any,
  192. openId: null as any,
  193. code: null as any,
  194. intervalFnRef: null as any, // 页面订时器
  195. registerExpireTime: null as any, // 结束时间
  196. instrumentCode: null as any, // 乐器编码
  197. activeOverTime: 0, // 活动结束时间
  198. activeOverStatus: true, // 活动是否结束 默认已结束
  199. gradePopupShow: false,
  200. gradePopupIndex: [] as any, // 年级下拉索引
  201. classPopupShow: false,
  202. classPopupIndex: [] as any // 班级下拉索引
  203. });
  204. const otherParams = reactive({
  205. showOtherSchool: false,
  206. showCloseButton: true, // 是否显示关闭按钮
  207. showOtherMessage: '',
  208. /** limit 超限制,change 更换学生,nickname 名称不一致 member 会员购买, payment 支付方式 */
  209. otherType: '' as 'limit' | 'change' | 'nickname' | 'member' | 'payment',
  210. showCancelButton: true,
  211. cancelButtonColor: '',
  212. cancelButtonText: '取消',
  213. showConfirmButton: true,
  214. confirmButtonColor: '',
  215. confirmButtonText: '确定',
  216. messageAlign: 'left' as 'center' | 'left' | 'right'
  217. });
  218. const state = reactive({
  219. showQrcode: false,
  220. qrCodeUrl: '',
  221. pay_channel: '',
  222. orderInfo: {} as any, // 订单信息
  223. authShow: false,
  224. orderNo: null as any,
  225. config: {} as any,
  226. paymentStatus: false,
  227. orderTimer: null as any,
  228. tipBoxPop: false, // 团购政策提示弹窗
  229. intrumentList: [] as any, // 赠送的乐器列表
  230. currentIntrument: null as any, // 当前匹配上的乐器
  231. giftDesc: '' as any, // 团购政策,赠送会员的提示信息
  232. descSecondsNum: 3, // 倒计时
  233. hideSecondsNum: false, // 隐藏倒计时文字
  234. });
  235. /*
  236. 新用户:
  237. autoRegister: true
  238. loginType: 'SMS'
  239. 已存在用户:
  240. autoRegister: false
  241. loginType: 'TOKEN'
  242. password: xxx
  243. */
  244. const studentInfo = reactive({
  245. autoRegister: true,
  246. multiUser: true, // 是否为多用户
  247. client_id: 'cooleshow-student',
  248. client_secret: 'cooleshow-student',
  249. extra: {
  250. nickname: '',
  251. currentGradeNum: '' as any,
  252. currentClass: '' as any,
  253. gender: 1 as any,
  254. registerType: null as any, // 报名类型
  255. giftVipDay: 0 // 赠送会员天数
  256. },
  257. grant_type: 'password',
  258. loginType: 'SMS',
  259. password: '',
  260. username: ''
  261. });
  262. // 页面定时
  263. const pageTimer = useInterval(1000, { controls: true });
  264. pageTimer.pause();
  265. const overCountDown = useCountDown({
  266. time: forms.activeOverTime,
  267. onFinish() {
  268. forms.activeOverStatus = true;
  269. if (forms.submitLoading) return;
  270. applyOver();
  271. }
  272. });
  273. /** 报名结束提示 */
  274. const applyOver = () => {
  275. forms.showTips = true;
  276. // forms.showMessage = '团购时间已截止,感谢您的参与';
  277. forms.showMessage =
  278. '<p style="color: #F44541">报名已截止,感谢您的参与</p>';
  279. forms.showButton = false;
  280. forms.intervalFnRef?.pause();
  281. };
  282. const onCodeSend = () => {
  283. forms.countDownStatus = false;
  284. nextTick(() => {
  285. countDownRef.value.start();
  286. });
  287. };
  288. const onSendCode = () => {
  289. // 发送验证码
  290. if (!checkPhone(studentInfo.username)) {
  291. return showToast('请输入正确的手机号码');
  292. }
  293. forms.imgCodeStatus = true;
  294. };
  295. const validatePhone = computed(() => {
  296. return checkPhone(studentInfo.username) ? true : false;
  297. });
  298. const onFinished = () => {
  299. forms.countDownStatus = true;
  300. countDownRef.value.reset();
  301. };
  302. const orderType = computed(() => {
  303. return state.orderInfo.orderType;
  304. });
  305. const getRegisterGoods = async () => {
  306. try {
  307. const { data } = await request.get(
  308. '/edu-app/open/userOrder/registerGoods/' + forms.schoolId,
  309. {
  310. noAuthorization: true // 是否请求接口的时候添加toekn
  311. }
  312. );
  313. // 默认选中商品
  314. studentRegisterStore.setVip(data.details || []);
  315. forms.details = deepClone(data.details || []);
  316. forms.registerDetails = data;
  317. forms.registerExpireTime = data.registerExpireTime; // '2024-03-27 17:33:52'; //
  318. if (forms.registerExpireTime) {
  319. if (dayjs(new Date()).isBefore(forms.registerExpireTime)) {
  320. // 活动没有结束
  321. forms.activeOverStatus = false;
  322. // 默认返回毫秒
  323. forms.activeOverTime = dayjs(forms.registerExpireTime).diff(
  324. dayjs(new Date())
  325. );
  326. overCountDown.reset(forms.activeOverTime);
  327. overCountDown.start();
  328. } else {
  329. applyOver();
  330. forms.activeOverStatus = true;
  331. }
  332. }
  333. if (forms.details.length > 0) {
  334. forms.detailVip = forms.details[0];
  335. const { giftPeriod, giftFlag, giftVipDay } = forms.detailVip
  336. forms.detailVip.zsUnit = giftPeriod === 'DAY' ? '天' : giftPeriod === 'MONTH' ? '月' : giftPeriod === 'YEAR' ? '年' : '天'
  337. /**
  338. * 计算赠品原价
  339. * giftFlag: 是否赠送会员
  340. * giftVipDay: 赠送天数
  341. * giftPeriod: 赠送单位,'DAY','MONTH', 'YEAR'(天月年)
  342. * 原价取值:学校管理-会员原价
  343. * 按天赠送:会员原价/365*赠送天数
  344. * 按月赠送:就会员原价/12*赠送月数
  345. * 按年赠送:就会员原价*年数
  346. */
  347. if (giftFlag) {
  348. if (giftPeriod === 'YEAR') {
  349. const preNum = convertToChineseNumber(giftVipDay)
  350. const totalNum = convertToChineseNumber(giftVipDay+1)
  351. state.giftDesc = `买一赠${preNum},即<span>团购一年,使用${totalNum}年</span>`
  352. } else {
  353. state.giftDesc = `团购一年,<span>赠送${giftVipDay}${forms.detailVip.zsUnit}有效期</span>`
  354. }
  355. }
  356. // forms.giftVipDay = forms.details[0].membershipDays;
  357. }
  358. forms.giftVipDay = data.giftVipDay || 0;
  359. forms.gradeYear = data.gradeYear;
  360. forms.schoolInstrumentSetType = data.schoolInstrumentSetType;
  361. forms.registerType = data.registerType;
  362. studentInfo.extra.registerType = data.registerType;
  363. const schoolInstrumentList = data.schoolInstrumentList || [];
  364. state.intrumentList = schoolInstrumentList
  365. if (data.schoolInstrumentSetType === 'SCHOOL' && forms.registerType === 'MUST_BUY_GOODS') {
  366. state.currentIntrument = schoolInstrumentList[0] || null
  367. }
  368. if (data.schoolInstrumentSetType === 'SCHOOL') {
  369. const instrumentCode = schoolInstrumentList[0]?.instrumentCode;
  370. forms.gradeList = getGradeList(data.gradeYear, instrumentCode);
  371. forms.classList = classList;
  372. } else if (data.schoolInstrumentSetType === 'GRADE') {
  373. schoolInstrumentList.forEach((item: any) => {
  374. forms.gradeList.push({
  375. text: GRADE_ENUM[item.gradeNum],
  376. value: item.gradeNum,
  377. instrumentId: item.instrumentId,
  378. instrumentCode: item.instrumentCode
  379. });
  380. });
  381. forms.gradeList.sort((a: any, b: any) => a.value - b.value);
  382. forms.classList = classList;
  383. } else if (data.schoolInstrumentSetType === 'CLASS') {
  384. // 班级
  385. const tempGradeList: any[] = [];
  386. schoolInstrumentList.forEach((item: any) => {
  387. if (!tempGradeList.includes(item.gradeNum)) {
  388. tempGradeList.push(item.gradeNum);
  389. }
  390. });
  391. const lastGradeList: any[] = [];
  392. tempGradeList.forEach((temp: any) => {
  393. const list = {
  394. text: GRADE_ENUM[temp],
  395. value: temp,
  396. instrumentId: '',
  397. instrumentCode: '',
  398. instrumentName: '',
  399. classList: [] as any
  400. };
  401. schoolInstrumentList.forEach((item: any) => {
  402. if (temp === item.gradeNum) {
  403. list.instrumentId = item.instrumentId;
  404. list.instrumentCode = item.instrumentCode;
  405. list.instrumentName = item.instrumentName;
  406. list.classList.push({
  407. text: item.classNum + '班',
  408. value: item.classNum,
  409. instrumentCode: item.instrumentCode
  410. });
  411. }
  412. });
  413. // 排序班级
  414. list.classList.sort((a: any, b: any) => a.value - b.value);
  415. lastGradeList.push(list);
  416. });
  417. console.log('显示11',schoolInstrumentList)
  418. lastGradeList.sort((a: any, b: any) => a.value - b.value);
  419. forms.gradeList = lastGradeList;
  420. forms.classList = [];
  421. } else {
  422. forms.gradeList = getGradeList(data.gradeYear);
  423. forms.classList = classList;
  424. }
  425. if (browser().weixin) {
  426. // if (
  427. // data.schoolStatus === 0 &&
  428. // forms.schoolId == '1770035687490105346'
  429. // ) {
  430. // forms.showTips = true;
  431. // forms.showMessage = '<p style="color: #F44541">报名已截止,感谢您的参与</p>';
  432. // forms.showButton = false;
  433. // return;
  434. // }
  435. /**
  436. * ['MUST_BUY_GOODS', 'SELECT_BUY_GOODS'].includes(
  437. data.registerType
  438. ))
  439. */
  440. if (
  441. (route.query.rt && route.query.rt !== data.registerType) ||
  442. data.schoolStatus === 0
  443. ) {
  444. forms.showTips = true;
  445. forms.showMessage = '二维码已经失效,详情请咨询学校老师';
  446. forms.showButton = false;
  447. return;
  448. }
  449. } else {
  450. forms.showTips = true;
  451. return;
  452. }
  453. // 判断是否有倒计时,倒计时是滞结束
  454. if (!forms.registerExpireTime || !forms.activeOverStatus) {
  455. pagePointInit();
  456. }
  457. } catch {}
  458. };
  459. // 计算金额
  460. const calcPrice = computed(() => {
  461. let amount: number = 0; //现价
  462. let originAmount: number = 0; // 原价
  463. const vipList: any[] = studentRegisterStore.getVip;
  464. vipList.forEach((vip: any) => {
  465. amount +=
  466. forms.joinType === 'digitalize' ? Number(vip.currentPrice) : 0;
  467. originAmount += Number(vip.originalPrice);
  468. });
  469. // 一页必买,需要加水赠送的价格和乐器价格
  470. if (forms.registerType === 'MUST_BUY_GOODS') {
  471. // 如果有赠送会员卡,需要加上会员卡的原价
  472. if (forms.detailVip.giftFlag && forms.detailVip.giftOriginalPrice) {
  473. originAmount = originAmount + forms.detailVip.giftOriginalPrice
  474. }
  475. originAmount = originAmount + (state.currentIntrument?.originalPrice || 0)
  476. }
  477. // const goodsList: any[] = studentRegisterStore.getGoods;
  478. // goodsList.forEach((good: any) => {
  479. // amount += Number(good.price) * good.quantity;
  480. // originAmount += Number(good.originalPrice) * good.quantity;
  481. // });
  482. return {
  483. amount,
  484. originAmount
  485. };
  486. });
  487. // 格式化提示状态
  488. const changeTipStatus = (register: boolean, school: boolean) => {
  489. forms.isTipRegister = register;
  490. forms.isChangeSchool = school;
  491. };
  492. const checkForm = (status = true) => {
  493. if (!checkPhone(studentInfo.username)) {
  494. status && showToast('请输入正确的手机号码');
  495. return true;
  496. } else if (!studentInfo.password) {
  497. status && showToast('请输入验证码');
  498. return true;
  499. } else if (!studentInfo.extra.nickname) {
  500. status && showToast('请输入学生姓名');
  501. return true;
  502. } else if (![0, 1].includes(studentInfo.extra.gender)) {
  503. status && showToast('请选择性别');
  504. return true;
  505. } else if (!studentInfo.extra.currentGradeNum) {
  506. status && showToast('请选择所在年级');
  507. return true;
  508. } else if (!studentInfo.extra.currentClass) {
  509. status && showToast('请选择所在班级');
  510. return true;
  511. }
  512. return false;
  513. };
  514. //
  515. const checkSubmit = () => {
  516. const { extra } = studentInfo;
  517. // console.log(
  518. // forms.studentItem.nickname,
  519. // extra.nickname,
  520. // forms.isRegister,
  521. // forms.isTipRegister,
  522. // 'isRegister'
  523. // );
  524. if (
  525. forms.studentItem.nickname !== extra.nickname &&
  526. forms.isTipRegister
  527. ) {
  528. otherParams.showOtherMessage =
  529. '学生姓名与上次提交信息不一致,请确认修改学生信息或创建新的学生账号';
  530. otherParams.showOtherSchool = true;
  531. otherParams.showCancelButton = true;
  532. otherParams.showCloseButton = true;
  533. otherParams.cancelButtonColor =
  534. 'linear-gradient( 224deg, #3FE1E6 0%, #00CDD4 100%)';
  535. otherParams.cancelButtonText = '新建学生';
  536. otherParams.confirmButtonColor =
  537. 'linear-gradient( 305deg, #40C8FF 0%, #3192FF 100%)';
  538. otherParams.confirmButtonText = '修改信息';
  539. otherParams.otherType = 'nickname';
  540. otherParams.messageAlign = 'left';
  541. return true;
  542. }
  543. // 判断新建学员是否上限了
  544. if (
  545. forms.isRegister === 'create' &&
  546. forms.studentList.length >= forms.multi_user_limit
  547. ) {
  548. otherParams.showOtherMessage = `同一手机号最多创建${forms.multi_user_limit}个学生`;
  549. otherParams.showOtherSchool = true;
  550. otherParams.showCancelButton = false;
  551. otherParams.showCloseButton = true;
  552. otherParams.confirmButtonColor =
  553. 'linear-gradient( 305deg, #40C8FF 0%, #3192FF 100%)';
  554. otherParams.confirmButtonText = '我知道了';
  555. otherParams.otherType = 'limit';
  556. otherParams.messageAlign = 'center';
  557. return true;
  558. }
  559. // 判断是否为同一个学校
  560. if (
  561. forms.studentItem.schoolId &&
  562. forms.studentItem.schoolId !== forms.registerDetails.schoolId &&
  563. !forms.isChangeSchool &&
  564. forms.isRegister === 'update'
  565. ) {
  566. otherParams.showOtherMessage = `您已绑定<span style="color: #2B85FF">【${
  567. forms.studentItem?.schoolName || ''
  568. }】</span>,提交后将更换到
  569. <span style="color: #2B85FF">【${
  570. forms.registerDetails.schoolName || ''
  571. }】</span>
  572. ,是否确认提交?`;
  573. otherParams.showOtherSchool = true;
  574. otherParams.showCloseButton = false;
  575. otherParams.showCancelButton = true;
  576. otherParams.cancelButtonColor = '';
  577. otherParams.cancelButtonText = '取消';
  578. otherParams.confirmButtonColor = '';
  579. otherParams.confirmButtonText = '确定';
  580. otherParams.otherType = 'change';
  581. otherParams.messageAlign = 'left';
  582. return true;
  583. }
  584. return false;
  585. };
  586. /**
  587. * 登记成功之后购买
  588. */
  589. const onSubmit = async () => {
  590. forms.submitLoading = true;
  591. try {
  592. if (checkForm() || checkSubmit()) {
  593. forms.submitLoading = false;
  594. return;
  595. }
  596. const { extra, loginType, autoRegister, password, multiUser, ...res } =
  597. studentInfo;
  598. /*
  599. 新用户:
  600. autoRegister: true
  601. loginType: 'SMS'
  602. 已存在用户:
  603. autoRegister: false
  604. loginType: 'TOKEN'
  605. password: xxx
  606. */
  607. let tLoginType = loginType,
  608. tAutoRegister = autoRegister,
  609. tPassword = password,
  610. tMultiUser = multiUser;
  611. if (forms.isRegister === 'update') {
  612. tLoginType = 'TOKEN';
  613. tAutoRegister = false;
  614. tPassword = forms.studentItem.token;
  615. tMultiUser = false;
  616. }
  617. const result = await request.post('/edu-app/userlogin', {
  618. requestType: 'form',
  619. data: {
  620. loginType: tLoginType,
  621. autoRegister: tAutoRegister,
  622. password: tPassword,
  623. multiUser: tMultiUser,
  624. ...res,
  625. extra: JSON.stringify({
  626. ...extra,
  627. giftVipDay:
  628. forms.detailVip.membershipDays || 0 + forms.giftVipDay || 0,
  629. schoolId: forms.schoolId
  630. })
  631. }
  632. });
  633. if (result.code !== 200) {
  634. if (result.code === 5436) {
  635. forms.showTips = true;
  636. forms.showMessage = '二维码已经失效,详情请咨询学校老师';
  637. forms.showButton = false;
  638. } else if (result.code === 5435) {
  639. forms.showTips = true;
  640. forms.showMessage = result.message;
  641. forms.showButton = true;
  642. } else if (result.code === 5437) {
  643. forms.showTips = true;
  644. forms.showMessage =
  645. '<p style="color: #F44541">报名已截止,感谢您的参与</p>'; //result.message;
  646. forms.showButton = false;
  647. }
  648. } else {
  649. studentRegisterStore.setToken(
  650. result.data.token_type + ' ' + result.data.access_token
  651. );
  652. setLoginInit();
  653. let joinType = 'NOT_REGISTER';
  654. if (forms.joinType === 'digitalize') {
  655. joinType = 'SELECT_INSTRUMENT';
  656. }
  657. if (forms.joinType === 'tradition') {
  658. joinType = 'NOT_BUY_INSTRUMENT';
  659. }
  660. // 更新时间
  661. const id = await updateStat(
  662. pageTimer.counter.value,
  663. joinType,
  664. result.data.userId,
  665. forms.schoolId
  666. );
  667. forms.saveId = id;
  668. forms.saveUserId = id;
  669. pageTimer.counter.value = 0;
  670. // 获取用户信息
  671. const res = await request.get('/edu-app/user/getUserInfo', {
  672. requestType: 'form'
  673. });
  674. setLogin(res.data);
  675. await onRegisterSubmit();
  676. }
  677. } catch {
  678. // 重置信息 - 如果是新建则不提示
  679. changeTipStatus(forms.isRegister === 'create' ? false : true, false);
  680. } finally {
  681. forms.submitLoading = false;
  682. }
  683. };
  684. const updateStudentInfo = async () => {
  685. try {
  686. const { extra, username } = studentInfo;
  687. const registerResult = await request.post('/edu-app/student/register', {
  688. data: {
  689. schoolId: forms.schoolId,
  690. clientType: 'STUDENT',
  691. ...extra,
  692. giftVipFlag: forms.registerDetails.giftVipFlag || false,
  693. giftVipDay: forms.giftVipDay || 0,
  694. schoolVerify: true,
  695. firstVipDay: forms.detailVip.membershipDays || 0,
  696. mobile: username,
  697. newRegUser: forms.isRegister === 'create' ? true : false
  698. }
  699. });
  700. if (registerResult.code !== 200) {
  701. if (registerResult.code === 5436) {
  702. forms.showTips = true;
  703. forms.showMessage = '二维码已经失效,详情请咨询学校老师';
  704. forms.showButton = false;
  705. } else if (registerResult.code === 5435) {
  706. forms.showTips = true;
  707. forms.showMessage = registerResult.message;
  708. forms.showButton = true;
  709. } else if (registerResult.code === 5437) {
  710. forms.showTips = true;
  711. forms.showMessage =
  712. '<p style="color: #F44541">报名已截止,感谢您的参与</p>'; //result.message;
  713. forms.showButton = false;
  714. }
  715. return false;
  716. } else {
  717. return true;
  718. }
  719. } catch {}
  720. };
  721. // 登记成功之后购买
  722. const onRegisterSubmit = async () => {
  723. try {
  724. // 请求是否有待支付订单,如果有则自动关闭
  725. const status = await paymentOrderUnpaid();
  726. if (status) return;
  727. const schoolInfo = await request.get(
  728. '/edu-app/userPaymentOrder/registerStatus/' + forms.schoolId
  729. );
  730. const vipList = studentRegisterStore.getVip;
  731. // 传统方式
  732. if (forms.joinType === 'tradition') {
  733. const updateStatus = await updateStudentInfo();
  734. if (!updateStatus) return;
  735. setTimeout(() => {
  736. showToast('报名成功');
  737. // router.push('/download');
  738. }, 100);
  739. setTimeout(() => {
  740. if (browser().weixin) {
  741. // 关闭微信
  742. (window as any).WeixinJSBridge.call('closeWindow');
  743. }
  744. }, 1000);
  745. return;
  746. }
  747. if (schoolInfo.data.hasBuyCourse && vipList.length > 0) {
  748. // forms.dialogConfirmStatus = true;
  749. otherParams.showOtherMessage = `该学员已购买会员,是否再次购买?`;
  750. otherParams.showOtherSchool = true;
  751. otherParams.showCloseButton = false;
  752. otherParams.showCancelButton = true;
  753. otherParams.cancelButtonColor = '';
  754. otherParams.cancelButtonText = '取消';
  755. otherParams.confirmButtonColor = '';
  756. otherParams.confirmButtonText = '确定';
  757. otherParams.otherType = 'member';
  758. otherParams.messageAlign = 'center';
  759. return;
  760. }
  761. await paymentContinue();
  762. } catch {
  763. // 重置信息 - 如果是新建则不提示
  764. changeTipStatus(forms.isRegister === 'create' ? false : true, false);
  765. }
  766. };
  767. const getUserInfos = async () => {
  768. if (
  769. studentInfo.password.length !== 6 ||
  770. !checkPhone(studentInfo.username)
  771. ) {
  772. return;
  773. }
  774. try {
  775. // 15907120131;
  776. const { data } = await request.get(
  777. `/edu-app/open/student/studentInfo?mobile=${studentInfo.username}&code=${studentInfo.password}&type=REGISTER`
  778. );
  779. forms.studentList = data || [];
  780. if (forms.studentList.length > 0) {
  781. const firstStudent: any = forms.studentList[0];
  782. forms.studentItem = firstStudent;
  783. studentInfo.extra.nickname = firstStudent.nickname;
  784. const tempGrade: any = forms.gradeList || [];
  785. tempGrade?.forEach((i: any) => {
  786. if (i.value === firstStudent.currentGradeNum) {
  787. forms.instrumentCode = i.instrumentCode;
  788. forms.gradeNumText = i.text;
  789. studentInfo.extra.currentGradeNum = firstStudent.currentGradeNum;
  790. if (forms.schoolInstrumentSetType === 'CLASS') {
  791. forms.classList = i.classList;
  792. }
  793. }
  794. });
  795. forms.classList.forEach((i: any) => {
  796. if (i.value === firstStudent.currentClass) {
  797. forms.currentClassText = i.text;
  798. studentInfo.extra.currentClass = firstStudent.currentClass;
  799. }
  800. });
  801. studentInfo.extra.gender = firstStudent.gender;
  802. forms.isRegister = 'update';
  803. changeTipStatus(true, false);
  804. // 根据注册信息反显乐器信息
  805. if (forms.registerType === 'MUST_BUY_GOODS' && (forms.schoolInstrumentSetType === 'CLASS' || forms.schoolInstrumentSetType === 'GRADE') ) {
  806. const { currentClass, currentGradeNum } = forms.studentList[0]
  807. if (forms.schoolInstrumentSetType === 'GRADE') {
  808. state.currentIntrument = state.intrumentList.find((item: any) => item.gradeNum === currentGradeNum)
  809. }
  810. if (forms.schoolInstrumentSetType === 'CLASS') {
  811. state.currentIntrument = state.intrumentList.find((item: any) => (item.gradeNum === currentGradeNum && item.classNum === currentClass) )
  812. }
  813. }
  814. } else {
  815. forms.isRegister = 'create';
  816. changeTipStatus(false, false);
  817. forms.studentItem = [];
  818. }
  819. } catch {
  820. //
  821. }
  822. };
  823. // 查询未支付订单
  824. const paymentOrderUnpaid = async () => {
  825. let result = false;
  826. try {
  827. const { data } = await request.get(
  828. '/edu-app/userPaymentOrder/schoolRegisterOrder?schoolId=' +
  829. forms.schoolId
  830. );
  831. // 判断是否有待支付订单
  832. if (data && data.length > 0) {
  833. let isPadding = false; // 是否有待支付订单
  834. let paddingConfig = {} as any;
  835. let paddingData = {} as any;
  836. let isFinal = false; // 是否有完成订单
  837. let finalConfig = {} as any;
  838. data.forEach((element: any) => {
  839. // 判断是否待支付
  840. if (element.status === 'PAYING' || element.status === 'WAIT_PAY') {
  841. isPadding = true;
  842. paddingConfig = element.paymentConfig;
  843. paddingData = element;
  844. }
  845. if (
  846. element.status === 'PAID' ||
  847. element.status === 'PART_REFUNDED' ||
  848. element.status === 'REFUNDED'
  849. ) {
  850. isFinal = true;
  851. finalConfig = element.paymentConfig;
  852. }
  853. });
  854. // 60s 关单提示文案
  855. // 判断是否有完成订单 并且选择 自备
  856. if (isFinal && forms.joinType === 'tradition') {
  857. // const studentResult = await updateStudentInfo();
  858. // if (!studentResult) return;
  859. setTimeout(() => {
  860. showToast('您已报名成功,请勿重复报名');
  861. }, 100);
  862. return true;
  863. }
  864. // 提交报名信息时,判断该手机号是否存在待支付订单,若存则判断本次提交的报名方式,若本次提交的是团购则提示【您有待支付的报名订单,是否继续支付 重新下单/继续支付】,点击重新下单时,关闭老订单,创建新订单;若本次提交的是自备,则提示 【您有数字化方式报名的待支付订单,请关闭订单后重新报名 取消/关闭】取消则停留在当前界面,关闭则关闭订单,并停留在当前界面,用户需要再次点击报名按钮提交信息
  865. if (isPadding && forms.joinType === 'tradition') {
  866. // forms.dialogStatus = true;
  867. // forms.dialogMessage =
  868. // '您有数字化方式报名的待支付订单,请关闭订单后重新报名';
  869. // forms.cancelButtonText = '取消';
  870. // forms.confirmButtonText = '关闭';
  871. // forms.dialogConfig = paddingConfig;
  872. // forms.messageAlign = 'left';
  873. forms.dialogConfig = paddingConfig;
  874. const cancelStatus = await cancelPaymentOrder();
  875. if (cancelStatus) {
  876. onSubmit();
  877. }
  878. // 重新下单 - 先关闭订单
  879. // resetOrderPayment();
  880. return true;
  881. }
  882. if (isPadding && forms.joinType === 'digitalize') {
  883. // 最终确认,有待支付订单直接去支付,没有则才会创建订单
  884. // state.config = paddingConfig?.paymentConfig;
  885. // state.orderNo = paddingConfig?.orderNo;
  886. // const updateStatus = await updateStudentInfo();
  887. // if (!updateStatus) return;
  888. // await lastSubmit();
  889. // 为了处理,有待支付订单,然后后台改了金额,会导致金额不一致
  890. forms.dialogConfig = paddingConfig;
  891. const cancelStatus = await cancelPaymentOrder();
  892. if (cancelStatus) {
  893. await paymentContinue();
  894. }
  895. return true;
  896. }
  897. return false;
  898. } else {
  899. return false;
  900. }
  901. } catch {
  902. // 重置信息 - 如果是新建则不提示
  903. changeTipStatus(forms.isRegister === 'create' ? false : true, false);
  904. }
  905. return result;
  906. };
  907. // 重新下单
  908. const resetOrderPayment = async () => {
  909. try {
  910. const orderNo = forms.dialogConfig?.orderNo;
  911. if (!orderNo) return;
  912. await request.post(
  913. '/edu-app/userPaymentOrder/cancelPayment/' + orderNo
  914. );
  915. await onRegisterSubmit();
  916. } catch {
  917. //
  918. }
  919. };
  920. // 取消订单
  921. const cancelPaymentOrder = async () => {
  922. try {
  923. const orderNo = forms.dialogConfig?.orderNo;
  924. if (!orderNo) return;
  925. await request.post(
  926. '/edu-app/userPaymentOrder/cancelPayment/' + orderNo
  927. );
  928. return true;
  929. } catch {
  930. return false;
  931. }
  932. };
  933. const paymentContinue = async () => {
  934. try {
  935. const vipList = studentRegisterStore.getVip;
  936. // const goodsList = studentRegisterStore.getGoods;
  937. const params: any[] = [];
  938. vipList.forEach((vip: any) => {
  939. params.push({
  940. giftVipDay: vip.membershipDays,
  941. giftPeriod: vip.giftPeriod,
  942. goodsId: vip.goodsId,
  943. goodsNum: 1,
  944. goodsType: vip.goodsType,
  945. paymentCashAmount: vip.currentPrice, // 现金支付金额
  946. paymentCouponAmount: 0 // 优惠券金额
  947. });
  948. });
  949. // 添加赠送的乐器
  950. if (state.currentIntrument?.instrumentId && forms.registerType === 'MUST_BUY_GOODS') {
  951. params.push({
  952. goodsId: state.currentIntrument?.instrumentId,
  953. goodsNum: 1,
  954. goodsType: "INSTRUMENTS",
  955. paymentCashAmount: 0,
  956. paymentCouponAmount: 0
  957. })
  958. }
  959. // goodsList.forEach((goods: any) => {
  960. // params.push({
  961. // goodsId: goods.productId,
  962. // goodsNum: goods.quantity,
  963. // goodsType: 'INSTRUMENTS',
  964. // paymentCashAmount: goods.price, // 现金支付金额
  965. // paymentCouponAmount: 0, // 优惠券金额
  966. // goodsSkuId: goods.productSkuId
  967. // });
  968. // });
  969. // 创建订单
  970. const updateStatus = await updateStudentInfo();
  971. // console.log(updateStatus, 'updateStatus');
  972. if (!updateStatus) return;
  973. const result = await request.post(
  974. '/edu-app/userPaymentOrder/executeOrder',
  975. {
  976. // hideLoading: false,
  977. data: {
  978. buryId: forms.saveUserId,
  979. registerType: forms.registerType,
  980. paymentType: forms.paymentType,
  981. bizId: forms.schoolId, // 乐团编号
  982. orderType: 'SCHOOL_REGISTER',
  983. paymentCashAmount: calcPrice.value.amount || 0,
  984. paymentCouponAmount: 0,
  985. goodsInfos: params,
  986. orderName: '学生登记',
  987. orderDesc: '学生登记'
  988. }
  989. }
  990. );
  991. if (result.code === 5436) {
  992. forms.showTips = true;
  993. forms.showMessage = '二维码已经失效,详情请咨询学校老师';
  994. forms.showButton = false;
  995. } else if (result.code === 5435) {
  996. forms.showTips = true;
  997. forms.showMessage = result.message;
  998. forms.showButton = true;
  999. } else {
  1000. state.config = {
  1001. ...result.data.paymentConfig,
  1002. paymentType: result.data.paymentType
  1003. };
  1004. state.orderNo = result.data.orderNo;
  1005. await lastSubmit();
  1006. }
  1007. } catch (e: any) {
  1008. console.log(e, 'any');
  1009. // 重置信息 - 如果是新建则不提示
  1010. changeTipStatus(forms.isRegister === 'create' ? false : true, false);
  1011. }
  1012. };
  1013. const lastSubmit = async () => {
  1014. try {
  1015. const users = baseState.user.data;
  1016. // 判断是否需要实名认证, 姓名,卡号 - 参数设置可以控制
  1017. if (
  1018. forms.contract_sign &&
  1019. (!users?.account.realName || !users?.account.idCardNo)
  1020. ) {
  1021. state.authShow = true;
  1022. return;
  1023. }
  1024. const { data } = await request.post(
  1025. '/edu-app/userPaymentOrder/updateReceiveAddress',
  1026. {
  1027. // hideLoading: false,
  1028. data: {
  1029. orderNo: state.orderNo,
  1030. orderType: 'SCHOOL_REGISTER'
  1031. }
  1032. }
  1033. );
  1034. state.pay_channel = data.paymentChannel;
  1035. if (data.status !== 'WAIT_PAY' && data.status !== 'PAYING') {
  1036. router.replace({
  1037. path: '/payment-result',
  1038. query: {
  1039. orderNo: state.orderNo
  1040. }
  1041. });
  1042. } else {
  1043. onCallback();
  1044. }
  1045. } catch {
  1046. // 重置信息 - 如果是新建则不提示
  1047. changeTipStatus(forms.isRegister === 'create' ? false : true, false);
  1048. }
  1049. };
  1050. /**
  1051. * @description 回调,判断是否有支付渠道,如果有则直接去支付
  1052. * @returns void
  1053. */
  1054. const onCallback = () => {
  1055. const pt = state.pay_channel;
  1056. // 判断是否有支付方式
  1057. if (pt) {
  1058. const payCode: string = beforeSubmit(state.pay_channel);
  1059. onConfirm({
  1060. payCode,
  1061. pay_channel: pt
  1062. });
  1063. } else {
  1064. if (orderType.value === 'VIP') {
  1065. state.paymentStatus = true;
  1066. } else {
  1067. // 直接去拉取微信支付
  1068. onConfirm({
  1069. payCode: 'payResult',
  1070. pay_channel: forms.paymentChannel
  1071. });
  1072. }
  1073. }
  1074. };
  1075. const onConfirm = (val: any) => {
  1076. const config: any = state.config;
  1077. state.pay_channel = val.pay_channel;
  1078. const params = qs.stringify({
  1079. pay_channel: val.pay_channel,
  1080. wxAppId: config.wxAppId,
  1081. alipayAppId: config.alipayAppId,
  1082. paymentType: forms.paymentType,
  1083. body: config.body,
  1084. price: config.price,
  1085. orderNo: config.merOrderNo,
  1086. userId: config.userId
  1087. });
  1088. // console.log(params, state.config);
  1089. // return;
  1090. if (val.payCode === 'payResult') {
  1091. window.location.href =
  1092. getHttpOrigin() + '/classroom-app/#/payResult?' + params;
  1093. } else {
  1094. state.qrCodeUrl =
  1095. getHttpOrigin() + '/classroom-app/#/payDefine?' + params;
  1096. state.showQrcode = true;
  1097. state.paymentStatus = false;
  1098. setTimeout(() => {
  1099. getPaymentOrderStatus();
  1100. }, 300);
  1101. }
  1102. };
  1103. // 放弃支付时,则取消订单
  1104. const onBackOut = async () => {
  1105. try {
  1106. await request.post(
  1107. '/edu-app/userPaymentOrder/cancelPayment/' + state.orderNo
  1108. );
  1109. // router.back();
  1110. } catch {
  1111. //
  1112. }
  1113. };
  1114. // 轮询查询订单状态
  1115. const getPaymentOrderStatus = async () => {
  1116. // 循环查询订单
  1117. // const orderNo = state.orderNo
  1118. const orderTimer = setInterval(async () => {
  1119. // 判断是否在当前路由,如果不是则清除定时器
  1120. if (route.name != 'student-register-form') {
  1121. clearInterval(orderTimer);
  1122. return;
  1123. }
  1124. state.orderTimer = orderTimer;
  1125. try {
  1126. const { data } = await request.post(
  1127. '/edu-app/open/userOrder/paymentStatus/' + state.orderNo,
  1128. {
  1129. hideLoading: true
  1130. }
  1131. );
  1132. if (data.status !== 'WAIT_PAY' && data.status !== 'PAYING') {
  1133. // 默认关闭支付二维码弹窗
  1134. state.showQrcode = false;
  1135. clearInterval(state.orderTimer);
  1136. setTimeout(() => {
  1137. router.replace({
  1138. path: '/payment-result',
  1139. query: {
  1140. orderNo: state.orderNo
  1141. }
  1142. });
  1143. }, 100);
  1144. }
  1145. } catch {
  1146. //
  1147. clearInterval(state.orderTimer);
  1148. }
  1149. }, 5000);
  1150. };
  1151. // 实名认证成功
  1152. const onAuthSuccess = () => {
  1153. //
  1154. state.authShow = false;
  1155. paymentContinue(); // 实名成功后自动支付
  1156. };
  1157. /**
  1158. * 页面停留时间
  1159. * @param pageBrowseTime 停留时间
  1160. * @param joinType 加入方式
  1161. * @param userId 用户编号
  1162. * @param schoolId 学校编号
  1163. */
  1164. const updateStat = async (
  1165. pageBrowseTime = 5,
  1166. joinType?: string,
  1167. userId?: string,
  1168. schoolId?: string
  1169. ) => {
  1170. try {
  1171. const { data } = await requestStudent.post(
  1172. '/edu-app/open/studentRegisterPointRecord/update',
  1173. {
  1174. data: {
  1175. id: forms.saveId,
  1176. useTime: pageBrowseTime, // 固定10秒
  1177. joinType,
  1178. userId,
  1179. schoolId
  1180. }
  1181. }
  1182. );
  1183. forms.saveId = data;
  1184. return data;
  1185. } catch {
  1186. //
  1187. }
  1188. };
  1189. const getAppIdAndCode = async (url?: string) => {
  1190. try {
  1191. const { data } = await request.get(
  1192. '/edu-app/open/paramConfig/wechatAppId'
  1193. );
  1194. // 判断是否有微信appId
  1195. if (data) {
  1196. closeToast();
  1197. goWechatAuth(data, url);
  1198. }
  1199. } catch {
  1200. //
  1201. }
  1202. };
  1203. if (browser().weixin) {
  1204. //授权
  1205. const openId = sessionStorage.getItem('active-open-id');
  1206. forms.openId = openId;
  1207. const code = getUrlCode();
  1208. if (!code) {
  1209. const newUrl =
  1210. getHttpOrigin() +
  1211. window.location.pathname +
  1212. '#' +
  1213. route.path +
  1214. '?' +
  1215. qs.stringify({
  1216. ...route.query
  1217. });
  1218. getAppIdAndCode(newUrl);
  1219. return '';
  1220. } else {
  1221. forms.code = code;
  1222. }
  1223. // 获取微信分享签名
  1224. weChatShare.getAppSignature()
  1225. }
  1226. const formatTimerTo = (num: number): string => {
  1227. if (num > 9) {
  1228. return num + '';
  1229. } else {
  1230. return '0' + num;
  1231. }
  1232. };
  1233. const pagePointInit = async () => {
  1234. try {
  1235. // 判断是否获取微信code码
  1236. if (!forms.code) return;
  1237. const { data } = await request.post(
  1238. '/edu-app/open/studentRegisterPointRecord/save',
  1239. {
  1240. data: {
  1241. code: forms.code,
  1242. schoolId: forms.schoolId,
  1243. openId: forms.openId
  1244. }
  1245. }
  1246. );
  1247. forms.saveId = data.id;
  1248. forms.openId = data.openId;
  1249. sessionStorage.setItem('active-open-id', data.openId);
  1250. // 间隔多少时间同步数据
  1251. forms.intervalFnRef = useIntervalFn(async () => {
  1252. // 页面时间恢复
  1253. pageTimer.counter.value = 0;
  1254. pageTimer.resume();
  1255. // 同步数据时先进行有效时间进行保存
  1256. await updateStat();
  1257. }, 5000);
  1258. } catch {}
  1259. };
  1260. /** 手机号变更时清空验证码信息,用户信息 */
  1261. const phoneChangeEmptyInfo = () => {
  1262. studentInfo.password = '';
  1263. studentInfo.extra.nickname = '';
  1264. studentInfo.extra.currentGradeNum = '';
  1265. studentInfo.extra.currentClass = '';
  1266. studentInfo.extra.gender = 1;
  1267. forms.currentClassText = '';
  1268. forms.gradeNumText = '';
  1269. forms.studentList = []; // 手机号关联学生列表
  1270. forms.studentItem = {}; // 选择的学生
  1271. forms.isRegister = 'create'; // 是否注册学生
  1272. forms.isTipRegister = false; // 是否显示名字不一致 - 默认显示
  1273. forms.isChangeSchool = false; // 是否切换学校
  1274. };
  1275. const tipCountdown = (seconds: number) => {
  1276. let remainingTime = seconds;
  1277. const interval = setInterval(() => {
  1278. remainingTime--;
  1279. state.descSecondsNum = state.descSecondsNum > 1 ? state.descSecondsNum - 1 : 1;
  1280. if (remainingTime < 1) {
  1281. clearInterval(interval); // 清除定时器
  1282. state.hideSecondsNum = true
  1283. }
  1284. }, 1000); // 每秒执行一次
  1285. }
  1286. // 切换学生,匹配赠送的乐器信息
  1287. const matchSwitchInstrument = (val: any) => {
  1288. if (forms.registerType === 'MUST_BUY_GOODS') {
  1289. // 学校
  1290. // if (forms.schoolInstrumentSetType === 'SCHOOL') {
  1291. // state.currentIntrument = state.intrumentList.find((item: any) => item.schoolId === val.schoolId)
  1292. // }
  1293. // if (!state.intrumentList.find((item: any) => item.schoolId === val.schoolId)) {
  1294. // state.currentIntrument = null;
  1295. // return
  1296. // }
  1297. // 年级
  1298. if (forms.schoolInstrumentSetType === 'GRADE') {
  1299. state.currentIntrument = state.intrumentList.find((item: any) => item.gradeNum === val.currentGradeNum)
  1300. }
  1301. // 班级
  1302. if (forms.schoolInstrumentSetType === 'CLASS') {
  1303. state.currentIntrument = state.intrumentList.find((item: any) => (item.classNum === val.currentClass && item.gradeNum === val.currentGradeNum) )
  1304. }
  1305. }
  1306. }
  1307. onMounted(async () => {
  1308. try {
  1309. // 获取支付类型
  1310. let expireDay = null;
  1311. const { data } = await request.get(
  1312. '/edu-app/open/paramConfig/queryByParamNameList',
  1313. {
  1314. requestType: 'form',
  1315. params: {
  1316. paramNames:
  1317. 'payment_service_provider,contract_sign,multi_user_limit,qr_code_expire_time'
  1318. }
  1319. }
  1320. );
  1321. if (data && Array.isArray(data)) {
  1322. data.forEach((item: any) => {
  1323. if (item.paramName === 'contract_sign') {
  1324. forms.contract_sign = item.paramValue === '1' ? true : false;
  1325. } else if (item.paramName === 'payment_service_provider') {
  1326. // forms.paymentType = item.paramValue || '';
  1327. const provider = JSON.parse(item.paramValue);
  1328. forms.paymentType = provider.vendor;
  1329. forms.paymentChannel = provider.channel;
  1330. } else if (item.paramName === 'multi_user_limit') {
  1331. forms.multi_user_limit = item.paramValue
  1332. ? Number(item.paramValue)
  1333. : 1;
  1334. } else if (item.paramName === 'qr_code_expire_time') {
  1335. expireDay = item.paramValue ? Number(item.paramValue) : null;
  1336. }
  1337. });
  1338. }
  1339. const createT = route.query.t;
  1340. if (createT && expireDay !== null) {
  1341. if (dayjs(Number(createT)).add(expireDay, 'day').isBefore(dayjs())) {
  1342. forms.showTips = true;
  1343. forms.showMessage = '二维码已经失效,详情请咨询学校老师';
  1344. forms.showButton = false;
  1345. }
  1346. }
  1347. await getRegisterGoods();
  1348. nextTick(() => {
  1349. // 一页展示(必买)才显示团购提示弹窗
  1350. if (forms.registerType === 'MUST_BUY_GOODS' && browser().weixin && !forms.showTips) {
  1351. // if (forms.registerType === 'MUST_BUY_GOODS') {
  1352. state.tipBoxPop = true
  1353. document.body.style.overflow = 'hidden';
  1354. tipCountdown(3)
  1355. }
  1356. })
  1357. } catch {}
  1358. });
  1359. onUnmounted(() => {
  1360. forms.intervalFnRef?.pause(); // 暂停回调
  1361. });
  1362. return () => (
  1363. <div class={styles['student-register']}>
  1364. <div class={[(forms.registerType === 'MUST_BUY_GOODS' || route.query.rt === 'MUST_BUY_GOODS') ? styles.studentRegisterContainer2 : styles.studentRegisterContainer]}>
  1365. {!forms.activeOverStatus && (
  1366. <div class={styles.countdownSection}>
  1367. <div class={styles.timer}>
  1368. <img src={icon3} class={styles.timerTitle} />
  1369. <div class={styles.timerAll}>
  1370. <span>{formatTimerTo(overCountDown.current.value.days)}</span>
  1371. <span>
  1372. {formatTimerTo(overCountDown.current.value.hours)}
  1373. </span>
  1374. <span>
  1375. {formatTimerTo(overCountDown.current.value.minutes)}
  1376. </span>
  1377. <span>
  1378. {formatTimerTo(overCountDown.current.value.seconds)}
  1379. </span>
  1380. </div>
  1381. </div>
  1382. <div class={styles.timerTip}>
  1383. 为了确保您能顺利参与学习,请在规定时间内报名
  1384. </div>
  1385. </div>
  1386. )}
  1387. <div
  1388. class={[
  1389. styles.studentSection,
  1390. styles.studentSectionForm,
  1391. forms.giftVipDay <= 0 && styles.noSendDay
  1392. ]}>
  1393. {
  1394. forms.registerType === 'MUST_BUY_GOODS' &&
  1395. <div class={styles.title1}></div>
  1396. }
  1397. <Form labelAlign="left" class={styles.registerForm}>
  1398. <Field
  1399. clearable={false}
  1400. label="联系方式(直接监护人)"
  1401. placeholder="请输入手机号码"
  1402. type="tel"
  1403. required
  1404. autocomplete="off"
  1405. inputAlign="right"
  1406. class={styles.username}
  1407. v-model={studentInfo.username}
  1408. border={false}
  1409. maxlength={11}
  1410. onUpdate:modelValue={() => {
  1411. phoneChangeEmptyInfo();
  1412. }}>
  1413. {{
  1414. label: () => (
  1415. <div>
  1416. 联系方式
  1417. {/* (直接监护人) */}
  1418. <p class={styles.tips}>(直接监护人)</p>
  1419. </div>
  1420. )
  1421. }}
  1422. </Field>
  1423. <div class={['van-hairline--bottom', styles.fieldTipsGroup]}>
  1424. <div class={[styles.fieldTips]}>
  1425. <i class={styles.iconQuestion}></i>
  1426. 手机号是音乐数字课堂的唯一登录账户
  1427. </div>
  1428. </div>
  1429. <Field
  1430. center
  1431. clearable={false}
  1432. required
  1433. inputAlign="right"
  1434. label="验证码"
  1435. placeholder="请输入验证码"
  1436. autocomplete="off"
  1437. type="number"
  1438. v-model={studentInfo.password}
  1439. maxlength={6}
  1440. onUpdate:modelValue={(val: any) => {
  1441. getUserInfos();
  1442. }}>
  1443. {{
  1444. button: () =>
  1445. forms.countDownStatus ? (
  1446. <span
  1447. class={[
  1448. styles.codeText,
  1449. !validatePhone.value ? styles.codeTextDisabled : ''
  1450. ]}
  1451. onClick={onSendCode}>
  1452. 获取验证码
  1453. </span>
  1454. ) : (
  1455. <CountDown
  1456. ref={(el: any) => (countDownRef.value = el)}
  1457. auto-start={false}
  1458. class={styles.countDown}
  1459. time={forms.countDownTime}
  1460. onFinish={onFinished}
  1461. format="ss秒后重试"
  1462. />
  1463. )
  1464. }}
  1465. </Field>
  1466. {/* 大于等于2,则可以切换学生 */}
  1467. {/* {forms.studentList.length > 1 && (
  1468. <div
  1469. class={[
  1470. styles.selectStudentGroup,
  1471. forms.showSelectStudent && styles.selectStudentGroupChecked
  1472. ]}
  1473. onClick={() => (forms.showSelectStudent = true)}>
  1474. <i
  1475. class={[
  1476. styles.studentIcon,
  1477. !forms.studentItem.userId && styles.studentIconAdd
  1478. ]}></i>
  1479. <span>
  1480. {forms.studentItem.userId
  1481. ? forms.studentItem.nickname
  1482. : '新增学生'}
  1483. </span>
  1484. </div>
  1485. )} */}
  1486. <Field
  1487. clearable={false}
  1488. required
  1489. inputAlign="right"
  1490. label="学生姓名"
  1491. placeholder="请输入学生姓名"
  1492. autocomplete="off"
  1493. maxlength={14}
  1494. v-model={studentInfo.extra.nickname}>
  1495. {{
  1496. extra: () =>
  1497. forms.studentList.length > 1 && (
  1498. <div
  1499. class={[
  1500. styles.selectStudentGroup,
  1501. forms.showSelectStudent &&
  1502. styles.selectStudentGroupChecked
  1503. ]}
  1504. onClick={() => (forms.showSelectStudent = true)}>
  1505. <span>
  1506. {forms.studentItem.userId ? '切换' : '新增'}
  1507. </span>
  1508. </div>
  1509. )
  1510. }}
  1511. </Field>
  1512. <Field
  1513. clearable={false}
  1514. required
  1515. inputAlign="right"
  1516. label="学生性别"
  1517. placeholder="请选择性别"
  1518. autocomplete="off"
  1519. // v-model={studentInfo.extra.nickname}
  1520. >
  1521. {{
  1522. input: () => (
  1523. <RadioGroup
  1524. checked-color="linear-gradient( 135deg, #31C7FF 0%, #007AFE 100%)"
  1525. v-model={studentInfo.extra.gender}
  1526. direction="horizontal">
  1527. <Tag
  1528. size="large"
  1529. type="primary"
  1530. color={
  1531. !(studentInfo.extra.gender === 1)
  1532. ? '#F5F6FA'
  1533. : 'linear-gradient( 135deg, #31C7FF 0%, #007AFE 100%)'
  1534. }
  1535. textColor={
  1536. !(studentInfo.extra.gender === 1) ? '#626264' : '#fff'
  1537. }
  1538. class={styles.radioSection}>
  1539. <Radio class={styles.radioItem} name={1}></Radio>男
  1540. </Tag>
  1541. <Tag
  1542. size="large"
  1543. type="primary"
  1544. color={
  1545. !(studentInfo.extra.gender === 0)
  1546. ? '#F5F6FA'
  1547. : 'linear-gradient( 135deg, #31C7FF 0%, #007AFE 100%)'
  1548. }
  1549. textColor={
  1550. !(studentInfo.extra.gender === 0) ? '#626264' : '#fff'
  1551. }
  1552. class={styles.radioSection}>
  1553. <Radio class={styles.radioItem} name={0}></Radio>女
  1554. </Tag>
  1555. </RadioGroup>
  1556. )
  1557. }}
  1558. </Field>
  1559. <Field
  1560. clearable={false}
  1561. required
  1562. inputAlign="right"
  1563. label="所在年级"
  1564. placeholder="请选择年级"
  1565. isLink
  1566. readonly
  1567. clickable={false}
  1568. modelValue={forms.gradeNumText}
  1569. onClick={() => {
  1570. forms.gradePopupIndex = [studentInfo.extra.currentGradeNum];
  1571. forms.gradeStatus = true;
  1572. }}
  1573. />
  1574. <Field
  1575. clearable={false}
  1576. required
  1577. inputAlign="right"
  1578. label="所在班级"
  1579. placeholder="请选择班级"
  1580. isLink
  1581. readonly
  1582. clickable={false}
  1583. modelValue={forms.currentClassText}
  1584. onClick={() => {
  1585. if (
  1586. forms.schoolInstrumentSetType === 'CLASS' &&
  1587. forms.classList.length <= 0
  1588. ) {
  1589. showToast('请先选择年级');
  1590. return;
  1591. }
  1592. forms.classPopupIndex = [studentInfo.extra.currentClass];
  1593. forms.classStatus = true;
  1594. }}
  1595. />
  1596. {(forms.giftVipDay > 0 && forms.registerDetails.giftVipFlag) ? (
  1597. <div class={styles.memberNumer}>
  1598. <img src={iconGift} class={styles.iconGift} />
  1599. <p>
  1600. 注册成功即可获得乐器AI学练工具
  1601. <span>{forms.giftVipDay || 0}</span>天有效期
  1602. </p>
  1603. </div>
  1604. ) : (
  1605. ''
  1606. )}
  1607. </Form>
  1608. </div>
  1609. {/* <div class={styles.studentSection}>
  1610. <div class={styles.title2}></div>
  1611. <div class={styles.goodsGroup}>
  1612. <div
  1613. class={[
  1614. styles.goodsItem,
  1615. styles.digitalize,
  1616. forms.joinType === 'digitalize' && styles.checked
  1617. ]}
  1618. onClick={() => {
  1619. //
  1620. if (checkForm()) {
  1621. showToast('请将资料填写完整');
  1622. return;
  1623. }
  1624. forms.joinType = 'digitalize';
  1625. nextTick(() => {
  1626. mstickyRef.value?.onChnageHeight();
  1627. setTimeout(() => {
  1628. window.scrollTo(0, 1000);
  1629. }, 50);
  1630. });
  1631. }}>
  1632. <div class={styles.goodsInner}>
  1633. <i class={styles.proposalTip}></i>
  1634. 数字化方式
  1635. </div>
  1636. </div>
  1637. <div
  1638. class={[
  1639. styles.goodsItem,
  1640. styles.tradition,
  1641. forms.joinType === 'tradition' && styles.checked1
  1642. ]}
  1643. onClick={() => {
  1644. if (checkForm()) {
  1645. showToast('请将资料填写完整');
  1646. return;
  1647. }
  1648. forms.joinType = 'tradition';
  1649. nextTick(() => {
  1650. mstickyRef.value?.onChnageHeight();
  1651. setTimeout(() => {
  1652. window.scrollTo(0, 1000);
  1653. }, 50);
  1654. });
  1655. }}>
  1656. <div class={styles.goodsInner}>传统方式</div>
  1657. </div>
  1658. </div>
  1659. </div> */}
  1660. {
  1661. forms.registerType !== 'MUST_BUY_GOODS' &&
  1662. <div class={[styles.goodsExtra]}>
  1663. {/* <i class={styles.iconArrow}></i> */}
  1664. <Cell
  1665. border={false}
  1666. class={[
  1667. styles.goodsCell,
  1668. forms.registerType === 'SELECT_BUY_GOODS' &&
  1669. styles.goodsBuyGoods
  1670. ]}
  1671. center
  1672. onClick={() => {
  1673. // console.log(forms.joinType, 'joinType');
  1674. if (forms.registerType !== 'SELECT_BUY_GOODS') return;
  1675. if (forms.joinType === 'digitalize') {
  1676. otherParams.showOtherMessage = `没有陪练工具,将无法实现同步练习`;
  1677. otherParams.showOtherSchool = true;
  1678. otherParams.showCloseButton = true;
  1679. otherParams.showCancelButton = true;
  1680. otherParams.cancelButtonColor = '';
  1681. otherParams.cancelButtonText = '确认取消';
  1682. otherParams.confirmButtonColor = '';
  1683. otherParams.confirmButtonText = '放弃取消';
  1684. otherParams.otherType = 'payment';
  1685. otherParams.messageAlign = 'center';
  1686. } else if (forms.joinType === 'tradition') {
  1687. forms.joinType = 'digitalize';
  1688. }
  1689. }}>
  1690. {{
  1691. icon: () =>
  1692. forms.registerType === 'SELECT_BUY_GOODS' && (
  1693. <div class={styles.checkedGroup}>
  1694. <i
  1695. class={[
  1696. styles.iconChecked,
  1697. forms.joinType === 'digitalize' && styles.selected
  1698. ]}></i>
  1699. {/* {forms.tipStatus && <i class={styles.showBg}></i>} */}
  1700. {forms.joinType === 'digitalize' && (
  1701. <i class={styles.showBg}></i>
  1702. )}
  1703. </div>
  1704. ),
  1705. title: () => (
  1706. <div class={styles.section}>
  1707. <Image
  1708. class={styles.img}
  1709. src={forms.detailVip.goodsUrl || tuangou}
  1710. />
  1711. <div class={styles.sectionContent}>
  1712. <img
  1713. src={
  1714. forms.registerType === 'SELECT_BUY_GOODS'
  1715. ? icon5
  1716. : icon10
  1717. }
  1718. class={styles.goodsName}
  1719. />
  1720. </div>
  1721. </div>
  1722. )
  1723. }}
  1724. </Cell>
  1725. </div>
  1726. }
  1727. {
  1728. forms.registerType === 'MUST_BUY_GOODS' &&
  1729. <div class={styles.giftBox}>
  1730. <img class={styles.titleIcon} src={giftBoxTitleIcon} />
  1731. <div class={styles.tools}>
  1732. <img class={styles.toolImg} src={forms.detailVip.goodsUrl || giftCard1Icon} />
  1733. <div class={styles.toolRight}>
  1734. <p>乐器AI学练工具一年卡</p>
  1735. <div class={styles.trDesc}>7天无理由退款</div>
  1736. <div class={styles.trBottom}>
  1737. <span class={styles.tcPrice}>¥ {Number(forms.detailVip.currentPrice).toFixed(2)}</span>
  1738. <span class={styles.toPrice}>|原价 <i>¥ {Number(forms.detailVip.originalPrice).toFixed(2)}</i></span>
  1739. </div>
  1740. </div>
  1741. </div>
  1742. {/** 有赠品才显示 */}
  1743. {
  1744. (forms.detailVip.giftFlag || state.currentIntrument?.instrumentId || forms.registerType === 'MUST_BUY_GOODS') &&
  1745. <div class={styles.extraTools}>
  1746. <div class={styles.exTitle}>
  1747. <img src={( (state.currentIntrument?.instrumentId || forms.detailVip.giftFlag) && forms.registerType === 'MUST_BUY_GOODS') ? giftExtraTitleIcon : giftExtraTitleIcon2} />
  1748. </div>
  1749. {/** 会员赠送 */}
  1750. {
  1751. forms.detailVip.giftFlag &&
  1752. <div class={styles.extItem}>
  1753. <img class={styles.toolImg} src={forms.detailVip.giftGoodsUrl} />
  1754. <div class={styles.toolRight}>
  1755. <p>乐器AI学练工具{forms.detailVip.giftPeriod === 'YEAR' ? convertToChineseNumber(forms.detailVip.giftVipDay) : forms.detailVip.giftVipDay}{forms.detailVip.zsUnit}卡</p>
  1756. <div class={styles.trBottom}>
  1757. <span class={styles.tcPrice}>¥ 0.00</span>
  1758. <span class={styles.toPrice}>|原价 <i>¥ {Number(forms.detailVip.giftOriginalPrice).toFixed(2)}</i></span>
  1759. </div>
  1760. </div>
  1761. <img class={styles.toolZsIcon} src={giftZsIcon} />
  1762. </div>
  1763. }
  1764. {/** 乐器赠送,注册类型为MUST_BUY_GOODS,才显示赠送乐器 */}
  1765. {
  1766. (state.currentIntrument?.instrumentId && forms.registerType === 'MUST_BUY_GOODS') &&
  1767. <div class={styles.extItem}>
  1768. <img class={[styles.toolImg, styles.toolImgYq]} src={state.currentIntrument.img} />
  1769. <div class={styles.toolRight}>
  1770. <p>{state.currentIntrument.instrumentName}</p>
  1771. <div class={styles.trBottom}>
  1772. <span class={styles.tcPrice}>¥ 0.00</span>
  1773. <span class={styles.toPrice}>|原价 <i>¥ {Number(state.currentIntrument.originalPrice).toFixed(2)}</i></span>
  1774. </div>
  1775. </div>
  1776. <img class={styles.toolZsIcon} src={giftZsIcon} />
  1777. </div>
  1778. }
  1779. {
  1780. (!state.currentIntrument?.instrumentId && forms.registerType === 'MUST_BUY_GOODS') &&
  1781. <img src={selectZsTip} class={styles.extTip} />
  1782. }
  1783. </div>
  1784. }
  1785. </div>
  1786. }
  1787. {/* <div class={[styles.memberNumer, styles.aiMemberNumber]}>
  1788. <img src={iconGift} class={styles.iconGift} />
  1789. <p>
  1790. 首次购买赠送乐器AI学练工具
  1791. <span>{forms.detailVip.membershipDays || 0}</span>天有效期
  1792. </p>
  1793. </div> */}
  1794. {forms.detailVip.membershipDays && forms.registerType !== 'MUST_BUY_GOODS' ? (
  1795. <div class={styles.vipGiftContainer}>
  1796. <img src={vipGiftTIps} class={styles.iconGift} />
  1797. <p>
  1798. 现在购买额外赠送有效期
  1799. <div>
  1800. <span class={styles.vipGiftNum}>
  1801. {forms.detailVip.membershipDays || 0}
  1802. </span>
  1803. <span class={styles.vipGiftPreviod}>
  1804. {vipGiftPeriodType[forms.detailVip.giftPeriod]}
  1805. </span>
  1806. </div>
  1807. </p>
  1808. </div>
  1809. ) : (
  1810. ''
  1811. )}
  1812. {/* {forms.joinType === 'tradition' && (
  1813. <div class={styles.goodsTradition}>
  1814. <i class={styles.iconArrow}></i>
  1815. <div class={styles.goodsTitle}></div>
  1816. <div class={styles.steps}>
  1817. <div class={styles.step}>
  1818. <span class={styles.nums}>
  1819. <span class={styles.numInner}>1</span>
  1820. </span>
  1821. <div class={styles.stepContent}>
  1822. <span>AI工具标准:</span>
  1823. 可以学练音乐教材中的乐曲,通过手机应用商店准备。
  1824. </div>
  1825. </div>
  1826. {['Panpipes', 'Ocarina', 'Tenor Recorder', 'Woodwind'].includes(
  1827. forms.instrumentCode
  1828. ) && (
  1829. <div class={styles.step}>
  1830. <span class={styles.nums}>
  1831. <span class={styles.numInner}>2</span>
  1832. </span>
  1833. <div class={styles.stepContent}>
  1834. <span>
  1835. {forms.instrumentCode === 'Panpipes' && '排箫'}
  1836. {forms.instrumentCode === 'Ocarina' && '陶笛'}
  1837. {forms.instrumentCode === 'Tenor Recorder' && '竖笛'}
  1838. {forms.instrumentCode === 'Woodwind' && '葫芦丝'}
  1839. 标准:
  1840. </span>
  1841. {forms.instrumentCode === 'Panpipes' &&
  1842. '管数不限,建议20管以上C调加嘴排箫(不需要重复更换),黑色,选择单一原调(调性多很难掌握);'}
  1843. {forms.instrumentCode === 'Ocarina' &&
  1844. 'C调、蓝色、十二孔高音、树脂或陶土均可;'}
  1845. {forms.instrumentCode === 'Tenor Recorder' &&
  1846. 'C调、木质、高音德式八孔;'}
  1847. {forms.instrumentCode === 'Woodwind' &&
  1848. 'C调、红木色、树脂或木质;'}
  1849. </div>
  1850. </div>
  1851. )}
  1852. </div>
  1853. </div>
  1854. )} */}
  1855. {forms.joinType && (
  1856. <MSticky position="bottom" ref={mstickyRef}>
  1857. <div class={[styles.paymentContainer, forms.registerType === 'MUST_BUY_GOODS' && styles.paymentContainer2]}>
  1858. <div class={styles.payemntPrice}>
  1859. {
  1860. forms.registerType === 'SELECT_BUY_GOODS' &&
  1861. <img src={giftTip} class={styles.giftTip} />
  1862. }
  1863. <div>
  1864. <span class={styles.needPrice}>
  1865. <i style="font-style: normal">¥ </i>
  1866. <span>{moneyFormat(calcPrice.value.amount)}</span>
  1867. {
  1868. forms.registerType === 'SELECT_BUY_GOODS' &&
  1869. <i class={styles.unit} style="font-style: normal">
  1870. /年
  1871. </i>
  1872. }
  1873. </span>
  1874. {calcPrice.value.originAmount > calcPrice.value.amount &&
  1875. forms.joinType === 'digitalize' ? (
  1876. <del class={styles.allPrice}>
  1877. ¥ {moneyFormat(calcPrice.value.originAmount)}
  1878. </del>
  1879. ) : (
  1880. ''
  1881. )}
  1882. </div>
  1883. </div>
  1884. <div
  1885. class={styles.paymentBtn}
  1886. onClick={() => {
  1887. onSubmit();
  1888. }}>
  1889. {
  1890. forms.registerType === 'MUST_BUY_GOODS' ?
  1891. <Button
  1892. round
  1893. disabled={forms.submitLoading}
  1894. loading={forms.submitLoading}>
  1895. 立即购买
  1896. </Button> :
  1897. <Button
  1898. round
  1899. disabled={forms.submitLoading}
  1900. loading={forms.submitLoading}>
  1901. {forms.joinType === 'digitalize'
  1902. ? '报名与支付'
  1903. : '提交报名'}
  1904. </Button>
  1905. }
  1906. </div>
  1907. {/* {forms.joinType === 'tradition' && (
  1908. <div
  1909. class={styles.traditionBtn}
  1910. onClick={() => {
  1911. onSubmit();
  1912. }}>
  1913. <Button
  1914. round
  1915. disabled={forms.submitLoading}
  1916. loading={forms.submitLoading}>
  1917. 提交报名
  1918. </Button>
  1919. </div>
  1920. )} */}
  1921. </div>
  1922. </MSticky>
  1923. )}
  1924. </div>
  1925. {forms.imgCodeStatus ? (
  1926. <MImgCode
  1927. v-model:value={forms.imgCodeStatus}
  1928. phone={studentInfo.username}
  1929. type="REGISTER"
  1930. onClose={() => {
  1931. forms.imgCodeStatus = false;
  1932. }}
  1933. onSendCode={onCodeSend}
  1934. />
  1935. ) : null}
  1936. {/* 年级 */}
  1937. <Popup
  1938. v-model:show={forms.gradeStatus}
  1939. position="bottom"
  1940. round
  1941. safeAreaInsetBottom
  1942. lazyRender={false}
  1943. class={'popupBottomSearch'}
  1944. onOpen={() => {
  1945. forms.gradePopupShow = true;
  1946. }}
  1947. onClosed={() => {
  1948. forms.gradePopupShow = false;
  1949. }}>
  1950. {forms.gradePopupShow && (
  1951. <Picker
  1952. showToolbar
  1953. v-model={forms.gradePopupIndex}
  1954. columns={forms.gradeList}
  1955. onCancel={() => (forms.gradeStatus = false)}
  1956. onConfirm={(val: any) => {
  1957. const selectedOption = val.selectedOptions[0];
  1958. studentInfo.extra.currentGradeNum = selectedOption.value;
  1959. forms.gradeNumText = selectedOption.text;
  1960. forms.gradeStatus = false;
  1961. if (
  1962. ['SCHOOL', 'GRADE'].includes(forms.schoolInstrumentSetType)
  1963. ) {
  1964. forms.instrumentCode = selectedOption.instrumentCode;
  1965. }
  1966. if (forms.schoolInstrumentSetType === 'CLASS') {
  1967. forms.classList = selectedOption.classList;
  1968. }
  1969. if (
  1970. ['CLASS', 'GRADE'].includes(forms.schoolInstrumentSetType)
  1971. ) {
  1972. forms.currentClassText = '';
  1973. studentInfo.extra.currentClass = '';
  1974. }
  1975. // 更换年级班级后,判断是否需要更换赠送的乐器
  1976. if (forms.schoolInstrumentSetType === 'GRADE' && forms.registerType === 'MUST_BUY_GOODS') {
  1977. state.currentIntrument = state.intrumentList.find((item: any) => (item.gradeNum === selectedOption.value))
  1978. }
  1979. if (forms.schoolInstrumentSetType === 'CLASS' && forms.registerType === 'MUST_BUY_GOODS') {
  1980. state.currentIntrument = null
  1981. }
  1982. console.log('选择111',state.currentIntrument)
  1983. }}
  1984. />
  1985. )}
  1986. </Popup>
  1987. {/* 班级 */}
  1988. <Popup
  1989. v-model:show={forms.classStatus}
  1990. position="bottom"
  1991. round
  1992. class={'popupBottomSearch'}
  1993. onOpen={() => {
  1994. forms.classPopupShow = true;
  1995. }}
  1996. onClosed={() => {
  1997. forms.classPopupShow = false;
  1998. }}>
  1999. {forms.classPopupShow && (
  2000. <Picker
  2001. showToolbar
  2002. v-model={forms.classPopupIndex}
  2003. columns={forms.classList}
  2004. onCancel={() => (forms.classStatus = false)}
  2005. onConfirm={(val: any) => {
  2006. const selectedOption = val.selectedOptions[0];
  2007. studentInfo.extra.currentClass = selectedOption.value;
  2008. forms.currentClassText = selectedOption.text;
  2009. forms.classStatus = false;
  2010. if (['CLASS'].includes(forms.schoolInstrumentSetType)) {
  2011. forms.instrumentCode = selectedOption.instrumentCode;
  2012. }
  2013. // 更换年级班级后,判断是否需要更换赠送的乐器
  2014. if (forms.schoolInstrumentSetType === 'CLASS' && forms.registerType === 'MUST_BUY_GOODS') {
  2015. state.currentIntrument = state.intrumentList.find((item: any) => (item.gradeNum === studentInfo.extra.currentGradeNum && item.classNum === selectedOption.value) )
  2016. }
  2017. console.log('选择222',state.currentIntrument)
  2018. }}
  2019. />
  2020. )}
  2021. </Popup>
  2022. {/* 已经购买过样品 */}
  2023. {/* <MDialog
  2024. title="提示"
  2025. v-model:show={forms.dialogConfirmStatus}
  2026. message={'已购买会员,是否确认购买?'}
  2027. primaryColor="#FF8057"
  2028. allowHtml={true}
  2029. confirmButtonText="确定"
  2030. showCancelButton
  2031. onConfirm={async () => {
  2032. await paymentContinue();
  2033. }}
  2034. onCancel={() => {
  2035. //取消支付,判断是否有结束时间,是否已经结束
  2036. if (forms.registerExpireTime && forms.activeOverStatus) {
  2037. applyOver();
  2038. }
  2039. }}
  2040. /> */}
  2041. <MDialog
  2042. title="提示"
  2043. v-model:show={forms.dialogStatus}
  2044. message={forms.dialogMessage}
  2045. allowHtml={true}
  2046. primaryColor="#FF8057"
  2047. showCancelButton={true}
  2048. messageAlign={forms.messageAlign}
  2049. confirmButtonText={forms.confirmButtonText}
  2050. cancelButtonText={forms.cancelButtonText}
  2051. onConfirm={async () => {
  2052. if (forms.joinType === 'tradition') {
  2053. //
  2054. await cancelPaymentOrder();
  2055. //取消支付,判断是否有结束时间,是否已经结束
  2056. if (forms.registerExpireTime && forms.activeOverStatus) {
  2057. applyOver();
  2058. }
  2059. }
  2060. if (forms.joinType === 'digitalize') {
  2061. // 继续支付
  2062. const paymentConfig = forms.dialogConfig;
  2063. state.config = paymentConfig?.paymentConfig;
  2064. state.orderNo = paymentConfig?.orderNo;
  2065. const updateStatus = await updateStudentInfo();
  2066. if (!updateStatus) return;
  2067. await lastSubmit();
  2068. }
  2069. }}
  2070. onCancel={(val: any) => {
  2071. // countDown.pause();
  2072. if (forms.joinType === 'tradition') {
  2073. forms.dialogStatus = false;
  2074. //取消支付,判断是否有结束时间,是否已经结束
  2075. if (forms.registerExpireTime && forms.activeOverStatus) {
  2076. applyOver();
  2077. }
  2078. }
  2079. if (forms.joinType === 'digitalize') {
  2080. // 重新下单 - 先关闭订单
  2081. resetOrderPayment();
  2082. }
  2083. }}
  2084. />
  2085. <Popup
  2086. show={state.paymentStatus}
  2087. closeOnClickOverlay={false}
  2088. position="bottom"
  2089. round
  2090. closeOnPopstate
  2091. safeAreaInsetBottom
  2092. style={{ minHeight: '30%' }}>
  2093. <Payment
  2094. paymentConfig={state.orderInfo}
  2095. onClose={() => (state.paymentStatus = false)}
  2096. onBackOut={onBackOut}
  2097. onConfirm={(val: any) => onConfirm(val)}
  2098. />
  2099. </Popup>
  2100. <Popup
  2101. v-model:show={state.showQrcode}
  2102. round
  2103. onClose={() => {
  2104. // 二维码关闭时清除定时器
  2105. clearInterval(state.orderTimer);
  2106. }}>
  2107. <QrcodePayment
  2108. url={state.qrCodeUrl}
  2109. pay_channel={state.pay_channel}
  2110. orderType={orderType.value}
  2111. />
  2112. </Popup>
  2113. <MPopup v-model:modelValue={state.authShow}>
  2114. <UserAuth onSuccess={onAuthSuccess} hideHeader={!browser().isApp} />
  2115. </MPopup>
  2116. {/* 是否在微信中打开 */}
  2117. <OWxTip
  2118. show={forms.showTips}
  2119. message={forms.showMessage}
  2120. showButton={forms.showButton}
  2121. buttonText="刷新"
  2122. onConfirm={() => window.location.reload()}
  2123. />
  2124. <MMessageTip
  2125. show={otherParams.showOtherSchool}
  2126. // showCloseButton={otherParams.showCloseButton}
  2127. messageAlign={otherParams.messageAlign}
  2128. message={otherParams.showOtherMessage}
  2129. showCancelButton={otherParams.showCancelButton}
  2130. cancelButtonColor={otherParams.cancelButtonColor}
  2131. cancelButtonText={otherParams.cancelButtonText}
  2132. confirmButtonColor={otherParams.confirmButtonColor}
  2133. confirmButtonText={otherParams.confirmButtonText}
  2134. onClose={() => (otherParams.showOtherSchool = false)}
  2135. onCancel={async () => {
  2136. otherParams.showOtherSchool = false;
  2137. if (otherParams.otherType === 'nickname') {
  2138. forms.isRegister = 'create'; // 新建
  2139. changeTipStatus(false, false);
  2140. onSubmit();
  2141. } else if (otherParams.otherType === 'member') {
  2142. const updateStatus = await updateStudentInfo();
  2143. if (!updateStatus) return;
  2144. //取消支付,判断是否有结束时间,是否已经结束
  2145. if (forms.registerExpireTime && forms.activeOverStatus) {
  2146. applyOver();
  2147. }
  2148. } else if (otherParams.otherType === 'payment') {
  2149. forms.joinType = 'tradition';
  2150. }
  2151. }}
  2152. onConfirm={async () => {
  2153. otherParams.showOtherSchool = false;
  2154. // 名字
  2155. if (otherParams.otherType === 'nickname') {
  2156. forms.isRegister = 'update'; // 修改
  2157. changeTipStatus(false, false);
  2158. // 直接注册
  2159. onSubmit();
  2160. } else if (otherParams.otherType === 'change') {
  2161. // 学校更换
  2162. forms.isChangeSchool = true;
  2163. // 直接注册
  2164. onSubmit();
  2165. } else if (otherParams.otherType === 'limit') {
  2166. // 人数超限制
  2167. changeTipStatus(
  2168. forms.isRegister === 'create' && !forms.studentItem.userId
  2169. ? false
  2170. : true,
  2171. false
  2172. );
  2173. } else if (otherParams.otherType === 'member') {
  2174. await paymentContinue();
  2175. }
  2176. }}
  2177. />
  2178. <Popup
  2179. v-model:show={forms.showSelectStudent}
  2180. round
  2181. position="bottom"
  2182. safeAreaInsetBottom
  2183. closeable>
  2184. <SelectStudent
  2185. studentItem={forms.studentItem}
  2186. list={forms.studentList}
  2187. onClose={() => (forms.showSelectStudent = false)}
  2188. onConfirm={(val: any) => {
  2189. console.log('测试111')
  2190. if (val.userId) {
  2191. forms.studentItem = val;
  2192. const firstStudent = val;
  2193. studentInfo.extra.nickname = firstStudent.nickname;
  2194. const tempGrade: any = forms.gradeList || [];
  2195. studentInfo.extra.currentGradeNum = null;
  2196. forms.gradeNumText = '';
  2197. forms.instrumentCode = '';
  2198. tempGrade?.forEach((i: any) => {
  2199. if (i.value === firstStudent.currentGradeNum) {
  2200. forms.instrumentCode = i.instrumentCode;
  2201. forms.gradeNumText = i.text;
  2202. studentInfo.extra.currentGradeNum =
  2203. firstStudent.currentGradeNum;
  2204. if (forms.schoolInstrumentSetType === 'CLASS') {
  2205. forms.classList = i.classList;
  2206. }
  2207. }
  2208. });
  2209. studentInfo.extra.currentClass = null;
  2210. forms.currentClassText = '';
  2211. forms.classList.forEach((i: any) => {
  2212. if (i.value === firstStudent.currentClass) {
  2213. forms.currentClassText = i.text;
  2214. studentInfo.extra.currentClass = firstStudent.currentClass;
  2215. }
  2216. });
  2217. studentInfo.extra.gender = firstStudent.gender;
  2218. forms.isRegister = 'update';
  2219. changeTipStatus(true, false);
  2220. forms.showSelectStudent = false;
  2221. } else {
  2222. // 判断新建学员是否上限了
  2223. if (forms.studentList.length >= forms.multi_user_limit) {
  2224. otherParams.showOtherMessage = `同一手机号最多创建${forms.multi_user_limit}个学生`;
  2225. otherParams.showOtherSchool = true;
  2226. otherParams.showCancelButton = false;
  2227. otherParams.showCloseButton = true;
  2228. otherParams.confirmButtonColor =
  2229. 'linear-gradient( 305deg, #40C8FF 0%, #3192FF 100%)';
  2230. otherParams.confirmButtonText = '我知道了';
  2231. otherParams.otherType = 'limit';
  2232. otherParams.messageAlign = 'center';
  2233. return true;
  2234. } else {
  2235. forms.studentItem = val;
  2236. forms.isRegister = 'create';
  2237. changeTipStatus(false, false);
  2238. studentInfo.extra.nickname = '';
  2239. studentInfo.extra.currentGradeNum = '';
  2240. studentInfo.extra.currentClass = '';
  2241. studentInfo.extra.gender = 1;
  2242. forms.currentClassText = '';
  2243. forms.gradeNumText = '';
  2244. forms.showSelectStudent = false;
  2245. }
  2246. }
  2247. // 切换学生,需要更换显示的乐器
  2248. matchSwitchInstrument(val)
  2249. }}
  2250. />
  2251. </Popup>
  2252. {
  2253. state.tipBoxPop &&
  2254. <div class={styles.tipBoxPop}>
  2255. <div class={[styles.tipBox, !state.giftDesc && styles.tipBox2]}>
  2256. <img class={styles.tipTitle} src={tipTitleIcon} />
  2257. <ul>
  2258. <li class={styles.tipItem}>
  2259. <img src={tipIcon1} />
  2260. <p>开课时赠送<span>全新乐器一支</span></p>
  2261. </li>
  2262. {
  2263. state.giftDesc &&
  2264. <li class={styles.tipItem}>
  2265. <img src={tipIcon2} />
  2266. <p v-html={state.giftDesc}></p>
  2267. </li>
  2268. }
  2269. <li class={styles.tipItem}>
  2270. <img src={state.giftDesc ? tipIcon3 : tipIcon2} />
  2271. <p><span>7天内无理由</span>全额退款保障</p>
  2272. </li>
  2273. </ul>
  2274. <div class={styles.tipBtn}>
  2275. <img src={tipBtnIcon} />
  2276. <span onClick={() => {
  2277. if (state.hideSecondsNum) {
  2278. state.tipBoxPop = false
  2279. document.body.style.overflow = '';
  2280. }
  2281. }}>
  2282. 我知道了
  2283. {
  2284. !state.hideSecondsNum && <i>({state.descSecondsNum}s)</i>
  2285. }
  2286. </span>
  2287. </div>
  2288. </div>
  2289. </div>
  2290. }
  2291. </div>
  2292. );
  2293. }
  2294. });