recordDetail.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <template>
  2. <div class="store-page">
  3. <Breadcrumb />
  4. <a-card title="记录详情">
  5. <a-skeleton animation :loading="loading">
  6. <StoreRecordSkeleton />
  7. <template #content>
  8. <a-descriptions
  9. :data="info"
  10. :column="isMobile ? 1 : 2"
  11. class="record-descriptions"
  12. />
  13. <MapContainer v-if="showMap" :point_list="data.result.point_list" :log_list="data.point_data" :pathData="data.data" threeD
  14. style="margin-top: 10px;" />
  15. </template>
  16. </a-skeleton>
  17. </a-card>
  18. </div>
  19. </template>
  20. <script setup>
  21. import { ref, onMounted, onUnmounted } from 'vue'
  22. import { adminGetRecordDetail } from '@/api/lepao'
  23. import { Notification } from '@arco-design/web-vue'
  24. import { useRoute } from 'vue-router'
  25. import MapContainer from '@/components/Map/MapContainer.vue'
  26. import StoreRecordSkeleton from '@/components/skeleton/StoreRecordSkeleton.vue'
  27. const route = useRoute()
  28. const uuidLike = /^[0-9a-fA-F-]{16,}$/
  29. const loading = ref(false)
  30. const showMap = ref(false)
  31. const data = ref({})
  32. const info = ref([])
  33. const isMobile = ref(false)
  34. let mobileResizeHandler = null
  35. const GetRecordDetail = async (routeId) => {
  36. try {
  37. loading.value = true
  38. showMap.value = false
  39. const raw = decodeURIComponent(String(routeId || ''))
  40. const payload = uuidLike.test(raw)
  41. ? { public_id: raw }
  42. : { id: raw }
  43. const res = await adminGetRecordDetail(payload)
  44. if (!res || res.code !== 0)
  45. return Notification.error({
  46. title: '获取路径数据失败!',
  47. content: res?.msg ?? '请稍后再试'
  48. })
  49. data.value = res.data
  50. showMap.value = true
  51. info.value = [
  52. { label: '账号名称', value: res.data.name },
  53. { label: '乐跑账号', value: res.data.lepao_account },
  54. { label: '乐跑类型', value: res.data.run_mode === 'manual' ? '手动乐跑' : '自动乐跑' },
  55. { label: '跑区名称', value: res.data.result.pass_tit },
  56. { label: '路线ID', value: res.data.path_id },
  57. { label: '记录时间', value: stramptoTime(res.data.time) },
  58. { label: '开始时间', value: stramptoTime(res.data.result.start_time * 1000) },
  59. { label: '乐跑状态', value: res.data.result.record_failed_reason },
  60. { label: '打卡点数量', value: res.data.result.point_list.length },
  61. { label: '跑步距离', value: res.data.result.distance + ' Km' },
  62. { label: '跑步时长', value: formatSecondsToMinSec(res.data.result.time) },
  63. { label: '平均配速', value: calculatePace(res.data.result.time, res.data.result.distance) }
  64. ]
  65. } catch (error) {
  66. Notification.error({
  67. title: '获取路径数据失败!',
  68. content: error.message || '请稍后再试'
  69. })
  70. } finally {
  71. loading.value = false
  72. }
  73. }
  74. onMounted(() => {
  75. mobileResizeHandler = () => {
  76. isMobile.value = window.innerWidth <= 768
  77. }
  78. mobileResizeHandler()
  79. window.addEventListener('resize', mobileResizeHandler)
  80. GetRecordDetail(route.params.id)
  81. })
  82. onUnmounted(() => {
  83. if (mobileResizeHandler) window.removeEventListener('resize', mobileResizeHandler)
  84. })
  85. const stramptoTime = (time) => {
  86. return new Date(time).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })
  87. }
  88. function calculatePace(seconds, kilometers) {
  89. const paceInSeconds = seconds / kilometers;
  90. const minutes = Math.floor(paceInSeconds / 60);
  91. const remainingSeconds = Math.round(paceInSeconds % 60);
  92. return `${minutes}'${remainingSeconds.toString().padStart(2, '0')}''`;
  93. }
  94. function formatSecondsToMinSec(totalSeconds) {
  95. const minutes = Math.floor(totalSeconds / 60);
  96. const seconds = totalSeconds % 60;
  97. return `${minutes}分${seconds.toString().padStart(2, '0')}秒`;
  98. }
  99. </script>
  100. <style scoped lang="less">
  101. .record-descriptions {
  102. margin-top: 8px;
  103. }
  104. @media (max-width: 768px) {
  105. .record-descriptions :deep(.arco-descriptions-item-label) {
  106. white-space: nowrap;
  107. width: 88px !important;
  108. }
  109. .record-descriptions :deep(.arco-descriptions-item-value) {
  110. white-space: nowrap;
  111. overflow: hidden;
  112. text-overflow: ellipsis;
  113. }
  114. }
  115. </style>