index-apply.tsx 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390
  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. onMounted(async () => {
  1277. try {
  1278. // 获取支付类型
  1279. let expireDay = null;
  1280. const { data } = await request.get(
  1281. '/edu-app/open/paramConfig/queryByParamNameList',
  1282. {
  1283. requestType: 'form',
  1284. params: {
  1285. paramNames:
  1286. 'payment_service_provider,contract_sign,multi_user_limit,qr_code_expire_time'
  1287. }
  1288. }
  1289. );
  1290. if (data && Array.isArray(data)) {
  1291. data.forEach((item: any) => {
  1292. if (item.paramName === 'contract_sign') {
  1293. forms.contract_sign = item.paramValue === '1' ? true : false;
  1294. } else if (item.paramName === 'payment_service_provider') {
  1295. // forms.paymentType = item.paramValue || '';
  1296. const provider = JSON.parse(item.paramValue);
  1297. forms.paymentType = provider.vendor;
  1298. forms.paymentChannel = provider.channel;
  1299. } else if (item.paramName === 'multi_user_limit') {
  1300. forms.multi_user_limit = item.paramValue
  1301. ? Number(item.paramValue)
  1302. : 1;
  1303. } else if (item.paramName === 'qr_code_expire_time') {
  1304. expireDay = item.paramValue ? Number(item.paramValue) : null;
  1305. }
  1306. });
  1307. }
  1308. const createT = route.query.t;
  1309. if (createT && expireDay !== null) {
  1310. if (dayjs(Number(createT)).add(expireDay, 'day').isBefore(dayjs())) {
  1311. forms.showTips = true;
  1312. forms.showMessage = '二维码已经失效,详情请咨询学校老师';
  1313. forms.showButton = false;
  1314. }
  1315. }
  1316. await getRegisterGoods();
  1317. nextTick(() => {
  1318. // 一页展示(必买)才显示团购提示弹窗
  1319. if (forms.registerType === 'MUST_BUY_GOODS' && browser().weixin) {
  1320. state.tipBoxPop = true
  1321. tipCountdown(3)
  1322. }
  1323. })
  1324. } catch {}
  1325. });
  1326. onUnmounted(() => {
  1327. forms.intervalFnRef?.pause(); // 暂停回调
  1328. });
  1329. return () => (
  1330. <div class={styles['student-register']}>
  1331. <div class={[(forms.registerType === 'MUST_BUY_GOODS' || route.query.rt === 'MUST_BUY_GOODS') ? styles.studentRegisterContainer2 : styles.studentRegisterContainer]}>
  1332. {!forms.activeOverStatus && (
  1333. <div class={styles.countdownSection}>
  1334. <div class={styles.timer}>
  1335. <img src={icon3} class={styles.timerTitle} />
  1336. <div class={styles.timerAll}>
  1337. <span>{formatTimerTo(overCountDown.current.value.days)}</span>
  1338. <span>
  1339. {formatTimerTo(overCountDown.current.value.hours)}
  1340. </span>
  1341. <span>
  1342. {formatTimerTo(overCountDown.current.value.minutes)}
  1343. </span>
  1344. <span>
  1345. {formatTimerTo(overCountDown.current.value.seconds)}
  1346. </span>
  1347. </div>
  1348. </div>
  1349. <div class={styles.timerTip}>
  1350. 为了确保您能顺利参与学习,请在规定时间内报名
  1351. </div>
  1352. </div>
  1353. )}
  1354. <div
  1355. class={[
  1356. styles.studentSection,
  1357. styles.studentSectionForm,
  1358. forms.giftVipDay <= 0 && styles.noSendDay
  1359. ]}>
  1360. {
  1361. forms.registerType === 'MUST_BUY_GOODS' &&
  1362. <div class={styles.title1}></div>
  1363. }
  1364. <Form labelAlign="left" class={styles.registerForm}>
  1365. <Field
  1366. clearable={false}
  1367. label="联系方式(直接监护人)"
  1368. placeholder="请输入手机号码"
  1369. type="tel"
  1370. required
  1371. autocomplete="off"
  1372. inputAlign="right"
  1373. class={styles.username}
  1374. v-model={studentInfo.username}
  1375. border={false}
  1376. maxlength={11}
  1377. onUpdate:modelValue={() => {
  1378. phoneChangeEmptyInfo();
  1379. }}>
  1380. {{
  1381. label: () => (
  1382. <div>
  1383. 联系方式
  1384. {/* (直接监护人) */}
  1385. <p class={styles.tips}>(直接监护人)</p>
  1386. </div>
  1387. )
  1388. }}
  1389. </Field>
  1390. <div class={['van-hairline--bottom', styles.fieldTipsGroup]}>
  1391. <div class={[styles.fieldTips]}>
  1392. <i class={styles.iconQuestion}></i>
  1393. 手机号是音乐数字课堂的唯一登录账户
  1394. </div>
  1395. </div>
  1396. <Field
  1397. center
  1398. clearable={false}
  1399. required
  1400. inputAlign="right"
  1401. label="验证码"
  1402. placeholder="请输入验证码"
  1403. autocomplete="off"
  1404. type="number"
  1405. v-model={studentInfo.password}
  1406. maxlength={6}
  1407. onUpdate:modelValue={(val: any) => {
  1408. getUserInfos();
  1409. }}>
  1410. {{
  1411. button: () =>
  1412. forms.countDownStatus ? (
  1413. <span
  1414. class={[
  1415. styles.codeText,
  1416. !validatePhone.value ? styles.codeTextDisabled : ''
  1417. ]}
  1418. onClick={onSendCode}>
  1419. 获取验证码
  1420. </span>
  1421. ) : (
  1422. <CountDown
  1423. ref={(el: any) => (countDownRef.value = el)}
  1424. auto-start={false}
  1425. class={styles.countDown}
  1426. time={forms.countDownTime}
  1427. onFinish={onFinished}
  1428. format="ss秒后重试"
  1429. />
  1430. )
  1431. }}
  1432. </Field>
  1433. {/* 大于等于2,则可以切换学生 */}
  1434. {/* {forms.studentList.length > 1 && (
  1435. <div
  1436. class={[
  1437. styles.selectStudentGroup,
  1438. forms.showSelectStudent && styles.selectStudentGroupChecked
  1439. ]}
  1440. onClick={() => (forms.showSelectStudent = true)}>
  1441. <i
  1442. class={[
  1443. styles.studentIcon,
  1444. !forms.studentItem.userId && styles.studentIconAdd
  1445. ]}></i>
  1446. <span>
  1447. {forms.studentItem.userId
  1448. ? forms.studentItem.nickname
  1449. : '新增学生'}
  1450. </span>
  1451. </div>
  1452. )} */}
  1453. <Field
  1454. clearable={false}
  1455. required
  1456. inputAlign="right"
  1457. label="学生姓名"
  1458. placeholder="请输入学生姓名"
  1459. autocomplete="off"
  1460. maxlength={14}
  1461. v-model={studentInfo.extra.nickname}>
  1462. {{
  1463. extra: () =>
  1464. forms.studentList.length > 1 && (
  1465. <div
  1466. class={[
  1467. styles.selectStudentGroup,
  1468. forms.showSelectStudent &&
  1469. styles.selectStudentGroupChecked
  1470. ]}
  1471. onClick={() => (forms.showSelectStudent = true)}>
  1472. <span>
  1473. {forms.studentItem.userId ? '切换' : '新增'}
  1474. </span>
  1475. </div>
  1476. )
  1477. }}
  1478. </Field>
  1479. <Field
  1480. clearable={false}
  1481. required
  1482. inputAlign="right"
  1483. label="学生性别"
  1484. placeholder="请选择性别"
  1485. autocomplete="off"
  1486. // v-model={studentInfo.extra.nickname}
  1487. >
  1488. {{
  1489. input: () => (
  1490. <RadioGroup
  1491. checked-color="linear-gradient( 135deg, #31C7FF 0%, #007AFE 100%)"
  1492. v-model={studentInfo.extra.gender}
  1493. direction="horizontal">
  1494. <Tag
  1495. size="large"
  1496. type="primary"
  1497. color={
  1498. !(studentInfo.extra.gender === 1)
  1499. ? '#F5F6FA'
  1500. : 'linear-gradient( 135deg, #31C7FF 0%, #007AFE 100%)'
  1501. }
  1502. textColor={
  1503. !(studentInfo.extra.gender === 1) ? '#626264' : '#fff'
  1504. }
  1505. class={styles.radioSection}>
  1506. <Radio class={styles.radioItem} name={1}></Radio>男
  1507. </Tag>
  1508. <Tag
  1509. size="large"
  1510. type="primary"
  1511. color={
  1512. !(studentInfo.extra.gender === 0)
  1513. ? '#F5F6FA'
  1514. : 'linear-gradient( 135deg, #31C7FF 0%, #007AFE 100%)'
  1515. }
  1516. textColor={
  1517. !(studentInfo.extra.gender === 0) ? '#626264' : '#fff'
  1518. }
  1519. class={styles.radioSection}>
  1520. <Radio class={styles.radioItem} name={0}></Radio>女
  1521. </Tag>
  1522. </RadioGroup>
  1523. )
  1524. }}
  1525. </Field>
  1526. <Field
  1527. clearable={false}
  1528. required
  1529. inputAlign="right"
  1530. label="所在年级"
  1531. placeholder="请选择年级"
  1532. isLink
  1533. readonly
  1534. clickable={false}
  1535. modelValue={forms.gradeNumText}
  1536. onClick={() => {
  1537. forms.gradePopupIndex = [studentInfo.extra.currentGradeNum];
  1538. forms.gradeStatus = true;
  1539. }}
  1540. />
  1541. <Field
  1542. clearable={false}
  1543. required
  1544. inputAlign="right"
  1545. label="所在班级"
  1546. placeholder="请选择班级"
  1547. isLink
  1548. readonly
  1549. clickable={false}
  1550. modelValue={forms.currentClassText}
  1551. onClick={() => {
  1552. if (
  1553. forms.schoolInstrumentSetType === 'CLASS' &&
  1554. forms.classList.length <= 0
  1555. ) {
  1556. showToast('请先选择年级');
  1557. return;
  1558. }
  1559. forms.classPopupIndex = [studentInfo.extra.currentClass];
  1560. forms.classStatus = true;
  1561. }}
  1562. />
  1563. {(forms.giftVipDay > 0 && forms.registerDetails.giftVipFlag) ? (
  1564. <div class={styles.memberNumer}>
  1565. <img src={iconGift} class={styles.iconGift} />
  1566. <p>
  1567. 注册成功即可获得乐器AI学练工具
  1568. <span>{forms.giftVipDay || 0}</span>天有效期
  1569. </p>
  1570. </div>
  1571. ) : (
  1572. ''
  1573. )}
  1574. </Form>
  1575. </div>
  1576. {/* <div class={styles.studentSection}>
  1577. <div class={styles.title2}></div>
  1578. <div class={styles.goodsGroup}>
  1579. <div
  1580. class={[
  1581. styles.goodsItem,
  1582. styles.digitalize,
  1583. forms.joinType === 'digitalize' && styles.checked
  1584. ]}
  1585. onClick={() => {
  1586. //
  1587. if (checkForm()) {
  1588. showToast('请将资料填写完整');
  1589. return;
  1590. }
  1591. forms.joinType = 'digitalize';
  1592. nextTick(() => {
  1593. mstickyRef.value?.onChnageHeight();
  1594. setTimeout(() => {
  1595. window.scrollTo(0, 1000);
  1596. }, 50);
  1597. });
  1598. }}>
  1599. <div class={styles.goodsInner}>
  1600. <i class={styles.proposalTip}></i>
  1601. 数字化方式
  1602. </div>
  1603. </div>
  1604. <div
  1605. class={[
  1606. styles.goodsItem,
  1607. styles.tradition,
  1608. forms.joinType === 'tradition' && styles.checked1
  1609. ]}
  1610. onClick={() => {
  1611. if (checkForm()) {
  1612. showToast('请将资料填写完整');
  1613. return;
  1614. }
  1615. forms.joinType = 'tradition';
  1616. nextTick(() => {
  1617. mstickyRef.value?.onChnageHeight();
  1618. setTimeout(() => {
  1619. window.scrollTo(0, 1000);
  1620. }, 50);
  1621. });
  1622. }}>
  1623. <div class={styles.goodsInner}>传统方式</div>
  1624. </div>
  1625. </div>
  1626. </div> */}
  1627. {
  1628. forms.registerType !== 'MUST_BUY_GOODS' &&
  1629. <div class={[styles.goodsExtra]}>
  1630. {/* <i class={styles.iconArrow}></i> */}
  1631. <Cell
  1632. border={false}
  1633. class={[
  1634. styles.goodsCell,
  1635. forms.registerType === 'SELECT_BUY_GOODS' &&
  1636. styles.goodsBuyGoods
  1637. ]}
  1638. center
  1639. onClick={() => {
  1640. // console.log(forms.joinType, 'joinType');
  1641. if (forms.registerType !== 'SELECT_BUY_GOODS') return;
  1642. if (forms.joinType === 'digitalize') {
  1643. otherParams.showOtherMessage = `没有陪练工具,将无法实现同步练习`;
  1644. otherParams.showOtherSchool = true;
  1645. otherParams.showCloseButton = true;
  1646. otherParams.showCancelButton = true;
  1647. otherParams.cancelButtonColor = '';
  1648. otherParams.cancelButtonText = '确认取消';
  1649. otherParams.confirmButtonColor = '';
  1650. otherParams.confirmButtonText = '放弃取消';
  1651. otherParams.otherType = 'payment';
  1652. otherParams.messageAlign = 'center';
  1653. } else if (forms.joinType === 'tradition') {
  1654. forms.joinType = 'digitalize';
  1655. }
  1656. }}>
  1657. {{
  1658. icon: () =>
  1659. forms.registerType === 'SELECT_BUY_GOODS' && (
  1660. <div class={styles.checkedGroup}>
  1661. <i
  1662. class={[
  1663. styles.iconChecked,
  1664. forms.joinType === 'digitalize' && styles.selected
  1665. ]}></i>
  1666. {/* {forms.tipStatus && <i class={styles.showBg}></i>} */}
  1667. {forms.joinType === 'digitalize' && (
  1668. <i class={styles.showBg}></i>
  1669. )}
  1670. </div>
  1671. ),
  1672. title: () => (
  1673. <div class={styles.section}>
  1674. <Image
  1675. class={styles.img}
  1676. src={forms.detailVip.goodsUrl || tuangou}
  1677. />
  1678. <div class={styles.sectionContent}>
  1679. <img
  1680. src={
  1681. forms.registerType === 'SELECT_BUY_GOODS'
  1682. ? icon5
  1683. : icon10
  1684. }
  1685. class={styles.goodsName}
  1686. />
  1687. </div>
  1688. </div>
  1689. )
  1690. }}
  1691. </Cell>
  1692. </div>
  1693. }
  1694. {
  1695. forms.registerType === 'MUST_BUY_GOODS' &&
  1696. <div class={styles.giftBox}>
  1697. <img class={styles.titleIcon} src={giftBoxTitleIcon} />
  1698. <div class={styles.tools}>
  1699. <img class={styles.toolImg} src={forms.detailVip.goodsUrl || giftCard1Icon} />
  1700. <div class={styles.toolRight}>
  1701. <p>乐器AI学练工具一年卡</p>
  1702. <div class={styles.trDesc}>7天无理由退款</div>
  1703. <div class={styles.trBottom}>
  1704. <span class={styles.tcPrice}>¥ {Number(forms.detailVip.currentPrice).toFixed(2)}</span>
  1705. <span class={styles.toPrice}>|原价 <i>¥ {Number(forms.detailVip.originalPrice).toFixed(2)}</i></span>
  1706. </div>
  1707. </div>
  1708. </div>
  1709. {/** 有赠品才显示 */}
  1710. {
  1711. (forms.detailVip.giftFlag || state.currentIntrument?.instrumentId) &&
  1712. <div class={styles.extraTools}>
  1713. <div class={styles.exTitle}>
  1714. <img src={giftExtraTitleIcon} />
  1715. </div>
  1716. {/** 会员赠送 */}
  1717. {
  1718. forms.detailVip.giftFlag &&
  1719. <div class={styles.extItem}>
  1720. <img class={styles.toolImg} src={giftCard2Icon} />
  1721. <div class={styles.toolRight}>
  1722. <p>乐器AI学练工具{forms.detailVip.giftPeriod === 'YEAR' ? convertToChineseNumber(forms.detailVip.giftVipDay) : forms.detailVip.giftVipDay}{forms.detailVip.zsUnit}卡</p>
  1723. <div class={styles.trBottom}>
  1724. <span class={styles.tcPrice}>¥ 0.00</span>
  1725. <span class={styles.toPrice}>|原价 <i>¥ {Number(forms.detailVip.giftOriginalPrice).toFixed(2)}</i></span>
  1726. </div>
  1727. </div>
  1728. <img class={styles.toolZsIcon} src={giftZsIcon} />
  1729. </div>
  1730. }
  1731. {/** 乐器赠送,注册类型为MUST_BUY_GOODS,才显示赠送乐器 */}
  1732. {
  1733. (state.currentIntrument?.instrumentId && forms.registerType === 'MUST_BUY_GOODS') &&
  1734. <div class={styles.extItem}>
  1735. <img class={styles.toolImg} src={state.currentIntrument.img} />
  1736. <div class={styles.toolRight}>
  1737. <p>{state.currentIntrument.instrumentName}</p>
  1738. <div class={styles.trBottom}>
  1739. <span class={styles.tcPrice}>¥ 0.00</span>
  1740. <span class={styles.toPrice}>|原价 <i>¥ {Number(state.currentIntrument.originalPrice).toFixed(2)}</i></span>
  1741. </div>
  1742. </div>
  1743. <img class={styles.toolZsIcon} src={giftZsIcon} />
  1744. </div>
  1745. }
  1746. </div>
  1747. }
  1748. </div>
  1749. }
  1750. {/* <div class={[styles.memberNumer, styles.aiMemberNumber]}>
  1751. <img src={iconGift} class={styles.iconGift} />
  1752. <p>
  1753. 首次购买赠送乐器AI学练工具
  1754. <span>{forms.detailVip.membershipDays || 0}</span>天有效期
  1755. </p>
  1756. </div> */}
  1757. {forms.detailVip.membershipDays && forms.registerType !== 'MUST_BUY_GOODS' ? (
  1758. <div class={styles.vipGiftContainer}>
  1759. <img src={vipGiftTIps} class={styles.iconGift} />
  1760. <p>
  1761. 现在购买额外赠送有效期
  1762. <div>
  1763. <span class={styles.vipGiftNum}>
  1764. {forms.detailVip.membershipDays || 0}
  1765. </span>
  1766. <span class={styles.vipGiftPreviod}>
  1767. {vipGiftPeriodType[forms.detailVip.giftPeriod]}
  1768. </span>
  1769. </div>
  1770. </p>
  1771. </div>
  1772. ) : (
  1773. ''
  1774. )}
  1775. {/* {forms.joinType === 'tradition' && (
  1776. <div class={styles.goodsTradition}>
  1777. <i class={styles.iconArrow}></i>
  1778. <div class={styles.goodsTitle}></div>
  1779. <div class={styles.steps}>
  1780. <div class={styles.step}>
  1781. <span class={styles.nums}>
  1782. <span class={styles.numInner}>1</span>
  1783. </span>
  1784. <div class={styles.stepContent}>
  1785. <span>AI工具标准:</span>
  1786. 可以学练音乐教材中的乐曲,通过手机应用商店准备。
  1787. </div>
  1788. </div>
  1789. {['Panpipes', 'Ocarina', 'Tenor Recorder', 'Woodwind'].includes(
  1790. forms.instrumentCode
  1791. ) && (
  1792. <div class={styles.step}>
  1793. <span class={styles.nums}>
  1794. <span class={styles.numInner}>2</span>
  1795. </span>
  1796. <div class={styles.stepContent}>
  1797. <span>
  1798. {forms.instrumentCode === 'Panpipes' && '排箫'}
  1799. {forms.instrumentCode === 'Ocarina' && '陶笛'}
  1800. {forms.instrumentCode === 'Tenor Recorder' && '竖笛'}
  1801. {forms.instrumentCode === 'Woodwind' && '葫芦丝'}
  1802. 标准:
  1803. </span>
  1804. {forms.instrumentCode === 'Panpipes' &&
  1805. '管数不限,建议20管以上C调加嘴排箫(不需要重复更换),黑色,选择单一原调(调性多很难掌握);'}
  1806. {forms.instrumentCode === 'Ocarina' &&
  1807. 'C调、蓝色、十二孔高音、树脂或陶土均可;'}
  1808. {forms.instrumentCode === 'Tenor Recorder' &&
  1809. 'C调、木质、高音德式八孔;'}
  1810. {forms.instrumentCode === 'Woodwind' &&
  1811. 'C调、红木色、树脂或木质;'}
  1812. </div>
  1813. </div>
  1814. )}
  1815. </div>
  1816. </div>
  1817. )} */}
  1818. {forms.joinType && (
  1819. <MSticky position="bottom" ref={mstickyRef}>
  1820. <div class={styles.paymentContainer}>
  1821. <div class={styles.payemntPrice}>
  1822. {
  1823. forms.registerType === 'SELECT_BUY_GOODS' &&
  1824. <img src={giftTip} class={styles.giftTip} />
  1825. }
  1826. <div>
  1827. <span class={styles.needPrice}>
  1828. <i style="font-style: normal">¥ </i>
  1829. <span>{moneyFormat(calcPrice.value.amount)}</span>
  1830. {
  1831. forms.registerType === 'SELECT_BUY_GOODS' &&
  1832. <i class={styles.unit} style="font-style: normal">
  1833. /年
  1834. </i>
  1835. }
  1836. </span>
  1837. {calcPrice.value.originAmount > calcPrice.value.amount &&
  1838. forms.joinType === 'digitalize' ? (
  1839. <del class={styles.allPrice}>
  1840. ¥ {moneyFormat(calcPrice.value.originAmount)}
  1841. </del>
  1842. ) : (
  1843. ''
  1844. )}
  1845. </div>
  1846. </div>
  1847. <div
  1848. class={styles.paymentBtn}
  1849. onClick={() => {
  1850. onSubmit();
  1851. }}>
  1852. {
  1853. forms.registerType === 'MUST_BUY_GOODS' ?
  1854. <Button
  1855. round
  1856. disabled={forms.submitLoading}
  1857. loading={forms.submitLoading}>
  1858. 立即购买
  1859. </Button> :
  1860. <Button
  1861. round
  1862. disabled={forms.submitLoading}
  1863. loading={forms.submitLoading}>
  1864. {forms.joinType === 'digitalize'
  1865. ? '报名与支付'
  1866. : '提交报名'}
  1867. </Button>
  1868. }
  1869. </div>
  1870. {/* {forms.joinType === 'tradition' && (
  1871. <div
  1872. class={styles.traditionBtn}
  1873. onClick={() => {
  1874. onSubmit();
  1875. }}>
  1876. <Button
  1877. round
  1878. disabled={forms.submitLoading}
  1879. loading={forms.submitLoading}>
  1880. 提交报名
  1881. </Button>
  1882. </div>
  1883. )} */}
  1884. </div>
  1885. </MSticky>
  1886. )}
  1887. </div>
  1888. {forms.imgCodeStatus ? (
  1889. <MImgCode
  1890. v-model:value={forms.imgCodeStatus}
  1891. phone={studentInfo.username}
  1892. type="REGISTER"
  1893. onClose={() => {
  1894. forms.imgCodeStatus = false;
  1895. }}
  1896. onSendCode={onCodeSend}
  1897. />
  1898. ) : null}
  1899. {/* 年级 */}
  1900. <Popup
  1901. v-model:show={forms.gradeStatus}
  1902. position="bottom"
  1903. round
  1904. safeAreaInsetBottom
  1905. lazyRender={false}
  1906. class={'popupBottomSearch'}
  1907. onOpen={() => {
  1908. forms.gradePopupShow = true;
  1909. }}
  1910. onClosed={() => {
  1911. forms.gradePopupShow = false;
  1912. }}>
  1913. {forms.gradePopupShow && (
  1914. <Picker
  1915. showToolbar
  1916. v-model={forms.gradePopupIndex}
  1917. columns={forms.gradeList}
  1918. onCancel={() => (forms.gradeStatus = false)}
  1919. onConfirm={(val: any) => {
  1920. const selectedOption = val.selectedOptions[0];
  1921. studentInfo.extra.currentGradeNum = selectedOption.value;
  1922. forms.gradeNumText = selectedOption.text;
  1923. forms.gradeStatus = false;
  1924. if (
  1925. ['SCHOOL', 'GRADE'].includes(forms.schoolInstrumentSetType)
  1926. ) {
  1927. forms.instrumentCode = selectedOption.instrumentCode;
  1928. }
  1929. if (forms.schoolInstrumentSetType === 'CLASS') {
  1930. forms.classList = selectedOption.classList;
  1931. }
  1932. if (
  1933. ['CLASS', 'GRADE'].includes(forms.schoolInstrumentSetType)
  1934. ) {
  1935. forms.currentClassText = '';
  1936. studentInfo.extra.currentClass = '';
  1937. }
  1938. // 更换年级班级后,判断是否需要更换赠送的乐器
  1939. if (forms.schoolInstrumentSetType === 'GRADE' && forms.registerType === 'MUST_BUY_GOODS') {
  1940. state.currentIntrument = state.intrumentList.find((item: any) => (item.gradeNum === selectedOption.value))
  1941. }
  1942. if (forms.schoolInstrumentSetType === 'CLASS' && forms.registerType === 'MUST_BUY_GOODS') {
  1943. state.currentIntrument = null
  1944. }
  1945. console.log('选择111',state.currentIntrument)
  1946. }}
  1947. />
  1948. )}
  1949. </Popup>
  1950. {/* 班级 */}
  1951. <Popup
  1952. v-model:show={forms.classStatus}
  1953. position="bottom"
  1954. round
  1955. class={'popupBottomSearch'}
  1956. onOpen={() => {
  1957. forms.classPopupShow = true;
  1958. }}
  1959. onClosed={() => {
  1960. forms.classPopupShow = false;
  1961. }}>
  1962. {forms.classPopupShow && (
  1963. <Picker
  1964. showToolbar
  1965. v-model={forms.classPopupIndex}
  1966. columns={forms.classList}
  1967. onCancel={() => (forms.classStatus = false)}
  1968. onConfirm={(val: any) => {
  1969. const selectedOption = val.selectedOptions[0];
  1970. studentInfo.extra.currentClass = selectedOption.value;
  1971. forms.currentClassText = selectedOption.text;
  1972. forms.classStatus = false;
  1973. if (['CLASS'].includes(forms.schoolInstrumentSetType)) {
  1974. forms.instrumentCode = selectedOption.instrumentCode;
  1975. }
  1976. // 更换年级班级后,判断是否需要更换赠送的乐器
  1977. if (forms.schoolInstrumentSetType === 'CLASS' && forms.registerType === 'MUST_BUY_GOODS') {
  1978. state.currentIntrument = state.intrumentList.find((item: any) => (item.gradeNum === studentInfo.extra.currentGradeNum && item.classNum === selectedOption.value) )
  1979. }
  1980. console.log('选择222',state.currentIntrument)
  1981. }}
  1982. />
  1983. )}
  1984. </Popup>
  1985. {/* 已经购买过样品 */}
  1986. {/* <MDialog
  1987. title="提示"
  1988. v-model:show={forms.dialogConfirmStatus}
  1989. message={'已购买会员,是否确认购买?'}
  1990. primaryColor="#FF8057"
  1991. allowHtml={true}
  1992. confirmButtonText="确定"
  1993. showCancelButton
  1994. onConfirm={async () => {
  1995. await paymentContinue();
  1996. }}
  1997. onCancel={() => {
  1998. //取消支付,判断是否有结束时间,是否已经结束
  1999. if (forms.registerExpireTime && forms.activeOverStatus) {
  2000. applyOver();
  2001. }
  2002. }}
  2003. /> */}
  2004. <MDialog
  2005. title="提示"
  2006. v-model:show={forms.dialogStatus}
  2007. message={forms.dialogMessage}
  2008. allowHtml={true}
  2009. primaryColor="#FF8057"
  2010. showCancelButton={true}
  2011. messageAlign={forms.messageAlign}
  2012. confirmButtonText={forms.confirmButtonText}
  2013. cancelButtonText={forms.cancelButtonText}
  2014. onConfirm={async () => {
  2015. if (forms.joinType === 'tradition') {
  2016. //
  2017. await cancelPaymentOrder();
  2018. //取消支付,判断是否有结束时间,是否已经结束
  2019. if (forms.registerExpireTime && forms.activeOverStatus) {
  2020. applyOver();
  2021. }
  2022. }
  2023. if (forms.joinType === 'digitalize') {
  2024. // 继续支付
  2025. const paymentConfig = forms.dialogConfig;
  2026. state.config = paymentConfig?.paymentConfig;
  2027. state.orderNo = paymentConfig?.orderNo;
  2028. const updateStatus = await updateStudentInfo();
  2029. if (!updateStatus) return;
  2030. await lastSubmit();
  2031. }
  2032. }}
  2033. onCancel={(val: any) => {
  2034. // countDown.pause();
  2035. if (forms.joinType === 'tradition') {
  2036. forms.dialogStatus = false;
  2037. //取消支付,判断是否有结束时间,是否已经结束
  2038. if (forms.registerExpireTime && forms.activeOverStatus) {
  2039. applyOver();
  2040. }
  2041. }
  2042. if (forms.joinType === 'digitalize') {
  2043. // 重新下单 - 先关闭订单
  2044. resetOrderPayment();
  2045. }
  2046. }}
  2047. />
  2048. <Popup
  2049. show={state.paymentStatus}
  2050. closeOnClickOverlay={false}
  2051. position="bottom"
  2052. round
  2053. closeOnPopstate
  2054. safeAreaInsetBottom
  2055. style={{ minHeight: '30%' }}>
  2056. <Payment
  2057. paymentConfig={state.orderInfo}
  2058. onClose={() => (state.paymentStatus = false)}
  2059. onBackOut={onBackOut}
  2060. onConfirm={(val: any) => onConfirm(val)}
  2061. />
  2062. </Popup>
  2063. <Popup
  2064. v-model:show={state.showQrcode}
  2065. round
  2066. onClose={() => {
  2067. // 二维码关闭时清除定时器
  2068. clearInterval(state.orderTimer);
  2069. }}>
  2070. <QrcodePayment
  2071. url={state.qrCodeUrl}
  2072. pay_channel={state.pay_channel}
  2073. orderType={orderType.value}
  2074. />
  2075. </Popup>
  2076. <MPopup v-model:modelValue={state.authShow}>
  2077. <UserAuth onSuccess={onAuthSuccess} hideHeader={!browser().isApp} />
  2078. </MPopup>
  2079. {/* 是否在微信中打开 */}
  2080. <OWxTip
  2081. show={forms.showTips}
  2082. message={forms.showMessage}
  2083. showButton={forms.showButton}
  2084. buttonText="刷新"
  2085. onConfirm={() => window.location.reload()}
  2086. />
  2087. <MMessageTip
  2088. show={otherParams.showOtherSchool}
  2089. // showCloseButton={otherParams.showCloseButton}
  2090. messageAlign={otherParams.messageAlign}
  2091. message={otherParams.showOtherMessage}
  2092. showCancelButton={otherParams.showCancelButton}
  2093. cancelButtonColor={otherParams.cancelButtonColor}
  2094. cancelButtonText={otherParams.cancelButtonText}
  2095. confirmButtonColor={otherParams.confirmButtonColor}
  2096. confirmButtonText={otherParams.confirmButtonText}
  2097. onClose={() => (otherParams.showOtherSchool = false)}
  2098. onCancel={async () => {
  2099. otherParams.showOtherSchool = false;
  2100. if (otherParams.otherType === 'nickname') {
  2101. forms.isRegister = 'create'; // 新建
  2102. changeTipStatus(false, false);
  2103. onSubmit();
  2104. } else if (otherParams.otherType === 'member') {
  2105. const updateStatus = await updateStudentInfo();
  2106. if (!updateStatus) return;
  2107. //取消支付,判断是否有结束时间,是否已经结束
  2108. if (forms.registerExpireTime && forms.activeOverStatus) {
  2109. applyOver();
  2110. }
  2111. } else if (otherParams.otherType === 'payment') {
  2112. forms.joinType = 'tradition';
  2113. }
  2114. }}
  2115. onConfirm={async () => {
  2116. otherParams.showOtherSchool = false;
  2117. // 名字
  2118. if (otherParams.otherType === 'nickname') {
  2119. forms.isRegister = 'update'; // 修改
  2120. changeTipStatus(false, false);
  2121. // 直接注册
  2122. onSubmit();
  2123. } else if (otherParams.otherType === 'change') {
  2124. // 学校更换
  2125. forms.isChangeSchool = true;
  2126. // 直接注册
  2127. onSubmit();
  2128. } else if (otherParams.otherType === 'limit') {
  2129. // 人数超限制
  2130. changeTipStatus(
  2131. forms.isRegister === 'create' && !forms.studentItem.userId
  2132. ? false
  2133. : true,
  2134. false
  2135. );
  2136. } else if (otherParams.otherType === 'member') {
  2137. await paymentContinue();
  2138. }
  2139. }}
  2140. />
  2141. <Popup
  2142. v-model:show={forms.showSelectStudent}
  2143. round
  2144. position="bottom"
  2145. safeAreaInsetBottom
  2146. closeable>
  2147. <SelectStudent
  2148. studentItem={forms.studentItem}
  2149. list={forms.studentList}
  2150. onClose={() => (forms.showSelectStudent = false)}
  2151. onConfirm={(val: any) => {
  2152. if (val.userId) {
  2153. forms.studentItem = val;
  2154. const firstStudent = val;
  2155. studentInfo.extra.nickname = firstStudent.nickname;
  2156. const tempGrade: any = forms.gradeList || [];
  2157. studentInfo.extra.currentGradeNum = null;
  2158. forms.gradeNumText = '';
  2159. forms.instrumentCode = '';
  2160. tempGrade?.forEach((i: any) => {
  2161. if (i.value === firstStudent.currentGradeNum) {
  2162. forms.instrumentCode = i.instrumentCode;
  2163. forms.gradeNumText = i.text;
  2164. studentInfo.extra.currentGradeNum =
  2165. firstStudent.currentGradeNum;
  2166. if (forms.schoolInstrumentSetType === 'CLASS') {
  2167. forms.classList = i.classList;
  2168. }
  2169. }
  2170. });
  2171. studentInfo.extra.currentClass = null;
  2172. forms.currentClassText = '';
  2173. forms.classList.forEach((i: any) => {
  2174. if (i.value === firstStudent.currentClass) {
  2175. forms.currentClassText = i.text;
  2176. studentInfo.extra.currentClass = firstStudent.currentClass;
  2177. }
  2178. });
  2179. studentInfo.extra.gender = firstStudent.gender;
  2180. forms.isRegister = 'update';
  2181. changeTipStatus(true, false);
  2182. forms.showSelectStudent = false;
  2183. } else {
  2184. // 判断新建学员是否上限了
  2185. if (forms.studentList.length >= forms.multi_user_limit) {
  2186. otherParams.showOtherMessage = `同一手机号最多创建${forms.multi_user_limit}个学生`;
  2187. otherParams.showOtherSchool = true;
  2188. otherParams.showCancelButton = false;
  2189. otherParams.showCloseButton = true;
  2190. otherParams.confirmButtonColor =
  2191. 'linear-gradient( 305deg, #40C8FF 0%, #3192FF 100%)';
  2192. otherParams.confirmButtonText = '我知道了';
  2193. otherParams.otherType = 'limit';
  2194. otherParams.messageAlign = 'center';
  2195. return true;
  2196. } else {
  2197. forms.studentItem = val;
  2198. forms.isRegister = 'create';
  2199. changeTipStatus(false, false);
  2200. studentInfo.extra.nickname = '';
  2201. studentInfo.extra.currentGradeNum = '';
  2202. studentInfo.extra.currentClass = '';
  2203. studentInfo.extra.gender = 1;
  2204. forms.currentClassText = '';
  2205. forms.gradeNumText = '';
  2206. forms.showSelectStudent = false;
  2207. }
  2208. }
  2209. }}
  2210. />
  2211. </Popup>
  2212. {
  2213. state.tipBoxPop &&
  2214. <div class={styles.tipBoxPop}>
  2215. <div class={styles.tipBox}>
  2216. <img class={styles.tipTitle} src={tipTitleIcon} />
  2217. <ul>
  2218. <li class={styles.tipItem}>
  2219. <img src={tipIcon1} />
  2220. <p>开课时赠送<span>全新乐器一支</span></p>
  2221. </li>
  2222. {
  2223. state.giftDesc &&
  2224. <li class={styles.tipItem}>
  2225. <img src={tipIcon2} />
  2226. <p v-html={state.giftDesc}></p>
  2227. </li>
  2228. }
  2229. <li class={styles.tipItem}>
  2230. <img src={state.giftDesc ? tipIcon3 : tipIcon2} />
  2231. <p><span>7天内无理由</span>全额退款保障</p>
  2232. </li>
  2233. </ul>
  2234. <div class={styles.tipBtn}>
  2235. <img src={tipBtnIcon} />
  2236. <span onClick={() => {
  2237. if (state.hideSecondsNum) {
  2238. state.tipBoxPop = false
  2239. }
  2240. }}>
  2241. 我知道了
  2242. {
  2243. !state.hideSecondsNum && <i>({state.descSecondsNum}s)</i>
  2244. }
  2245. </span>
  2246. </div>
  2247. </div>
  2248. </div>
  2249. }
  2250. </div>
  2251. );
  2252. }
  2253. });