workorder-item.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <template>
  2. <view class="workorder-card" @tap="handleClick">
  3. <view class="edit-icon">
  4. <u-icon name="edit-pen" color="#1b77f0" size="18"></u-icon>
  5. </view>
  6. <view class="content">
  7. <u-image :src="imgSrc" width="160rpx" height="190rpx" radius="8" mode="aspectFill" @click="previewImage"></u-image>
  8. <view class="details">
  9. <view class="row">
  10. <text class="label">快递单号:</text>
  11. <text class="value">{{ item.waybillCode || '-' }}</text>
  12. </view>
  13. <view class="row">
  14. <text class="label">任务类型:</text>
  15. <text class="value">{{ item.taskTypeName || item.taskType || '-' }}</text>
  16. </view>
  17. <view class="row">
  18. <text class="label">创建时间:</text>
  19. <text class="value">{{ item.createTime || '-' }}</text>
  20. </view>
  21. <view class="row" v-if="showDuration">
  22. <text class="label danger">处理时长:</text>
  23. <text class="value danger">{{ durationText }}</text>
  24. </view>
  25. </view>
  26. </view>
  27. </view>
  28. </template>
  29. <script setup name="workorderItem">
  30. import { computed, ref, onMounted, onUnmounted } from 'vue'
  31. const emit = defineEmits(['click'])
  32. const props = defineProps({
  33. item: {
  34. type: Object,
  35. default: () => ({})
  36. },
  37. showDuration: {
  38. type: Boolean,
  39. default: false
  40. }
  41. })
  42. const currentTime = ref(Date.now())
  43. // 每秒更新当前时间
  44. let timer = null
  45. onMounted(() => {
  46. timer = setInterval(() => {
  47. currentTime.value = Date.now()
  48. }, 100)
  49. })
  50. onUnmounted(() => {
  51. if (timer) {
  52. clearInterval(timer)
  53. }
  54. })
  55. const imgSrc = computed(() => {
  56. // 优先使用 imgInfo.imgUrlList
  57. if (props.item.imgInfo && props.item.imgInfo.imgUrlList && props.item.imgInfo.imgUrlList[0]) {
  58. return props.item.imgInfo.imgUrlList[0]
  59. }
  60. // 然后使用其他图片字段
  61. return props.item.imgUrl || props.item.imageUrl || props.item.imgPath || '/static/img/book.png'
  62. })
  63. const durationText = computed(() => {
  64. // 计算创建时间到当前时间的差值
  65. const createTime = new Date(props.item.createTime).getTime()
  66. if (!createTime) return '0 小时 0 分 0 秒 0'
  67. const diff = Math.max(0, currentTime.value - createTime)
  68. const ms = diff % 1000
  69. const s = Math.floor(diff / 1000)
  70. const h = Math.floor(s / 3600)
  71. const m = Math.floor((s % 3600) / 60)
  72. const ss = s % 60
  73. return `${h}小时${m}分${ss}秒${ms}`
  74. })
  75. const handleClick = () => {
  76. emit('click', props.item)
  77. }
  78. const previewImage = () => {
  79. // 优先使用 imgInfo.imgUrlList
  80. if (props.item.imgInfo && props.item.imgInfo.imgUrlList && props.item.imgInfo.imgUrlList.length > 0) {
  81. uni.previewImage({
  82. urls: props.item.imgInfo.imgUrlList,
  83. current: 0
  84. })
  85. } else if (imgSrc.value && imgSrc.value !== '/static/img/book.png') {
  86. uni.previewImage({
  87. urls: [imgSrc.value]
  88. })
  89. }
  90. }
  91. </script>
  92. <style lang="scss" scoped>
  93. .workorder-card {
  94. background: #ffffff;
  95. border-radius: 12rpx;
  96. padding: 20rpx;
  97. box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.04);
  98. position: relative;
  99. }
  100. .edit-icon {
  101. position: absolute;
  102. right: 16rpx;
  103. top: 16rpx;
  104. }
  105. .content {
  106. display: flex;
  107. gap: 20rpx;
  108. align-items: flex-start;
  109. }
  110. .details {
  111. flex: 1;
  112. }
  113. .row {
  114. display: flex;
  115. align-items: baseline;
  116. margin-bottom: 10rpx;
  117. }
  118. .label {
  119. font-size: 28rpx;
  120. color: #666666;
  121. }
  122. .value {
  123. font-size: 28rpx;
  124. color: #333333;
  125. }
  126. .danger {
  127. color: #ff4d4f;
  128. font-weight: 500;
  129. }
  130. </style>