浏览代码

Merge branch 'dev' into dev_g

AmandaG 4 月之前
父节点
当前提交
642b8a0f73

+ 76 - 0
src/api/module/Delivery.ts

@@ -198,4 +198,80 @@ export const SaveBookingList = (params: any, config: any) => {
     },
     },
     config
     config
   )
   )
+}
+
+/**
+ * 获取delivery booking表格数据
+ */
+export const getDeliveryBookingTableColumn = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_booking',
+      operate: 'destination_delivery_search',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取delivery booking表格数据
+ */
+export const getDeliveryBookingTableData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_booking',
+      operate: 'search',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取delivery booking dialog详情
+ */
+export const getDeliveryBookingDialogData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_booking',
+      operate: 'view_detail',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * delivery_booking 邮件留言Save
+ */
+export const saveDliveryBookingEmail = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_booking',
+      operate: 'email_message_board',
+      ...params
+    },
+    config
+  )
+}
+
+
+/**
+ * 审核delivery_booking
+ */
+export const reviewDliveryBooking = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_booking',
+      operate: 'review',
+      ...params
+    },
+    config
+  )
 }
 }

+ 6 - 2
src/components/NotificationMessageCard/src/NotificationMessageCard.vue

@@ -17,6 +17,7 @@ const props = withDefaults(
     updateReadCardsOnChange?: boolean // 是否在数据变化时请求接口更新已读卡片
     updateReadCardsOnChange?: boolean // 是否在数据变化时请求接口更新已读卡片
     topOffset?: number // 应减去高度
     topOffset?: number // 应减去高度
     isShowInsertionTime?: boolean // 是否显示插入时间
     isShowInsertionTime?: boolean // 是否显示插入时间
+    isDrawer?: boolean // 是否在抽屉中使用
   }>(),
   }>(),
   {
   {
     isObserver: true,
     isObserver: true,
@@ -213,7 +214,7 @@ const loadMore = async () => {
 
 
 const onScroll = () => {
 const onScroll = () => {
   const el = scrollContainerRef.value
   const el = scrollContainerRef.value
-  if (!el || loading.value || finished.value) return
+  if (!el || loading.value || finished.value || el.scrollTop === 0) return
 
 
   prevScrollTop.value = el.scrollTop + 50
   prevScrollTop.value = el.scrollTop + 50
 
 
@@ -264,6 +265,7 @@ defineExpose({
             @view-more="handleViewMore"
             @view-more="handleViewMore"
             v-else-if="item.notificationType === 'feature'"
             v-else-if="item.notificationType === 'feature'"
             :data="item.info"
             :data="item.info"
+            :is-drawer="props.isDrawer"
           />
           />
           <slot></slot>
           <slot></slot>
           <div class="insertion-time" v-if="isShowInsertionTime">
           <div class="insertion-time" v-if="isShowInsertionTime">
@@ -274,7 +276,9 @@ defineExpose({
     </template>
     </template>
     <div
     <div
       class="footer"
       class="footer"
-      v-if="pageData?.[0]?.notificationType !== 'feature' && pageData?.length > 0"
+      v-if="
+        (pageData?.[0]?.notificationType !== 'feature' && pageData?.length > 0) || props.isDrawer
+      "
     >
     >
       <el-divider v-if="loading"> loading... </el-divider>
       <el-divider v-if="loading"> loading... </el-divider>
       <el-divider v-if="finished && pageData.length > 0">
       <el-divider v-if="finished && pageData.length > 0">

+ 20 - 4
src/components/NotificationMessageCard/src/components/EventCard.vue

@@ -47,14 +47,15 @@ const props = defineProps<{
 }>()
 }>()
 
 
 const emit = defineEmits<{ seeAll: []; jumpTracking: [] }>()
 const emit = defineEmits<{ seeAll: []; jumpTracking: [] }>()
-const handleSeeAll = (data: EventCardPropsData) => {
+const handleSeeAll = (data: EventCardPropsData, numData) => {
   emit('seeAll')
   emit('seeAll')
   router.push({
   router.push({
     name: 'System Message Detail',
     name: 'System Message Detail',
     query: {
     query: {
       frequency_type: data.frequency_type,
       frequency_type: data.frequency_type,
       insert_date_format: data.insert_date_format,
       insert_date_format: data.insert_date_format,
-      rules_type: data.rules_type
+      rules_type: data.rules_type,
+      ...numData
     }
     }
   })
   })
 }
 }
@@ -80,7 +81,14 @@ const jumpTracking = (data: EventCardPropsData) => {
         v-if="(data.type === 'milestone' || data.type === 'container') && data.numericRecords"
         v-if="(data.type === 'milestone' || data.type === 'container') && data.numericRecords"
       >
       >
         <span>Latest Status Updates ({{ data.numericRecords }}) </span>
         <span>Latest Status Updates ({{ data.numericRecords }}) </span>
-        <el-button @click="handleSeeAll(data)" class="see-all-icon el-button--text">
+        <el-button
+          @click="
+            handleSeeAll(data, {
+              numericRecords: data.numericRecords
+            })
+          "
+          class="see-all-icon el-button--text"
+        >
           See All
           See All
           <span class="font_family icon-icon_next_b"></span>
           <span class="font_family icon-icon_next_b"></span>
         </el-button>
         </el-button>
@@ -101,7 +109,15 @@ const jumpTracking = (data: EventCardPropsData) => {
             }})
             }})
           </span>
           </span>
         </div>
         </div>
-        <el-button @click="handleSeeAll(data)" class="see-all-icon el-button--text">
+        <el-button
+          @click="
+            handleSeeAll(data, {
+              etdOrdeparturNum: data.info?.etdOrdeparturNum,
+              etaOrarrivalNum: data.info?.etaOrarrivalNum
+            })
+          "
+          class="see-all-icon el-button--text"
+        >
           See All
           See All
           <span class="font_family icon-icon_next_b"></span>
           <span class="font_family icon-icon_next_b"></span>
         </el-button>
         </el-button>

+ 26 - 6
src/components/NotificationMessageCard/src/components/FeatureUpdateCard.vue

@@ -14,6 +14,7 @@ interface FeatureUpdateCardPropsData {
 
 
 const props = defineProps<{
 const props = defineProps<{
   data: FeatureUpdateCardPropsData
   data: FeatureUpdateCardPropsData
+  isDrawer?: boolean // 是否在抽屉中使用
 }>()
 }>()
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
@@ -30,6 +31,14 @@ const handleViewMore = () => {
   })
   })
   emit('viewMore')
   emit('viewMore')
 }
 }
+
+const handleContent = (header) => {
+  if (header === 'New Feature: AI Smart Assistant') {
+    return 'Smart Assistant is live! Ask in natural language, get real-time shipment data with multi-language support.'
+  }else {
+    return 'Smart Notification is here! Four key event alerts with customizable rules and multi-channel delivery.'
+  }
+}
 </script>
 </script>
 
 
 <template>
 <template>
