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

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