Browse Source

feat: Shipment Status部分内容新增delivered info

Jack Zhou 1 month ago
parent
commit
4703d3dfd2
1 changed files with 177 additions and 4 deletions
  1. 177 4
      src/components/ShipmentStatus/src/ShipmentStatus.vue

+ 177 - 4
src/components/ShipmentStatus/src/ShipmentStatus.vue

@@ -22,6 +22,34 @@ watch(
   }
   }
 )
 )
 
 
+const isShowDeliveryInfo = ref(false)
+const deliveredInfoRef = ref()
+const simplexContentRef = ref()
+const handleSeeAllDeliveryInfo = () => {
+  nextTick(() => {
+    console.log('isShowDeliveryInfo', deliveredInfoRef.value)
+    // if (deliveredInfoRef.value) {
+    //   deliveredInfoRef.value[0]?.scrollIntoView({ behavior: 'smooth' })
+    // }
+    if (!simplexContentRef.value || !deliveredInfoRef.value) return
+    console.log('simplexContentRef', simplexContentRef.value)
+    console.log('deliveredInfoRef', deliveredInfoRef.value)
+    // 4. 计算滚动位置
+    // 获取子元素相对于父容器顶部的位置
+    const parentRect = simplexContentRef.value.getBoundingClientRect()
+    const childRect = deliveredInfoRef.value[0].getBoundingClientRect()
+
+    // 计算需要滚动的距离
+    // 子元素顶部 - 父容器顶部 - 20px(你想要的偏移量)
+    const scrollTop = simplexContentRef.value.scrollTop + (childRect.top - parentRect.top) - 30
+
+    // 5. 执行滚动(只在父容器内)
+    simplexContentRef.value.scrollTo({
+      top: scrollTop,
+      behavior: 'smooth'
+    })
+  })
+}
 // 中间点 每两个节点之间加上26px  上边距离28px 下边距离54px  如果没有中间点则高度为56px
 // 中间点 每两个节点之间加上26px  上边距离28px 下边距离54px  如果没有中间点则高度为56px
 const getSimplexLineHeight = (index: number) => {
 const getSimplexLineHeight = (index: number) => {
   if (index === 0) {
   if (index === 0) {
@@ -30,17 +58,34 @@ const getSimplexLineHeight = (index: number) => {
     return 28 + 56 + 26 * (index - 1)
     return 28 + 56 + 26 * (index - 1)
   }
   }
 }
 }
+const getDeliverySimplexHeight = (stepItem) => {
+  let curHeight = 0
+  curHeight = 28 + 26 * (stepItem.children?.length > 0 ? stepItem.children.length - 1 : 0)
+  // if (!stepItem.deliveredData?.length) return curHeight
+  // curHeight =
+  //   curHeight + 90 * stepItem.deliveredData?.length + 8 * (stepItem.deliveredData?.length - 1)
+  return curHeight
+}
+const getDeliverySimplexLineHeight = (stepItem) => {
+  if (!stepItem.children?.length) return 0
+  return 28 + 26 * (stepItem.children.length - 1)
+}
+
+const getDeliveryInfoTop = (stepItem) => {
+  if (!stepItem.children?.length) return 0
+  return 30 + 26 * stepItem.children.length
+}
+
 const getDateHeight = (index: number) => {
 const getDateHeight = (index: number) => {
   return 42 + 26 * index
   return 42 + 26 * index
 }
 }
-
 const pathRef = ref()
 const pathRef = ref()
 
 
 const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
 const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="simplex-content">
+  <div class="simplex-content" ref="simplexContentRef">
     <div
     <div
       class="detail-step-item"
       class="detail-step-item"
       :class="{
       :class="{
@@ -73,6 +118,49 @@ const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
             <div class="label">{{ dateItem.label }}</div>
             <div class="label">{{ dateItem.label }}</div>
             <div class="divider"></div>
             <div class="divider"></div>
             <div class="date">{{ formatTimezone(dateItem.date) }}</div>
             <div class="date">{{ formatTimezone(dateItem.date) }}</div>
+            <!-- <el-button
+              @click="isShowDeliveryInfo = !isShowDeliveryInfo"
+              v-if="dateItem.label === 'Delivered'"
+              class="see-all-icon el-button--text"
+            >
+              See All
+              <span class="font_family icon-icon_next_b"></span>
+            </el-button> -->
+            <see-all-icon
+              v-if="dateItem.label === 'Delivered'"
+              v-model="isShowDeliveryInfo"
+              @collapse="handleSeeAllDeliveryInfo"
+            ></see-all-icon>
+          </div>
+          <div
+            :style="{ top: getDeliveryInfoTop(stepItem) + 'px' }"
+            class="delivered-info"
+            style="scroll-margin-top: 20px"
+            v-if="stepItem.label === 'Place of Delivery' && isShowDeliveryInfo"
+            ref="deliveredInfoRef"
+          >
+            <div
+              class="delivered-item"
+              v-for="(deliveredItem, deliveredIndex) in stepItem.deliveredData"
+              :key="deliveredIndex"
+            >
+              <div class="top">
+                <div class="top-left">
+                  <div class="label">{{ deliveredItem.label }}</div>
+                  <div class="date">
+                    {{ formatTimezone(deliveredItem.date, deliveredItem.timezone) }}
+                  </div>
+                </div>
+                <div class="top-right">{{ deliveredItem.location }}</div>
+              </div>
+              <div class="bottom">
+                <span class="font_family icon-icon_container_b"></span>
+                <div style="margin-top: 1px; margin-left: 4px">Container:</div>
+                <div style="margin-left: 4px; margin-top: 3px; font-weight: 700">
+                  {{ deliveredItem.container }}
+                </div>
+              </div>
+            </div>
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
@@ -81,6 +169,22 @@ const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
         v-if="stepItem.label !== 'Place of Delivery'"
         v-if="stepItem.label !== 'Place of Delivery'"
         :style="{ height: getSimplexLineHeight(stepItem.children?.length || 0) + 'px' }"
         :style="{ height: getSimplexLineHeight(stepItem.children?.length || 0) + 'px' }"
       ></div>
       ></div>
+      <div
+        class="place-of-delivery-line"
+        v-if="stepItem.label === 'Place of Delivery'"
+        :style="{ height: getDeliverySimplexHeight(stepItem) + 'px' }"
+      >
+        <div
+          class="dashed-line"
+          :style="{
+            height: getDeliverySimplexLineHeight(stepItem) + 'px',
+            borderStyle: stepItem.isArrival ? 'solid' : 'dashed',
+            borderColor: stepItem.isArrival
+              ? 'var(--color-neutral-2)'
+              : 'var(--color-shipment-status-label-bg)'
+          }"
+        ></div>
+      </div>
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>
@@ -88,8 +192,11 @@ const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 // 单式样式
 // 单式样式
 .simplex-content {
 .simplex-content {
+  position: relative;
   width: 100%;
   width: 100%;
-  padding: 24px 8px 9px 16px;
+  height: 100%;
+  overflow: auto;
+  padding: 24px 8px 24px 16px;
 }
 }
 .detail-step-item {
 .detail-step-item {
   & > .data {
   & > .data {
@@ -164,6 +271,7 @@ const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
         gap: 8px;
         gap: 8px;
         width: calc(100% + 20px);
         width: calc(100% + 20px);
         .label {
         .label {
+          margin-left: 3px;
           font-weight: 700;
           font-weight: 700;
         }
         }
         .divider {
         .divider {
@@ -175,14 +283,79 @@ const { isOverflow: isPathOverflow } = useOverflow(pathRef, props)
         .date {
         .date {
           font-size: 12px;
           font-size: 12px;
         }
         }
+        :deep(.see-all-icon) {
+          width: 52px;
+          height: 24px;
+          padding-top: 3px;
+          span {
+            font-size: 12px;
+          }
+          .btn {
+            margin-left: 2px;
+          }
+        }
+      }
+      .delivered-info {
+        position: absolute;
+        margin-top: 8px;
+        width: 100%;
+        .delivered-item {
+          width: 100%;
+          margin-bottom: 8px;
+          border-radius: 6px;
+          background: var(--color-table-header-bg);
+          &:last-child {
+            margin-bottom: 20px;
+          }
+          .top {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            height: 58px;
+            border-bottom: 1px solid var(--color-border);
+            .top-left {
+              flex: 1;
+              display: flex;
+              flex-direction: column;
+              gap: 4px;
+              padding: 8px;
+              border-right: 1px solid var(--color-border);
+              .label {
+                font-weight: 700;
+              }
+              .date {
+                font-size: 12px;
+              }
+            }
+            .top-right {
+              padding: 0 23px;
+              text-align: center;
+              font-weight: 700;
+              color: var(--color-neutral-1);
+            }
+          }
+          .bottom {
+            display: flex;
+            align-items: center;
+            height: 32px;
+            padding: 8px;
+          }
+        }
       }
       }
     }
     }
   }
   }
   & > .line {
   & > .line {
-    height: 72px;
     margin-left: 7px;
     margin-left: 7px;
     border-left: 1px solid var(--color-neutral-1);
     border-left: 1px solid var(--color-neutral-1);
   }
   }
+  & > .place-of-delivery-line {
+    margin-left: 7px;
+    // border-left: 1px dashed var(--color-neutral-3);
+    .dashed-line {
+      height: 50px;
+      border-left: 1px dashed var(--color-neutral-2);
+    }
+  }
   &.last {
   &.last {
     & > .data {
     & > .data {
       .left-step-icon {
       .left-step-icon {