apply.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. import request from '@/helpers/request'
  2. import {
  3. Button,
  4. CellGroup,
  5. Dialog,
  6. Field,
  7. Form,
  8. Picker,
  9. Popup,
  10. Radio,
  11. RadioGroup,
  12. showToast,
  13. Tag
  14. } from 'vant'
  15. import { defineComponent, onMounted, reactive } from 'vue'
  16. import { useRoute, useRouter } from 'vue-router'
  17. import styles from '../index.module.less'
  18. import { setLogout } from '@/state'
  19. // 乐团交付,乐团停止或关闭,有新的交付团;则不允许报名
  20. const classList: any = []
  21. for (let i = 1; i <= 40; i++) {
  22. classList.push({ text: i + '班', value: i })
  23. }
  24. export default defineComponent({
  25. name: 'apply',
  26. props: {
  27. schoolSystem: {
  28. type: String,
  29. default: 'sixYearSystem' // 默认为六年制
  30. },
  31. registerInfo: {
  32. type: Object,
  33. defualt: {}
  34. },
  35. code: {
  36. type: String,
  37. default: ''
  38. }
  39. },
  40. emits: ['next'],
  41. setup(props, { slots, attrs, emit }) {
  42. const route = useRoute()
  43. const router = useRouter()
  44. const state = reactive({
  45. // code: '' as any, // 微信授权code码
  46. detail: {} as any, // 学生详情
  47. currentGrade: [
  48. { text: '一年级', value: 1 },
  49. { text: '二年级', value: 2 },
  50. { text: '三年级', value: 3 },
  51. { text: '四年级', value: 4 },
  52. { text: '五年级', value: 5 }
  53. ], // 年级数组列表
  54. classList: classList,
  55. subjectList: [] as any, // 声部列表
  56. gradeStatus: false,
  57. classStatus: false,
  58. subjectStatus: false,
  59. pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
  60. nameReg: /^[\u4E00-\u9FA5]+$/,
  61. subjectChangeStatus: false // 更换声部时
  62. })
  63. const forms = reactive({
  64. username: null,
  65. sex: null as any,
  66. currentGrade: null,
  67. currentGradeTxt: null, // 年级编号
  68. currentClass: '', // 班级
  69. currentClassTxt: null, // 年级编号
  70. registerSubjectId: '',
  71. registerSubjectTxt: null, // 所在声部
  72. parentName: null,
  73. phone: null
  74. })
  75. // 获取乐团报名信息
  76. const studentRegister = async () => {
  77. try {
  78. const { data } = await request.get(
  79. '/api-student/orchestraRegister/register/' + route.query.id
  80. )
  81. const detail = data || {}
  82. state.detail = detail
  83. const grade: any = state.currentGrade.find((item: any) => item.value == detail.currentGrade)
  84. const cls: any = state.classList.find((item: any) => item.value == detail.currentClass)
  85. const subjects: any = state.subjectList.find(
  86. (item: any) => item.value == detail.registerSubjectId
  87. )
  88. forms.username = detail.username
  89. forms.sex = detail.sex ? 1 : 0
  90. forms.currentGrade = detail.currentGrade
  91. forms.currentGradeTxt = grade.text
  92. forms.currentClass = detail.currentClass
  93. forms.currentClassTxt = cls.text
  94. forms.registerSubjectId = detail.registerSubjectId
  95. forms.registerSubjectTxt = subjects.text
  96. forms.parentName = detail.parentName
  97. forms.phone = detail.phone
  98. } catch {
  99. //
  100. }
  101. }
  102. // 获取声部信息
  103. const getSubjects = async () => {
  104. try {
  105. const subjects = await request.post(
  106. '/api-student/open/orchestraSubjectConfig/pageByOrchestraId',
  107. {
  108. data: {
  109. orchestraId: route.query.id,
  110. page: 1,
  111. rows: 100
  112. }
  113. }
  114. )
  115. const rows = subjects.data.rows || []
  116. rows.forEach((item: any) => {
  117. state.subjectList.push({
  118. text: item.name,
  119. value: item.subjectId
  120. })
  121. })
  122. } catch {
  123. //
  124. }
  125. }
  126. const validator = (val: any) => {
  127. // 校验函数返回 true 表示校验通过,false 表示不通过
  128. return state.nameReg.test(val) && val.length >= 2 && val.length <= 15
  129. }
  130. const message = (value: any) => {
  131. if (!value) {
  132. return '请填写学员真实姓名'
  133. } else if (!state.nameReg.test(value)) {
  134. return '学员姓名必须为中文'
  135. } else if (value.length < 2 || value.length > 15) {
  136. return '学员姓名必须为2~15个字'
  137. } else {
  138. return ''
  139. }
  140. }
  141. // 乐团报名
  142. const onSubmit = async () => {
  143. try {
  144. const params: any = {
  145. orchestraId: route.query.id,
  146. schoolId: state.detail.schoolId,
  147. ...forms
  148. }
  149. // 判断是否已报过名
  150. if (state.detail.id) {
  151. params.id = state.detail.id
  152. }
  153. await request.post('/api-student/orchestraRegister/save', {
  154. data: {
  155. ...params,
  156. code: props.code
  157. }
  158. })
  159. setTimeout(() => {
  160. // showToast('报名成功')
  161. emit('next', 'payment')
  162. }, 100)
  163. } catch {
  164. //
  165. }
  166. }
  167. onMounted(async () => {
  168. // state.code = route.query.code || ''
  169. // console.log('pre register code: ' + state.code)
  170. await getSubjects()
  171. // 判断学年制
  172. if (props.schoolSystem === 'sixYearSystem') {
  173. state.currentGrade.push({ text: '六年级', value: 6 })
  174. }
  175. await studentRegister()
  176. // 判断是否有授权码
  177. // if (!props.code) {
  178. // setLogout()
  179. // const query = {
  180. // returnUrl: route.path,
  181. // ...route.query
  182. // } as any
  183. // router.replace({
  184. // path: '/loginMusic',
  185. // query: query
  186. // })
  187. // }
  188. })
  189. return () => (
  190. <div class={styles.preApplyC}>
  191. <Form validateFirst scrollToError onSubmit={onSubmit} ref="form" class={styles.form}>
  192. <div class={styles.applyTitle}>学生信息</div>
  193. <CellGroup inset class={styles.applyCellGroup}>
  194. <Field
  195. required
  196. label="学生信息"
  197. placeholder="请填写学生真实姓名"
  198. inputAlign="right"
  199. v-model={forms.username}
  200. maxlength={15}
  201. rules={[{ validator, message }]}
  202. />
  203. <Field
  204. required
  205. label="性别"
  206. inputAlign="right"
  207. rules={[{ required: true, message: '请选择性别' }]}
  208. >
  209. {{
  210. input: () => (
  211. <RadioGroup v-model={forms.sex}>
  212. <Tag
  213. size="large"
  214. type="primary"
  215. color={!(forms.sex === 1) ? '#EAEAEA' : '#FF8057'}
  216. textColor={!(forms.sex === 1) ? '#AAA' : '#FFF'}
  217. class={styles.radioSection}
  218. round
  219. >
  220. <Radio class={styles.radioItem} name={1}></Radio>男生
  221. </Tag>
  222. <Tag
  223. size="large"
  224. type="primary"
  225. color={!(forms.sex === 0) ? '#EAEAEA' : '#FF8057'}
  226. textColor={!(forms.sex === 0) ? '#AAA' : '#FFF'}
  227. class={styles.radioSection}
  228. round
  229. >
  230. <Radio class={styles.radioItem} name={0}></Radio>女生
  231. </Tag>
  232. </RadioGroup>
  233. )
  234. }}
  235. </Field>
  236. <Field
  237. required
  238. label="年级"
  239. inputAlign="right"
  240. readonly
  241. isLink
  242. placeholder="请选择年级"
  243. v-model={forms.currentGradeTxt}
  244. onClick={() => (state.gradeStatus = true)}
  245. rules={[{ required: true, message: '请选择年级' }]}
  246. />
  247. <Field
  248. required
  249. label="班级"
  250. inputAlign="right"
  251. readonly
  252. isLink
  253. placeholder="请选择班级"
  254. v-model={forms.currentClassTxt}
  255. onClick={() => (state.classStatus = true)}
  256. rules={[{ required: true, message: '请选择班级' }]}
  257. />
  258. </CellGroup>
  259. <div class={styles.applyTitle}>声部信息</div>
  260. <CellGroup inset class={styles.applyCellGroup}>
  261. <Field
  262. required
  263. label="声部"
  264. inputAlign="right"
  265. readonly
  266. isLink
  267. placeholder="请选择声部"
  268. v-model={forms.registerSubjectTxt}
  269. onClick={() => {
  270. if (state.subjectList.length <= 0) {
  271. showToast('暂无报名声部')
  272. return
  273. }
  274. // 切换订单时判断是否有支付中和已支付的订单,并且已注册过
  275. // 判断学生所在乐团状态,如果在读则不允许更换声部(只能退团重新报名)
  276. // 退团重新报名也不能更新声部
  277. if (
  278. props.registerInfo?.registerStatus === 'LEARNING' ||
  279. (props.registerInfo?.registerStatus === 'OUTOF_ORCHESTRA' &&
  280. props.registerInfo?.orderNumber > 0)
  281. ) {
  282. state.subjectChangeStatus = true
  283. return
  284. }
  285. state.subjectStatus = true
  286. }}
  287. rules={[{ required: true, message: '请选择声部' }]}
  288. />
  289. </CellGroup>
  290. <div class={styles.applyTitle}>家长信息</div>
  291. <CellGroup inset class={styles.applyCellGroup}>
  292. <Field
  293. required
  294. label="家长姓名"
  295. inputAlign="right"
  296. placeholder="请填写家长真实姓名"
  297. v-model={forms.parentName}
  298. maxlength={15}
  299. rules={[{ required: true, message: '请填写家长真实姓名' }]}
  300. />
  301. <Field
  302. required
  303. label="手机号"
  304. inputAlign="right"
  305. placeholder="请输入手机号"
  306. v-model={forms.phone}
  307. maxlength={11}
  308. type="tel"
  309. rules={[{ pattern: state.pattern, message: '输入监护人手机号码有误' }]}
  310. />
  311. </CellGroup>
  312. <div class={'btnGroup'} style={{ paddingTop: '30px' }}>
  313. <Button type="primary" round block native-type="submit">
  314. 下一步
  315. </Button>
  316. </div>
  317. </Form>
  318. {/* 年级 */}
  319. <Popup
  320. v-model:show={state.gradeStatus}
  321. position="bottom"
  322. round
  323. safeAreaInsetBottom
  324. // duration={0}
  325. lazyRender={false}
  326. >
  327. <Picker
  328. showToolbar
  329. columns={state.currentGrade}
  330. onCancel={() => (state.gradeStatus = false)}
  331. onConfirm={(val: any) => {
  332. const selectedOption = val.selectedOptions[0]
  333. forms.currentGrade = selectedOption.value
  334. forms.currentGradeTxt = selectedOption.text
  335. state.gradeStatus = false
  336. }}
  337. />
  338. </Popup>
  339. {/* 班级 */}
  340. <Popup v-model:show={state.classStatus} position="bottom" round>
  341. <Picker
  342. showToolbar
  343. columns={state.classList}
  344. onCancel={() => (state.classStatus = false)}
  345. onConfirm={(val: any) => {
  346. const selectedOption = val.selectedOptions[0]
  347. forms.currentClass = selectedOption.value
  348. forms.currentClassTxt = selectedOption.text
  349. state.classStatus = false
  350. }}
  351. />
  352. </Popup>
  353. {/* 声部 */}
  354. <Popup v-model:show={state.subjectStatus} position="bottom" round>
  355. <Picker
  356. showToolbar
  357. columns={state.subjectList}
  358. onCancel={() => (state.subjectStatus = false)}
  359. onConfirm={(val: any) => {
  360. const selectedOption = val.selectedOptions[0]
  361. forms.registerSubjectId = selectedOption.value
  362. forms.registerSubjectTxt = selectedOption.text
  363. state.subjectStatus = false
  364. }}
  365. />
  366. </Popup>
  367. <Dialog
  368. v-model:show={state.subjectChangeStatus}
  369. message={'您已有报名订单,不可更换声部'}
  370. messageAlign="center"
  371. confirmButtonText="确定"
  372. >
  373. {{
  374. title: () => (
  375. <div class={styles.dialogTitle}>
  376. <i></i>
  377. 提示
  378. </div>
  379. )
  380. }}
  381. </Dialog>
  382. </div>
  383. )
  384. }
  385. })