Ver Fonte

feat: 实现Tracking详情页分享链接功能以及表格右键菜单从新tab页打开功能

zhouyuhao há 11 meses atrás
pai
commit
ff9e584de2

+ 12 - 4
src/styles/icons/iconfont.css

@@ -1,9 +1,9 @@
 @font-face {
   font-family: "font_family"; /* Project id 4672385 */
-  src: url('iconfont.woff2?t=1733995908700') format('woff2'),
-       url('iconfont.woff?t=1733995908700') format('woff'),
-       url('iconfont.ttf?t=1733995908700') format('truetype'),
-       url('iconfont.svg?t=1733995908700#font_family') format('svg');
+  src: url('iconfont.woff2?t=1736324058852') format('woff2'),
+       url('iconfont.woff?t=1736324058852') format('woff'),
+       url('iconfont.ttf?t=1736324058852') format('truetype'),
+       url('iconfont.svg?t=1736324058852#font_family') format('svg');
 }
 
 .font_family {
@@ -14,6 +14,14 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-icon_currentlink_b:before {
+  content: "\e6fc";
+}
+
+.icon-icon_jumplink_b1:before {
+  content: "\e6fd";
+}
+
 .icon-icon_arrow_b:before {
   content: "\e6fb";
 }

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
src/styles/icons/iconfont.js


+ 4 - 0
src/styles/icons/iconfont.svg

@@ -14,6 +14,10 @@
     />
       <missing-glyph />
       
+      <glyph glyph-name="icon_currentlink_b" unicode="&#59132;" d="M102.4 384a409.6 409.6 0 1 0 819.2 0A409.6 409.6 0 0 0 102.4 384zM512 870.4a486.4 486.4 0 1 1 0-972.8A486.4 486.4 0 0 1 512 870.4z m0-742.336a256 256 0 1 1 0 512 256 256 0 0 1 0-512z"  horiz-adv-x="1024" />
+      
+      <glyph glyph-name="icon_jumplink_b1" unicode="&#59133;" d="M636.416 633.28h-252.16v96h368a48 48 0 0 0 48-48v-368h-96v252.16l-370.56-370.624-67.904 67.84 370.56 370.624z m305.6-610.24h-832v96h832v-96z"  horiz-adv-x="1088" />
+      
       <glyph glyph-name="icon_arrow_b" unicode="&#59131;" d="M491.328 763.456a32 32 0 0 0 58.56 0L882.56 5.76a32 32 0 0 0-41.216-42.56l-308.8 123.52a32 32 0 0 1-23.744 0l-308.8-123.52a32 32 0 0 0-41.216 42.56L491.328 763.456z"  horiz-adv-x="1088" />
       
       <glyph glyph-name="icon_dark_b1" unicode="&#59129;" d="M7.616 738.432a38.4 38.4 0 0 0 38.4 38.4h622.08a38.4 38.4 0 0 0 38.4-38.4v-111.68h148.992a38.4 38.4 0 0 0 29.632-14.08l150.528-183.36a38.4 38.4 0 0 0 8.768-24.32v-289.088a38.4 38.4 0 0 0-38.4-38.4h-71.68a133.184 133.184 0 0 0-250.752 3.648 38.208 38.208 0 0 0-15.424-3.2H383.616a133.184 133.184 0 0 0-249.728 0H46.08a38.4 38.4 0 0 0-38.4 38.4v622.08z m698.88-529.792a133.184 133.184 0 0 0 232.832-54.4h28.288V391.296l-130.304 158.72H706.56v-341.312z m-76.8-53.888V700.032H84.48v-545.28h44.672a133.184 133.184 0 0 0 259.328 0h241.28zM358.72 443.776V566.784h-76.8v-161.408a38.4 38.4 0 0 1 38.4-38.4H526.08v76.8H358.656z m-99.904-263.04a56.32 56.32 0 1 1 0-112.768 56.32 56.32 0 0 1 0 112.704z m494.528-56.384a56.32 56.32 0 1 1 112.64 0 56.32 56.32 0 0 1-112.64 0z"  horiz-adv-x="1088" />

BIN
src/styles/icons/iconfont.ttf


BIN
src/styles/icons/iconfont.woff


BIN
src/styles/icons/iconfont.woff2


+ 12 - 4
src/styles/theme.scss

@@ -81,8 +81,6 @@
 
   --color-mune-active-bg: #fdf5f1;
 
-  --color-table-header-bg: #f8f9fd;
-
   --color-dialog-header-bg: #f6f8fa;
   --color-dialog-body-bg: #ffffff;
   --color-drawer-body-bg: #fff;
@@ -185,7 +183,7 @@
 
   --color-message-box-header-bg: #f6f8fa;
   --color-table-header-bg: #f8f9fd;
-  --color-table-click-row-bg: #ffe3cc;
+  --color-table-click-row-bg: #fff1e6;
 
   --color-download-file-filter-tag-bg: #eceef0;
   --color-download-file-selected-column-tag-bg: #eceef0;
@@ -222,6 +220,10 @@
 
   --color-container-status-node-bg: #f8f9fd;
 
+  --color-table-stripe-bg: #ffffff;
+  --color-table-row-hover-bg: #f2f2f2;
+
+  --color-share-link-bg: #f8f9fd;
   // 输入框禁用的颜色
   --input-disabled-bg-color: #f5f7fa;
   --input-disabled-text-color: #a8abb2;
@@ -295,6 +297,11 @@
   --color-btn-default-dark-hover-bg: #d56200;
 
   --color-btn-icon-bg: #3f434a;
+
+  --color-table-stripe-bg: #2b2f36;
+  --color-table-row-hover-bg: #3c4049;
+
+  --color-share-link-bg: #3a4149;
   // 滚动条
   --color-scrollbar-thumb: #656f7d;
 
@@ -361,6 +368,7 @@
   --vxe-ui-table-column-icon-border-color: #6a6d73;
   --color-table-header-bg: #30353c;
   --vxe-ui-table-header-background-color: #30353c;
-  --color-table-click-row-bg: #8b582f;
+  --color-table-click-row-bg: #403631;
   --vxe-ui-input-border-color: #656f7d;
+  --vxe-ui-table-menu-background-color: #3e454f;
 }

