1 line
16 KiB
Plaintext
1 line
16 KiB
Plaintext
{"version":3,"file":"detail.js","sources":["../../../../../src/pages/service/detail.vue","../../../../../uniPage:/cGFnZXMvc2VydmljZS9kZXRhaWwudnVl"],"sourcesContent":["<route lang=\"json5\">\n{\n style: {\n navigationBarTitleText: '宠托师服务详情',\n navigationStyle: 'custom',\n },\n}\n</route>\n\n<template>\n <TopBar />\n <view class=\"bg-[#F5F5F5] h-[135vh]\">\n <!-- 顶部背景和头像 -->\n <view class=\"relative\">\n <image\n :src=\"baseUrl + serviceData.bgUrl\"\n class=\"w-full h-40 object-cover\"\n mode=\"widthFix\"\n ></image>\n <view class=\"absolute left-4 bottom-[-20px]\">\n <image\n :src=\"baseUrl + serviceData.userAvatar\"\n mode=\"aspectFill\"\n class=\"w-20 h-20 object-cover rounded-full border-4 border-white\"\n ></image>\n </view>\n </view>\n\n <!-- 宠托师信息 -->\n <view class=\"bg-white p-4\">\n <text class=\"text-2xl font-bold\">{{ serviceData.userName }}</text>\n <view class=\"flex items-center mt-2\">\n <text class=\"text-sm text-gray-500 mr-2\">认证{{ serviceData.certificationTime }}</text>\n <text class=\"text-sm text-gray-500\">服务过 {{ serviceData.serviceNumber }} 次</text>\n </view>\n <view class=\"flex items-center mt-2\">\n <wd-icon name=\"location\" size=\"20\" class=\"text-[#ffc107]\"></wd-icon>\n <text class=\"ml-2 text-gray-600\">{{ serviceData.address }}</text>\n </view>\n <text class=\"mt-4 text-gray-600\">{{ serviceData.description }}</text>\n </view>\n\n <!-- 服务和费用 -->\n <view class=\"bg-white p-4\">\n <text class=\"text-lg font-bold mb-2\">{{ serviceData.serviceName }}服务费</text>\n <view class=\"flex justify-between items-center mb-4\">\n <view class=\"flex items-center space-x-4\">\n <view class=\"flex flex-col items-center\">\n <wd-icon name=\"bowl\" size=\"24\" class=\"text-pink-500\"></wd-icon>\n <text class=\"text-pink-500 text-sm\">食具清洁</text>\n </view>\n <view class=\"flex flex-col items-center\">\n <wd-icon name=\"water\" size=\"24\" class=\"text-pink-500\"></wd-icon>\n <text class=\"text-pink-500 text-sm\">添粮换水</text>\n </view>\n <view class=\"flex flex-col items-center\">\n <wd-icon name=\"litter\" size=\"24\" class=\"text-pink-500\"></wd-icon>\n <text class=\"text-pink-500 text-sm\">铲屎添砂</text>\n </view>\n </view>\n <text class=\"text-lg text-red-500\">¥{{ serviceData.price }}/次</text>\n </view>\n </view>\n\n <!-- 其他费用 -->\n <view class=\"bg-white p-4\">\n <text class=\"text-lg font-bold mb-2\">其他费用</text>\n <view class=\"flex justify-between items-center mb-4\">\n <view class=\"flex flex-col items-center\">\n <wd-icon name=\"home\" size=\"24\" class=\"text-gray-500\"></wd-icon>\n <text class=\"text-gray-500 text-sm\">基础上门费</text>\n <text class=\"text-gray-500 text-sm\">1km以内23元</text>\n </view>\n <view class=\"flex flex-col items-center\">\n <wd-icon name=\"scooter\" size=\"24\" class=\"text-gray-500\"></wd-icon>\n <text class=\"text-gray-500 text-sm\">每公里加价</text>\n <text class=\"text-gray-500 text-sm\">每多1km加10元</text>\n </view>\n </view>\n </view>\n\n <!-- 用户评价 -->\n <view class=\"bg-white p-4\">\n <text class=\"text-lg font-bold mb-2\">用户评价</text>\n <view class=\"mb-4\" v-if=\"serviceData.comment\">\n <view class=\"flex items-center mb-2\">\n <text class=\"text-pink-500 text-lg\">{{ serviceData.comment.star }}</text>\n <view class=\"flex items-center ml-2\">\n <wd-icon\n v-for=\"num in serviceData.comment.star\"\n name=\"star-on\"\n size=\"20\"\n class=\"text-[#ffc107]\"\n ></wd-icon>\n </view>\n <text class=\"text-gray-500 ml-2\">({{ serviceData.comment.commentNum }}条评论)</text>\n </view>\n <text class=\"text-gray-600\">{{ serviceData.comment.comment }}</text>\n </view>\n <view class=\"text-gray-500 pt-2 w-full text-center\" v-else>暂无评论</view>\n </view>\n\n <!-- 底部地图展示 -->\n <view class=\"flex flex-col justify-center items-center bg-[#ffff] pb-[50px]\">\n <text class=\"text-lg font-bold mb-2 w-full pl-[20px]\" style=\"text-align: left\">服务位置</text>\n <view class=\"w-full h-[20vh]\">\n <Map\n :locationName=\"'服务位置'\"\n :initialLatitude=\"serviceData.latitude\"\n :initialLongitude=\"serviceData.longitude\"\n />\n </view>\n </view>\n\n <!-- 底部操作栏 -->\n <view\n class=\"fixed bottom-0 w-full bg-white flex justify-between items-center px-[10px] mt-4 py-[10px] z-10\"\n >\n <text class=\"text-red-500 text-lg\">¥{{ serviceData.price }}/次 起</text>\n <view class=\"flex space-x-4\">\n <button @click=\"message\" class=\"bg-gray-200 text-gray-600 rounded-full py-[2px] px-6\">\n 消息\n </button>\n <button\n class=\"bg-[#ffc107] text-white rounded-full py-[2px] px-6\"\n @click=\"openReservationModal\"\n >\n 预约宠托师\n </button>\n </view>\n </view>\n </view>\n\n <!-- 预约弹窗 -->\n <view\n v-if=\"showReservationModal\"\n class=\"z-999 fixed inset-0 flex items-center justify-center bg-black bg-opacity-50\"\n >\n <view class=\"bg-white rounded-lg p-4 w-11/12\">\n <view class=\"text-lg font-bold mb-4\">选择预约信息</view>\n\n <!-- 服务宠物选择 -->\n <text class=\"text-sm text-gray-500 mb-2\">服务宠物</text>\n <view v-if=\"pets.length > 0\" class=\"flex space-x-4 mb-4 scroll-x overflow-x-auto\" scroll-x>\n <view\n v-for=\"pet in pets\"\n :key=\"pet.id\"\n class=\"flex flex-col items-center\"\n @click=\"selectPet(pet.id)\"\n :class=\"selectedPetId == pet.id ? 'border-4 border-[#ffc107] color-[#ffc107]' : ''\"\n >\n <image\n :src=\"baseUrl + pet.profileUrl\"\n class=\"w-20 h-20 rounded-full object-cover\"\n ></image>\n <text class=\"text-sm\">{{ pet.name }}</text>\n </view>\n </view>\n <view v-else class=\"pet-item add-pet\" @click=\"toPath('/pages/pet/pet-add-page')\">\n <w-avatar :size=\"80\" class=\"pet-avatar add-avatar\">\n <view class=\"add-icon\">+</view>\n </w-avatar>\n </view>\n\n <!-- 预约时间 -->\n <text class=\"text-sm text-gray-500 mb-2\">预约时间</text>\n <picker mode=\"date\" :start=\"today\" :end=\"weekFromToday\" @change=\"handleDateChange\">\n <view class=\"bg-gray-100 p-2 rounded mb-4\">{{ reservationDate || '选择日期' }}</view>\n </picker>\n\n <!-- 选择预约小时 -->\n <text class=\"text-sm text-gray-500 mb-2\">选择服务时长</text>\n <view>\n <wd-input-number v-model=\"hours\" @change=\"hoursHandleChange\" :min=\"1\" :max=\"12\" />\n </view>\n\n <!-- 服务地址选择 -->\n <text class=\"text-sm text-gray-500 mb-2\">选择地址</text>\n <picker\n v-if=\"addressList.length > 0\"\n mode=\"selector\"\n range-key=\"display\"\n :range=\"addressList\"\n @change=\"handleAddressChange\"\n >\n <view class=\"bg-gray-100 p-2 rounded mb-4\">\n {{ selectedAddress.display || '请选择地址' }}\n </view>\n </picker>\n <view v-else class=\"pet-item add-pet\" @click=\"toPath('/pages/address/index')\">\n <w-avatar :size=\"80\" class=\"pet-avatar add-avatar\">\n <view class=\"add-icon\">+</view>\n </w-avatar>\n </view>\n\n <!-- 操作按钮 -->\n <view class=\"fixed bottom-0 left-0 w-full p-4 bg-white shadow-up\">\n <view class=\"flex justify-between\">\n <button\n class=\"flex-1 mx-2 py-2 px-6 bg-gray-200 text-gray-600 rounded-full\"\n @click=\"closeReservationModal\"\n >\n 取消\n </button>\n <button\n class=\"flex-1 mx-2 py-2 px-6 bg-[#ffc107] text-white rounded-full\"\n @click=\"confirmReservation\"\n >\n 确认预约\n </button>\n </view>\n </view>\n </view>\n </view>\n\n <LoadingAnimation v-model=\"loading\" />\n</template>\n\n<script lang=\"js\" setup>\nimport { ref } from 'vue'\nimport { httpGet } from '@/utils/http'\nimport { baseUrl, toast, toPath } from '@/utils/commUtils'\nimport { pay } from '@/logic/pay'\nimport TopBar from '@/components/TopBar.vue'\nimport Map from '@/components/Map.vue'\nimport LoadingAnimation from '@/components/LoadingAnimation.vue'\n\n// 获取当前日期\nconst nowday = new Date()\nconst year = nowday.getFullYear()\nconst month = (nowday.getMonth() + 1).toString().padStart(2, '0') // 月份从0开始,需加1\nconst day = nowday.getDate().toString().padStart(2, '0')\nconst reservationDate = ref(`${year}-${month}-${day}`)\nconst loading = ref(false)\nconst serviceData = ref({})\nconst pets = ref([])\nconst addressList = ref([])\nconst showReservationModal = ref(false)\nconst selectedPetId = ref('')\nconst today = ref('')\nconst weekFromToday = ref('')\nconst personalServiceId = ref('')\nconst hours = ref(1)\nconst selectedAddress = ref({})\n\nconst hoursHandleChange = ({ value }) => {\n if (value >= 1 && value <= 12) {\n hours.value = value\n } else {\n toast('选择的服务时长在1-12小时')\n }\n}\n\nconst message = () => {}\n\nconst detailPay = async () => {\n const order = {\n reservationTime: `${reservationDate.value} 00:00:00`,\n personalServiceId: personalServiceId.value,\n personalServiceUserId: serviceData.value.serviceUserId,\n price: serviceData.value.price * hours.value,\n paymentMethod: 'wxpay',\n address: selectedAddress.value.id,\n pet: selectedPetId.value,\n serviceHours: hours.value,\n }\n await pay(order)\n closeReservationModal()\n}\n\n// 获取当前日期并计算一周后的日期\nconst setDateRange = () => {\n const now = new Date()\n today.value = now.toISOString().split('T')[0]\n\n const weekLater = new Date(now)\n weekLater.setDate(now.getDate() + 7)\n weekFromToday.value = weekLater.toISOString().split('T')[0]\n}\n\n// 选择时间\nconst handleDateChange = (e) => {\n reservationDate.value = e.detail.value\n}\n\n// 选择地址\nconst handleAddressChange = (e) => {\n selectedAddress.value = addressList.value[e.detail.value]\n}\n\n// 打开预约弹窗\nconst openReservationModal = () => {\n showReservationModal.value = true\n}\n\n// 关闭预约弹窗\nconst closeReservationModal = () => {\n showReservationModal.value = false\n}\n\n// 选择宠物\nconst selectPet = (id) => {\n selectedPetId.value = id\n}\n\n// 确认预约\nconst confirmReservation = async () => {\n if (!selectedPetId.value || !reservationDate.value || !selectedAddress.value.display) {\n toast('请选择宠物、日期和地址')\n return\n }\n await detailPay()\n closeReservationModal()\n}\n\n// 页面加载时获取服务详情数据、宠物信息和地址信息并初始化地图\nonLoad(async (options) => {\n loading.value = true\n try {\n if (!options.id) {\n toast('该服务不存在!')\n // 返回到上一级页面\n uni.navigateBack()\n return\n }\n const id = options.id\n personalServiceId.value = options.id\n setDateRange()\n\n // 获取服务详情\n const serviceResponse = await httpGet(`/personal-service/service/${id}`)\n if (serviceResponse.code === 200) {\n serviceData.value = serviceResponse.data\n } else {\n toast(serviceResponse.message)\n }\n\n // 获取宠物信息\n const petsResponse = await httpGet('/petInfo/my')\n if (petsResponse.code === 200) {\n pets.value = petsResponse.data\n if (pets.value.length !== 0) selectedPetId.value = pets.value[0].id\n } else {\n toast(petsResponse.message)\n }\n\n // 获取地址信息\n const addressResponse = await httpGet('/china-address/my')\n if (addressResponse.code === 200) {\n addressList.value = addressResponse.data\n addressList.value.forEach((item) => {\n item.display = `${item.province} ${item.city} ${item.district} ${item.detailAddress}`\n })\n selectedAddress.value = addressList.value[0]\n } else {\n toast(addressResponse.message)\n }\n } catch (e) {\n console.log(e)\n toast('获取服务详情失败!')\n }\n\n loading.value = false\n})\n</script>\n\n<style scoped>\n.pet-item {\n display: flex;\n flex-direction: column;\n}\n\n.pet-avatar {\n border: 2px solid #fcd038;\n border-radius: 50%;\n}\n\n.add-avatar {\n width: 102rpx;\n height: 102rpx;\n background-color: #fff;\n border: 2px dashed #fcd038;\n}\n\n.pet-label {\n font-size: 14px;\n color: #666;\n}\n\n.add-icon {\n font-size: 36px;\n line-height: 45px;\n color: #fcd038;\n text-align: center;\n}\n\n.options {\n position: fixed;\n bottom: 0;\n width: 100%;\n background-color: #fff;\n}\n.mapContainer {\n width: 100%;\n height: 20vh;\n}\n\n.fixed {\n position: fixed;\n}\n\n.bottom-0 {\n bottom: 0;\n}\n\n.left-0 {\n left: 0;\n}\n\n.right-0 {\n right: 0;\n}\n\n.bg-white {\n background-color: white;\n}\n\n.rounded-full {\n border-radius: 9999px;\n}\n\n.shadow {\n box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);\n}\n\n.text-red-500 {\n color: #f56565;\n}\n\n.border-4 {\n border-width: 4px;\n}\n</style>\n","import MiniProgramPage from 'D:/App/Work/addr/acdr-ui/src/pages/service/detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","toast","pay","onLoad","uni","httpGet"],"mappings":"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"} |