@@ -46,20 +55,31 @@ const handleViewMore = () => {
           <span class="gradient-text">{{ data.header }}</span>
           <span class="gradient-text">{{ data.header }}</span>
         </div>
         </div>
         <div class="content-text">
         <div class="content-text">
-          <span>{{ data.content }}</span>
+          <pre style="white-space: pre-wrap; line-height: 21px" v-if="props.isDrawer">{{ handleContent(data.header) }}</pre>
+          <pre style="white-space: pre-wrap; line-height: 21px" v-else>{{ data.content }}</pre>
         </div>
         </div>
-        <div class="feature-img">
-          <el-image :src="data.imgSrc" fit="contain" alt="feature-img"></el-image>
+        <div class="feature-img" style="text-align: center">
+          <img
+            :src="data.imgSrc"
+            style="max-height: 400px; max-width: 100%;object-fit: contain"
+            
+            alt="feature-img"
+          ></img>
+          <!-- <img
+            src="./img/testaa.png"
+            alt=""
+            style="max-height: 400px; max-width: 100%; object-fit: contain"
+          /> -->
         </div>
         </div>
 
 
         <div class="change-btn" style="text-align: center">
         <div class="change-btn" style="text-align: center">
-          <el-button
+          <!-- <el-button
             @click="handleViewMore"
             @click="handleViewMore"
             class="el-button--main"
             class="el-button--main"
             style="height: 40px; padding: 0 32px"
             style="height: 40px; padding: 0 32px"
           >
           >
             View more</el-button
             View more</el-button
-          >
+          > -->
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
@@ -95,7 +115,7 @@ const handleViewMore = () => {
     }
     }
   }
   }
   .card-content {
   .card-content {
-    padding: 16px 16px 24px 8px;
+    padding: 16px 16px 16px 8px;
     background: linear-gradient(
     background: linear-gradient(
       137deg,
       137deg,
       var(--color-feature-card-first-bg) 12.41%,
       var(--color-feature-card-first-bg) 12.41%,

+ 13 - 1
src/styles/vxeTable.scss

@@ -18,15 +18,24 @@
 
 
 // 重置表格stripe样式
 // 重置表格stripe样式
 .vxe-table--render-default tr.vxe-body--row.row--stripe {
 .vxe-table--render-default tr.vxe-body--row.row--stripe {
+  &>.vxe-body--column {
+    background-color: var(--color-table-stripe-bg) !important;
+  }
   background-color: var(--color-table-stripe-bg);
   background-color: var(--color-table-stripe-bg);
 }
 }
 .vxe-table--render-default tr.vxe-body--row.row--current,
 .vxe-table--render-default tr.vxe-body--row.row--current,
 .vxe-table--render-default tr.vxe-body--row.row--stripe.row--current {
 .vxe-table--render-default tr.vxe-body--row.row--stripe.row--current {
-  background-color: rgba(255, 117, 0, 0.2);
+  background-color: rgba(255, 117, 0, 0.2) ;
+  &>.vxe-body--column {
+  background-color: rgba(255, 117, 0, 0.2) ;
+  }
 }
 }
 .vxe-table--render-default .vxe-body--row.visited-row,
 .vxe-table--render-default .vxe-body--row.visited-row,
 .vxe-table--render-default .vxe-body--row.row--stripe.visited-row {
 .vxe-table--render-default .vxe-body--row.row--stripe.visited-row {
   background-color: var(--color-vxe-table-visited-row-bg);
   background-color: var(--color-vxe-table-visited-row-bg);
+   &>.vxe-body--column {
+  background-color: var(--color-vxe-table-visited-row-bg);
+  }
 }
 }
 
 
 .vxe-table--render-default .vxe-body--column.col--ellipsis,
 .vxe-table--render-default .vxe-body--column.col--ellipsis,
@@ -75,6 +84,9 @@ div.vxe-table--render-default tr.vxe-body--row.row--hover,
 div.vxe-table--render-default tr.vxe-body--row.row--hover.row--current,
 div.vxe-table--render-default tr.vxe-body--row.row--hover.row--current,
 .vxe-table--render-default tr.vxe-body--row.row--stripe.row--hover {
 .vxe-table--render-default tr.vxe-body--row.row--stripe.row--hover {
   background-color: var(--color-table-row-hover-bg);
   background-color: var(--color-table-row-hover-bg);
+  &>.vxe-body--column {
+    background-color: var(--color-table-row-hover-bg);
+  }
 }
 }
 div.vxe-table--render-default tr.vxe-body--row.vxe-table-row-clicked-style {
 div.vxe-table--render-default tr.vxe-body--row.vxe-table-row-clicked-style {
   background-color: var(--border-hover-color);
   background-color: var(--border-hover-color);

+ 87 - 65
src/views/DestinationDelivery/src/DestinationDelivery.vue

@@ -5,35 +5,33 @@ import DeliveryDate from './components/DeliveryDate.vue'
 import { useRouter } from 'vue-router'
 import { useRouter } from 'vue-router'
 
 
 const router = useRouter()
 const router = useRouter()
-const OperationSearch = ref()
 const filterRef: Ref<HTMLElement | null> = ref(null)
 const filterRef: Ref<HTMLElement | null> = ref(null)
 const containerHeight = useCalculatingHeight(document.documentElement, 376, [filterRef])
 const containerHeight = useCalculatingHeight(document.documentElement, 376, [filterRef])
-const searchData = ref({
-  inputModel: '',
-  startDate: '',
-  endDate: '',
-  userType: '',
-  questionType: '',
-  answerType: '',
-  answerSatisfaction: '',
-  comparator: 'thanOrEqual',
-  responseDuration: 0
+const queryData = ref({
+  text_search: '',
+  created_time_start: '',
+  created_time_end: '',
+  delivery_mode: '',
+  delivery_date_start: '',
+  delivery_date_end: '',
+  filterTag: ['ALL']
 })
 })
 
 
-const userTypeList = [
+const modeList = [
   {
   {
-    label: 'Customer',
-    value: 'customer'
+    label: 'Truck',
+    value: 'Truck'
   },
   },
   {
   {
-    label: 'Employee',
-    value: 'employee'
+    label: 'Rail',
+    value: 'Rail'
   }
   }
 ]
 ]
 
 
-const numberCards = [
+const numberCards = ref([
   {
   {
     label: 'Total Bookings',
     label: 'Total Bookings',
+    key: 'ALL',
     value: 0,
     value: 0,
     color: '#2b2f36'
     color: '#2b2f36'
   },
   },
@@ -61,15 +59,20 @@ const numberCards = [
     color: '#243041',
     color: '#243041',
     icon: 'icon_cancelled_b'
     icon: 'icon_cancelled_b'
   }
   }
-]
-const activeCard = ref(0)
-const clickCard = (index: number) => {
-  activeCard.value = index
+])
+const clickCard = (filterTagItem: string) => {
+  queryData.value.filterTag.pop()
+  queryData.value.filterTag.push(filterTagItem)
+  handleSearch()
 }
 }
 
 
 const DateChange = (date: any) => {
 const DateChange = (date: any) => {
-  searchData.value.startDate = date[0]
-  searchData.value.endDate = date[1]
+  queryData.value.created_time_start = date[0]
+  queryData.value.created_time_end = date[1]
+}
+const deliveryDataChange = (date) => {
+  queryData.value.delivery_date_start = date[0]
+  queryData.value.delivery_date_end = date[1]
 }
 }
 
 
 const handleConfigurations = () => {
 const handleConfigurations = () => {
@@ -79,13 +82,16 @@ const handleCreate = () => {
   router.push({ name: 'Create New Booking' })
   router.push({ name: 'Create New Booking' })
 }
 }
 
 
-const handleTest = () => {
-  // Handle test logic here
-  router.push({ name: 'Modify Booking' })
-}
-
 const DateStart = ref([])
 const DateStart = ref([])
 const tableRef = ref()
 const tableRef = ref()
+
+const setNumberCards = (cards) => {
+  numberCards.value = cards
+}
+
+const handleSearch = () => {
+  tableRef.value.SearchOperationLog()
+}
 </script>
 </script>
 <template>
 <template>
   <div class="destination-delivery">
   <div class="destination-delivery">
@@ -104,32 +110,34 @@ const tableRef = ref()
           <span style="margin-right: 4px" class="font_family icon-icon_add_b"></span>
           <span style="margin-right: 4px" class="font_family icon-icon_add_b"></span>
           <span style="font-weight: 400">Create New Booking</span>
           <span style="font-weight: 400">Create New Booking</span>
         </el-button>
         </el-button>
-
-        <el-button @click="handleTest">测试</el-button>
       </div>
       </div>
     </div>
     </div>
     <div class="display">
     <div class="display">
-      <div class="heaer_top">
-        <div class="date-tips_filter">
-          <CalendarDate @DateChange="DateChange"></CalendarDate>
+      <div class="header_top">
+        <div class="date-tips_filter filter-item">
+          <span class="label">Delivery Date:</span>
+          <DeliveryDate @DateChange="deliveryDataChange" :Date="DateStart" />
         </div>
         </div>
-        <div class="tips_filter">
-          <el-select v-model="searchData.userType" placeholder="User Type">
+
+        <div class="tips_filter filter-item">
+          <span class="label">Delivery Mode:</span>
+          <el-select v-model="queryData.delivery_mode" placeholder="" clearable>
             <el-option
             <el-option
-              v-for="item in userTypeList"
+              v-for="item in modeList"
               :key="item.value"
               :key="item.value"
               :label="item.label"
               :label="item.label"
               :value="item.value"
               :value="item.value"
             />
             />
           </el-select>
           </el-select>
         </div>
         </div>
-        <div class="date-tips_filter">
-          <DeliveryDate :Date="DateStart" />
+        <div class="date-tips_filter filter-item">
+          <span class="label">Creation Date</span>
+          <CalendarDate @DateChange="DateChange"></CalendarDate>
         </div>
         </div>
-        <div class="input-tips_filter">
+        <div class="input-tips_filter filter-item">
           <el-input
           <el-input
-            placeholder="Search Question ID、User"
-            v-model="OperationSearch"
+            placeholder="Search Question Booking No、HBOL No、MBL No、Container No、Consignee"
+            v-model="queryData.text_search"
             class="log_input"
             class="log_input"
           >
           >
             <template #prefix>
             <template #prefix>
@@ -141,13 +149,17 @@ const tableRef = ref()
             </template>
             </template>
           </el-input>
           </el-input>
         </div>
         </div>
-        <el-button class="el-button--dark">Search</el-button>
+        <el-button class="el-button--dark" @click="handleSearch">Search</el-button>
       </div>
       </div>
       <div class="number-cards">
       <div class="number-cards">
         <div
         <div
           class="card"
           class="card"
-          :class="{ 'is-active': index === activeCard }"
-          @click="clickCard(index)"
+          :class="{
+            'is-active':
+              queryData.filterTag.includes(item.key as string | undefined) ||
+              queryData.filterTag.includes(item.label)
+          }"
+          @click="clickCard((item.key || item.label) as string)"
           v-for="(item, index) in numberCards"
           v-for="(item, index) in numberCards"
           :key="index"
           :key="index"
         >
         >
@@ -166,7 +178,12 @@ const tableRef = ref()
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
-    <TableView :height="containerHeight" ref="tableRef"></TableView>
+    <TableView
+      @get-number-cards="setNumberCards"
+      :height="containerHeight"
+      :queryData="queryData"
+      ref="tableRef"
+    ></TableView>
   </div>
   </div>
 </template>
 </template>
 
 
@@ -181,11 +198,11 @@ const tableRef = ref()
   align-items: center;
   align-items: center;
   justify-content: space-between;
   justify-content: space-between;
 }
 }
-.heaer_top {
-  margin-top: 6.57px;
+.header_top {
   margin-bottom: 8px;
   margin-bottom: 8px;
   padding-right: 8px;
   padding-right: 8px;
   display: flex;
   display: flex;
+  align-items: flex-end;
 }
 }
 .number-cards {
 .number-cards {
   display: flex;
   display: flex;
@@ -248,35 +265,40 @@ const tableRef = ref()
   height: 32px;
   height: 32px;
   background-color: var(--color-mode) !important;
   background-color: var(--color-mode) !important;
 }
 }
-.tips_filter {
+.filter-item {
   flex: 1;
   flex: 1;
-  height: 30px;
-  max-width: 170px;
+  display: flex;
+  flex-direction: column;
+  align-items: flex-end;
+  justify-content: flex-end;
   margin-right: 8px;
   margin-right: 8px;
+  .label {
+    align-self: flex-start;
+    font-size: 12px;
+    margin-bottom: 3px;
+  }
+}
+.tips_filter {
+  min-width: 170px;
+  max-width: 220px;
 }
 }
 .input-tips_filter {
 .input-tips_filter {
-  flex: 1;
-  max-width: 320px;
-  height: 32px;
-  margin-right: 8px;
+  max-width: 540px;
   :deep(.el-input__wrapper) {
   :deep(.el-input__wrapper) {
     height: 32px;
     height: 32px;
+    input {
+      width: 100%;
+      white-space: nowrap; /* 防止换行 */
+      overflow: hidden; /* 超出部分隐藏 */
+      text-overflow: ellipsis; /* 超出部分显示为省略号 */
+    }
   }
   }
 }
 }
 .date-tips_filter {
 .date-tips_filter {
-  flex: 1;
   max-width: 250px;
   max-width: 250px;
-  height: 32px;
-  margin-right: 8px;
-}
-.comparator-tips_filter {
-  flex: 1;
-  display: flex;
-  align-items: center;
-  max-width: 260px;
-  height: 32px;
-  margin-right: 8px;
+  height: 56px;
 }
 }
+
 .destination-delivery {
 .destination-delivery {
   position: relative;
   position: relative;
   background-color: var(--color-mode);
   background-color: var(--color-mode);

+ 2 - 6
src/views/DestinationDelivery/src/components/DeliveryDate.vue

@@ -37,7 +37,7 @@ watch(
   { immediate: true, deep: true }
   { immediate: true, deep: true }
 )
 )
 
 
-const testDate = {
+const stateDataList = {
   '2025-06-01': {
   '2025-06-01': {
     pending: 3,
     pending: 3,
     approved: 3
     approved: 3
@@ -48,7 +48,7 @@ const testDate = {
   }
   }
 }
 }
 const isShowStatus = (date: string) => {
 const isShowStatus = (date: string) => {
-  return testDate[date] ? true : false
+  return stateDataList[date] ? true : false
 }
 }
 
 
 const emit = defineEmits(['DateRangeChange', 'DateChange'])
 const emit = defineEmits(['DateRangeChange', 'DateChange'])
@@ -120,10 +120,6 @@ const handlePanelChange = (value: any, mode: any) => {
     isShowExtra.value = true
     isShowExtra.value = true
   }
   }
 }
 }
-// 判断失焦时是否两个都有值
-const isTwoDate = (date: any) => {
-  console.log(date)
-}
 </script>
 </script>
 <template>
 <template>
   <div class="delivery-date">
   <div class="delivery-date">

+ 126 - 38
src/views/DestinationDelivery/src/components/TableView/src/TableView.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { ref, nextTick, onMounted } from 'vue'
 import { ref, nextTick, onMounted } from 'vue'
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
-// import { autoWidth } from '@/utils/table'
+import { autoWidth } from '@/utils/table'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
 import { formatTimezone, formatNumber } from '@/utils/tools'
 import { formatTimezone, formatNumber } from '@/utils/tools'
@@ -15,6 +15,10 @@ const props = defineProps({
   height: {
   height: {
     type: Number,
     type: Number,
     default: 440
     default: 440
+  },
+  queryData: {
+    type: Object,
+    default: () => ({})
   }
   }
 })
 })
 
 
