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

496 lines
11 KiB

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