index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. <!-- 订单详情 -->
  2. <template>
  3. <view>
  4. <view class="order-detail">
  5. <view class="service-info">
  6. <PositioningMap :address="detaile.address" />
  7. </view>
  8. <view class="user-info order-card">
  9. <!-- <view class="user-box">
  10. <view class="info-list">
  11. <view>被服务人员:{{ detaile.name }}</view>
  12. <view style="display: flex;">服务类别: <dict-tag :options="lrr_service_category"
  13. :value="detaile.serviceCategory" /></view>
  14. <view @click="onPhone">电话号码:<label class="phone">{{ detaile.telephone }}</label></view>
  15. <view>地址:{{ detaile.address }}</view>
  16. <view>是否有传染疾病:{{ detaile.isContagion === 1 ? '是' : '否' }}</view>
  17. <view v-if="detaile.isContagion === 1">疾病备注:{{ detaile.haveContagion }}</view>
  18. <view>备注信息:{{ detaile.remark }}</view>
  19. </view>
  20. </view> -->
  21. <view class="handle-user">
  22. <view class="handle-user-left">
  23. <img src='/static/serverImg/mine/user.png' alt=""
  24. style="width: 96rpx;height: 96rpx;margin-right: 32rpx;">
  25. <view class="handle-user-info">
  26. <view class="user-name">{{ detaile.name }}</view>
  27. <view class="user-id" style="display: flex;">服务类别:<dict-tag :options="lrr_service_category"
  28. :value="detaile.serviceCategory" /></view>
  29. </view>
  30. </view>
  31. <view class="user-phone" @click="onPhone(detaile.telephone)">
  32. <up-icon name="phone" color="#fff" size="25"></up-icon>
  33. </view>
  34. </view>
  35. <view class="handle-adress">
  36. <up-icon name="map" color="rgba(156, 163, 175, 1)" size="20"></up-icon>
  37. <view class="adress-text">{{ detaile.address }}</view>
  38. <up-icon name="pushpin" color="rgba(221, 94, 69, 1)" size="25"></up-icon>
  39. </view>
  40. <view class="handle-remark">
  41. <view class="remark-title">备注</view>
  42. <view class="remark-text">{{ detaile.remark || '暂无备注' }}</view>
  43. </view>
  44. </view>
  45. </view>
  46. <view class="footer-g">
  47. <view class="handle-start" v-if="orderStatus && serveTimes">
  48. 服务已开始:<text class="handle-time">{{ dateData }}</text>
  49. </view>
  50. <Slide ref="verify" @change='change' :sliderText="slideData" />
  51. </view>
  52. </view>
  53. </template>
  54. <script setup>
  55. import { ref } from 'vue';
  56. import { onLoad, onUnload } from '@dcloudio/uni-app';
  57. import { getVolunteerOrderInfo, getTimesByDate, } from '@/api/volunteer.js'
  58. import { getAddress } from '@/api/address.js'
  59. import PositioningMap from '@/pages_classify/components/PositioningMap/index.vue'
  60. import Slide from '@/pages_classify/components/Slide/index.vue'
  61. import { useDict } from '@/utils/dict.js';
  62. import DictTag from '@/components/DictTag/index.vue'
  63. import { wxMakePhoneCall } from '@/utils/wxRequest.js'
  64. import { computed } from 'vue';
  65. import dayjs from 'dayjs'
  66. const fileList = ref([]);
  67. const orderId = ref('');
  68. const detaile = ref({});
  69. const verify = ref(null);
  70. const rateValue = ref(3)
  71. const {
  72. lrr_service_category
  73. } = useDict('lrr_service_category');
  74. const orderStatus = ref(false);//false:未开始服务 true:服务已开始,待上传图片
  75. const onPhone = (phone) => {
  76. if(phone){
  77. wxMakePhoneCall(phone)
  78. }
  79. }
  80. const dateData = ref('00:00:00');
  81. let timer = null;
  82. // const dateData = computed(()=>{
  83. // return dayjs(new Date()).format("hh:mm:ss")
  84. // })
  85. const slideData = computed(() => {
  86. //服务已开始,待上传图片
  87. if (orderStatus.value) {
  88. return { successText: '服务已完成', startText: '拖动滑块结束服务', successColor: '#f64a1f', btnText: '上传照片' }
  89. }
  90. return { successText: '服务已开始', startText: '拖动滑块开始服务', successColor: '#72c13f', btnText: '开始' }
  91. })
  92. const getOrderDetail = async () => {
  93. try {
  94. uni.showLoading({
  95. title: '数据加载中...'
  96. });
  97. const res = await getVolunteerOrderInfo({ orderId: orderId.value });
  98. // const ad_res = await getAddress(res.data.addressId);
  99. let data = res.data.secondOrder;
  100. detaile.value = { ...res.data.secondOrder, ...res.data.address,serveTimes:res.data.secondOrder.updateTime }
  101. if (data.orderStatus === '3') {
  102. orderStatus.value = true;
  103. }
  104. if (res.data.secondOrder.updateTime) {
  105. timer = setInterval(() => {
  106. console.log('time', res.data.secondOrder.updateTime);
  107. const timeDiff = Math.abs(new Date() - new Date(res.data.secondOrder.updateTime));
  108. const units = {
  109. day: Math.floor(timeDiff / (1000 * 60 * 60 * 24)),
  110. hour: Math.floor(timeDiff / (1000 * 60 * 60)),
  111. minute: Math.floor(timeDiff / (1000 * 60)),
  112. second: Math.floor(timeDiff / 1000)
  113. };
  114. // 默认返回完整格式
  115. const hours = units.hour % 24;
  116. const minutes = units.minute % 60;
  117. const seconds = units.second % 60;
  118. dateData.value = `${hours}小时${minutes}分钟${seconds}秒`;
  119. }, 1000);
  120. }
  121. console.log('xxxx', detaile.value);
  122. } catch (error) {
  123. console.log('error', error);
  124. uni.showToast({
  125. title: error.msg,
  126. icon: 'error',
  127. })
  128. } finally {
  129. uni.hideLoading();
  130. }
  131. }
  132. const change = (e) => {
  133. console.log('验证信息:', e)
  134. console.log('验证是否成功:' + e.state)
  135. console.log('验证次数:' + e.verification)
  136. if (e.state && !orderStatus.value) {
  137. getTimesByDate(orderId.value).then(res => {
  138. if (res.code === 200) {
  139. uni.showToast({
  140. title: '已开始服务',
  141. icon: 'success',
  142. success: () => {
  143. verify.value.initialization();
  144. // 验证成功
  145. orderStatus.value = true;
  146. }
  147. })
  148. }
  149. })
  150. }
  151. if (e.state && orderStatus.value) {
  152. uni.showToast({
  153. title: '操作成功',
  154. icon: 'success',
  155. success: () => {
  156. setTimeout(() => {
  157. uni.redirectTo({ url: `/pages_classify/pages/order/index?orderId=${orderId.value}` });
  158. }, 800)
  159. }
  160. })
  161. }
  162. }
  163. onLoad((options) => {
  164. console.log('options', options);
  165. orderId.value = options.orderId;
  166. getOrderDetail();
  167. })
  168. onUnload(() => {
  169. timer = null;
  170. })
  171. </script>
  172. <style lang="scss" scoped>
  173. .order-detail {
  174. position: fixed;
  175. top: 0;
  176. left: 0;
  177. right: 0;
  178. bottom: 280rpx;
  179. overflow-y: auto;
  180. // padding: 12px 12px 24px;
  181. // background: rgba(245, 245, 245, 1);
  182. .order-card {
  183. border-radius: 8px;
  184. background: rgba(255, 255, 255, 1);
  185. padding: 12px;
  186. margin-bottom: 12px;
  187. }
  188. .font-title {
  189. margin-bottom: 12px;
  190. }
  191. .user-box {
  192. display: flex;
  193. .user-img {
  194. width: 65.8px;
  195. height: 65.8px;
  196. margin-right: 12px;
  197. }
  198. }
  199. .register-box {
  200. display: flex;
  201. margin-bottom: 12px;
  202. .register-img {
  203. width: 90px;
  204. height: 90px;
  205. margin-right: 12px;
  206. }
  207. }
  208. .info-list {
  209. flex: 1;
  210. font-size: 14px;
  211. font-weight: 500;
  212. letter-spacing: 0px;
  213. line-height: 23.27px;
  214. color: rgba(51, 51, 51, 1);
  215. }
  216. .price {
  217. font-size: 18px;
  218. font-weight: 500;
  219. color: rgba(246, 74, 31, 1);
  220. .price-yuan {
  221. font-size: 13px;
  222. font-weight: 700;
  223. color: rgba(246, 74, 31, 1);
  224. }
  225. }
  226. .upload-img {
  227. height: 68px;
  228. width: 68px;
  229. margin-right: 12px;
  230. margin-bottom: 12px;
  231. }
  232. .upload-box {
  233. display: flex;
  234. flex-wrap: wrap;
  235. .upload-img-item {
  236. position: relative;
  237. .delete-icon {
  238. position: absolute;
  239. top: -7px;
  240. right: 7px;
  241. z-index: 1;
  242. }
  243. }
  244. }
  245. .phone {
  246. color: #3c9cff;
  247. }
  248. }
  249. .handle-user {
  250. display: flex;
  251. align-items: center;
  252. justify-content: space-between;
  253. .handle-user-left {
  254. display: flex;
  255. align-items: center;
  256. .handle-user-info {
  257. .user-name {
  258. font-size: 32rpx;
  259. font-weight: 400;
  260. color: rgba(17, 24, 39, 1);
  261. }
  262. .user-id {
  263. font-size: 28rpx;
  264. font-weight: 400;
  265. color: rgba(107, 114, 128, 1);
  266. }
  267. }
  268. }
  269. .user-phone {
  270. display: flex;
  271. align-items: center;
  272. justify-content: center;
  273. width: 80rpx;
  274. height: 80rpx;
  275. border-radius: 50%;
  276. background: rgba(221, 94, 69, 1);
  277. }
  278. }
  279. .handle-adress {
  280. display: flex;
  281. align-items: center;
  282. justify-content: space-between;
  283. margin-top: 38rpx;
  284. .adress-text {
  285. flex: 1;
  286. text-align: left;
  287. padding-left: 24rpx;
  288. }
  289. }
  290. .handle-remark {
  291. margin-top: 30rpx;
  292. .remark-title {
  293. font-size: 28rpx;
  294. font-weight: 400;
  295. color: rgba(17, 24, 39, 1);
  296. margin-bottom: 20rpx;
  297. }
  298. .remark-text {
  299. border-radius: 16rpx;
  300. background: rgba(249, 250, 251, 1);
  301. padding: 32rpx;
  302. font-size: 32rpx;
  303. font-weight: 400;
  304. line-height: 48rpx;
  305. color: rgba(75, 85, 99, 1);
  306. }
  307. }
  308. .handle-start {
  309. margin-bottom: 30rpx;
  310. font-size: 32rpx;
  311. font-weight: 400;
  312. color: rgba(75, 85, 99, 1);
  313. text-align: center;
  314. .handle-time {
  315. font-size: 32rpx;
  316. font-weight: 400;
  317. color: rgba(17, 24, 39, 1);
  318. }
  319. }
  320. .footer-g {
  321. padding: 12px;
  322. position: absolute;
  323. bottom: 18px;
  324. left: 0px;
  325. right: 0px;
  326. background: rgba(255, 255, 255, 1);
  327. }
  328. </style>