猫妈狗爸伴宠师小程序前端代码
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.

494 lines
13 KiB

4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
2 weeks ago
2 weeks ago
4 months ago
4 months ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
  1. <template>
  2. <view class="page bg-fff">
  3. <view class="size-22 color-ffb flex-rowl tip">
  4. <image class="icon" :src="configList.my_information_statement.paramValueImage"></image>
  5. <view>
  6. <up-parse :content="configList.my_information_statement.paramValueArea" containerStyle="{
  7. color: '#FFBF60',
  8. fontSize: '22rpx',
  9. lineHeight: '40rpx',
  10. }"></up-parse>
  11. </view>
  12. </view>
  13. <view class="info">
  14. <view class="title mt24">
  15. 基本资料
  16. </view>
  17. <view class="flex-colc">
  18. <button class="btn-avatar" :plain="true" :hairline="false" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
  19. <view class="flex-colc">
  20. <image class="head" :src="form.headImage" mode="aspectFill"></image>
  21. <!-- <image class="head" :src="form.headImage" mode="widthFix"></image> -->
  22. <text class="size-28 color-999 mt10">点击更换头像</text>
  23. </view>
  24. </button>
  25. </view>
  26. <view class="form">
  27. <up-form label-position="left" :model="baseFormData" :rules="baseRules" ref="baseFormRef" labelWidth="200rpx">
  28. <up-form-item label="昵称" prop="userName">
  29. <up-input inputAlign="right" v-model="baseFormData.userName" placeholder="请输入" border="none" fontSize="28rpx"></up-input>
  30. </up-form-item>
  31. <up-form-item label="手机号" prop="userTelephone">
  32. <up-input inputAlign="right" v-model="baseFormData.userTelephone" placeholder="请输入" border="none" fontSize="28rpx"></up-input>
  33. </up-form-item>
  34. <up-form-item label="性别" prop="sex">
  35. <view class="flex-rowr" @click="openSexSelectPopup">
  36. <text>{{ baseFormData.sex || '请选择' }}</text>
  37. <up-icon name="arrow-right" color="#999999" size="32rpx"></up-icon>
  38. </view>
  39. </up-form-item>
  40. </up-form>
  41. </view>
  42. </view>
  43. <view class="info">
  44. <view class="title mt24 flex-rowl">
  45. 展示信息
  46. <text class="size-22 color-ffb fw700">(重要)</text>
  47. </view>
  48. <view class="form">
  49. <up-form label-position="left" :model="formData" :rules="rules" ref="dFormRef" labelWidth="200rpx">
  50. <up-form-item label="个人简介" prop="userBrief">
  51. <up-input v-model="formData.userBrief"
  52. placeholder="请输入个人简介" border="none"
  53. inputAlign="right"
  54. fontSize="28rpx">
  55. </up-input>
  56. </up-form-item>
  57. <up-form-item label="养宠经验" prop="experience">
  58. <up-input inputAlign="right" v-model="formData.experience" placeholder="请输入养宠经验"
  59. border="none" fontSize="28rpx">
  60. <template #suffix>
  61. </template>
  62. </up-input>
  63. </up-form-item>
  64. <up-form-item label="服务记录" prop="serviceRecord">
  65. <view class="flex-rowr" @click="jumpToServeRecord">
  66. <text>{{ `${serviceCount}` }}</text>
  67. <up-icon name="arrow-right" color="#999999" size="32rpx"></up-icon>
  68. </view>
  69. </up-form-item>
  70. </up-form>
  71. </view>
  72. </view>
  73. <view class="info">
  74. <view class="title mt24 flex-rowl">
  75. 服务资料
  76. </view>
  77. <view class="form">
  78. <up-form label-position="left" :model="serveFormData" ref="serveFormRef" labelWidth="200rpx">
  79. <up-form-item label="服务宠物类型" prop="type">
  80. <view class="flex-rowr" @click="openTypeSelectPopup">
  81. <text>{{ typeDesc }}</text>
  82. <up-icon name="arrow-right" color="#999999" size="32rpx"></up-icon>
  83. </view>
  84. </up-form-item>
  85. <up-form-item label="基础服务" prop="jc">
  86. <view class="flex-rowr">
  87. <text>宠物喂养上门遛狗</text>
  88. <!-- <up-icon name="arrow-right" color="#999999" size="32rpx"></up-icon> -->
  89. </view>
  90. </up-form-item>
  91. <up-form-item label="增值服务" prop="serve">
  92. <view class="flex-rowr" @click="openServeSelectPopup">
  93. <text>{{ serveDesc }}</text>
  94. <up-icon name="arrow-right" color="#999999" size="32rpx"></up-icon>
  95. </view>
  96. </up-form-item>
  97. </up-form>
  98. </view>
  99. </view>
  100. <!-- -->
  101. <view class="size-24 color-ffb flex-rowc mt32 pb28"
  102. @click="configPopupRef.open('serve_rule')">
  103. 伴宠师查看服务酬劳服务时长等规则
  104. </view>
  105. <popupTypeSelect ref="popupTypeSelectRef" v-model="form.type" @confirm="fetchUpdate" ></popupTypeSelect>
  106. <popupServeSelect ref="popupServeSelectRef"
  107. :certificate="tData.license"
  108. v-model="serveFormData.serve"
  109. @confirm="fetchUpdate" ></popupServeSelect>
  110. <popupSexSelect ref="popupSexSelectRef" v-model="baseFormData.sex" @confirm="fetchUpdate" ></popupSexSelect>
  111. <view class="uni-btn-color"
  112. @click="submit">
  113. 保存
  114. </view>
  115. <configPopup ref="configPopupRef" />
  116. <!-- 客服组件 -->
  117. <CustomerService />
  118. </view>
  119. </template>
  120. <script setup>
  121. import { ref, reactive, computed, onMounted, nextTick } from "vue";
  122. import { useStore } from 'vuex'
  123. import { onShow } from '@dcloudio/uni-app'
  124. import { ossUpload } from '@/utils/oss-upload/oss/index.js'
  125. import configPopup from '@/components/configPopup.vue'
  126. import popupTypeSelect from "./popupTypeSelect.vue";
  127. import popupServeSelect from "./popupServeSelect.vue";
  128. import popupSexSelect from "./popupSexSelect.vue";
  129. import { serviceLogList } from '@/api/serviceLog'
  130. import {
  131. binBaseInfo,
  132. } from "@/api/home.js"
  133. import { getUserOne, udpateUser } from '@/api/userTeacher'
  134. import { updateUserInfo } from '@/api/user/user'
  135. const store = useStore()
  136. const configPopupRef = ref(null)
  137. const configList = computed(() => {
  138. return store.getters.configList
  139. })
  140. const userInfo = computed(() => {
  141. return store.getters.userInfo
  142. })
  143. const serviceCount = ref(0)
  144. const baseFormData = reactive({
  145. userName: '',
  146. userTelephone: '',
  147. sex: ''
  148. })
  149. const baseRules = {
  150. userName: {
  151. type: 'string',
  152. required: true,
  153. message: '请输入昵称',
  154. trigger: ['blur', 'change']
  155. },
  156. userTelephone: {
  157. type: 'string',
  158. required: true,
  159. message: '请输入手机号',
  160. trigger: ['blur', 'change']
  161. },
  162. sex: {
  163. type: 'string',
  164. required: true,
  165. message: '请选择性别',
  166. trigger: ['blur', 'change']
  167. }
  168. }
  169. const baseFormRef = ref(null)
  170. const tData = ref({})
  171. const formData = reactive({
  172. introduction: '',
  173. experience: '',
  174. serviceRecord: '',
  175. userBrief : '',
  176. })
  177. const rules = {
  178. introduction: {
  179. type: 'string',
  180. required: true,
  181. message: '请输入个人简介',
  182. trigger: ['blur', 'change']
  183. },
  184. experience: {
  185. type: 'string',
  186. required: true,
  187. message: '请输入养宠经验',
  188. trigger: ['blur', 'change']
  189. }
  190. }
  191. const dFormRef = ref(null)
  192. const form = reactive({
  193. headImage: null,
  194. type: [],
  195. id : 0,
  196. })
  197. const serveFormData = reactive({
  198. serve: []
  199. })
  200. const serveFormRef = ref(null)
  201. const fetchUserInfo = async () => {
  202. try {
  203. const data = await getUserOne(userInfo.value.userId)
  204. if (data) {
  205. tData.value = data
  206. // 设置基本资料
  207. baseFormData.userName = userInfo.value.userName || ''
  208. baseFormData.userTelephone = data.phone || userInfo.value.userTelephone || ''
  209. baseFormData.sex = data.sex == 0 ? '男' : '女'
  210. // 设置展示信息
  211. formData.userBrief = data.userBrief || ''
  212. formData.experience = data.experience || ''
  213. form.headImage = userInfo.value.userImage || ''
  214. form.id = data.id || 0
  215. // 设置服务资料
  216. if (data.petType) {
  217. form.type = data.petType.split ? data.petType.split(',').map(n => parseInt(n)) : [parseInt(data.petType)]
  218. }
  219. // 设置增值服务
  220. if (data.addServices) {
  221. serveFormData.serve = data.addServices.split(';').map(item => parseInt(item))
  222. }
  223. }
  224. } catch (err) {
  225. console.log('--err', err)
  226. }
  227. }
  228. const fetchUpdate = () => {
  229. // 表单数据已更新,无需额外处理
  230. }
  231. const onChooseAvatar = (res) => {
  232. ossUpload(res.target.avatarUrl)
  233. .then(url => {
  234. form.headImage = url
  235. fetchUpdate()
  236. })
  237. }
  238. const jumpToServeRecord = () => {
  239. uni.navigateTo({
  240. url: "/otherPages/authentication/serve/record"
  241. })
  242. }
  243. const popupTypeSelectRef = ref()
  244. const openTypeSelectPopup = () => {
  245. popupTypeSelectRef.value.open()
  246. }
  247. const popupSexSelectRef = ref()
  248. const openSexSelectPopup = () => {
  249. popupSexSelectRef.value.open()
  250. }
  251. const petTypeOptions = computed(() => {
  252. return store.getters.petTypeOptions
  253. })
  254. const typeDesc = computed(() => {
  255. const typeIds = form.type
  256. if (!typeIds.length) {
  257. return '请选择'
  258. }
  259. let descArr = typeIds.map(typeId => {
  260. let t = petTypeOptions.value.find(item => item.id === typeId)
  261. return t && t.title
  262. })
  263. return descArr.join('、')
  264. })
  265. const popupServeSelectRef = ref()
  266. const increaseServiceOptions = computed(() => {
  267. return store.getters.increaseServiceOptions
  268. })
  269. const openServeSelectPopup = () => {
  270. popupServeSelectRef.value.open()
  271. }
  272. const serveDesc = computed(() => {
  273. const serveIds = serveFormData.serve
  274. if (!serveIds.length) {
  275. return '请选择'
  276. }
  277. let descArr = serveIds.map(serveId => {
  278. return increaseServiceOptions.value.find(option => option.id == serveId)?.title
  279. })
  280. return descArr.join('、')
  281. })
  282. function getCountSerivce(){
  283. serviceLogList({ userId: userInfo.value.userId })
  284. .then(res => {
  285. serviceCount.value = res.length
  286. })
  287. }
  288. const getBaseInfo = () => {
  289. binBaseInfo(userInfo.value.userId).then(res => {
  290. baseInfo.value = res.data
  291. uni.setStorageSync(JSON.stringify(res.data))
  292. })
  293. }
  294. function submit(){
  295. // 先验证基本资料表单
  296. baseFormRef.value.validate().then(() => {
  297. // 再验证展示信息表单
  298. return dFormRef.value.validate()
  299. }).then(res => {
  300. const submitData = {
  301. id : form.id,
  302. phone: baseFormData.userTelephone,
  303. sex: baseFormData.sex == '男' ? 0 : 1,
  304. userBrief: formData.userBrief,
  305. experience: formData.experience,
  306. petType: form.type.length > 0 ? form.type.join(',') : null,
  307. addServices: serveFormData.serve.join(';'),
  308. }
  309. if (form.headImage) {
  310. updateUserInfo({
  311. userImage : form.headImage,
  312. userName: baseFormData.userName,
  313. id : userInfo.value.id,
  314. userId : userInfo.value.userId,
  315. }).then(() => {
  316. store.dispatch('getUserInfo')
  317. })
  318. }
  319. udpateUser(submitData).then(() => {
  320. uni.showToast({
  321. title: '保存成功',
  322. icon: 'success'
  323. })
  324. setTimeout(uni.navigateBack, 1000, -1)
  325. }).catch(err => {
  326. console.error(err)
  327. uni.showToast({
  328. title: '保存失败',
  329. icon: 'error'
  330. })
  331. })
  332. }).catch(err => {
  333. console.log('表单验证失败', err)
  334. })
  335. }
  336. onShow(() => {
  337. getCountSerivce()
  338. fetchUserInfo()
  339. store.dispatch('fetchPetTypeOptions')
  340. store.dispatch('fetchIncreaseServiceOptions')
  341. })
  342. onMounted(()=> {
  343. })
  344. </script>
  345. <style lang="scss" scoped>
  346. .page {
  347. padding-top: 16rpx;
  348. padding-bottom: 150rpx;
  349. .tip {
  350. background-color: rgba($color: #FFBF60, $alpha: 0.16);
  351. padding: 13rpx 22rpx;
  352. margin: 0 28rpx 37rpx 28rpx;
  353. .icon {
  354. width: 36rpx;
  355. height: 36rpx;
  356. margin-right: 15rpx;
  357. }
  358. }
  359. }
  360. .info {
  361. & + & {
  362. margin-top: 50rpx;
  363. }
  364. }
  365. .head {
  366. width: 165rpx;
  367. height: 165rpx;
  368. margin-top: 28rpx;
  369. }
  370. .btn-avatar {
  371. border: none;
  372. padding: 0;
  373. .head{
  374. width: 140rpx;
  375. height: 140rpx;
  376. border-radius: 50%;
  377. }
  378. }
  379. .title {
  380. font-size: 30rpx;
  381. font-weight: 700;
  382. display: flex;
  383. align-items: center;
  384. padding: 0 40rpx;
  385. &:before {
  386. display: inline-block;
  387. content: "";
  388. width: 10rpx;
  389. border-radius: 5rpx;
  390. height: 33rpx;
  391. background-color: #FFBF60;
  392. margin-right: 7rpx;
  393. }
  394. }
  395. .form {
  396. padding: 0 38rpx;
  397. :deep(.form-item){
  398. padding-left: 24rpx;
  399. padding-right: 30rpx;
  400. box-sizing: border-box;
  401. }
  402. .form-item {
  403. min-height: 90rpx;
  404. padding-top: 10rpx;
  405. width: 100%;
  406. border-bottom: 1rpx solid #f5f5f5;
  407. }
  408. .flex-rowr {
  409. display: flex;
  410. justify-content: flex-end;
  411. align-items: center;
  412. }
  413. .ml10 {
  414. margin-left: 10rpx;
  415. }
  416. }
  417. .uni-btn-color{
  418. border-radius: 40rpx;
  419. padding: 20rpx;
  420. margin: 40rpx;
  421. background: #FFBF60;
  422. color: #fff;
  423. text-align: center;
  424. font-size: 28rpx;
  425. }
  426. </style>