index-apply.tsx 85 KB

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