index.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. import { defineComponent, onMounted, onUnmounted, reactive, ref } from 'vue';
  2. import styles from './index.module.less';
  3. // import signinTips from './images/signin-tips.png';
  4. import {
  5. Button,
  6. CellGroup,
  7. Field,
  8. Picker,
  9. Popup,
  10. closeToast,
  11. showToast
  12. } from 'vant';
  13. import { useRoute, useRouter } from 'vue-router';
  14. import threeMan from './images/update/three-man.png'
  15. import OWxTip from '@/components/m-wx-tip';
  16. import { browser, getHttpOrigin, getUrlCode } from '@/helpers/utils';
  17. import qs from 'query-string';
  18. import request from '@/helpers/request';
  19. import { goWechatAuth } from '@/state';
  20. import { useInterval, useIntervalFn } from '@vueuse/core';
  21. import MMessageTip from '@/components/m-message-tip';
  22. const classList: any = [];
  23. for (let i = 1; i <= 40; i++) {
  24. classList.push({ text: i + '班', value: i });
  25. }
  26. const GRADE_ENUM = {
  27. '1': '一年级',
  28. '2': '二年级',
  29. '3': '三年级',
  30. '4': '四年级',
  31. '5': '五年级',
  32. '6': '六年级',
  33. '7': '七年级',
  34. '8': '八年级',
  35. '9': '九年级'
  36. } as any;
  37. const getGradeList = (gradeYear: string, instrumentCode?: string) => {
  38. let tempList: any = [];
  39. const five = [
  40. { text: '一年级', value: 1, instrumentCode },
  41. { text: '二年级', value: 2, instrumentCode },
  42. { text: '三年级', value: 3, instrumentCode },
  43. { text: '四年级', value: 4, instrumentCode },
  44. { text: '五年级', value: 5, instrumentCode }
  45. ];
  46. const one = [{ text: '六年级', value: 6, instrumentCode }];
  47. const three = [
  48. { text: '七年级', value: 7, instrumentCode },
  49. { text: '八年级', value: 8, instrumentCode },
  50. { text: '九年级', value: 9, instrumentCode }
  51. ];
  52. if (gradeYear === 'FIVE_YEAR_SYSTEM') {
  53. tempList.push(...[...five]);
  54. } else if (gradeYear === 'SIX_YEAR_SYSTEM') {
  55. tempList.push(...[...five, ...one]);
  56. } else if (gradeYear === 'THREE_YEAR_SYSTEM') {
  57. tempList.push(...[...three]);
  58. } else if (gradeYear === 'FORE_YEAR_SYSTEM') {
  59. tempList.push(...[...one, ...three]);
  60. } else {
  61. tempList.push(...[...five, ...one, ...three]);
  62. }
  63. return tempList;
  64. };
  65. export default defineComponent({
  66. name: 'pre-register',
  67. setup() {
  68. // 页面定时
  69. const pageTimer = useInterval(1000, { controls: true });
  70. pageTimer.pause();
  71. const router = useRouter();
  72. const route = useRoute();
  73. const forms = reactive({
  74. loading: true,
  75. schoolId: route.query.id,
  76. code: null,
  77. showPicker: false,
  78. classPicker: false,
  79. gradeStatus: false,
  80. classStatus: false,
  81. gradePopupShow: false,
  82. gradePopupIndex: [] as any, // 年级下拉索引
  83. classPopupShow: false,
  84. classPopupIndex: [] as any, // 班级下拉索引
  85. gradeList: [] as any,
  86. classList: [] as any,
  87. schoolInstrumentSetType: null as any,
  88. nameReg: /^[\u4E00-\u9FA5]+$/,
  89. openId: '' as any,
  90. id: null,
  91. videoBrowseData: null,
  92. videoBrowsePoint: null,
  93. username: '',
  94. currentGrade: '', // 年级
  95. currentClass: '', // 班级
  96. intervalFnRef: null as any,
  97. applyStatus: false,
  98. isPageHide: false,
  99. parentConferencesAgenda: ''
  100. });
  101. const showPopup = ref(false);
  102. const showPopupMessage = ref('');
  103. const message = (value: string) => {
  104. if (!value) {
  105. return '请填写学生真实姓名';
  106. } else if (!forms.nameReg.test(value)) {
  107. return '学员姓名必须为中文';
  108. } else if (value.length < 2 || value.length > 15) {
  109. return '学员姓名必须为2~15个字';
  110. }
  111. };
  112. const onSubmit = async () => {
  113. try {
  114. if (forms.applyStatus) {
  115. showToast('家长会调查问卷已结束');
  116. return;
  117. }
  118. if (message(forms.username)) {
  119. showToast(message(forms.username));
  120. return;
  121. }
  122. if (!forms.currentGrade) {
  123. showToast('请选择年级');
  124. return;
  125. }
  126. if (!forms.currentClass) {
  127. showToast('请选择班级');
  128. return;
  129. }
  130. // 暂停回调
  131. forms.intervalFnRef?.pause();
  132. // 页面计时暂停
  133. pageTimer.pause();
  134. await request.post('/edu-app/open/studentBrowseRecord/updateStat', {
  135. data: {
  136. id: forms.id,
  137. pageBrowseTime: pageTimer.counter.value,
  138. username: forms.username,
  139. currentGrade: forms.currentGrade,
  140. currentClass: forms.currentClass ? Number(forms.currentClass) : null
  141. }
  142. });
  143. router.push({
  144. path: '/pre-register-video',
  145. query: {
  146. saveId: forms.id,
  147. id: forms.schoolId, // 乐团编号
  148. openId: forms.openId //
  149. }
  150. });
  151. } catch {
  152. // 还原
  153. forms.intervalFnRef?.resume();
  154. pageTimer.resume();
  155. }
  156. // router.push('/pre-register-video')
  157. };
  158. const formatterClass = (value: any, list: any[]) => {
  159. let txt = '';
  160. list.forEach((listItem: any) => {
  161. if (listItem.value == value) {
  162. txt = listItem.text;
  163. }
  164. });
  165. return txt;
  166. };
  167. // 更新时间
  168. const updateStat = async (pageBrowseTime = 10) => {
  169. try {
  170. await request.post('/edu-app/open/studentBrowseRecord/updateStat', {
  171. data: {
  172. id: forms.id,
  173. pageBrowseTime // 固定10秒
  174. }
  175. });
  176. } catch {
  177. //
  178. }
  179. };
  180. onMounted(async () => {
  181. try {
  182. if (!forms.schoolId) {
  183. showToast('信息获取失败,请联系老师');
  184. }
  185. const { data } = await request.get(
  186. '/edu-app/open/schoolExtend/detail?id=' + forms.schoolId
  187. );
  188. const schoolExtend = data.schoolExtend;
  189. forms.parentConferencesAgenda = schoolExtend.parentConferencesAgenda;
  190. forms.schoolInstrumentSetType = data.school?.instrumentSetType;
  191. const schoolInstrumentList = data.school?.schoolInstrumentList || [];
  192. if (forms.schoolInstrumentSetType === 'SCHOOL') {
  193. const instrumentCode = schoolInstrumentList[0]?.instrumentCode;
  194. forms.gradeList = getGradeList(data.school?.gradeYear, instrumentCode);
  195. forms.classList = classList;
  196. } else if (forms.schoolInstrumentSetType === 'GRADE') {
  197. schoolInstrumentList.forEach((item: any) => {
  198. forms.gradeList.push({
  199. text: GRADE_ENUM[item.gradeNum],
  200. value: item.gradeNum,
  201. instrumentId: item.instrumentId,
  202. instrumentCode: item.instrumentCode
  203. });
  204. });
  205. forms.gradeList.sort((a: any, b: any) => a.value - b.value);
  206. forms.classList = classList;
  207. } else if (forms.schoolInstrumentSetType === 'CLASS') {
  208. // 班级
  209. const tempGradeList: any[] = [];
  210. schoolInstrumentList.forEach((item: any) => {
  211. if (!tempGradeList.includes(item.gradeNum)) {
  212. tempGradeList.push(item.gradeNum);
  213. }
  214. });
  215. const lastGradeList: any[] = [];
  216. tempGradeList.forEach((temp: any) => {
  217. const list = {
  218. text: GRADE_ENUM[temp],
  219. value: temp,
  220. instrumentId: '',
  221. instrumentCode: '',
  222. instrumentName: '',
  223. classList: [] as any
  224. };
  225. schoolInstrumentList.forEach((item: any) => {
  226. if (temp === item.gradeNum) {
  227. list.instrumentId = item.instrumentId;
  228. list.instrumentCode = item.instrumentCode;
  229. list.instrumentName = item.instrumentName;
  230. list.classList.push({
  231. text: item.classNum + '班',
  232. value: item.classNum,
  233. instrumentCode: item.instrumentCode
  234. });
  235. }
  236. });
  237. // 排序班级
  238. list.classList.sort((a: any, b: any) => a.value - b.value);
  239. lastGradeList.push(list);
  240. });
  241. lastGradeList.sort((a: any, b: any) => a.value - b.value);
  242. forms.gradeList = lastGradeList;
  243. forms.classList = [];
  244. } else {
  245. forms.gradeList = getGradeList(data.school.gradeYear);
  246. forms.classList = classList;
  247. }
  248. // 判断是否获取微信code码
  249. if (!forms.code) return;
  250. // // 乐团注册
  251. // if (data.status !== 'PRE_REGISTER') {
  252. // showToast('家长会调查问卷已结束')
  253. // forms.applyStatus = true
  254. // return
  255. // }
  256. // 家长会注册
  257. // 'DOING' | 'DONE'
  258. // if (
  259. // data.orchestraRegisterType === 'PARENT_CONFERENCES' &&
  260. // data.status !== 'PARENT_TEACHER_REGISTRATION' &&
  261. // data.status !== 'DOING' &&
  262. // data.status !== 'DONE'
  263. // ) {
  264. // showToast('家长会调查问卷已结束')
  265. // forms.applyStatus = true
  266. // return
  267. // }
  268. // if (!forms.schoolId) {
  269. // // 提示乐团报名失败
  270. // showPopupMessage.value = '二维码已过期';
  271. // showPopup.value = true;
  272. // return;
  273. // }
  274. const recordAdd = await request.post(
  275. '/edu-app/open/studentBrowseRecord/add',
  276. {
  277. data: {
  278. schoolId: forms.schoolId,
  279. code: forms.code,
  280. openId: forms.openId
  281. }
  282. }
  283. );
  284. const recordObj = recordAdd.data;
  285. forms.currentClass = recordObj.currentClass;
  286. forms.currentGrade = recordObj.currentGrade;
  287. forms.openId = recordObj.openId;
  288. forms.username = recordObj.username;
  289. forms.videoBrowseData = recordObj.videoBrowseData;
  290. forms.videoBrowsePoint = recordObj.videoBrowsePoint;
  291. forms.id = recordObj.id;
  292. sessionStorage.setItem('active-open-id', recordObj.openId);
  293. console.log(forms, 'forms')
  294. pageTimer.resume();
  295. // 间隔10秒更新停留时间
  296. forms.intervalFnRef = useIntervalFn(() => {
  297. // 页面时间恢复
  298. pageTimer.counter.value = 0;
  299. pageTimer.resume();
  300. updateStat();
  301. }, 10000);
  302. } catch {
  303. //
  304. }
  305. });
  306. const getAppIdAndCode = async (url?: string) => {
  307. try {
  308. const { data } = await request.get(
  309. '/edu-app/open/paramConfig/wechatAppId'
  310. );
  311. // 判断是否有微信appId
  312. if (data) {
  313. closeToast();
  314. goWechatAuth(data, url);
  315. }
  316. } catch(e) {
  317. //
  318. console.log(e)
  319. }
  320. };
  321. if (browser().weixin) {
  322. //授权
  323. const openId = sessionStorage.getItem('active-open-id');
  324. forms.openId = openId;
  325. const code = getUrlCode();
  326. console.log(code, 'code')
  327. if (!code) {
  328. const newUrl =
  329. getHttpOrigin() +
  330. window.location.pathname +
  331. '#' +
  332. route.path +
  333. '?' +
  334. qs.stringify({
  335. ...route.query
  336. });
  337. getAppIdAndCode(newUrl);
  338. return '';
  339. } else {
  340. forms.code = code;
  341. }
  342. }
  343. const onPageShow = () => {
  344. console.log(forms.isPageHide, 'showInfo');
  345. if (forms.isPageHide) {
  346. window.location.reload();
  347. }
  348. };
  349. // 处理监听页面返回不刷新的问题
  350. window.addEventListener('pageshow', onPageShow);
  351. const onPageHide = () => {
  352. console.log(forms.isPageHide, 'showInfo');
  353. forms.isPageHide = true;
  354. };
  355. window.addEventListener('pagehide', onPageHide);
  356. onUnmounted(() => {
  357. window.removeEventListener('pageshow', onPageShow);
  358. window.removeEventListener('pagehide', onPageHide);
  359. });
  360. return () => (
  361. <div class={styles['per-register-active']}>
  362. <img class={styles.imgMan} src={threeMan} />
  363. <div class={styles.flowPath}>
  364. <i class={styles.flowPathTitle}></i>
  365. <div
  366. class={styles.flowPathContent}
  367. v-html={forms.parentConferencesAgenda}></div>
  368. </div>
  369. <div class={styles.signin}>
  370. <i class={styles.signinTitle}></i>
  371. <CellGroup class={styles.cellGroup} border={false}>
  372. <Field
  373. label="学生姓名"
  374. required
  375. labelAlign="top"
  376. placeholder="请输入学生姓名"
  377. autocomplete="off"
  378. v-model={forms.username}
  379. border={false}
  380. />
  381. <Field
  382. label="年级"
  383. required
  384. labelAlign="top"
  385. placeholder="请选择年级"
  386. rightIcon={!forms.gradeStatus ? "arrow-down" : "arrow-up"}
  387. readonly
  388. border={false}
  389. modelValue={formatterClass(forms.currentGrade, forms.gradeList)}
  390. clickable={false}
  391. onClick={() => {
  392. forms.gradePopupIndex = [forms.currentGrade];
  393. forms.gradeStatus = true;
  394. }}
  395. />
  396. <Field
  397. label="班级"
  398. required
  399. labelAlign="top"
  400. placeholder="请选择班级"
  401. rightIcon={!forms.classStatus ? "arrow-down" : "arrow-up"}
  402. readonly
  403. border={false}
  404. modelValue={formatterClass(forms.currentClass, forms.classList)}
  405. clickable={false}
  406. onClick={() => {
  407. if (
  408. forms.schoolInstrumentSetType === 'CLASS' &&
  409. forms.classList.length <= 0
  410. ) {
  411. showToast('请先选择年级');
  412. return;
  413. }
  414. forms.classPopupIndex = [forms.currentClass];
  415. forms.classStatus = true;
  416. }}
  417. />
  418. <div class={styles.submitBtn} onClick={onSubmit}></div>
  419. </CellGroup>
  420. </div>
  421. {/* 是否在微信中打开 */}
  422. <OWxTip />
  423. {/* 年级 */}
  424. <Popup
  425. v-model:show={forms.gradeStatus}
  426. position="bottom"
  427. round
  428. safeAreaInsetBottom
  429. lazyRender={false}
  430. class={'popupBottomSearch'}
  431. onOpen={() => {
  432. forms.gradePopupShow = true;
  433. }}
  434. onClosed={() => {
  435. forms.gradePopupShow = false;
  436. }}>
  437. {forms.gradePopupShow && (
  438. <Picker
  439. showToolbar
  440. v-model={forms.gradePopupIndex}
  441. columns={forms.gradeList}
  442. onCancel={() => (forms.gradeStatus = false)}
  443. onConfirm={(val: any) => {
  444. const selectedOption = val.selectedOptions[0];
  445. forms.currentGrade = selectedOption.value;
  446. forms.gradeStatus = false;
  447. if (forms.schoolInstrumentSetType === 'CLASS') {
  448. forms.classList = selectedOption.classList;
  449. }
  450. if (
  451. ['CLASS', 'GRADE'].includes(forms.schoolInstrumentSetType)
  452. ) {
  453. forms.currentClass = '';
  454. }
  455. }}
  456. />
  457. )}
  458. </Popup>
  459. {/* 班级 */}
  460. <Popup
  461. v-model:show={forms.classStatus}
  462. position="bottom"
  463. round
  464. class={'popupBottomSearch'}
  465. onOpen={() => {
  466. forms.classPopupShow = true;
  467. }}
  468. onClosed={() => {
  469. forms.classPopupShow = false;
  470. }}>
  471. {forms.classPopupShow && (
  472. <Picker
  473. showToolbar
  474. v-model={forms.classPopupIndex}
  475. columns={forms.classList}
  476. onCancel={() => (forms.classStatus = false)}
  477. onConfirm={({ selectedValues }) => {
  478. forms.currentClass = selectedValues[0];
  479. forms.classStatus = false;
  480. }}
  481. />
  482. )}
  483. </Popup>
  484. {/* <Popup
  485. v-model:show={showPopup.value}
  486. round
  487. style={{ width: '88%' }}
  488. closeOnClickOverlay={false}
  489. class={styles.wxPopupDialog}>
  490. <div class={styles.popupContainer}>
  491. <p class={styles.title}>温馨提示</p>
  492. <p class={styles.popupTips} v-html={showPopupMessage.value}></p>
  493. </div>
  494. </Popup> */}
  495. <MMessageTip show={showPopup.value} title='温馨提示' message={showPopupMessage.value} showCloseButton={false} showConfirmButton={false} />
  496. </div>
  497. );
  498. }
  499. });