manage-teacher-register.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. import { areas } from '@/helpers/area'
  2. import request from '@/helpers/request'
  3. import {
  4. CellGroup,
  5. Form,
  6. Field,
  7. RadioGroup,
  8. Tag,
  9. Icon,
  10. Checkbox,
  11. Radio,
  12. Button,
  13. showToast,
  14. showDialog,
  15. showLoadingToast,
  16. closeToast,
  17. Picker,
  18. Popup,
  19. CountDown
  20. } from 'vant'
  21. import { defineComponent, onMounted, reactive } from 'vue'
  22. import { useRoute } from 'vue-router'
  23. import styles from './manage-teacher-register.module.less'
  24. import ImgCode from '@/components/o-img-code'
  25. import schoolLogo from './images/school-logo.png'
  26. import iconClose from './images/icon-close.png'
  27. import topBanner1 from './images/top-banner.png'
  28. import { checkPhone } from '@/helpers/validate'
  29. import dayjs from 'dayjs'
  30. import { browser } from '@/helpers/utils'
  31. export default defineComponent({
  32. name: 'companion-teacher-register',
  33. setup() {
  34. const route = useRoute()
  35. const state = reactive({
  36. showPicker: false,
  37. showSubject: false,
  38. submitStatus: false,
  39. id: route.query.id,
  40. name: route.query.name,
  41. t: route.query.t as any, // 过期时间
  42. qrCodeStatus: false, // 二维码是否失效
  43. pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
  44. columns: [] as any,
  45. pickerType: null, // 下拉类型
  46. forms: {
  47. realName: '',
  48. phone: null,
  49. gender: 1,
  50. idCardNo: null,
  51. smsValidCode: ''
  52. },
  53. btnLoading: false,
  54. checkPhone: false,
  55. checked: true,
  56. columnSubject: [] as any,
  57. countDownStatus: true, // 是否发送验证码
  58. countDownTime: 120, // 倒计时时间
  59. // countDownRef: null as any, // 倒计时实例
  60. imgCodeStatus: false,
  61. showPopup: false
  62. })
  63. const onSubmit = async () => {
  64. if (state.qrCodeStatus) {
  65. showDialog({
  66. title: '提示',
  67. message: '二维码已失效',
  68. theme: 'round-button',
  69. confirmButtonColor: '#64A9FF'
  70. })
  71. return
  72. }
  73. if (!state.checked) {
  74. showToast('请阅读并同意协议')
  75. return
  76. }
  77. state.btnLoading = true
  78. try {
  79. const forms = state.forms
  80. await request.post('/api-school/open/schoolStaff/registerTeacher', {
  81. data: {
  82. ...forms,
  83. schoolId: state.id
  84. }
  85. })
  86. state.submitStatus = true
  87. } catch {
  88. //
  89. }
  90. state.btnLoading = false
  91. }
  92. const onSendCode = () => {
  93. // 发送验证码
  94. if (!checkPhone(state.forms.phone as any)) {
  95. return showToast('请输入正确的手机号码')
  96. }
  97. state.imgCodeStatus = true
  98. }
  99. const onCodeSend = () => {
  100. state.countDownStatus = false
  101. const clearTimer = setInterval(() => {
  102. state.countDownTime = state.countDownTime - 1
  103. if (state.countDownTime <= 0) {
  104. state.countDownTime = 120
  105. state.countDownStatus = true
  106. clearInterval(clearTimer)
  107. }
  108. }, 1000)
  109. }
  110. const onFinished = () => {
  111. state.countDownStatus = true
  112. // ;(this.$refs.countDownRef as any).reset()
  113. }
  114. onMounted(async () => {
  115. if (!state.id) {
  116. showToast('信息获取失败,请联系老师')
  117. }
  118. // 判断是否是微信,只能微信中打开
  119. // if (!browser().weixin) {
  120. // state.showPopup = true
  121. // return
  122. // }
  123. // t: route.query.t, // 过期时间
  124. try {
  125. const res = await request.post('/api-school/open/schoolTeacherStudent/queryQrCodeStatus', {
  126. data: {
  127. schoolId: state.id,
  128. qrCodeEffectiveStartTime: state.t
  129. ? dayjs(Number(state.t)).format('YYYY-MM-DD HH:mm:ss')
  130. : null
  131. }
  132. })
  133. if (res.code === 999) {
  134. state.qrCodeStatus = true
  135. showDialog({
  136. title: '提示',
  137. message: res.message,
  138. theme: 'round-button',
  139. confirmButtonColor: '#64A9FF'
  140. })
  141. }
  142. } catch (e: any) {
  143. //
  144. console.log(e)
  145. }
  146. try {
  147. const tempareas: any = []
  148. areas.forEach((item) => {
  149. const temp = {
  150. name: item.name,
  151. code: item.code,
  152. areas: [] as any
  153. }
  154. if (item.areas && item.areas.length > 0) {
  155. item.areas.forEach((child) => {
  156. temp.areas.push({
  157. name: child.name,
  158. code: child.code
  159. })
  160. })
  161. }
  162. tempareas.push(temp)
  163. })
  164. state.columns = tempareas || []
  165. const { data } = await request.post(
  166. '/api-school/open/orchestraSubjectConfig/pageByOrchestraId',
  167. {
  168. data: {
  169. orchestraId: state.id,
  170. page: 1,
  171. rows: 50
  172. }
  173. }
  174. )
  175. const rows = data.rows || []
  176. const tempSubjects: any = []
  177. rows.forEach((item) => {
  178. tempSubjects.push({
  179. text: item.name,
  180. value: item.subjectId
  181. })
  182. })
  183. state.columnSubject = tempSubjects
  184. } catch {
  185. showDialog({
  186. message: '信息获取失败,请联系老师',
  187. theme: 'round-button',
  188. confirmButtonColor: '#64A9FF'
  189. })
  190. }
  191. })
  192. const onPreview = () => {
  193. window.open(
  194. window.location.origin + window.location.pathname + '#/preview-protocol',
  195. '_blank'
  196. )
  197. }
  198. return () => (
  199. <div class={styles.register}>
  200. <div class={styles.title}>
  201. <p class={styles.tips}>
  202. <img src={schoolLogo} />
  203. <span>{state.name}</span>
  204. </p>
  205. </div>
  206. <Form validateFirst scrollToError onSubmit={onSubmit} ref="form" class={styles.form}>
  207. <CellGroup inset class={styles['cell-group']}>
  208. <Field
  209. label="真实姓名"
  210. v-model={state.forms.realName}
  211. rules={[{ required: true, message: '请填写真实姓名' }]}
  212. name="realName"
  213. placeholder="请填写真实姓名"
  214. maxlength="5"
  215. ></Field>
  216. <Field
  217. label="手机号码"
  218. v-model={state.forms.phone}
  219. rules={[
  220. { required: true, message: '请输入手机号码' },
  221. { pattern: state.pattern, message: '输入手机号码有误' }
  222. ]}
  223. name="phone"
  224. placeholder="请输入手机号码"
  225. maxlength={11}
  226. type="tel"
  227. ></Field>
  228. <div class={styles.phoneTips}>
  229. <Icon name="warning" size="16" />
  230. 提示:手机号码将成为您管乐团管理端登录账号
  231. </div>
  232. <Field
  233. label="身份证号码"
  234. v-model={state.forms.idCardNo}
  235. rules={[
  236. { required: true, message: '请输入身份证号' },
  237. {
  238. pattern:
  239. /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
  240. message: '请输入正确的身份证号'
  241. }
  242. ]}
  243. name="idCardNo"
  244. placeholder="请输入身份证号码"
  245. ></Field>
  246. <Field label="性别" name="gender" rules={[{ required: true, message: '请选择性别' }]}>
  247. {{
  248. input: () => (
  249. <RadioGroup
  250. checked-color="#64A9FF"
  251. v-model={state.forms.gender}
  252. direction="horizontal"
  253. >
  254. <Tag
  255. size="large"
  256. type="primary"
  257. color={!(state.forms.gender === 1) ? '#EAEAEA' : '#64A9FF'}
  258. textColor={!(state.forms.gender === 1) ? '#AAA' : '#FFF'}
  259. class={styles.radioSection}
  260. round
  261. >
  262. <Radio class={styles.radioItem} name={1}></Radio>男
  263. </Tag>
  264. <Tag
  265. size="large"
  266. type="primary"
  267. color={!(state.forms.gender === 0) ? '#EAEAEA' : '#64A9FF'}
  268. textColor={!(state.forms.gender === 0) ? '#AAA' : '#FFF'}
  269. class={styles.radioSection}
  270. round
  271. >
  272. <Radio class={styles.radioItem} name={0}></Radio>女
  273. </Tag>
  274. </RadioGroup>
  275. )
  276. }}
  277. </Field>
  278. <Field
  279. label="验证码"
  280. v-model={state.forms.smsValidCode}
  281. name="smsValidCode"
  282. rules={[{ required: true, message: '请输入验证码', trigger: 'onChange' }]}
  283. placeholder="请输入验证码"
  284. maxlength={6}
  285. type="tel"
  286. >
  287. {{
  288. button: () =>
  289. state.countDownStatus ? (
  290. <Button type="primary" round size="small" color="#64A9FF" onClick={onSendCode}>
  291. 发送验证码
  292. </Button>
  293. ) : (
  294. <Button
  295. type="default"
  296. round
  297. size="small"
  298. disabled
  299. style={{ minWidth: '60px' }}
  300. onClick={onSendCode}
  301. >
  302. {state.countDownTime + 's'}
  303. </Button>
  304. )
  305. }}
  306. </Field>
  307. </CellGroup>
  308. <div class={styles.protocol}>
  309. <Checkbox
  310. v-model={state.checked}
  311. icon-size="16"
  312. style="margin-right: 6px"
  313. checked-color="#64A9FF"
  314. ></Checkbox>
  315. <span
  316. onClick={() => {
  317. state.checked = !state.checked
  318. }}
  319. >
  320. 请认真阅读并勾选
  321. </span>
  322. <span class={styles.c} onClick={onPreview}>
  323. 《乐团管理老师注册协议》
  324. </span>
  325. </div>
  326. <Button
  327. size="large"
  328. block
  329. round
  330. class={styles['btn-submit']}
  331. color="#64A9FF"
  332. loading={state.btnLoading}
  333. native-type="submit"
  334. >
  335. 完成
  336. </Button>
  337. </Form>
  338. <Popup v-model:show={state.submitStatus} round style="width: 75%" closeOnClickOverlay>
  339. <div class={styles.stautsS}>
  340. {/* <img
  341. class={styles['icon-close']}
  342. src={iconClose}
  343. onClick={() => {
  344. state.submitStatus = false
  345. window.location.href =
  346. window.location.origin + '/orchestra-student/#/download?type=manage'
  347. }}
  348. /> */}
  349. <img src={topBanner1} class={styles['submit-img']} />
  350. <div class={styles['submit-container']}>
  351. <p class={styles['submit-title']}>恭喜您已成功登记为</p>
  352. <p class={styles['submit-o']}>
  353. {state.name} <br />
  354. <span>【管理老师】</span>
  355. </p>
  356. <p class={styles['submit-tips']}>请下载管乐团管理端APP</p>
  357. <Button
  358. type="primary"
  359. color="#64A9FF"
  360. block
  361. round
  362. onClick={() => {
  363. state.submitStatus = false
  364. window.location.href =
  365. window.location.origin + '/orchestra-student/#/download?type=manage'
  366. }}
  367. >
  368. 立即下载
  369. </Button>
  370. </div>
  371. </div>
  372. </Popup>
  373. {state.imgCodeStatus ? (
  374. <ImgCode
  375. v-model:value={state.imgCodeStatus}
  376. phone={state.forms.phone as any}
  377. onClose={() => {
  378. state.imgCodeStatus = false
  379. }}
  380. onSendCode={onCodeSend}
  381. />
  382. ) : null}
  383. <Popup
  384. v-model:show={state.showPopup}
  385. round
  386. style={{ width: '88%' }}
  387. closeOnClickOverlay={false}
  388. class={styles.wxPopupDialog}
  389. >
  390. <div class={styles.popupContainer}>
  391. <p class={styles.title1}>温馨提示</p>
  392. <p class={styles.popupTips}>请使用微信打开</p>
  393. </div>
  394. </Popup>
  395. </div>
  396. )
  397. }
  398. })