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

295 lines
6.5 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <template>
  2. <view class="page">
  3. <view class="tips color-ffb size-22">
  4. 注意:这段内容将会在您的喂养员个人主页做为"服务案例展示并开放给其他铲屎官查看请认真编辑哟
  5. </view>
  6. <view class="li bg-fff">
  7. <view class="title">
  8. 服务类型
  9. <text class="size-22 color-999 ml10">可多选</text>
  10. </view>
  11. <up-checkbox-group v-model="form.serviceType">
  12. <view class="flex-between mt40" style="width: 100%;">
  13. <up-checkbox shape="circle" class="mr10" :customStyle="{marginBottom: '8px'}"
  14. v-for="item in petTypeOptions" :key="`serviceType-${item.id}`" :label="item.title" :name="item.id" activeColor="#FFBF60">
  15. </up-checkbox>
  16. </view>
  17. </up-checkbox-group>
  18. </view>
  19. <view class="li bg-fff">
  20. <view class="title">
  21. 服务时间
  22. </view>
  23. <view class="flex-between mt16">
  24. <text class="size-28 color-999">选择服务时间</text>
  25. <view class="flex-rowr" @click="openTimePicker">
  26. <view class="t-r size-28 mr10" :class="[form.serviceTime ? 'highlight' : '']">{{ serveTimeDesc }}</view>
  27. <up-icon name="arrow-right" color="#999999" size="27rpx"></up-icon>
  28. </view>
  29. </view>
  30. <up-datetime-picker
  31. v-model="form.serviceTime"
  32. :show="showTimePicker"
  33. mode="date"
  34. :closeOnClickOverlay="true"
  35. @close="closeTimePicker"
  36. @cancel="closeTimePicker"
  37. @confirm="closeTimePicker"
  38. ></up-datetime-picker>
  39. </view>
  40. <view class="li bg-fff">
  41. <view class="title">
  42. 服务地点
  43. </view>
  44. <view class="flex-between mt16">
  45. <text class="size-28 color-999">选择服务地点</text>
  46. <view class="flex-rowr" @click="selectAddr">
  47. <view class="t-r size-28 mr10" :class="[form.serviceSpot ? 'highlight' : '']">{{ form.serviceSpot || '请选择' }}</view>
  48. <up-icon name="arrow-right" color="#999999" size="27rpx"></up-icon>
  49. </view>
  50. </view>
  51. </view>
  52. <view class="li bg-fff">
  53. <view class="title">
  54. 文字记录
  55. </view>
  56. <textarea class="text"
  57. v-model="form.text"
  58. placeholder="请输入文字记录,可简单描述服务过程中发生的趣事,或夸奖一下服务宠物吧,10-100字"
  59. ></textarea>
  60. </view>
  61. <view class="li bg-fff">
  62. <view class="title">
  63. 图片记录
  64. </view>
  65. <view class="size-28 color-999 mt16">
  66. 请选择具有代表性的2-3张服务宠物图片服务过程图片或视频截图让铲屎官感受到您对毛孩子的爱吧
  67. </view>
  68. <view style="margin-top: 34rpx;">
  69. <up-upload
  70. :fileList="form.fileList"
  71. @afterRead="afterRead"
  72. @delete="deletePic"
  73. multiple
  74. >
  75. <image src="../static/list/icon-upload.png" style="width: 144rpx;height: 144rpx;"></image>
  76. </up-upload>
  77. </view>
  78. </view>
  79. <view class="footer-btn">
  80. <view class="btn" @click="onSave">
  81. 立即上传
  82. </view>
  83. </view>
  84. </view>
  85. </template>
  86. <script setup>
  87. import { ref, reactive, computed } from 'vue';
  88. import { onLoad } from '@dcloudio/uni-app'
  89. import { useStore } from 'vuex'
  90. import dayjs from 'dayjs'
  91. import { ossUpload } from '@/utils/oss-upload/oss/index.js'
  92. import { insertServiceLog, udpateServiceLog } from '@/api/serviceLog'
  93. import { serviceLogList, deleteServiceLog } from '@/api/serviceLog'
  94. const store = useStore()
  95. const id = ref(0)
  96. const form = reactive({
  97. serviceType: [],
  98. serviceTime: null,
  99. serviceSpot: null,
  100. latitude: null,
  101. longitude: null,
  102. text: null,
  103. fileList: [],
  104. })
  105. const fetchServiceLogDetail = async () => {
  106. try {
  107. const data = (await serviceLogList({ id: id.value }))?.[0]
  108. // const data = uni.getStorageSync('serviceLogData')
  109. const {
  110. serviceType,
  111. serviceTime,
  112. serviceSpot,
  113. text,
  114. image,
  115. } = data
  116. form.serviceType = serviceType?.split?.(',').map(item => parseInt(item)) || []
  117. form.serviceTime = serviceTime
  118. form.serviceSpot = serviceSpot
  119. form.text = text
  120. form.fileList = image?.split?.(',').map(url => ({ url })) || []
  121. } catch (err) {
  122. console.error(err);
  123. }
  124. }
  125. const petTypeOptions = computed(() => {
  126. return store.getters.petTypeOptions
  127. })
  128. const showTimePicker = ref(false)
  129. const openTimePicker = () => {
  130. showTimePicker.value = true
  131. }
  132. const closeTimePicker = () => {
  133. showTimePicker.value = false
  134. }
  135. const serveTimeDesc = computed(() => {
  136. if (!form.serviceTime) {
  137. return '请选择'
  138. }
  139. return dayjs(form.serviceTime).format('YYYY/MM/DD')
  140. })
  141. const setAddress = (res) => {
  142. //经纬度信息
  143. form.latitude = res.latitude
  144. form.longitude = res.longitude
  145. if (!res.address && res.name) { //用户直接选择城市的逻辑
  146. return form.serviceSpot = res.name
  147. }
  148. if (res.address || res.name) {
  149. return form.serviceSpot = res.address + res.name
  150. }
  151. form.serviceSpot = '' //用户啥都没选就点击勾选
  152. }
  153. const selectAddr = () => {
  154. uni.chooseLocation({
  155. success: function(res) {
  156. setAddress(res)
  157. }
  158. })
  159. }
  160. const afterRead = (event) => {
  161. event.file.forEach(n => {
  162. ossUpload(n.url)
  163. .then(url => {
  164. form.fileList.push({
  165. url
  166. })
  167. })
  168. })
  169. };
  170. const deletePic = (event) => {
  171. form.fileList.splice(event.index, 1);
  172. };
  173. const onSave = async () => {
  174. try {
  175. const {
  176. serviceType,
  177. serviceTime,
  178. serviceSpot,
  179. text,
  180. fileList,
  181. } = form
  182. const data = {
  183. userId: store.getters.userInfo.userId,
  184. serviceType: serviceType.join(','),
  185. serviceTime: dayjs(serviceTime).format('YYYY-MM-DD HH:mm:ss'),
  186. serviceSpot,
  187. text,
  188. image: fileList.map(item => item.url).join(',')
  189. }
  190. if (id.value) {
  191. data.id = id.value
  192. await udpateServiceLog(data)
  193. } else {
  194. await insertServiceLog(data)
  195. }
  196. uni.showToast({
  197. title: '上传成功!',
  198. icon: "none"
  199. })
  200. setTimeout(() => {
  201. uni.navigateBack()
  202. }, 1000)
  203. } catch (err) {
  204. }
  205. }
  206. onLoad((option) => {
  207. store.dispatch('fetchPetTypeOptions')
  208. id.value = option.id
  209. if (id.value) {
  210. fetchServiceLogDetail()
  211. }
  212. })
  213. </script>
  214. <style lang="scss" scoped>
  215. .page {
  216. min-height: 100vh;
  217. padding-bottom: 144rpx;
  218. }
  219. .text {
  220. padding: 16rpx;
  221. background-color: #F3F3F3;
  222. font-size: 28rpx;
  223. margin-top: 16rpx;
  224. border-radius: 20rpx;
  225. }
  226. .tips {
  227. padding: 8rpx 16rpx;
  228. background-color: rgb(255, 250, 242);
  229. }
  230. .li {
  231. margin: 20rpx;
  232. border-radius: 20rpx;
  233. padding: 24rpx 36rpx;
  234. }
  235. .title {
  236. font-size: 30rpx;
  237. font-weight: 700;
  238. display: flex;
  239. align-items: center;
  240. &:before {
  241. display: block;
  242. content: "";
  243. width: 10rpx;
  244. border-radius: 10rpx;
  245. height: 34rpx;
  246. background-color: #FFBF60;
  247. margin-right: 15rpx;
  248. }
  249. }
  250. .highlight {
  251. color: #FFBF60;
  252. }
  253. .footer-btn {
  254. z-index: 4;
  255. }
  256. </style>