index.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. import React, { useCallback, useEffect, useRef, useState } from 'react'
  2. import styles from './index.module.scss'
  3. import TopCom from '@/components/TopCom'
  4. import classNames from 'classnames'
  5. import { Button, Form, FormInstance, Input, InputNumber } from 'antd'
  6. import TextArea from 'antd/es/input/TextArea'
  7. import { EyeOutlined, CloseOutlined } from '@ant-design/icons'
  8. import MyPopconfirm from '@/components/MyPopconfirm'
  9. import { ImageViewer } from 'antd-mobile'
  10. import { domShowFu } from '@/utils/domShow'
  11. import dayjs from 'dayjs'
  12. import htmlToPdf2 from '@/utils/htmlToPdf2'
  13. import { MessageFu } from '@/utils/message'
  14. import ZinfoPop from '@/components/ZinfoPop'
  15. import history from '@/utils/history'
  16. type FormType = {
  17. name: string
  18. phone: string
  19. ID: string
  20. num1: null | number
  21. num2: null | null
  22. jigou: string
  23. miaoshu: string
  24. }
  25. function A5order() {
  26. useEffect(() => {
  27. FormBoxRef.current?.setFieldsValue({
  28. name: '王大锤',
  29. phone: '18702025091',
  30. ID: '421083199504071212',
  31. num1: 3,
  32. num2: null,
  33. jigou: '机构机构',
  34. miaoshu: ''
  35. })
  36. }, [])
  37. // 表单的ref
  38. const FormBoxRef = useRef<FormInstance>(null)
  39. // 没有通过校验
  40. const onFinishFailed = useCallback(() => {}, [])
  41. // 点击提交的页面元素显示和隐藏
  42. const [time, setTime] = useState('')
  43. // 导出pdf文本域换行问题
  44. const [tetx, setText] = useState({
  45. 1: '',
  46. 2: ''
  47. })
  48. // 打开提示弹窗
  49. const [titPop, setTitPop] = useState('')
  50. // 通过校验点击确定
  51. const onFinish = useCallback(async (values: FormType) => {
  52. setTitPop('succ')
  53. console.log(123, values)
  54. // domShowFu('#AsyncSpinLoding', true)
  55. // setText({
  56. // 1: values.jigou.replaceAll(/(\n|\r|\r\n)/g, '<br />'),
  57. // 2: values.miaoshu.replaceAll(/(\n|\r|\r\n)/g, '<br />')
  58. // })
  59. // const time = dayjs(new Date()).format('YYYY-MM-DD HH:mm')
  60. // setTime(time)
  61. // window.setTimeout(() => {
  62. // const dom = document.querySelector('.A5listMain') as HTMLDivElement
  63. // if (dom) {
  64. // const name = '预约申请单'
  65. // htmlToPdf2(dom, name, () => {
  66. // // 打开预约成功的弹窗
  67. // // setTime('')
  68. // // domShowFu('#AsyncSpinLoding', false)
  69. // })
  70. // } else {
  71. // MessageFu.warning('找不到元素!')
  72. // setTime('')
  73. // domShowFu('#AsyncSpinLoding', false)
  74. // }
  75. // }, 500)
  76. }, [])
  77. const [fileUrl, setFileUrl] = useState({
  78. src: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
  79. name: ''
  80. })
  81. return (
  82. <div className={styles.A5order}>
  83. <TopCom txt='填写信息' />
  84. <div className={classNames('A5main')}>
  85. <div className='A5list'>
  86. <div className='A5listMain'>
  87. {/* 顶部 */}
  88. <div className='A5lTop'>
  89. <p>
  90. <span>预约日期:</span>11月21日上午
  91. </p>
  92. <p>
  93. <span>预约课程:</span>英语课程英语课程英语
  94. </p>
  95. {time ? (
  96. <p>
  97. <span>申请时间:</span>
  98. {time}
  99. </p>
  100. ) : null}
  101. </div>
  102. <div className='A5lKaBox'>
  103. <Form
  104. ref={FormBoxRef}
  105. name='basic'
  106. // labelCol={{ span: 3 }}
  107. onFinish={onFinish}
  108. onFinishFailed={onFinishFailed}
  109. autoComplete='off'
  110. scrollToFirstError
  111. >
  112. {/* 第一个卡片 */}
  113. <div className='A5lKa'>
  114. <div className='A5tit'>负责人信息</div>
  115. <Form.Item
  116. label='负责人姓名'
  117. name='name'
  118. rules={[{ required: true, message: '请输入负责人姓名!' }]}
  119. getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
  120. >
  121. <Input placeholder='请输入内容,不超过6个字' maxLength={6} />
  122. </Form.Item>
  123. <Form.Item
  124. label='联系方式'
  125. name='phone'
  126. rules={[
  127. { required: true, message: '请输入联系方式!' },
  128. {
  129. pattern: /^1[3-9][0-9]{9}$/,
  130. message: '请输入正确格式的手机号!'
  131. }
  132. ]}
  133. >
  134. <Input placeholder='请输入11位数字' maxLength={11} />
  135. </Form.Item>
  136. <Form.Item
  137. label='身份证号'
  138. name='ID'
  139. rules={[
  140. { required: true, message: '请输入身份证号!' },
  141. {
  142. pattern:
  143. /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
  144. message: '请输入正确格式的身份证号!'
  145. }
  146. ]}
  147. >
  148. <Input placeholder='请输入18位证件编码' maxLength={18} />
  149. </Form.Item>
  150. </div>
  151. {/* 第二个卡片 */}
  152. <div className='A5lKa'>
  153. <div className='A5tit'>团队信息</div>
  154. <Form.Item
  155. label='参观学生人数'
  156. name='num1'
  157. rules={[{ required: true, message: '请输入参观学生人数!' }]}
  158. >
  159. <InputNumber min={0} max={999} precision={0} placeholder='请输入数字' />
  160. </Form.Item>
  161. <Form.Item className='A5llmove' label='随堂老师人数' name='num2'>
  162. <InputNumber
  163. min={0}
  164. max={999}
  165. precision={0}
  166. placeholder={time ? ' - ' : '请输入数字'}
  167. />
  168. </Form.Item>
  169. {/* 文本域不换行问题 */}
  170. {time ? (
  171. <>
  172. <div className='A5TextPdf'>
  173. <div>
  174. <span>*</span>所属机构
  175. </div>
  176. <div dangerouslySetInnerHTML={{ __html: tetx[1] || ' - ' }}></div>
  177. </div>
  178. <div className='A5TextPdf'>
  179. <div>
  180. <span style={{ opacity: 0 }}>*</span>团队描述
  181. </div>
  182. <div dangerouslySetInnerHTML={{ __html: tetx[2] || ' - ' }}></div>
  183. </div>
  184. </>
  185. ) : (
  186. <>
  187. <Form.Item
  188. className='A5Text20'
  189. label='所属机构'
  190. name='jigou'
  191. rules={[{ required: true, message: '请输入所属机构!' }]}
  192. getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
  193. >
  194. <TextArea autoSize placeholder='请输入内容,不超过20个字' maxLength={20} />
  195. </Form.Item>
  196. <Form.Item label='团队描述' name='miaoshu' className='A5Text'>
  197. <TextArea
  198. autoSize
  199. maxLength={200}
  200. placeholder='请输入内容,不超过200个字'
  201. />
  202. </Form.Item>
  203. </>
  204. )}
  205. </div>
  206. {time ? null : (
  207. <Button className='A5btn' type='primary' htmlType='submit'>
  208. 提交
  209. </Button>
  210. )}
  211. </Form>
  212. {/* 第三个卡片 */}
  213. <div className='A5lKa' hidden={!!time && !fileUrl}>
  214. <div className='A5tit'>健康生活教育课程预约单</div>
  215. {time ? null : (
  216. <div className='A5LA1'>
  217. 预约单模板
  218. <a className='A5LA1btn' href='xxx' download='预约单模板'>
  219. 下载
  220. </a>
  221. </div>
  222. )}
  223. {time ? null : (
  224. <div className='A5LA1'>
  225. <div className='A5LA1ll'>
  226. <p>上传填写结果</p>
  227. <span>仅限jpg,png格式;大小不超过5M;最多1个文件</span>
  228. </div>
  229. <div className='A5LA1btn' hidden={!!fileUrl}>
  230. 上传
  231. </div>
  232. </div>
  233. )}
  234. {fileUrl.src ? (
  235. <div className='A5file'>
  236. <img src={fileUrl.src} alt='' />
  237. {time ? null : (
  238. <div className='A5file2'>
  239. <EyeOutlined onClick={() => ImageViewer.show({ image: fileUrl.src })} />
  240. <MyPopconfirm
  241. txtK='删除'
  242. onConfirm={() => setFileUrl({ src: '', name: '' })}
  243. Dom={<CloseOutlined className='clearCover' />}
  244. />
  245. </div>
  246. )}
  247. </div>
  248. ) : null}
  249. {time ? null : (
  250. <div className='A5LAkuang'>
  251. <div>
  252. <p>1.下载模板</p>
  253. <p>2.填写模板 </p>
  254. <p>3.将填写结果导出PNG或JPG图片格式</p>
  255. <p>4.上传填写结果</p>
  256. </div>
  257. </div>
  258. )}
  259. </div>
  260. </div>
  261. </div>
  262. </div>
  263. </div>
  264. {/* 预约成功的弹窗 */}
  265. {titPop ? <ZinfoPop type={titPop as 'succ'} callFu={() => history.push('/my')} /> : null}
  266. </div>
  267. )
  268. }
  269. const MemoA5order = React.memo(A5order)
  270. export default MemoA5order