猫妈狗爸伴宠师小程序前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

430 lines
8.0 KiB

2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
  1. <template>
  2. <view class="containers po-r">
  3. <image src="" mode="" class="mainBg"></image>
  4. <view class="w-100 po-a content">
  5. <stepProgress :step="1"></stepProgress>
  6. <view class="bg-fff mt22 form ">
  7. <view class="title fw700 size-30 flex-rowl">
  8. 基本信息
  9. </view>
  10. <dForm ref="formRef" :list="state.list" labelWidth="220rpx" :isFooter="false" @input="onFormInput"></dForm>
  11. </view>
  12. <view class="license__view" v-if="form.isHave">
  13. <view class="license">
  14. <up-checkbox-group
  15. v-model="licenseData.selected"
  16. shape="circle"
  17. activeColor="#FFBF60"
  18. labelColor="#000000"
  19. labelSize="26rpx"
  20. >
  21. <view class="license-options">
  22. <up-checkbox
  23. v-for="item in licenseOptions"
  24. :key="`license-${item.id}`"
  25. :label="item.title"
  26. :name="item.id"
  27. >
  28. </up-checkbox>
  29. </view>
  30. </up-checkbox-group>
  31. <view class="tips">
  32. {{ configList.pet_news.paramValueText }}
  33. </view>
  34. <up-upload
  35. :fileList="licenseData.fileList"
  36. @afterRead="afterRead"
  37. @delete="deletePic"
  38. multiple
  39. >
  40. <image src="../static/list/icon-upload.png" style="width: 144rpx;height: 144rpx;"></image>
  41. </up-upload>
  42. </view>
  43. </view>
  44. <view class="bg-fff mt22 form bt120">
  45. <view class="title fw700 size-30 flex-rowl">
  46. 个人宠物类型
  47. </view>
  48. <view class="flex-between wrap mt32">
  49. <view class="type" v-for="item in petTypeOptions" :key="`petType-${item.id}`">
  50. <image :src="item.imageNo" mode="widthFix" @click="onSelectPetType(item.id)"></image>
  51. <template v-if="petType === item.id">
  52. <image class="active" :src="item.image" mode="widthFix"></image>
  53. <view class="active-icon">
  54. <up-icon name="checkmark-circle" color="#FFBF60" size="32rpx"></up-icon>
  55. </view>
  56. </template>
  57. </view>
  58. </view>
  59. </view>
  60. <view class="footer-btn" @click="toNext">
  61. <view class="btn">
  62. 下一步
  63. </view>
  64. </view>
  65. </view>
  66. </view>
  67. </template>
  68. <script setup>
  69. import { ref, reactive, computed } from "vue";
  70. import { useStore } from 'vuex'
  71. import { onLoad } from '@dcloudio/uni-app'
  72. import { ossUpload } from '@/utils/oss-upload/oss/index.js'
  73. import { getLicenseList } from '@/api/examination'
  74. import { insertUser, udpateUser, getUserOne } from '@/api/userTeacher'
  75. import dForm from "@/components/dForm/index.vue"
  76. import stepProgress from '../components/stepProgress.vue';
  77. const store = useStore()
  78. const configList = computed(() => {
  79. return store.getters.configList
  80. })
  81. const userId = computed(() => {
  82. return store.state.user.userInfo.userId
  83. })
  84. const id = ref(null)
  85. const state = reactive({
  86. list: [{
  87. type: "input",
  88. label: "姓名",
  89. key: "name",
  90. placeholder: "请输入您的真实姓名",
  91. },
  92. {
  93. type: "input",
  94. label: "身份证号",
  95. key: "idCard",
  96. placeholder: "请输入您的真实身份证号",
  97. },
  98. {
  99. type: "radio",
  100. label: "性别",
  101. key: "sex",
  102. options: [{
  103. name: "男",
  104. value: 0,
  105. },
  106. {
  107. name: "女",
  108. value: 1,
  109. }
  110. ]
  111. },
  112. {
  113. type: "input",
  114. label: "年龄",
  115. key: "age",
  116. placeholder: "请输入您的年龄",
  117. },
  118. {
  119. type: "input",
  120. label: "手机号",
  121. key: "phone",
  122. placeholder: "请输入您的手机号",
  123. },
  124. {
  125. type: "input",
  126. label: "养宠经验",
  127. key: "experience",
  128. placeholder: "请输入您的养宠年限",
  129. unit: "年"
  130. },
  131. {
  132. type: "radio",
  133. label: "是否有专业执照",
  134. key: "isHave",
  135. placeholder: "请选择",
  136. options: [{
  137. name: "是",
  138. value: 1,
  139. }, {
  140. name: "没有",
  141. value: 0,
  142. }]
  143. },
  144. ]
  145. })
  146. const formRef = ref()
  147. const form = ref({})
  148. const onFormInput = (e) => {
  149. form.value = e
  150. }
  151. const fetchUserInfo = async () => {
  152. try {
  153. const { userTelephone } = store.state.user.userInfo
  154. const data = await getUserOne(userId.value)
  155. if (data) {
  156. const {
  157. id: _id,
  158. status,
  159. name,
  160. idCard,
  161. sex,
  162. age,
  163. phone,
  164. experience,
  165. isHave,
  166. license,
  167. images,
  168. petType: _petType,
  169. } = data
  170. if ([1,2].includes(status)) { // status: 0-审核中 1-通过 2-不通过
  171. uni.navigateTo({
  172. url: `/otherPages/authentication/examination/trainCompleted/index?status=${status}`
  173. })
  174. return
  175. }
  176. id.value = _id
  177. formRef.value.setData({
  178. name,
  179. idCard,
  180. sex,
  181. age,
  182. phone: phone || userTelephone,
  183. experience,
  184. isHave,
  185. })
  186. licenseData.selected = license?.split?.(';').map(str => parseInt(str)) || []
  187. licenseData.fileList = images?.split?.(';').map(url => ({ url })) || []
  188. petType.value = _petType
  189. } else {
  190. formRef.value.setData({
  191. phone: userTelephone,
  192. })
  193. }
  194. store.dispatch('fetchPetTypeOptions')
  195. fetchLicenseOptions()
  196. } catch (err) {
  197. console.log('--err', err)
  198. }
  199. }
  200. const licenseData = reactive({
  201. selected: [],
  202. fileList: []
  203. })
  204. const licenseOptions = ref([])
  205. const fetchLicenseOptions = async () => {
  206. try {
  207. licenseOptions.value = await getLicenseList()
  208. } catch (err) {
  209. }
  210. }
  211. const afterRead = (event) => {
  212. event.file.forEach(n => {
  213. ossUpload(n.url)
  214. .then(url => {
  215. licenseData.fileList.push({
  216. url
  217. })
  218. })
  219. })
  220. };
  221. const deletePic = (event) => {
  222. licenseData.fileList.splice(event.index, 1);
  223. };
  224. const petType = ref()
  225. const petTypeOptions = computed(() => {
  226. return store.getters.petTypeOptions
  227. })
  228. const onSelectPetType = (type) => {
  229. petType.value = type
  230. }
  231. const toNext = async () => {
  232. try {
  233. const {
  234. name,
  235. idCard,
  236. sex,
  237. age,
  238. phone,
  239. experience,
  240. isHave,
  241. } = form.value
  242. const data = {
  243. userId: userId.value,
  244. name,
  245. idCard,
  246. sex,
  247. age,
  248. phone,
  249. experience,
  250. isHave,
  251. petType: petType.value,
  252. }
  253. if (isHave) {
  254. const { selected, fileList } = licenseData
  255. data.license = selected.join(';')
  256. data.images = fileList.map(item => item.url).join(';')
  257. }
  258. if (id.value) {
  259. data.id = id.value
  260. await udpateUser(data)
  261. } else {
  262. await insertUser(data)
  263. }
  264. uni.navigateTo({
  265. url: `/otherPages/authentication/examination/start?petType=${petType.value}`
  266. })
  267. } catch (err) {
  268. }
  269. }
  270. onLoad(() => {
  271. fetchUserInfo()
  272. store.dispatch('fetchPetTypeOptions')
  273. })
  274. </script>
  275. <style lang="scss" scoped>
  276. .bt120 {
  277. margin-bottom: 120rpx;
  278. width: 716rpx;
  279. box-sizing: border-box;
  280. }
  281. .footer-btn {
  282. width: 100vw;
  283. height: 144rpx;
  284. background-color: #fff;
  285. display: flex;
  286. justify-content: center;
  287. position: fixed;
  288. bottom: 0;
  289. left: 0;
  290. align-items: center;
  291. .btn {
  292. font-size: 30rpx;
  293. color: #fff;
  294. display: flex;
  295. justify-content: center;
  296. align-items: center;
  297. width: 574rpx;
  298. height: 94rpx;
  299. border-radius: 94rpx;
  300. background-color: #FFBF60;
  301. }
  302. }
  303. .type {
  304. width: 190rpx;
  305. margin-bottom: 74rpx;
  306. position: relative;
  307. image {
  308. width: 100%;
  309. }
  310. .active {
  311. position: absolute;
  312. top: 0;
  313. left: 0;
  314. &-icon {
  315. position: absolute;
  316. top: 14rpx;
  317. right: 18rpx;
  318. }
  319. }
  320. }
  321. .form {
  322. padding: 40rpx 32rpx;
  323. box-sizing: border-box;
  324. width: 716rpx;
  325. }
  326. .title {
  327. &::before {
  328. content: "";
  329. display: block;
  330. width: 9rpx;
  331. height: 33rpx;
  332. background-color: #FFBF60;
  333. margin-right: 7rpx;
  334. }
  335. }
  336. .mb6 {
  337. margin-bottom: 6rpx;
  338. }
  339. .containers {
  340. .mainBg {
  341. width: 100vw;
  342. height: 442rpx;
  343. background-image: linear-gradient(to bottom, #FFBF60, #f5f5f5);
  344. }
  345. .content {
  346. top: 0;
  347. left: 0;
  348. padding: 16rpx;
  349. }
  350. }
  351. .license__view {
  352. width: 716rpx;
  353. padding-bottom: 40rpx;
  354. box-sizing: border-box;
  355. background-color: #FFFFFF;
  356. .license {
  357. width: 100%;
  358. padding: 13rpx 16rpx;
  359. box-sizing: border-box;
  360. background-color: #FFFCF1;
  361. &-options {
  362. display: grid;
  363. grid-template-columns: repeat(2, 1fr);
  364. }
  365. }
  366. .tips {
  367. margin: 22rpx 0 24rpx 0;
  368. color: #FFBF60;
  369. font-size: 22rpx;
  370. width: 100%;
  371. word-break: break-all;
  372. }
  373. }
  374. </style>