manage-teacher-register.tsx 11 KB

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