@@ -38,14 +42,6 @@ const handleColumns = (columns: any, status?: string) => {
         ...curColumn,
         ...curColumn,
         slots: { default: 'link' }
         slots: { default: 'link' }
       }
       }
-    } else if (item.type === 'mode' && status !== 'all') {
-      curColumn = {
-        ...curColumn,
-        slots: { default: 'mode' },
-        formatter: ({ cellValue }: any) => {
-          return cellValue
-        }
-      }
     }
     }
     // 格式化
     // 格式化
     if (item.formatter === 'date' || item.formatter === 'dateTime') {
     if (item.formatter === 'date' || item.formatter === 'dateTime') {
@@ -62,11 +58,11 @@ const handleColumns = (columns: any, status?: string) => {
 // 获取表格列
 // 获取表格列
 const getTableColumns = async () => {
 const getTableColumns = async () => {
   tableLoadingColumn.value = true
   tableLoadingColumn.value = true
-  await $api.getOperationTableColumns().then((res: any) => {
+  await $api.getDeliveryBookingTableColumn().then((res: any) => {
     if (res.code === 200) {
     if (res.code === 200) {
       tableData.value.columns = [
       tableData.value.columns = [
         { type: 'checkbox', width: 50, fixed: 'left' },
         { type: 'checkbox', width: 50, fixed: 'left' },
-        ...handleColumns(res.data.OperationTableColumns)
+        ...handleColumns(res.data.TrackingTableColumns)
       ]
       ]
       console.log('tableData.value.columns', tableData.value.columns)
       console.log('tableData.value.columns', tableData.value.columns)
       const index = tableData.value.columns.findIndex((item: any) => item.title === 'Action')
       const index = tableData.value.columns.findIndex((item: any) => item.title === 'Action')
@@ -82,7 +78,7 @@ const getTableColumns = async () => {
     }
     }
   })
   })
   nextTick(() => {
   nextTick(() => {
-    // tableRef.value && autoWidth(tableData.value, tableRef.value)
+    tableRef.value && autoWidth(tableData.value, tableRef.value)
     tableLoadingColumn.value = false
     tableLoadingColumn.value = false
     selectedTableData.value = []
     selectedTableData.value = []
   })
   })
@@ -109,59 +105,99 @@ const assignTableData = (data: any) => {
   }
   }
 }
 }
 
 
-let searchdata: any = {}
+const isEmployeeRole = ref(true)
+
+const emit = defineEmits(['getNumberCards'])
+const rtnNumberCards = (data) => {
+  const cards = [
+    {
+      label: 'Total Bookings',
+      value: data.All || 0,
+      color: '#2b2f36',
+      key: 'ALL'
+    },
+    {
+      label: 'Pending Approval',
+      value: data.pending_approval_rc || 0,
+      color: '#edb82f',
+      icon: 'icon_time_b'
+    },
+    {
+      label: 'Approved',
+      value: data.approved_rc || 0,
+      color: '#00a870',
+      icon: 'icon_confirm_b'
+    },
+    {
+      label: 'Rejected',
+      value: data.rejected_rc || 0,
+      color: '#c9353f',
+      icon: 'icon_reject_b'
+    },
+    {
+      label: 'Cancelled',
+      value: data.cancelled_rc || 0,
+      color: '#243041',
+      icon: 'icon_cancelled_b'
+    }
+  ]
+  emit('getNumberCards', cards)
+}
 // 获取表格数据
 // 获取表格数据
 const getTableData = async (isPageChange?: boolean) => {
 const getTableData = async (isPageChange?: boolean) => {
   const rc = isPageChange ? pageInfo.value.total : -1
   const rc = isPageChange ? pageInfo.value.total : -1
   tableLoadingTableData.value = true
   tableLoadingTableData.value = true
   await $api
   await $api
-    .SearchOperationLog({
+    .getDeliveryBookingTableData({
       cp: pageInfo.value.pageNo,
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       ps: pageInfo.value.pageSize,
       rc,
       rc,
-      ...searchdata
+      ...props.queryData
     })
     })
     .then((res: any) => {
     .then((res: any) => {
       if (res.code === 200) {
       if (res.code === 200) {
+        isEmployeeRole.value = res.data.is_employee
         assignTableData(res.data)
         assignTableData(res.data)
+        rtnNumberCards(res.data)
       }
       }
     })
     })
     .finally(() => {
     .finally(() => {
       selectedTableData.value = []
       selectedTableData.value = []
       nextTick(() => {
       nextTick(() => {
-        // tableRef.value && autoWidth(tableData.value, tableRef.value)
+        tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
         tableLoadingTableData.value = false
       })
       })
     })
     })
 }
 }
-const SearchOperationLog = (val: any) => {
-  searchdata = val
+const SearchOperationLog = () => {
   tableLoadingTableData.value = true
   tableLoadingTableData.value = true
   $api
   $api
-    .SearchOperationLog({
+    .getDeliveryBookingTableData({
       cp: pageInfo.value.pageNo,
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       ps: pageInfo.value.pageSize,
       rc: -1,
       rc: -1,
-      ...val
+      ...props.queryData
     })
     })
     .then((res: any) => {
     .then((res: any) => {
       if (res.code === 200) {
       if (res.code === 200) {
+        isEmployeeRole.value = res.data.is_employee
         assignTableData(res.data)
         assignTableData(res.data)
+        rtnNumberCards(res.data)
       }
       }
     })
     })
     .finally(() => {
     .finally(() => {
       selectedTableData.value = []
       selectedTableData.value = []
       nextTick(() => {
       nextTick(() => {
-        // tableRef.value && autoWidth(tableData.value, tableRef.value)
+        tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
         tableLoadingTableData.value = false
       })
       })
     })
     })
 }
 }
 onMounted(() => {
 onMounted(() => {
   Promise.all([getTableColumns(), getTableData(false)]).finally(() => {
   Promise.all([getTableColumns(), getTableData(false)]).finally(() => {
-    // nextTick(() => {
-    //   tableRef.value && autoWidth(tableData.value, tableRef.value)
-    // })
+    nextTick(() => {
+      tableRef.value && autoWidth(tableData.value, tableRef.value)
+    })
   })
   })
 })
 })
 
 
@@ -227,7 +263,7 @@ const tableData = ref<VxeGridProps<any>>({
     }
     }
   },
   },
   columnConfig: { resizable: true, useKey: true },
   columnConfig: { resizable: true, useKey: true },
-  rowConfig: { isHover: true },
+  rowConfig: { isHover: true, isCurrent: true },
   exportConfig: {
   exportConfig: {
     types: ['csv', 'html', 'txt', 'xlsx'],
     types: ['csv', 'html', 'txt', 'xlsx'],
     modes: ['current', 'selected', 'all']
     modes: ['current', 'selected', 'all']
@@ -256,9 +292,9 @@ const handleCustomizeColumns = () => {
 // 定制表格
 // 定制表格
 const customizeColumns = async () => {
 const customizeColumns = async () => {
   await getTableColumns()
   await getTableColumns()
-  // nextTick(() => {
-  //   tableRef.value && autoWidth(tableData.value, tableRef.value)
-  // })
+  nextTick(() => {
+    tableRef.value && autoWidth(tableData.value, tableRef.value)
+  })
 }
 }
 
 
 const tableLoadingColumn = ref(false)
 const tableLoadingColumn = ref(false)
@@ -281,7 +317,7 @@ const handelEdit = (row: any) => {
   console.log(row)
   console.log(row)
   router.push({
   router.push({
     path: '/destination-delivery/CreateNewBooking',
     path: '/destination-delivery/CreateNewBooking',
-    query: { a: row._serial_no}
+    query: { a: row._serial_no }
   })
   })
 }
 }
 
 
@@ -290,7 +326,25 @@ const handleCreate = () => {
   console.log('Create new booking')
   console.log('Create new booking')
 }
 }
 
 
-const tipsDialogModel = ref(false)
+const handleLinkClick = (row: any, column: any) => {
+  if (column.title === 'Booking No.') {
+    router.push({
+      path: '/booking/detail',
+      query: { a: row.__serial_no, _schemas: row._schemas, status: row.Status }
+    })
+    // visitedRowState.setBookingTableData(row['__serial_no'])
+  } else if (column.title === 'HBOL/HAWB No.') {
+    router.push({
+      path: '/tracking/detail',
+      query: { a: row.__serial_no, _schemas: row._schemas }
+    })
+  }
+}
+
+const tipsDialogRef = ref()
+const handleTips = (type: string) => {
+  tipsDialogRef.value.openDialog(type)
+}
 
 
 defineExpose({
 defineExpose({
   SearchOperationLog
   SearchOperationLog
@@ -346,33 +400,67 @@ defineExpose({
           class="action-btn el-button--blue"
           class="action-btn el-button--blue"
           style="height: 24px; width: 24px"
           style="height: 24px; width: 24px"
         >
         >
-          <span style="color: 'red'" class="font_family icon-icon_view_b"> </span>
+          <span class="font_family icon-icon_view_b"> </span>
         </el-button>
         </el-button>
         <!-- email -->
         <!-- email -->
         <el-button
         <el-button
           @click="clickEmailBtn(row)"
           @click="clickEmailBtn(row)"
           class="action-btn el-button--blue"
           class="action-btn el-button--blue"
           style="height: 24px; width: 24px"
           style="height: 24px; width: 24px"
+          v-if="isEmployeeRole && row.status === 'Approved'"
         >
         >
-          <span style="color: 'red'" class="font_family icon-icon_email_b"> </span>
+          <span class="font_family icon-icon_email_b"> </span>
         </el-button>
         </el-button>
         <!-- edit -->
         <!-- edit -->
         <el-button
         <el-button
           @click="handelEdit(row)"
           @click="handelEdit(row)"
           class="action-btn el-button--blue"
           class="action-btn el-button--blue"
           style="height: 24px; width: 24px"
           style="height: 24px; width: 24px"
+          v-if="isEmployeeRole && row.status === 'Pending Approval'"
         >
         >
-          <span style="color: 'red'" class="font_family icon-icon_edit_b"> </span>
+          <span class="font_family icon-icon_edit_b"> </span>
+        </el-button>
+        <!-- cancel -->
+        <el-button
+          @click="handleTips('cancel')"
+          class="action-btn el-button--blue"
+          style="height: 24px; width: 24px"
+          v-if="isEmployeeRole && row.status === 'Pending Approval'"
+        >
+          <span class="font_family icon-icon_cancelled_b"> </span>
         </el-button>
         </el-button>
         <!-- confirm -->
         <!-- confirm -->
-        <el-button class="action-btn el-button--blue" style="height: 24px; width: 24px">
-          <span style="color: 'red'" class="font_family icon-icon_confirm_b"> </span>
+        <el-button
+          v-if="!isEmployeeRole && row.status === 'Pending Approval'"
+          @click="handleTips('confirm')"
+          class="action-btn el-button--blue"
+          style="height: 24px; width: 24px"
+        >
+          <span class="font_family icon-icon_confirm_b"> </span>
         </el-button>
         </el-button>
         <!-- reject -->
         <!-- reject -->
-        <el-button class="action-btn el-button--blue" style="height: 24px; width: 24px">
-          <span style="color: 'red'" class="font_family icon-icon_reject_b"> </span>
+        <el-button
+          v-if="!isEmployeeRole && row.status === 'Pending Approval'"
+          @click="handleTips('reject')"
+          class="action-btn el-button--blue"
+          style="height: 24px; width: 24px"
+        >
+          <span class="font_family icon-icon_reject_b"> </span>
         </el-button>
         </el-button>
       </template>
       </template>
+      <!-- Status字段的插槽 -->
+      <template #status="{ row, column }">
+        <VTag :type="row[column.field]">{{ row[column.field] }}</VTag>
+      </template>
+      <!-- Booking No字段的插槽 -->
+      <template #link="{ row, column }">
+        <span
+          style="color: var(--color-theme); cursor: pointer"
+          @click="handleLinkClick(row, column)"
+        >
+          {{ row[column.field] }}
+        </span>
+      </template>
     </vxe-grid>
     </vxe-grid>
 
 
     <div class="bottom-pagination">
     <div class="bottom-pagination">
@@ -395,7 +483,7 @@ defineExpose({
     <CustomizeColumns @customize="customizeColumns" ref="CustomizeColumnsRef" />
     <CustomizeColumns @customize="customizeColumns" ref="CustomizeColumnsRef" />
     <BookingDetailDialog ref="bookingDetailDiaRef" />
     <BookingDetailDialog ref="bookingDetailDiaRef" />
     <EmailDialog ref="emailDialogRef" />
     <EmailDialog ref="emailDialogRef" />
-    <TipsDialog ref="tipsDialogRef" v-model="tipsDialogModel" type="reject" booking-no="123" />
+    <TipsDialog ref="tipsDialogRef" type="reject" booking-no="123" />
   </div>
   </div>
 </template>
 </template>
 
 

+ 131 - 65
src/views/DestinationDelivery/src/components/TableView/src/components/BookingDetailDialog.vue

@@ -2,42 +2,105 @@
 import DetailStep from './DetailStep.vue'
 import DetailStep from './DetailStep.vue'
 import ShipmentInforTable from './ShipmentInforTable.vue'
 import ShipmentInforTable from './ShipmentInforTable.vue'
 import OperationLogProcess from './OperationLogProcess.vue'
 import OperationLogProcess from './OperationLogProcess.vue'
+import { formatTimezone } from '@/utils/tools'
 
 
 const visible = ref(false)
 const visible = ref(false)
+const loading = ref(false)
 
 
+const shipmentInfoTableData = ref([])
 const openDialog = (row: any) => {
 const openDialog = (row: any) => {
   visible.value = true
   visible.value = true
-  console.log(row)
+  loading.value = true
+  $api
+    .getDeliveryBookingDialogData({ serial_no: row._serial_no })
+    .then((res) => {
+      console.log('res', res)
+      const data = res.data.data
+      if (data.update_time !== data.create_time && data.status === 'Pending Approval') {
+        data.status = 'Modified'
+      }
+      handleStepData(data.status, data)
+      deliveryInfoData.value = {
+        modeType: data.delivery_mode || '--',
+        deliveryDate: data.delivery_date || '--',
+        deliveryAddress: data.delivery_address || '--',
+        specialRequirements: data.special_requirements || '--'
+      }
+      shipmentInfoTableData.value = data.shipmentsData || []
+    })
+    .finally(() => {
+      loading.value = false
+    })
 }
 }
 
 
-const stepList: any = ref([
-  {
-    id: 1,
+const stepList: any = ref([])
+
+const handleStepData = (status, data) => {
+  stepList.value.push({
     label: 'Created',
     label: 'Created',
-    date: 'Jun-01-2024',
-    icon: 'icon_submit_b',
-    status: 'completed'
-  },
-  {
-    label: 'Pending',
-    date: 'Current',
-    icon: 'icon_time_b',
-    status: 'current'
-  },
-  {
-    label: 'Rejected',
-    date: 'Jun-03-2024',
-    icon: 'icon_reject_b',
-    status: 'rejected'
-  },
-  {
-    label: 'Approved',
-    date: 'Jun-03-2024',
-    icon: 'icon_confirm_b',
-    status: 'current'
+    date: data.created_time || '--',
+    icon: 'icon_submit_b'
+  })
+  if (status === 'Modified') {
+    stepList.value.push({
+      label: 'Modified',
+      date: data.update_time || '--',
+      icon: 'icon_edit_b'
+    })
+  }
+  if (status === 'Pending Approval' || status === 'Modified') {
+    stepList.value.push({
+      label: 'Pending',
+      date: 'Current',
+      icon: 'icon_time_b',
+      status: 'current'
+    })
+    stepList.value.push({
+      label: 'Approved',
+      date: '--',
+      icon: 'icon_confirm_b',
+      status: 'unfinished'
+    })
+  } else if (status === 'Approved') {
+    stepList.value.push({
+      label: 'Approved',
+      date: '--',
+      icon: 'icon_confirm_b',
+      status: 'unfinished'
+    })
+  } else if (status === 'Rejected') {
+    stepList.value.push({
+      label: 'Rejected',
+      date: 'Jun-05-2024',
+      icon: 'icon_reject_b',
+      status: 'rejected'
+    })
+  } else if (status === 'Cancelled') {
+    stepList.value.push({
+      label: 'Cancelled',
+      date: 'Jun-05-2024',
+      icon: 'icon_cancelled_b',
+      status: 'completed'
+    })
   }
   }
-])
+}
+const deliveryInfoData = ref({
+  modeType: '',
+  deliveryDate: '',
+  deliveryAddress: '',
+  specialRequirements: ''
+})
 
 
+const clearData = () => {
+  shipmentInfoTableData.value = []
+  stepList.value = []
+  deliveryInfoData.value = {
+    modeType: '',
+    deliveryDate: '',
+    deliveryAddress: '',
+    specialRequirements: ''
+  }
+}
 defineExpose({
 defineExpose({
   openDialog
   openDialog
 })
 })
@@ -51,51 +114,54 @@ defineExpose({
     :close-on-click-modal="false"
     :close-on-click-modal="false"
     width="1000px"
     width="1000px"
     top="10vh"
     top="10vh"
+    @closed="clearData"
     v-if="visible"
     v-if="visible"
   >
   >
-    <DetailStep :stepList="stepList" />
-    <div class="booking-info">
-      <div class="booking-no">
-        <span class="no">Booking No.B83131200164</span>
-        <v-tag class="tag" type="Pending Approval">Pending Approval</v-tag>
-      </div>
-      <div class="created-time">Created Time:Jun-01-2024</div>
-    </div>
-    <ShipmentInforTable></ShipmentInforTable>
-    <div class="delivery-information">
-      <div class="label">Delivery Information</div>
-      <div class="delivery-info">
-        <div class="delivery-item inline-flex" style="width: 200px">
-          <span class="item-label">Mode Type</span>
-          <span class="item-value">Shanghai, China</span>
+    <div v-vloading="loading">
+      <DetailStep :stepList="stepList" />
+      <div class="booking-info">
+        <div class="booking-no">
+          <span class="no">Booking No.B83131200164</span>
+          <v-tag class="tag" type="Pending Approval">Pending Approval</v-tag>
         </div>
         </div>
-        <div class="delivery-item inline-flex">
-          <span class="item-label">Delivery Date</span>
-          <span class="item-value">
-            <span class="font_family icon-icon_date_b" style="margin-right: 4px"></span>
-            <span style="margin-top: 1px">Jun-15-2024</span>
-          </span>
-        </div>
-        <div class="delivery-item">
-          <span class="item-label">Delivery Address</span>
-          <span class="item-value">
-            <span class="font_family icon-icon_location_b" style="margin-right: 2px"></span>
-            <span style="margin-top: 1px"
-              >Main Distribution Center,160#BEIJING ROAD, JINGAN District, Shenzhen, China</span
-            >
-          </span>
-        </div>
-        <div class="delivery-item">
-          <span class="item-label">Special Requirements</span>
-          <span class="item-value">
-            <span class="font_family icon-icon_paragraph_b" style="margin-right: 2px"></span>
-            <span style="margin-top: 1px">Tail Lift Required</span>
-          </span>
+        <div class="created-time">Created Time:Jun-01-2024</div>
+      </div>
+      <ShipmentInforTable :data="shipmentInfoTableData" />
+      <div class="delivery-information">
+        <div class="label">Delivery Information</div>
+        <div class="delivery-info">
+          <div class="delivery-item inline-flex" style="width: 200px">
+            <span class="item-label">Mode Type</span>
+            <span class="item-value">{{ deliveryInfoData.modeType }}</span>
+          </div>
+          <div class="delivery-item inline-flex">
+            <span class="item-label">Delivery Date</span>
+            <span class="item-value">
+              <span class="font_family icon-icon_date_b" style="margin-right: 4px"></span>
+              <span style="margin-top: 1px">{{
+                formatTimezone(deliveryInfoData.deliveryDate)
+              }}</span>
+            </span>
+          </div>
+          <div class="delivery-item">
+            <span class="item-label">Delivery Address</span>
+            <span class="item-value">
+              <span class="font_family icon-icon_location_b" style="margin-right: 2px"></span>
+              <span style="margin-top: 1px">{{ deliveryInfoData.deliveryAddress }}</span>
+            </span>
+          </div>
+          <div class="delivery-item">
+            <span class="item-label">Special Requirements</span>
+            <span class="item-value">
+              <span class="font_family icon-icon_paragraph_b" style="margin-right: 2px"></span>
+              <span style="margin-top: 1px">{{ deliveryInfoData.specialRequirements }}</span>
+            </span>
+          </div>
         </div>
         </div>
       </div>
       </div>
+      <el-divider style="margin-top: 8px; margin-bottom: 20px" />
+      <OperationLogProcess />
     </div>
     </div>
-    <el-divider style="margin-top: 8px; margin-bottom: 20px" />
-    <OperationLogProcess />
   </el-dialog>
   </el-dialog>
 </template>
 </template>
 
 

+ 8 - 2
src/views/DestinationDelivery/src/components/TableView/src/components/DetailStep.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts">
 <script setup lang="ts">
+import { formatTimezone } from '@/utils/tools'
 const props = defineProps<{
 const props = defineProps<{
   stepList: Array<{
   stepList: Array<{
     id?: number
     id?: number
@@ -6,6 +7,7 @@ const props = defineProps<{
     date?: string
     date?: string
     icon: string
     icon: string
     status: 'completed' | 'current' | 'unfinished' | 'rejected' | 'approved'
     status: 'completed' | 'current' | 'unfinished' | 'rejected' | 'approved'
+    description?: string
   }>
   }>
 }>()
 }>()
 </script>
 </script>
@@ -44,7 +46,7 @@ const props = defineProps<{
               trigger="hover"
               trigger="hover"
               effect="dark"
               effect="dark"
               placement="top"
               placement="top"
-              content="This is some description information about the pending task, if there is too much content."
+              :content="step.description || ''"
             >
             >
               <span
               <span
                 style="font-size: 12px"
                 style="font-size: 12px"
@@ -53,7 +55,11 @@ const props = defineProps<{
               ></span>
               ></span>
             </el-tooltip>
             </el-tooltip>
           </div>
           </div>
-          <div class="step-date">{{ step.date || '--' }}</div>
+          <div class="step-date">
+            {{
+              step.date !== '--' && step.date !== 'Current' ? formatTimezone(step.date) : step.date
+            }}
+          </div>
         </div>
         </div>
       </div>
       </div>
 
 

+ 1 - 2
src/views/DestinationDelivery/src/components/TableView/src/components/EmailDialog.vue

@@ -148,8 +148,7 @@ const sendEmail = () => {
   const html = editorRef.value.getHtml()
   const html = editorRef.value.getHtml()
   const text = editorRef.value.getText()
   const text = editorRef.value.getText()
   $api
   $api
-    .sendEmailApi({
-      action: 'ocean_booking',
+    .saveDliveryBookingEmail({
       email: emailData.value.email,
       email: emailData.value.email,
       communication_cc: emailData.value.ccEmail,
       communication_cc: emailData.value.ccEmail,
       serial_no: emailData.value.serial_no,
       serial_no: emailData.value.serial_no,

+ 4 - 2
src/views/DestinationDelivery/src/components/TableView/src/components/OperationLogProcess.vue

@@ -1,13 +1,15 @@
 <script setup lang="ts">
 <script setup lang="ts">
 const processList = ref([
 const processList = ref([
   {
   {
-    time: 'Jun-01-2024 16:25:31 UTC+3',
+    time: 'Jun-01-2024 16:25:31 ',
+    timezone: 'UTC+3',
     label: 'Submit Booking',
     label: 'Submit Booking',
     createdBy: 'Customer A',
     createdBy: 'Customer A',
     tips: '--'
     tips: '--'
   },
   },
   {
   {
-    time: 'May-15-2024 16:25:31 UTC+3',
+    time: 'May-15-2024 16:25:31 ',
+    timezone: 'UTC+3',
     label: 'Reject Booking',
     label: 'Reject Booking',
     createdBy: 'John Doe',
     createdBy: 'John Doe',
     tips: 'Too early'
     tips: 'Too early'

+ 37 - 86
src/views/DestinationDelivery/src/components/TableView/src/components/ShipmentInforTable.vue

@@ -1,6 +1,5 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
-import { autoWidth } from '@/utils/table'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import { formatTimezone, formatNumber } from '@/utils/tools'
 import { formatTimezone, formatNumber } from '@/utils/tools'
 
 
@@ -12,7 +11,34 @@ const tableData = ref<VxeGridProps<any>>({
   minHeight: 70,
   minHeight: 70,
   border: true,
   border: true,
   round: true,
   round: true,
-  columns: [],
+  columns: [
+    {
+      field: 'HBOL No.',
+      title: 'HBOL No.',
+      width: 120
+    },
+    {
+      field: 'Container No.',
+      title: 'Container No.'
+    },
+    {
+      field: 'Service Type',
+      title: 'Service Type'
+    },
+    {
+      field: 'ETA',
+      title: 'ETA',
+      minWidth: 100,
+      formatter: ({ cellValue }: any) => formatTimezone(cellValue)
+    },
+
+    {
+      field: 'Recommended Delivery Date',
+      title: 'Recommended Delivery Date',
+      width: 220,
+      formatter: ({ cellValue }: any) => formatTimezone(cellValue)
+    }
+  ],
   data: [],
   data: [],
   scrollY: { enabled: true, oSize: 20, gt: 30 },
   scrollY: { enabled: true, oSize: 20, gt: 30 },
   emptyText: ' ',
   emptyText: ' ',
@@ -25,94 +51,22 @@ const tableData = ref<VxeGridProps<any>>({
   rowConfig: { isHover: true }
   rowConfig: { isHover: true }
 })
 })
 
 
-const tableLoadingTable = ref()
-const tableLoadingColumn = ref(false)
-const handleColumns = (columns: any) => {
-  const newColumns = columns.map((item: any) => {
-    let curColumn: any = {
-      title: item.title,
-      field: item.field,
-      minWidth: 30
-    }
-
-    // 格式化
-    if (item.formatter === 'date' || item.formatter === 'dateTime') {
-      curColumn = {
-        ...curColumn,
-        formatter: ({ cellValue }: any) => formatTimezone(cellValue)
-      }
-    } else if (item.formatter === 'number') {
-      curColumn = {
-        ...curColumn,
-        formatter: ({ cellValue }: any) => formatNumber(Number(cellValue), item?.digits)
-      }
-    }
-    return curColumn
-  })
-  return newColumns
+// 获得表格数据后赋值
+const assignTableData = (data: any) => {
+  tableData.value.data = data || []
 }
 }
 watch(
 watch(
   () => props.data,
   () => props.data,
-  (newVal) => {
-    const containers = newVal?.containers
-    if (containers && containers.container_column) {
-      tableData.value.columns = handleColumns(containers.container_column)
-      tableData.value.data = containers.container_data
-      nextTick(() => {
-        tableRef.value && autoWidth(tableData.value, tableRef.value)
-      })
+  (newData) => {
+    if (newData) {
+      assignTableData(newData)
     }
     }
   },
   },
-  {
-    immediate: true,
-    deep: true
-  }
+  { immediate: true, deep: true }
 )
 )
+const tableLoadingTable = ref()
 
 
-const tableOriginColumnsField = ref()
-// 获取表格列
-const getTableColumns = async () => {
-  tableLoadingColumn.value = true
-  await $api.getOperationTableColumns().then((res: any) => {
-    if (res.code === 200) {
-      tableData.value.columns = [
-        { type: 'checkbox', width: 50, fixed: 'left' },
-        ...handleColumns(res.data.OperationTableColumns),
-        {}
-      ]
-      const index = tableData.value.columns.findIndex((item: any) => item.title === 'Action')
-      if (index !== -1) {
-        tableData.value.columns.push({
-          title: 'Action',
-          fixed: 'right',
-          width: 120,
-          slots: { default: 'action' }
-        })
-      }
-      tableOriginColumnsField.value = res.data.OperationTableColumns
-    }
-  })
-  nextTick(() => {
-    tableLoadingColumn.value = false
-  })
-}
 let searchdata: any = {}
 let searchdata: any = {}
-// 获得表格数据后赋值
-const assignTableData = (data: any) => {
-  tableData.value.data = data.searchData || []
-
-  if (tableData.value.columns.length > 0) {
-    const index = tableData.value.columns.findIndex((item: any) => item.title === 'Action')
-    if (index === -1) {
-      tableData.value.columns.push({
-        title: 'Action',
-        fixed: 'right',
-        width: 120,
-        slots: { default: 'action' }
-      })
-    }
-  }
-}
 
 
 // 获取表格数据
 // 获取表格数据
 const getTableData = async () => {
 const getTableData = async () => {
@@ -135,9 +89,6 @@ const getTableData = async () => {
     })
     })
 }
 }
 
 
-onMounted(() => {
-  Promise.all([getTableColumns(), getTableData()]).finally(() => {})
-})
 // 实现行点击样式
 // 实现行点击样式
 useRowClickStyle(tableRef)
 useRowClickStyle(tableRef)
 </script>
 </script>
@@ -146,7 +97,7 @@ useRowClickStyle(tableRef)
   <div class="shipment-infor-table">
   <div class="shipment-infor-table">
     <div class="label">Shipment Information</div>
     <div class="label">Shipment Information</div>
     <vxe-grid
     <vxe-grid
-      v-vloading="tableLoadingTable || tableLoadingColumn"
+      v-vloading="tableLoadingTable"
       ref="tableRef"
       ref="tableRef"
       v-bind="tableData"
       v-bind="tableData"
       max-height="240"
       max-height="240"

+ 14 - 7
src/views/Layout/src/components/Header/components/NotificationDrawer.vue

@@ -24,7 +24,7 @@ const pageInfo = ref({
   cp: 1,
   cp: 1,
   ps: 30
   ps: 30
 })
 })
-const getNotificationList = () => {
+const getNotificationList = (isChangeType?: boolean) => {
   loading.value = true
   loading.value = true
   $api
   $api
     .getNotificationList({
     .getNotificationList({
@@ -38,9 +38,6 @@ const getNotificationList = () => {
         if (res.data.length === 0 || res.data.length < pageInfo.value.ps) {
         if (res.data.length === 0 || res.data.length < pageInfo.value.ps) {
           notificationMessageCardRef.value.finished = true
           notificationMessageCardRef.value.finished = true
         }
         }
-        // nextTick(() => {
-        //   init()
-        // })
       }
       }
     })
     })
     .finally(() => {
     .finally(() => {
@@ -48,7 +45,7 @@ const getNotificationList = () => {
       pageInfo.value.cp += 1
       pageInfo.value.cp += 1
       notificationMessageCardRef.value.loading = false
       notificationMessageCardRef.value.loading = false
 
 
-      notificationMessageCardRef.value.adjustScrollTop()
+      notificationMessageCardRef.value.adjustScrollTop(isChangeType ? 0 : undefined)
     })
     })
 }
 }
 
 
@@ -82,9 +79,18 @@ const handleSettingMessage = () => {
   })
   })
 }
 }
 
 
+const handleChangeNotificationType = async (value: string) => {
+  notificationList.value = []
+  pageInfo.value.cp = 1
+  notificationMessageCardRef.value.adjustScrollTop(0)
+  notificationMessageCardRef.value.finished = false
+  getNotificationList(true)
+}
+
 const closeDrawer = () => {
 const closeDrawer = () => {
   notificationList.value = []
   notificationList.value = []
   notificationType.value = 'all'
   notificationType.value = 'all'
+  notificationMessageCardRef.value.adjustScrollTop(0)
   notificationMsgStore.markMessageAsRead()
   notificationMsgStore.markMessageAsRead()
   pageInfo.value.cp = 1
   pageInfo.value.cp = 1
 }
 }
@@ -93,7 +99,7 @@ const closeDrawer = () => {
 <template>
 <template>
   <el-drawer
   <el-drawer
     ref="drawerRef"
     ref="drawerRef"
-    @open="getNotificationList"
+    @open="getNotificationList(true)"
     @closed="closeDrawer"
     @closed="closeDrawer"
     class="notice-drawer"
     class="notice-drawer"
     size="432px"
     size="432px"
@@ -101,7 +107,7 @@ const closeDrawer = () => {
     <template #header>
     <template #header>
       <el-select
       <el-select
         size="large"
         size="large"
-        @change="getNotificationList"
+        @change="handleChangeNotificationType"
         v-model="notificationType"
         v-model="notificationType"
         class="notification-type"
         class="notification-type"
       >
       >
@@ -146,6 +152,7 @@ const closeDrawer = () => {
             @loading="getNotificationList"
             @loading="getNotificationList"
             :data="notificationList"
             :data="notificationList"
             :topOffset="185"
             :topOffset="185"
+            :isDrawer="true"
             ref="notificationMessageCardRef"
             ref="notificationMessageCardRef"
           />
           />
         </div>
         </div>

+ 1 - 0
src/views/Layout/src/components/Header/components/TrainingCard.vue

@@ -136,6 +136,7 @@ const closeMessage = () => {
       v-if="curCard"
       v-if="curCard"
       :data="[curCard]"
       :data="[curCard]"
       :topOffset="0"
       :topOffset="0"
+      :isDrawer="true"
     ></NotificationMessageCard>
     ></NotificationMessageCard>
   </div>
   </div>
 </template>
 </template>

+ 19 - 6
src/views/Layout/src/components/Menu/MenuView.vue

@@ -73,11 +73,21 @@ const getMenuList = () => {
         },
         },
         {
         {
           index: '4-3',
           index: '4-3',
+          label: 'Chat Log',
+          path: '/chat-log'
+        },
+        {
+          index: '4-4',
+          label: 'AI API Log',
+          path: '/ai-api-log'
+        },
+        {
+          index: '4-5',
           label: 'Operation Log',
           label: 'Operation Log',
           path: '/Operationlog'
           path: '/Operationlog'
         },
         },
         {
         {
-          index: '4-4',
+          index: '4-6',
           label: 'Prompt Configuration',
           label: 'Prompt Configuration',
           path: '/PromptConfiguration'
           path: '/PromptConfiguration'
         }
         }
@@ -138,10 +148,17 @@ router.afterEach(() => {
 
 
 // 路由跳转函数
 // 路由跳转函数
 const changeRouter = (path: any) => {
 const changeRouter = (path: any) => {
+  if (localStorage.getItem('loginAI')) {
+    localStorage.removeItem('loginAI')
+    emitter.emit('login-success')
+  }
   if (path == '/PromptConfiguration') {
   if (path == '/PromptConfiguration') {
     emitter.emit('checkPrompt')
     emitter.emit('checkPrompt')
   } else {
   } else {
-    emitter.emit('checknoPrompt')
+    if (localStorage.getItem('loginAI')) {
+      localStorage.removeItem('loginAI')
+      emitter.emit('checknoPrompt')
+    }
   }
   }
   if (sessionStorage.getItem('searchTableQeury')) {
   if (sessionStorage.getItem('searchTableQeury')) {
     sessionStorage.removeItem('searchTableQeury')
     sessionStorage.removeItem('searchTableQeury')
@@ -156,10 +173,6 @@ const changeRouter = (path: any) => {
   }
   }
   sessionStorage.removeItem('trackingTablePageInfo')
   sessionStorage.removeItem('trackingTablePageInfo')
   sessionStorage.removeItem('bookingTablePageInfo')
   sessionStorage.removeItem('bookingTablePageInfo')
-  if (localStorage.getItem('loginAI')) {
-    localStorage.removeItem('loginAI')
-    emitter.emit('login-success')
-  }
   let toPath = path
   let toPath = path
   if (path === '/tracking' && !userStore.userInfo?.uname) {
   if (path === '/tracking' && !userStore.userInfo?.uname) {
     toPath = '/public-tracking'
     toPath = '/public-tracking'

+ 15 - 11
src/views/SystemMessage/src/components/SystemMessageDetail.vue

@@ -86,9 +86,7 @@ const init = async () => {
     await getNotificationList()
     await getNotificationList()
   }
   }
 }
 }
-// onMounted(() => {
-//   init()
-// })
+
 const watchScope = watch(
 const watchScope = watch(
   () => route.query,
   () => route.query,
   () => {
   () => {
@@ -117,25 +115,31 @@ const handleIframeLoaded = () => {
         <div class="status-icon"></div>
         <div class="status-icon"></div>
         <div class="title">{{ notificationData.title }}</div>
         <div class="title">{{ notificationData.title }}</div>
       </div>
       </div>
-      <div class="total-tips" v-if="notificationData.numericRecords > -1">
-        Latest Status Updates ({{ notificationData.numericRecords }})
+      <div
+        class="total-tips"
+        v-if="route.query.numericRecords && Number(route.query.numericRecords) > -1"
+      >
+        Latest Status Updates ({{ route.query.numericRecords }})
       </div>
       </div>
       <div
       <div
         class="total-tips"
         class="total-tips"
-        v-else-if="notificationData.etdOrdeparturNum > -1 || notificationData.etaOrarrivalNum > -1"
+        v-else-if="
+          (route.query.etdOrdeparturNum && Number(route.query.etdOrdeparturNum) > -1) ||
+          (route.query.etaOrarrivalNum && Number(route.query.etaOrarrivalNum) > -1)
+        "
       >
       >
         <div>
         <div>
-          <span v-if="notificationData.etdOrdeparturNum"
+          <span v-if="route.query.etdOrdeparturNum"
             >{{ notificationData.type === 'delay' ? 'Departure Delay' : 'ETD Change' }} ({{
             >{{ notificationData.type === 'delay' ? 'Departure Delay' : 'ETD Change' }} ({{
-              notificationData.etdOrdeparturNum
+              route.query.etdOrdeparturNum
             }})</span
             }})</span
           >
           >
-          <span v-if="notificationData.etdOrdeparturNum && notificationData.etaOrarrivalNum">
+          <span v-if="route.query.etdOrdeparturNum && route.query.etaOrarrivalNum">
             &nbsp;&nbsp;|&nbsp;&nbsp;</span
             &nbsp;&nbsp;|&nbsp;&nbsp;</span
           >
           >
-          <span v-if="notificationData.etaOrarrivalNum">
+          <span v-if="route.query.etaOrarrivalNum">
             {{ notificationData.type === 'delay' ? 'Arrival Delay' : 'ETA Change' }} ({{
             {{ notificationData.type === 'delay' ? 'Arrival Delay' : 'ETA Change' }} ({{
-              notificationData.etaOrarrivalNum
+              route.query.etaOrarrivalNum
             }})
             }})
           </span>
           </span>
         </div>
         </div>