register.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. <template>
  2. <view class="container">
  3. <!-- 提示信息区域 -->
  4. <view class="header">
  5. <view class="header_top">欢迎加入{{ currentClass }}!!</view>
  6. <view>为确保您的信息顺利通过,请上传有效信息</view>
  7. </view>
  8. <!-- 姓名区域 -->
  9. <view class="box">
  10. <view class="box_key">
  11. <text class="text">*</text>
  12. 孩子姓名
  13. </view>
  14. <view class="box_value">
  15. <input class="input" type="text" placeholder="请输入孩子姓名" v-model="name" />
  16. </view>
  17. </view>
  18. <!-- 性别区域 -->
  19. <view class="box">
  20. <view class="box_key">
  21. <text class="text">*</text>
  22. 性别
  23. </view>
  24. <view class="box_value">
  25. <view class="men" @click="handlegender(1)">
  26. <radio color="#0061FF" style="transform: scale(0.7)" :checked="gender == 1" />
  27. </view>
  28. <view class="women" @click="handlegender(2)">
  29. <radio color="#0061FF" style="transform: scale(0.7)" :checked="gender == 2" />
  30. </view>
  31. </view>
  32. </view>
  33. <!-- 人脸图片区域 -->
  34. <view class="box2">
  35. <view class="box_key">
  36. <text class="text">*</text>
  37. 人脸图片
  38. </view>
  39. <view v-if="!headImage" class="box_upload" @click="handleUpload">
  40. <uni-icons type="plusempty" size="30" color="#666666"></uni-icons>
  41. 上传照片
  42. </view>
  43. <view v-else class="box_upload">
  44. <image :src="headImage" mode="aspectFill" style="width: 160rpx; height: 160rpx" @click="clickImg(headImage)"></image>
  45. <!-- 图片删除图标 -->
  46. <view class="delete" @click="deleteImg">
  47. <uni-icons type="close" size="20"></uni-icons>
  48. </view>
  49. </view>
  50. </view>
  51. <view class="tips">注:支持.jpg .png,五官清晰无遮挡,大小不超过2M</view>
  52. <!-- 时间组区域 -->
  53. <!-- <view class="box">
  54. <view class="box_key">
  55. <text class="text">*</text>
  56. 时间组
  57. </view>
  58. <picker @change="bindPickerChange" :value="currentIndex" :range="array">
  59. <view class="box_value" :class="{ unactive: !currentIndex }">
  60. {{ currentIndex ? array[currentIndex] : '请选择' }}
  61. <image class="value_img" src="/static/images/bottom2.png" mode="aspectFill"></image>
  62. </view>
  63. </picker>
  64. </view> -->
  65. <view v-for="(item, index) in list" :key="index">
  66. <!-- 家属区域 -->
  67. <view class="box">
  68. <view class="box_key">
  69. <text class="text">*</text>
  70. 家属{{ index + 1 }}
  71. </view>
  72. <view class="box_value">
  73. <input v-model="item.name" class="input" type="text" placeholder="请输入称呼或职业" />
  74. <view class="value_icon">
  75. <uni-icons v-if="index == 0" type="plus" size="25" color="#0061FF" @click="handleAdd"></uni-icons>
  76. <uni-icons v-else type="close" size="25" color="#0061FF" @click="handleDelete(index)"></uni-icons>
  77. </view>
  78. </view>
  79. </view>
  80. <!-- 手机号码区域 -->
  81. <view class="box">
  82. <view class="box_key">
  83. <text class="text">*</text>
  84. 手机号码
  85. </view>
  86. <view class="box_value">
  87. <input v-model="item.phone" class="input" type="text" placeholder="请输入手机号码" />
  88. </view>
  89. </view>
  90. <!-- 家属与本人的关系区域 -->
  91. <view class="box">
  92. <view class="box_key">
  93. <text class="text">*</text>
  94. 家属与本人的关系
  95. </view>
  96. <view class="box_value">
  97. <input v-model="item.ship" class="input" type="text" placeholder="请输入家属与本人的关系" />
  98. </view>
  99. </view>
  100. </view>
  101. <view class="btn" @click="handleConfirm">确认</view>
  102. <!-- 用于图片压缩的canvas画布 -->
  103. <canvas
  104. :style="{
  105. width: cw + 'px',
  106. height: cw + 'px',
  107. position: 'absolute',
  108. zIndex: -1,
  109. left: '-10000rpx',
  110. top: '-10000rpx'
  111. }"
  112. canvas-id="zipCanvas"
  113. ></canvas>
  114. <!--画布结束-->
  115. </view>
  116. </template>
  117. <script setup>
  118. import { onLoad } from '@dcloudio/uni-app'
  119. import { ref } from 'vue'
  120. import { getQueryString } from '@/utils/getParams.js'
  121. import { myRequest } from '@/utils/api.js'
  122. import { decryptDes } from '@/utils/des.js'
  123. import getLessLimitSizeImage from '@/utils/imageCompress.js'
  124. // 姓名
  125. const name = ref('')
  126. // 性别
  127. const gender = ref(1)
  128. // 照片
  129. const headImage = ref('')
  130. // 时间组当前激活索引
  131. // const currentIndex = ref()
  132. // 时间组数据
  133. // const array = ref(['上午', '下午'])
  134. const gradeId = ref('')
  135. const classId = ref('')
  136. const departmentId = ref('')
  137. const departmentId_list = ref('')
  138. const currentClass = ref('')
  139. const list = ref([
  140. {
  141. name: '',
  142. phone: '',
  143. ship: '',
  144. departmentId: departmentId_list.value
  145. }
  146. ])
  147. //画板边长默认是屏幕宽度,正方形画布
  148. const cw = uni.getSystemInfoSync().windowWidth
  149. onLoad((options) => {
  150. // console.log(options)
  151. if (options.q) {
  152. const data = decodeURIComponent(options.q)
  153. gradeId.value = getQueryString(data, 'gradeId')
  154. classId.value = getQueryString(data, 'classId')
  155. departmentId.value = getQueryString(data, 'departmentId')
  156. departmentId_list.value = getQueryString(data, 'departmentId_list')
  157. currentClass.value = getQueryString(data, 'currentClass')
  158. } else {
  159. gradeId.value = options.gradeId
  160. classId.value = options.classId
  161. departmentId.value = options.departmentId
  162. departmentId_list.value = options.departmentId_list
  163. currentClass.value = options.currentClass
  164. }
  165. })
  166. // 切换性别回调
  167. const handlegender = (v) => {
  168. gender.value = v
  169. }
  170. // 切换时间组回调
  171. // const bindPickerChange = (e) => {
  172. // currentIndex.value = e.detail.value
  173. // }
  174. // 上传照片回调
  175. const handleUpload = () => {
  176. uni.chooseMedia({
  177. count: 1,
  178. mediaType: ['image'],
  179. sourceType: ['album'],
  180. sizeType: ['compressed'],
  181. success: (res) => {
  182. // console.log(res.tempFiles)
  183. res.tempFiles.forEach((ele) => {
  184. if (ele.fileType === 'image' && ele.size > 1024 * 1024 * 2) {
  185. //这里的id和页面中写的html代码的canvas的id要一致
  186. let canvasId = 'zipCanvas'
  187. //原图的路径
  188. let imagePath = ele.tempFilePath
  189. //大小限制1024kb
  190. let limitSize = 1024 * 2
  191. //初始绘画区域是画布自身的宽度也就是屏幕宽度
  192. let drawWidth = uni.getSystemInfoSync().windowWidth
  193. // 图片过大压缩
  194. getLessLimitSizeImage(canvasId, imagePath, limitSize, drawWidth, (resPath) => {
  195. handleUploadMini({ tempFilePath: resPath, fileType: ele.fileType })
  196. })
  197. } else {
  198. handleUploadMini(ele)
  199. }
  200. })
  201. }
  202. })
  203. }
  204. const handleUploadMini = (ele) => {
  205. uni.showLoading({
  206. title: '上传中,请稍后',
  207. mask: true
  208. })
  209. uni.uploadFile({
  210. url: `https://www.campussmartlife.com/smartApi/wanzai/api/upload/toCos`,
  211. filePath: ele.tempFilePath,
  212. name: 'files',
  213. header: {
  214. token: uni.getStorageSync('token') || '',
  215. user_head: uni.getStorageSync('userhead') || ''
  216. },
  217. success: (uploadFileRes) => {
  218. // console.log(uploadFileRes)
  219. let imgUrl = JSON.parse(uploadFileRes.data).data
  220. const result = JSON.parse(decryptDes(imgUrl))
  221. // console.log(result)
  222. headImage.value = result
  223. },
  224. fail: () => {
  225. uni.showToast({
  226. title: '上传失败',
  227. icon: 'error'
  228. })
  229. },
  230. complete: () => {
  231. uni.hideLoading()
  232. }
  233. })
  234. }
  235. // 点击图片回调
  236. const clickImg = (url) => {
  237. uni.previewImage({
  238. urls: [url],
  239. current: 1
  240. })
  241. }
  242. // 删除图片回调
  243. const deleteImg = () => {
  244. uni.showModal({
  245. title: '提示',
  246. content: '确定删除该图片吗?',
  247. success: (res) => {
  248. if (res.confirm) {
  249. headImage.value = ''
  250. }
  251. }
  252. })
  253. }
  254. // 家属添加图标回调
  255. const handleAdd = () => {
  256. list.value.push({
  257. name: '',
  258. phone: '',
  259. ship: '',
  260. departmentId: departmentId_list.value
  261. })
  262. }
  263. // 家属删除图标回调
  264. const handleDelete = (index) => {
  265. // console.log(index)
  266. uni.showModal({
  267. title: '提示',
  268. content: '确定删除该家属吗?',
  269. success: (res) => {
  270. if (res.confirm) {
  271. list.value.splice(index, 1)
  272. }
  273. }
  274. })
  275. }
  276. // 确认按钮回调
  277. const handleConfirm = () => {
  278. const flag = verify()
  279. if (flag) {
  280. uni.showModal({
  281. title: '提示',
  282. content: '确定提交吗?',
  283. success: (res) => {
  284. if (res.confirm) {
  285. handleConfirmReq()
  286. }
  287. }
  288. })
  289. }
  290. }
  291. // 验证提交数据是否合法
  292. const verify = () => {
  293. if (!name.value) {
  294. uni.showToast({
  295. title: '请输入姓名',
  296. icon: 'none'
  297. })
  298. return false
  299. }
  300. let reg_name = /^[\u4e00-\u9fa5]{2,4}$/
  301. if (!reg_name.test(name.value)) {
  302. uni.showToast({
  303. title: '姓名格式错误',
  304. icon: 'none'
  305. })
  306. return false
  307. }
  308. if (!headImage.value) {
  309. uni.showToast({
  310. title: '请上传图片',
  311. icon: 'none'
  312. })
  313. return false
  314. }
  315. // if (!currentIndex.value) {
  316. // uni.showToast({
  317. // title: '请选择时间组',
  318. // icon: 'none'
  319. // })
  320. // return false
  321. // }
  322. let res = list.value.some((ele) => !ele.name || !ele.phone || !ele.ship)
  323. if (res) {
  324. uni.showToast({
  325. title: '家属数据不能为空',
  326. icon: 'none'
  327. })
  328. return false
  329. }
  330. let res2 = list.value.some((ele) => !reg_name.test(ele.name))
  331. if (res2) {
  332. uni.showToast({
  333. title: '家属姓名格式错误',
  334. icon: 'none'
  335. })
  336. return false
  337. }
  338. let reg_phone = /^1[3-9]\d{9}$/
  339. let res3 = list.value.some((ele) => !reg_phone.test(ele.phone))
  340. if (res3) {
  341. uni.showToast({
  342. title: '家属手机号码格式错误',
  343. icon: 'none'
  344. })
  345. return false
  346. }
  347. return true
  348. }
  349. // 确认请求
  350. const handleConfirmReq = async () => {
  351. let data = {
  352. name: name.value,
  353. sexId: gender.value,
  354. headImage: headImage.value,
  355. departmentId: departmentId.value,
  356. gradeId: gradeId.value,
  357. classId: classId.value,
  358. list: list.value
  359. }
  360. // console.log(data)
  361. const res = await myRequest({
  362. url: '/wanzai/api/smartEnrollmentUser/insertSmartEnrollmentUser',
  363. method: 'post',
  364. data
  365. })
  366. // console.log(res)
  367. if (res.code == 200) {
  368. uni.showToast({
  369. title: '添加成功,请等待审核',
  370. icon: 'none'
  371. })
  372. // setTimeout(() => {
  373. // uni.reLaunch({
  374. // url: '/pages/studentManage/studentManage'
  375. // })
  376. // }, 1500)
  377. }
  378. }
  379. </script>
  380. <style lang="scss" scoped>
  381. .container {
  382. box-sizing: border-box;
  383. padding: 10rpx 0 30rpx 15rpx;
  384. min-height: 100vh;
  385. font-size: 28rpx;
  386. .header {
  387. display: flex;
  388. flex-direction: column;
  389. justify-content: center;
  390. padding: 0 20rpx;
  391. height: 137rpx;
  392. font-size: 24rpx;
  393. font-weight: bold;
  394. background-color: #f2f7ff;
  395. .header_top {
  396. margin-bottom: 5rpx;
  397. font-size: 32rpx;
  398. }
  399. }
  400. .box {
  401. display: flex;
  402. justify-content: space-between;
  403. align-items: center;
  404. height: 96rpx;
  405. border-bottom: 2rpx solid #e6e6e6;
  406. .box_key {
  407. display: flex;
  408. align-items: center;
  409. font-weight: bold;
  410. .text {
  411. color: #d43030;
  412. }
  413. }
  414. .box_value {
  415. display: flex;
  416. align-items: center;
  417. justify-content: flex-end;
  418. padding-right: 20rpx;
  419. width: 320rpx;
  420. height: 96rpx;
  421. .input {
  422. height: 100%;
  423. text-align: right;
  424. }
  425. .men,
  426. .women {
  427. display: flex;
  428. align-items: center;
  429. }
  430. .women {
  431. margin-left: 20rpx;
  432. }
  433. .value_icon {
  434. margin-left: 15rpx;
  435. }
  436. .value_img {
  437. margin-left: 20rpx;
  438. width: 27rpx;
  439. height: 16rpx;
  440. }
  441. }
  442. .unactive {
  443. color: #6a6a6a;
  444. }
  445. }
  446. .box2 {
  447. display: flex;
  448. margin-top: 40rpx;
  449. .box_key {
  450. display: flex;
  451. font-weight: bold;
  452. .text {
  453. color: #d43030;
  454. }
  455. }
  456. .box_upload {
  457. position: relative;
  458. display: flex;
  459. flex-direction: column;
  460. justify-content: center;
  461. align-items: center;
  462. margin-left: 30rpx;
  463. width: 160rpx;
  464. height: 160rpx;
  465. font-size: 24rpx;
  466. color: #666666;
  467. border-radius: 6rpx;
  468. background-color: #f2f2f2;
  469. .delete {
  470. position: absolute;
  471. right: 10rpx;
  472. top: 10rpx;
  473. }
  474. }
  475. }
  476. .tips {
  477. margin-top: 20rpx;
  478. margin-bottom: 5rpx;
  479. font-size: 24rpx;
  480. color: #a6a6a6;
  481. }
  482. .btn {
  483. display: flex;
  484. justify-content: center;
  485. align-items: center;
  486. margin: 80rpx auto 0;
  487. width: 710rpx;
  488. height: 100rpx;
  489. color: #fff;
  490. font-size: 32rpx;
  491. border-radius: 8rpx;
  492. background-color: #0061ff;
  493. }
  494. }
  495. </style>