+ 42 - 2
src/styles/vxeTable.scss

@@ -18,7 +18,7 @@
 
 // 重置表格stripe样式
 .vxe-table--render-default tr.vxe-body--row.row--stripe {
-  background-color: var(--color-table-header-bg);
+  background-color: var(--color-table-stripe-bg);
 }
 .vxe-table--render-default .vxe-body--row.row--current {
   background-color: rgba(255, 117, 0, 0.2) !important;
@@ -68,7 +68,7 @@ div.vxe-table .vxe-sort--desc-btn.sort--active {
 }
 div.vxe-table--render-default tr.vxe-body--row.row--hover,
 .vxe-table--render-default tr.vxe-body--row.row--stripe.row--hover {
-  background-color: var(--border-hover-color);
+  background-color: var(--color-table-row-hover-bg);
 }
 div.vxe-table--render-default tr.vxe-body--row.vxe-table-row-clicked-style {
   background-color: var(--border-hover-color);
@@ -113,3 +113,43 @@ button.w-e-menu-tooltip-v5:before {
 button.w-e-menu-tooltip-v5:after {
   border: 0;
 }
+
+div.vxe-table--context-menu-wrapper {
+  padding: 8px;
+  border-radius: 12px;
+  box-shadow: 4px 4px 16px 0px rgba(0, 0, 0, 0.1);
+  border: none;
+  .vxe-context-menu--option-wrapper {
+    border: none;
+  }
+  li {
+    display: flex;
+    align-items: center;
+    height: 40px;
+    border: none;
+    border-radius: 6px;
+    .vxe-context-menu--link {
+      width: auto;
+      .vxe-context-menu--link-suffix {
+        display: none;
+      }
+      .vxe-context-menu--link-prefix {
+        i {
+          color: var(--color-neutral-1);
+        }
+      }
+    }
+    &.link--active {
+      background-color: var(--border-hover-color);
+
+      .vxe-context-menu--link-content {
+        color: var(--color-theme);
+      }
+      .vxe-context-menu--link-prefix {
+        i {
+          color: var(--color-theme);
+        }
+      }
+    }
+  }
+}

+ 30 - 1
src/views/Booking/src/components/BookingTable/src/BookingTable.vue

@@ -194,6 +194,19 @@ const bookingTable = ref<VxeGridProps<any>>({
   headerRowStyle: {
     backgroundColor: 'var(--color-table-header-bg)'
   },
+  menuConfig: {
+    body: {
+      options: [
+        [
+          {
+            code: 'newTab',
+            name: 'Open in New Tab',
+            prefixConfig: { icon: 'icon-icon_jumplink_b1 font_family' }
+          }
+        ]
+      ]
+    }
+  },
   sortConfig: {
     sortMethod: (params) => {
       const { data, sortList } = params
@@ -241,7 +254,7 @@ const bookingTable = ref<VxeGridProps<any>>({
     }
   },
   columnConfig: { resizable: true, useKey: true },
-  rowConfig: { isHover: true },
+  rowConfig: { isHover: true, isCurrent: true },
   exportConfig: {
     types: ['csv', 'html', 'txt', 'xlsx'],
     modes: ['current', 'selected', 'all']
@@ -415,6 +428,20 @@ const handleCheckAllChange = ({ records }: any) => {
   selectedNumber.value = records.length
   selectedTableData.value = records
 }
+
+// 表格右键点击事件
+const handleCurrentRow = (params) => {
+  tableRef.value?.setCurrentRow(params.row)
+}
+// 表格右键菜单点击事件
+const handleTableMenuClick = () => {
+  const curRow = tableRef.value?.getCurrentRecord()
+  window.open(
+    `${window.location.protocol}//${window.location.host}/tracking/detail?a=${curRow.__serial_no}&_schemas=${curRow._schemas}`,
+    '_blank'
+  )
+}
+
 defineExpose({
   searchTableData,
   getLoadingData,
@@ -455,6 +482,8 @@ defineExpose({
       @cell-dblclick="handleCellDblclick"
       @checkbox-change="handleCheckboxChange"
       @checkbox-all="handleCheckAllChange"
+      @menu-click="handleTableMenuClick"
+      @cell-menu="handleCurrentRow"
     >
       <!-- 空数据时的插槽 -->
       <template #empty v-if="!tableLoadingTable && bookingTable.data.length === 0">

+ 38 - 2
src/views/Tracking/src/components/PublicTracking/src/components/PublicTrackingDetail.vue

@@ -6,6 +6,7 @@ import { useRoute } from 'vue-router'
 import { useOverflow } from '@/hooks/useOverflow'
 import { useThemeStore } from '@/stores/modules/theme'
 import { formatTimezone } from '@/utils/tools'
+import ShareLinkDialog from './ShareLinkDialog.vue'
 
 const route = useRoute()
 
@@ -71,10 +72,21 @@ const originRef = ref()
 const destinationRef = ref()
 const { isOverflow: isOriginOverflow } = useOverflow(originRef, allData)
 const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allData)
+
+const dialogVModel = ref(false)
+const openShareDialog = () => {
+  dialogVModel.value = true
+}
 </script>
 
 <template>
   <div class="tracking-detail">
+    <!-- 分享链接 -->
+    <div class="share-link" @click="openShareDialog">
+      <el-tooltip content="Share" :offset="4">
+        <span class="font_family icon-icon_share_b share-icon"></span>
+      </el-tooltip>
+    </div>
     <div class="header" :class="{ 'is-dark': themeStore.theme === 'dark' }">
       <div class="detail-status">
         <span
@@ -82,8 +94,10 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
           :class="[`icon-${transportationMode?.[allData?.transportInfo?.mode]}`]"
           style="font-size: 64px"
         ></span>
-        <div class="no">Tracking No. {{ allData.transportInfo['Tracking No.'] }}</div>
-        <VTag large :type="allData.transportInfo?.status">{{ allData.transportInfo?.status }}</VTag>
+        <div class="no">Tracking No. {{ allData?.transportInfo['Tracking No.'] }}</div>
+        <VTag large :type="allData?.transportInfo?.status">{{
+          allData?.transportInfo?.status
+        }}</VTag>
       </div>
       <div class="detail-info">
         <div class="item transport-way">
@@ -172,6 +186,7 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
         </template>
       </VBox>
     </div>
+    <ShareLinkDialog v-model="dialogVModel"></ShareLinkDialog>
   </div>
 </template>
 
@@ -184,6 +199,7 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
   border-right: 1px solid var(--color-border);
 }
 .tracking-detail {
+  position: relative;
   padding-bottom: 16px;
   & > .header {
     background: linear-gradient(
@@ -294,6 +310,26 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
       }
     }
   }
+  .share-link {
+    position: fixed;
+    bottom: 152px;
+    right: 0px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 64px;
+    height: 64px;
+    z-index: 1500;
+    background-color: var(--management-bg-color);
+    box-shadow: -2px 2px 12px rgba(0, 0, 0, 0.15);
+    border-radius: 12px 0 0 12px;
+    &:hover {
+      background-color: var(--border-hover-color);
+    }
+    .share-icon {
+      font-size: 24px;
+    }
+  }
 }
 
 .info-content {

+ 110 - 0
src/views/Tracking/src/components/PublicTracking/src/components/ShareLinkDialog.vue

@@ -0,0 +1,110 @@
+<script setup lang="ts">
+const dialogVModel = defineModel('dialogVModel', {
+  type: Boolean,
+  default: false
+})
+
+const shareLink = computed(() => {
+  return `${window.location.href}`
+})
+
+// 是否已复制的标志
+const copied = ref(false)
+
+// 复制到剪贴板的函数
+const copyToClipboard = async () => {
+  try {
+    // 使用 navigator.clipboard.writeText() 复制文本
+    await navigator.clipboard.writeText(shareLink.value)
+    ElMessage.success('Copied to clipboard')
+    // 设置已复制标志
+    copied.value = true
+
+    // 一段时间后重置标志
+    setTimeout(() => {
+      copied.value = false
+    }, 2000)
+  } catch (err) {
+    ElMessage.error('Failed to copy')
+  }
+}
+</script>
+
+<template>
+  <el-dialog width="480" top="25vh" class="share-link-dialog" v-model="dialogVModel">
+    <div class="share-link-body">
+      <div class="title">
+        <img src="../images/share-link.png" />
+      </div>
+      <div class="tips">
+        <span>Copy the link to share this shipment with anyone.</span>
+      </div>
+      <div class="link">
+        <span>{{ shareLink }}</span>
+      </div>
+    </div>
+    <template #footer>
+      <el-button
+        style="width: 240px; height: 40px"
+        class="el-button--dark"
+        @click="copyToClipboard"
+      >
+        <span class="font_family icon-icon_text_links_b"></span>
+        <span style="margin-left: 4px">Copy Link</span>
+      </el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<style lang="scss" scoped>
+.share-link-body {
+  padding: 0 20px 8px;
+  .title {
+    text-align: center;
+    img {
+      width: 100px;
+    }
+  }
+  .tips {
+    margin-top: 10px;
+    text-align: center;
+    span {
+      color: var(--color-neutral-1);
+      font-size: 18px;
+      font-weight: 700;
+    }
+  }
+  .link {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 80px;
+    margin-top: 8px;
+    padding: 0 10px;
+    border-radius: 12px;
+    background-color: var(--color-share-link-bg);
+    span {
+      text-align: center;
+      color: var(--color-theme);
+      text-decoration: none;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.share-link-dialog {
+  button.el-dialog__headerbtn {
+    height: 64px;
+    width: 64px;
+  }
+  .el-dialog__header {
+    background-color: var(--color-dialog-body-bg);
+  }
+  .el-dialog__body {
+    padding-top: 0;
+  }
+  .el-dialog__footer {
+    text-align: center;
+  }
+}
+</style>

BIN
src/views/Tracking/src/components/PublicTracking/src/images/share-link.png


+ 37 - 4
src/views/Tracking/src/components/TrackingDetail/src/TrackingDetail.vue

@@ -15,6 +15,7 @@ import { useRoute } from 'vue-router'
 import { useOverflow } from '@/hooks/useOverflow'
 import { formatTimezone } from '@/utils/tools'
 import { useThemeStore } from '@/stores/modules/theme'
+import ShareLinkDialog from './components/ShareLinkDialog.vue'
 
 const route = useRoute()
 
@@ -78,9 +79,6 @@ const handleDraggable = (type: string, id: number) => {
 }
 
 const emailDrawerRef = ref()
-const handleEmailDrawer = () => {
-  emailDrawerRef.value.openDrawer(allData.value)
-}
 
 const AMSISFDrawerRef = ref()
 const handleAMSISF = () => {
@@ -112,10 +110,21 @@ const originRef = ref()
 const destinationRef = ref()
 const { isOverflow: isOriginOverflow } = useOverflow(originRef, allData)
 const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allData)
+
+const dialogVModel = ref(false)
+const openShareDialog = () => {
+  dialogVModel.value = true
+}
 </script>
 
 <template>
   <div class="tracking-detail" v-vloading="loading">
+    <!-- 分享链接 -->
+    <div class="share-link" @click="openShareDialog">
+      <el-tooltip content="Share" :offset="4">
+        <span class="font_family icon-icon_share_b share-icon"></span>
+      </el-tooltip>
+    </div>
     <div class="header" :class="{ 'is-dark': themeStore.theme === 'dark' }">
       <div class="detail-status">
         <span
@@ -287,8 +296,11 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
       </VueDraggable>
       <EmailDrawer @sendEmailSuccess="getData" :data="allData" ref="emailDrawerRef"></EmailDrawer>
     </div>
-
     <AMSISFDrawer ref="AMSISFDrawerRef"></AMSISFDrawer>
+    <ShareLinkDialog
+      v-model="dialogVModel"
+      :searchNo="allData?.basicInfo?.['HAWB/HBOL']"
+    ></ShareLinkDialog>
   </div>
 </template>
 
@@ -301,6 +313,7 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
   border-right: 1px solid var(--color-border);
 }
 .tracking-detail {
+  position: relative;
   padding-bottom: 16px;
   & > .header {
     background: linear-gradient(
@@ -430,6 +443,26 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
     margin-bottom: 8px;
     padding: 0 24px;
   }
+  .share-link {
+    position: fixed;
+    bottom: 152px;
+    right: 0px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 64px;
+    height: 64px;
+    z-index: 1500;
+    background-color: var(--management-bg-color);
+    box-shadow: -2px 2px 12px rgba(0, 0, 0, 0.15);
+    border-radius: 12px 0 0 12px;
+    &:hover {
+      background-color: var(--border-hover-color);
+    }
+    .share-icon {
+      font-size: 24px;
+    }
+  }
 }
 
 .ghost-class {

+ 115 - 0
src/views/Tracking/src/components/TrackingDetail/src/components/ShareLinkDialog.vue

@@ -0,0 +1,115 @@
+<script setup lang="ts">
+const dialogVModel = defineModel('dialogVModel', {
+  type: Boolean,
+  default: false
+})
+const props = defineProps({
+  searchNo: {
+    type: String,
+    default: ''
+  }
+})
+const shareLink = computed(() => {
+  return `${window.location.protocol}//${window.location.host}/public-tracking/detail?searchNo=${props.searchNo || ''}`
+})
+
+// 是否已复制的标志
+const copied = ref(false)
+
+// 复制到剪贴板的函数
+const copyToClipboard = async () => {
+  try {
+    // 使用 navigator.clipboard.writeText() 复制文本
+    await navigator.clipboard.writeText(shareLink.value)
+    ElMessage.success('Copied to clipboard')
+    // 设置已复制标志
+    copied.value = true
+
+    // 一段时间后重置标志
+    setTimeout(() => {
+      copied.value = false
+    }, 2000)
+  } catch (err) {
+    ElMessage.error('Failed to copy')
+  }
+}
+</script>
+
+<template>
+  <el-dialog width="480" top="25vh" class="share-link-dialog" v-model="dialogVModel">
+    <div class="share-link-body">
+      <div class="title">
+        <img src="../images/share-link.png" />
+      </div>
+      <div class="tips">
+        <span>Copy the link to share this shipment with anyone.</span>
+      </div>
+      <div class="link">
+        <span>{{ shareLink }}</span>
+      </div>
+    </div>
+    <template #footer>
+      <el-button
+        style="width: 240px; height: 40px"
+        class="el-button--dark"
+        @click="copyToClipboard"
+      >
+        <span class="font_family icon-icon_text_links_b"></span>
+        <span style="margin-left: 4px">Copy Link</span>
+      </el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<style lang="scss" scoped>
+.share-link-body {
+  padding: 0 20px 8px;
+  .title {
+    text-align: center;
+    img {
+      width: 100px;
+    }
+  }
+  .tips {
+    margin-top: 10px;
+    text-align: center;
+    span {
+      color: var(--color-neutral-1);
+      font-size: 18px;
+      font-weight: 700;
+    }
+  }
+  .link {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 80px;
+    margin-top: 8px;
+    padding: 0 10px;
+    border-radius: 12px;
+    background-color: var(--color-share-link-bg);
+    span {
+      text-align: center;
+      color: var(--color-theme);
+      text-decoration: none;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.share-link-dialog {
+  button.el-dialog__headerbtn {
+    height: 64px;
+    width: 64px;
+  }
+  .el-dialog__header {
+    background-color: var(--color-dialog-body-bg);
+  }
+  .el-dialog__body {
+    padding-top: 0;
+  }
+  .el-dialog__footer {
+    text-align: center;
+  }
+}
+</style>

BIN
src/views/Tracking/src/components/TrackingDetail/src/images/share-link.png


+ 29 - 16
src/views/Tracking/src/components/TrackingTable/src/TrackingTable.vue

@@ -268,13 +268,19 @@ const trackingTable = ref<any>({
   headerRowStyle: {
     backgroundColor: 'var(--color-table-header-bg)'
   },
-  // menuConfig: {
-  //   body: {
-  //     options: [
-  //       [{ code: 'custom3', name: 'Open in New Tab', prefixConfig: { icon: 'vxe-icon-download' } }]
-  //     ]
-  //   }
-  // },
+  menuConfig: {
+    body: {
+      options: [
+        [
+          {
+            code: 'newTab',
+            name: 'Open in New Tab',
+            prefixConfig: { icon: 'icon-icon_jumplink_b1 font_family' }
+          }
+        ]
+      ]
+    }
+  },
   sortConfig: {
     sortMethod: (params) => {
       const { data, sortList } = params
@@ -322,7 +328,7 @@ const trackingTable = ref<any>({
     }
   },
   columnConfig: { resizable: true, useKey: true },
-  rowConfig: { isHover: true },
+  rowConfig: { isHover: true, isCurrent: true },
   exportConfig: {
     types: ['csv', 'html', 'txt', 'xlsx'],
     modes: ['current', 'selected', 'all']
@@ -512,20 +518,25 @@ const handleVGM = (row) => {
 
 const loadingState = useLoadingState()
 
+// 表格右键点击事件
+const handleCurrentRow = (params) => {
+  tableRef.value?.setCurrentRow(params.row)
+}
+// 表格右键菜单点击事件
+const handleTableMenuClick = () => {
+  const curRow = tableRef.value?.getCurrentRecord()
+  window.open(
+    `${window.location.protocol}//${window.location.host}/tracking/detail?a=${curRow.__serial_no}&_schemas=${curRow._schemas}`,
+    '_blank'
+  )
+}
+
 defineExpose({
   searchTableData,
   getSharedTableData,
   getLoadingData,
   pageInfo
 })
-
-// const test1 = (params) => {
-//   console.log(params, '12223')
-//   window.open(
-//     `http://localhost/k_new_online/tracking/detail?a=${params.row.__serial_no}&_schemas=${params.row._schemas}`,
-//     '_blank'
-//   )
-// }
 </script>
 
 <template>
@@ -562,6 +573,8 @@ defineExpose({
       @cell-dblclick="handleCellDblclick"
       @checkbox-change="handleCheckboxChange"
       @checkbox-all="handleCheckAllChange"
+      @menu-click="handleTableMenuClick"
+      @cell-menu="handleCurrentRow"
     >
       <!-- 空数据时的插槽 -->
       <template #empty v-if="!tableLoadingTable && trackingTable.data.length === 0">

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff