index-apply.tsx 84 KB

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