20 Revīzijas f2ef9c8451 ... bdd3a17b45

Autors SHA1 Ziņojums Datums
  Jack Zhou bdd3a17b45 Merge branch 'test_zyh' of United_Software/k_online_ui into test 4 dienas atpakaļ
  Jack Zhou 45c8611781 Merge branch 'master_zyh' into test_zyh 4 dienas atpakaļ
  Jack Zhou cfdf8592ae Merge branch 'test' into test_zyh 4 dienas atpakaļ
  Jack Zhou 792278705f feat: 放开system settings通过邮件发送功能的权限为所有用户 4 dienas atpakaļ
  Jack Zhou ea20268b20 fix: 解决Booking、Tracking筛选项和首页联动的bug 5 dienas atpakaļ
  Jack Zhou f5946cd4ff feat: 解决首页图表警告 1 nedēļu atpakaļ
  Jack Zhou ed73073dff Merge branch 'test_zyh' of United_Software/k_online_ui into test 1 nedēļu atpakaļ
  Jack Zhou 4e76dc30a5 fix: 解决图表重复初始化报错bug、解决首页点击图表跳转Tracking详情页重复请求以及部分筛选项不生效bug 1 nedēļu atpakaļ
  Jack Zhou b456879f59 feat: 实现图表下载功能 1 nedēļu atpakaļ
  Jack Zhou 78a3271cda Merge branch 'test_zyh' of United_Software/k_online_ui into test 1 nedēļu atpakaļ
  Jack Zhou 81e6b8369d feat: 重构booking Tracking筛选项daterange 1 nedēļu atpakaļ
  Jack Zhou e4ba396cbf fix: 解决delivery 页面中recommend部分复选框选中不能回显bug 1 nedēļu atpakaļ
  Jack Zhou 987224b35e feat: 调整保存接口参数 1 nedēļu atpakaļ
  Jack Zhou a42a3f21f7 feat: create new booking 页表格新增customize columns功能 1 nedēļu atpakaļ
  Jack Zhou 5182f011a7 feat: create new booking加上delivery date筛选项 2 nedēļas atpakaļ
  Jack Zhou 88fe0f56b1 feat: 实现delivery 表格下载项 2 nedēļas atpakaļ
  Jack Zhou 77c1e3d040 Merge branch 'feat_download_zyh' of United_Software/k_online_ui into test 2 nedēļas atpakaļ
  Jack Zhou 8e372d0b3d Merge branch 'feat_download_zyh' of United_Software/k_online_ui into test 2 nedēļas atpakaļ
  Jack Zhou 787087e1dd Merge branch 'test_zyh' of United_Software/k_online_ui into test 2 nedēļas atpakaļ
  Jack Zhou e33a3c9474 Merge branch 'test_zyh' of United_Software/k_online_ui into test 3 nedēļas atpakaļ
27 mainītis faili ar 1354 papildinājumiem un 962 dzēšanām
  1. 2 0
      .gitignore
  2. 15 0
      src/api/module/Delivery.ts
  3. 2 6
      src/components/AddRules/src/components/NotiMethods.vue
  4. 2 6
      src/components/CreateAddRules/src/components/NotiMethods.vue
  5. 9 10
      src/components/CustomizeColumns/src/CustomizeColumns.vue
  6. 157 208
      src/components/DateRange/src/DateRange.vue
  7. 8 20
      src/components/DateRange/src/components/CalendarDate.vue
  8. 33 18
      src/components/TransportMode/src/TransportMode.vue
  9. 5 1
      src/utils/table.ts
  10. 65 28
      src/views/Booking/src/BookingView.vue
  11. 6 2
      src/views/Booking/src/components/BookingTable/src/BookingTable.vue
  12. 28 20
      src/views/Dashboard/src/DashboardView.vue
  13. 49 15
      src/views/Dashboard/src/components/BarChart.vue
  14. 74 39
      src/views/Dashboard/src/components/PieChart.vue
  15. 0 1
      src/views/Dashboard/src/components/RecentStatus.vue
  16. 35 99
      src/views/Dashboard/src/components/RevenueChart.vue
  17. 32 7
      src/views/Dashboard/src/components/SellerChart.vue
  18. 1 1
      src/views/Dashboard/src/components/TopMap.vue
  19. 221 190
      src/views/DestinationDelivery/src/components/ConfiguRations/src/components/CreateNewRule.vue
  20. 245 150
      src/views/DestinationDelivery/src/components/ConfiguRations/src/components/RecommendDate.vue
  21. 77 50
      src/views/DestinationDelivery/src/components/CreateNewBooking/src/CreateNewbooking.vue
  22. 129 4
      src/views/DestinationDelivery/src/components/CreateNewBooking/src/components/NewbookingTable.vue
  23. 2 0
      src/views/Layout/src/components/Menu/MenuView.vue
  24. 150 82
      src/views/Tracking/src/TrackingView.vue
  25. 1 1
      src/views/Tracking/src/components/DownloadAttachment/src/DownloadAttachment.vue
  26. 0 1
      src/views/Tracking/src/components/TrackingDetail/src/TrackingDetail.vue
  27. 6 3
      src/views/Tracking/src/components/TrackingTable/src/TrackingTable.vue

+ 2 - 0
.gitignore

@@ -17,6 +17,8 @@ components.d.ts
 package-lock.json
 pnpm-lock.yaml
 auto-imports.d.ts
+*.rar
+*.zip
 
 stats.html
 

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

@@ -318,4 +318,19 @@ export const getEmailRecords = (params: any, config: any) => {
     },
     config
   )
+}
+
+/**
+ * create new booking 表格中 Packing List 和 Commercial Invoice 列的下载功能
+ */
+export const downloadBookingTableFile = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_booking',
+      operate: 'batch_download_ci_p_file',
+      ...params
+    },
+    config
+  )
 }

+ 2 - 6
src/components/AddRules/src/components/NotiMethods.vue

@@ -77,11 +77,7 @@ defineExpose({
   <div style="margin-top: 11px">
     <div class="Method">
       <el-checkbox-group v-model="checkMethodList" @change="changeMethod">
-        <el-checkbox
-          class="methodcheckbox"
-          value="By Email"
-          v-if="user_type != null && user_type != 'customer'"
-        >
+        <el-checkbox class="methodcheckbox" value="By Email">
           <div>By Email</div>
           <div class="methos_image"><img src="../images/illustration_email@2x.png" /></div>
         </el-checkbox>
@@ -109,4 +105,4 @@ defineExpose({
 .methos_image {
   margin: 9px 0;
 }
-</style>
+</style>

+ 2 - 6
src/components/CreateAddRules/src/components/NotiMethods.vue

@@ -65,11 +65,7 @@ const user_type = localStorage.getItem('user_type')
   <div style="margin-top: 11px">
     <div class="Method">
       <el-checkbox-group v-model="checkMethodList" @change="changeMethod">
-        <el-checkbox
-          class="methodcheckbox"
-          value="By Email"
-          v-if="user_type != null && user_type != 'customer'"
-        >
+        <el-checkbox class="methodcheckbox" value="By Email">
           <div>By Email</div>
           <div class="methos_image"><img src="../images/illustration_email@2x.png" /></div>
         </el-checkbox>
@@ -97,4 +93,4 @@ const user_type = localStorage.getItem('user_type')
 .methos_image {
   margin: 9px 0;
 }
-</style>
+</style>

+ 9 - 10
src/components/CustomizeColumns/src/CustomizeColumns.vue

@@ -166,10 +166,12 @@ const getData = async (reset?: string) => {
 }
 
 const params = ref()
+const tipsString = ref('')
 // rightDistance是右侧箭头消失所需要translateX的值
-const openDialog = async (paramsData: Object, rightDistance: number) => {
+const openDialog = async (paramsData: Object, rightDistance: number, tips: string) => {
   firstLoad.value = localStorage.getItem('firstLoadCustomizeColumns')
   params.value = paramsData
+  tipsString.value = tips
   dialogVisible.value = true
   await getData()
   rightArrowHideDistance.value = rightDistance
@@ -233,23 +235,23 @@ const handleRightRemove = (e: any) => {
     return index !== -1
   })
 
-  if (curGroup.name !== originalGroup.name && curGroup.name !== 'All') {
+  if (curGroup.name !== originalGroup?.name && curGroup.name !== 'All') {
     // 从当前分组中删除移入的数据
     curGroup.children.forEach((item: any, index: number) => {
       item.field === curItem.field && curGroup.children.splice(index, 1)
     })
     // 在对应分组中添加移入的数据
     groupColumns.value.forEach((item: any) => {
-      item.name === originalGroup.name && item.children.push(curItem)
+      item.name === originalGroup?.name && item.children.push(curItem)
     })
     // 添加到All分组里
     groupColumns.value[0].children.push(curItem)
   } else if (curGroup.name === 'All') {
     // 在对应分组中添加移入的数据
     groupColumns.value.forEach((item: any) => {
-      item.name === originalGroup.name && item.children.push(curItem)
+      item.name === originalGroup?.name && item.children.push(curItem)
     })
-  } else if (curGroup.name === originalGroup.name) {
+  } else if (curGroup.name === originalGroup?.name) {
     groupColumns.value[0].children.push(curItem)
   }
 }
@@ -272,7 +274,7 @@ const handleDeleteSelect = (curItem: any) => {
   })
   // 在对应分组中添加移入的数据
   groupColumns.value.forEach((item: any) => {
-    item.name === originalGroup.name && item.children.push(curItem)
+    item.name === originalGroup?.name && item.children.push(curItem)
   })
   // 添加到All分组里
   groupColumns.value[0].children.push(curItem)
@@ -361,10 +363,7 @@ defineExpose({
       </div>
       <div class="tips">
         <span style="font-size: 16px">* </span>
-        <span
-          >Drag item over to this selection or click "add" icon to show the column on your
-          {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list</span
-        >
+        <span>{{ tipsString }}</span>
       </div>
     </div>
     <div class="draggable-list">

+ 157 - 208
src/components/DateRange/src/DateRange.vue

@@ -11,16 +11,18 @@ const formatDate = userStore.dateFormat
 const valueFormatDate = 'MM/DD/YYYY'
 
 onMounted(() => {
-  defaultDate()
+  const emitPayload = defaultDate()
+  // 统一 emit(只调用一次)
+  emit('defaultDate', daterangeObj2, emitPayload)
   emitter.on('clearTag', (tag: any) => {
     if (tag.includes('ETD')) {
-      clearDateStart()
+      clearETdDateRange()
     }
     if (tag.includes('ETA')) {
-      clearDateEnd()
+      clearEtaDateRange()
     }
     if (tag.includes('Creation Time')) {
-      clearDateEnd()
+      clearEtaDateRange()
     }
   })
   emitter.on('clearDaterangeObj', () => {
@@ -45,8 +47,8 @@ const AddDateType = ref()
 AddDateType.value = []
 const AddType = () => {
   AddDateType.value.push({
-    value: '',
-    number: ''
+    label: '',
+    value: ''
   })
 }
 const deleteType = (i: any) => {
@@ -57,204 +59,155 @@ const deleteType = (i: any) => {
 const props = defineProps({
   isShipment: Boolean
 })
-let daterangeObj: any = {}
-const DateStart = ref()
-DateStart.value = []
-const DateEnd = ref()
-DateEnd.value = []
+const etdDateRange = ref()
+etdDateRange.value = []
+const etaDateRange = ref()
+etaDateRange.value = []
 const DateCreation = ref()
-DateCreation.value = []
-const searchTableQeury = ref()
-const searchTableQeuryTracking = ref()
 // 查询默认日期
 const defaultDate = () => {
-  if (props.isShipment) {
-    if (
-      sessionStorage.getItem('clickParams') == null ||
-      sessionStorage.getItem('clickParams') == '{}'
-    ) {
-      if (sessionStorage.getItem('searchTableQeuryTracking') == null) {
-        DateStart.value = [dayjs().subtract(2, 'month').startOf('month'), dayjs().add(1, 'month')]
-        daterangeObj.ETD =
-          DateStart.value[0].format(formatDate) + ' To ' + DateStart.value[1].format(formatDate)
-        const obj = {
-          title: 'ETD',
-          data: [
-            DateStart.value[0].format(valueFormatDate),
-            DateStart.value[1].format(valueFormatDate)
-          ]
-        }
-
-        daterangeObj2.ETD = obj
-      } else {
-        searchTableQeuryTracking.value =
-          JSON.parse(sessionStorage.getItem('searchTableQeuryTracking') as string) || {}
-        if (searchTableQeuryTracking.value.etd_start) {
-          DateStart.value = [
-            dayjs(searchTableQeuryTracking.value.etd_start),
-            dayjs(searchTableQeuryTracking.value.etd_end)
-          ]
-          daterangeObj.ETD =
-            DateStart.value[0].format(formatDate) + ' To ' + DateStart.value[1].format(formatDate)
-          const obj = {
-            title: 'ETD',
-            data: [
-              DateStart.value[0].format(valueFormatDate),
-              DateStart.value[1].format(valueFormatDate)
-            ]
-          }
-          daterangeObj2.ETD = obj
-        }
-        if (searchTableQeuryTracking.value.eta_start) {
-          DateEnd.value = [
-            dayjs(searchTableQeuryTracking.value.eta_start),
-            dayjs(searchTableQeuryTracking.value.eta_end)
-          ]
-          daterangeObj.ETA =
-            DateEnd.value[0].format(formatDate) + ' To ' + DateEnd.value[1].format(formatDate)
-          const obj = {
-            title: 'ETA',
-            data: [
-              DateEnd.value[0].format(valueFormatDate),
-              DateEnd.value[1].format(valueFormatDate)
-            ]
-          }
-          daterangeObj2.ETA = obj
-        }
-        if (searchTableQeuryTracking.value.created_time_start) {
-          DateCreation.value = [
-            dayjs(searchTableQeuryTracking.value.created_time_start),
-            dayjs(searchTableQeuryTracking.value.created_time_end)
-          ]
-          daterangeObj['Creation Time'] =
-            DateCreation.value[0].format(formatDate) +
-            ' To ' +
-            DateCreation.value[1].format(formatDate)
-          const obj = {
-            title: 'Creation Time',
-            data: [
-              DateCreation.value[0].format(valueFormatDate),
-              DateCreation.value[1].format(valueFormatDate)
-            ]
-          }
-          daterangeObj2['Creation Time'] = obj
-        }
-      }
-      emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeuryTracking.value)
-    } else {
-      const data = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
-      searchTableQeuryTracking.value =
-        JSON.parse(sessionStorage.getItem('searchTableQeuryTracking') as string) || {}
-      if (data.eta_start) {
-        DateEnd.value = [dayjs(data.eta_start), dayjs(data.eta_end)]
-        daterangeObj.ETA =
-          DateEnd.value[0].format(formatDate) + ' To ' + DateEnd.value[1].format(formatDate)
-        const obj = {
-          title: 'ETA',
-          data: [DateEnd.value[0].format(valueFormatDate), DateEnd.value[1].format(valueFormatDate)]
-        }
+  // 工具函数:安全格式化日期范围
+  const formatDateRange = (startStr: string | null, endStr: string | null) => {
+    if (!startStr || !endStr) return [null, null]
+    const start = dayjs(startStr)
+    const end = dayjs(endStr)
+    return start.isValid() && end.isValid()
+      ? [start.format(formatDate), end.format(formatDate)]
+      : [null, null]
+  }
 
-        daterangeObj2.ETA = obj
-        emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeuryTracking.value)
-      }
-      if (data.etd_start) {
-        DateStart.value = [dayjs(data.etd_start), dayjs(data.etd_end)]
-        daterangeObj.ETD =
-          DateStart.value[0].format(formatDate) + ' To ' + DateStart.value[1].format(formatDate)
-        const obj = {
-          title: 'ETD',
-          data: [
-            DateStart.value[0].format(valueFormatDate),
-            DateStart.value[1].format(valueFormatDate)
-          ]
-        }
-        daterangeObj2.ETD = obj
-        emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeuryTracking.value)
-      }
+  // 工具函数:设置 daterangeObj2 条目
+  const setRange = (key: string, title: string, startStr: string | null, endStr: string | null) => {
+    const [start, end] = formatDateRange(startStr, endStr)
+    if (start && end) {
+      daterangeObj2[key] = { title, data: [start, end] }
     }
-  } else {
-    if (sessionStorage.getItem('searchTableQeury') == null) {
-      DateStart.value = [dayjs().subtract(2, 'month').startOf('month'), dayjs().add(1, 'month')]
-      daterangeObj.ETD =
-        DateStart.value[0].format(formatDate) + ' To ' + DateStart.value[1].format(formatDate)
-      const obj = {
-        title: 'ETD',
-        data: [
-          DateStart.value[0].format(valueFormatDate),
-          DateStart.value[1].format(valueFormatDate)
-        ]
-      }
-      daterangeObj2.ETD = obj
+  }
+
+  // 工具函数:设置 AddDateType(仅用于 Creation Time)
+  const setAddDateType = (startStr: string | null, endStr: string | null) => {
+    const [start, end] = formatDateRange(startStr, endStr)
+    AddDateType.value = [{ label: 'Creation Time', value: [start, end] }]
+  }
+
+  // 默认时间范围(2个月前月初 到 下个月)
+  const getDefaultRange = () => [
+    dayjs().subtract(2, 'month').startOf('month').format(formatDate),
+    dayjs().add(1, 'month').format(formatDate)
+  ]
+
+  // ----------------------------
+  // 主逻辑开始
+  // ----------------------------
+
+  let trackingData: Record<string, any> = {}
+  let emitPayload: Record<string, any> = {}
+
+  if (props.isShipment) {
+    const clickParams = sessionStorage.getItem('clickParams')
+    if (clickParams && clickParams !== '{}') {
+      // 场景 A: 有 clickParams → 读取 reportList
+      const reportList = JSON.parse(sessionStorage.getItem('reportList') || '{}')
+      trackingData = JSON.parse(sessionStorage.getItem('searchTableQeuryTracking') || '{}')
+      etdDateRange.value = [
+        reportList.etd_start
+          ? dayjs(reportList.etd_start, valueFormatDate).format(formatDate)
+          : null,
+        reportList.etd_end ? dayjs(reportList.etd_end, valueFormatDate).format(formatDate) : null
+      ]
+      etaDateRange.value = [
+        reportList.eta_start
+          ? dayjs(reportList.eta_start, valueFormatDate).format(formatDate)
+          : null,
+        reportList.eta_end ? dayjs(reportList.eta_end, valueFormatDate).format(formatDate) : null
+      ]
+      setRange('ETD', 'ETD', reportList.etd_start, reportList.etd_end)
+      setRange('ETA', 'ETA', reportList.eta_start, reportList.eta_end)
     } else {
-      searchTableQeury.value =
-        JSON.parse(sessionStorage.getItem('searchTableQeury') as string) || {}
-      if (searchTableQeury.value.f_etd_start) {
-        DateStart.value = [
-          dayjs(searchTableQeury.value.f_etd_start).format(valueFormatDate),
-          dayjs(searchTableQeury.value.f_etd_end).format(valueFormatDate)
+      // 场景 B: 无 clickParams → 读取 searchTableQeuryTracking
+      const stored = sessionStorage.getItem('searchTableQeuryTracking')
+      if (!stored) {
+        // 子场景 B1: 无存储 → 用默认值
+        const [start, end] = getDefaultRange()
+        etdDateRange.value = [start, end]
+        setRange('ETD', 'ETD', start, end)
+      } else {
+        // 子场景 B2: 有存储
+        trackingData = JSON.parse(stored)
+        etdDateRange.value = [
+          trackingData.etd_start ? trackingData.etd_start : null,
+          trackingData.etd_end ? trackingData.etd_end : null
         ]
-        daterangeObj.ETD =
-          DateStart.value[0].format(formatDate) + ' To ' + DateStart.value[1].format(formatDate)
-        const obj = {
-          title: 'ETD',
-          data: [
-            DateStart.value[0].format(valueFormatDate),
-            DateStart.value[1].format(valueFormatDate)
-          ]
-        }
-        daterangeObj2.ETD = obj
-      }
-      if (searchTableQeury.value.m_eta_start) {
-        DateEnd.value = [
-          dayjs(searchTableQeury.value.m_eta_start),
-          dayjs(searchTableQeury.value.m_eta_end)
+        etaDateRange.value = [
+          trackingData.eta_start ? trackingData.eta_start : null,
+          trackingData.eta_end ? trackingData.eta_end : null
         ]
-        daterangeObj.ETA =
-          DateEnd.value[0].format(formatDate) + ' To ' + DateEnd.value[1].format(formatDate)
-        const obj = {
-          title: 'ETA',
-          data: [DateEnd.value[0].format(valueFormatDate), DateEnd.value[1].format(valueFormatDate)]
+        setRange('ETD', 'ETD', trackingData.etd_start, trackingData.etd_end)
+        setRange('ETA', 'ETA', trackingData.eta_start, trackingData.eta_end)
+        if (trackingData.created_time_start) {
+          setAddDateType(trackingData.created_time_start, trackingData.created_time_end)
+          setRange(
+            'Creation Time',
+            'Creation Time',
+            trackingData.created_time_start,
+            trackingData.created_time_end
+          )
         }
-        daterangeObj2.ETA = obj
       }
-      if (searchTableQeury.value.created_time_start) {
-        DateCreation.value = [
-          dayjs(searchTableQeury.value.created_time_start),
-          dayjs(searchTableQeury.value.created_time_end)
-        ]
-        daterangeObj['Creation Time'] =
-          DateCreation.value[0].format(formatDate) +
-          ' To ' +
-          DateCreation.value[1].format(formatDate)
-        const obj = {
-          title: 'Creation Time',
-          data: [
-            DateCreation.value[0].format(valueFormatDate),
-            DateCreation.value[1].format(valueFormatDate)
-          ]
-        }
-        daterangeObj2['Creation Time'] = obj
+    }
+    emitPayload = trackingData
+  } else {
+    // 非 shipment 场景
+    const stored = sessionStorage.getItem('searchTableQeury')
+    if (!stored) {
+      // 无存储 → 默认值
+      const [start, end] = getDefaultRange()
+      etdDateRange.value = [start, end]
+      setRange('ETD', 'ETD', start, end)
+    } else {
+      // 有存储
+      const queryData = JSON.parse(stored)
+      emitPayload = queryData
+
+      etdDateRange.value = [
+        queryData.f_etd_start ? queryData.f_etd_start : null,
+        queryData.f_etd_end ? queryData.f_etd_end : null
+      ]
+      etaDateRange.value = [
+        queryData.m_eta_start ? queryData.m_eta_start : null,
+        queryData.m_eta_end ? queryData.m_eta_end : null
+      ]
+      setRange('ETD', 'ETD', queryData.f_etd_start, queryData.f_etd_end)
+      setRange('ETA', 'ETA', queryData.m_eta_start, queryData.m_eta_end)
+      if (queryData.created_time_start) {
+        setAddDateType(queryData.created_time_start, queryData.created_time_end)
+        setRange(
+          'Creation Time',
+          'Creation Time',
+          queryData.created_time_start,
+          queryData.created_time_end
+        )
       }
     }
-    emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeury.value)
   }
+  return emitPayload
 }
 const daterangedata = ref()
 daterangedata.value = []
 let daterangeObj2: any = {}
 const DateRangeChange = (val: any) => {
   if (val.data != null) {
-    const date1 = dayjs(String(val.data[0])).format(formatDate)
-    const date2 = dayjs(String(val.data[1])).format(formatDate)
-    daterangeObj[val.title] = date1 + ' To ' + date2
+    val.data = [
+      dayjs(val.data[0], valueFormatDate).format(formatDate),
+      dayjs(val.data[1], valueFormatDate).format(formatDate)
+    ]
     daterangeObj2[val.title] = val
   } else {
-    delete daterangeObj[val.title]
     delete daterangeObj2[val.title]
     if (val.title == 'ETD') {
-      DateStart.value = []
+      etdDateRange.value = []
     } else if (val.title == 'ETA') {
-      DateEnd.value = []
+      etaDateRange.value = []
     } else {
       DateCreation.value = []
       AddDateType.value = []
@@ -264,34 +217,26 @@ const DateRangeChange = (val: any) => {
 }
 const emit = defineEmits(['DateRangeSearch', 'clearDaterangeTags', 'defaultDate'])
 const DateRangeSearch = () => {
-  emit('DateRangeSearch', daterangeObj, daterangeObj2)
+  emit('DateRangeSearch', daterangeObj2)
   Date_visible.value = false
 }
-const CalendarTitle = ref('Date Range')
-watch(
-  () => DateType.value,
-  (current) => {
-    CalendarTitle.value = current
-  }
-)
+
 // 清除
-const clearrest = () => {
+const clearRest = () => {
   emit('clearDaterangeTags')
-  clearDateStart()
-  clearDateEnd()
+  clearETdDateRange()
+  clearEtaDateRange()
   clearDateCreation()
   clearDaterangeObj()
 }
 // 清除EDT
-const clearDateStart = () => {
-  DateStart.value = []
-  delete daterangeObj['ETD']
+const clearETdDateRange = () => {
+  etdDateRange.value = []
   delete daterangeObj2['ETD']
 }
 // 清除EDA
-const clearDateEnd = () => {
-  DateEnd.value = []
-  delete daterangeObj['ETA']
+const clearEtaDateRange = () => {
+  etaDateRange.value = []
   delete daterangeObj2['ETA']
 }
 // 清除Creation Time
@@ -299,19 +244,23 @@ const clearDateCreation = () => {
   DateCreation.value = []
   AddDateType.value = []
   DateType.value = ''
-  CalendarTitle.value = 'Date Range'
-  delete daterangeObj['Creation Time']
   delete daterangeObj2['Creation Time']
 }
 // 清除 daterangeObj
 const clearDaterangeObj = () => {
-  daterangeObj = {}
   daterangeObj2 = {}
 }
 </script>
 <template>
   <div class="select">
-    <el-popover trigger="click" :width="400" :visible="Date_visible" popper-class="DaterangeClass">
+    <el-popover
+      trigger="click"
+      :width="400"
+      :visible="Date_visible"
+      popper-class="DaterangeClass"
+      @before-enter="defaultDate()"
+      @hide="clearDateCreation()"
+    >
       <template #reference>
         <div class="Date_Range" @blur="Date_visible = false" @click="Date_visible = !Date_visible">
           <div class="select_title">Date Range</div>
@@ -327,18 +276,18 @@ const clearDaterangeObj = () => {
         <div class="ETD">
           <CalendarDate
             CalendarTitle="ETD"
-            :Date="DateStart"
+            :Date="etdDateRange"
             @DateRangeChange="DateRangeChange"
           ></CalendarDate>
         </div>
         <div class="ETA">
           <CalendarDate
             CalendarTitle="ETA"
-            :Date="DateEnd"
+            :Date="etaDateRange"
             @DateRangeChange="DateRangeChange"
           ></CalendarDate>
         </div>
-        <div class="AddType" v-for="(item, index) in AddDateType" :key="item">
+        <div class="AddType" v-for="(item, index) in AddDateType" :key="item.value">
           <div>
             <div class="ETD_title Date_Title">
               <div class="Date_type">Date Type</div>
@@ -351,7 +300,7 @@ const clearDaterangeObj = () => {
             <el-select
               :suffix-icon="IconDropDown"
               placeholder="Please Select Date Type"
-              v-model="DateType"
+              v-model="item.label"
             >
               <el-option
                 v-for="item in DateTypeoptions"
@@ -364,9 +313,9 @@ const clearDaterangeObj = () => {
           </div>
           <div style="margin-top: 16px">
             <CalendarDate
-              :CalendarTitle="CalendarTitle"
+              :CalendarTitle="item.label || 'Date Range'"
               CalendarWidth="352px"
-              :Date="DateCreation"
+              :Date="item.value"
               @DateRangeChange="DateRangeChange"
               :isType="true"
             ></CalendarDate>
@@ -376,7 +325,7 @@ const clearDaterangeObj = () => {
           <el-button class="el-button--noborder moretype">+ More Date Type</el-button>
         </div>
         <div class="daterange_bottom">
-          <div><el-button type="default" @click="clearrest" class="Clear">Reset</el-button></div>
+          <div><el-button type="default" @click="clearRest" class="Clear">Reset</el-button></div>
           <div>
             <el-button class="search el-button--dark" @click="DateRangeSearch">Search</el-button>
           </div>

+ 8 - 20
src/components/DateRange/src/components/CalendarDate.vue

@@ -4,6 +4,7 @@ import { ref, watch } from 'vue'
 import { useUserStore } from '@/stores/modules/user'
 
 const userStore = useUserStore()
+const formatDate = userStore.dateFormat
 const valueFormatDate = 'MM/DD/YYYY'
 // type RangeValue = [Dayjs, Dayjs]
 // const ETDDate = ref<RangeValue>()
@@ -48,8 +49,8 @@ watch(
   (current: any) => {
     if (current?.length == 2) {
       ETDDate.value = [
-        current[0] ? dayjs(current[0]).format(valueFormatDate) : '',
-        current[1] ? dayjs(current[1]).format(valueFormatDate) : ''
+        current[0] ? dayjs(current[0], formatDate).format(valueFormatDate) : '',
+        current[1] ? dayjs(current[1], formatDate).format(valueFormatDate) : ''
       ]
     } else {
       ETDDate.value = []
@@ -76,15 +77,10 @@ const daterange = (val: any) => {
 }
 const ChangeToday = (val: any) => {
   if (val == 'Earliest') {
-    // ETDDate.value = [dayjs(), dayjs()]
-    ETDDate.value[0] = dayjs()
-    const date1 = dayjs(String(ETDDate.value[0])).format(valueFormatDate)
-    DateList.value[0] = date1
+    DateList.value[0] = dayjs().format(valueFormatDate)
     daterange(DateList.value[1])
   } else {
-    ETDDate.value[1] = dayjs()
-    const date1 = dayjs(String(ETDDate.value[1])).format(valueFormatDate)
-    DateList.value[1] = date1
+    DateList.value[1] = dayjs().format(valueFormatDate)
     daterange(DateList.value[0])
   }
 }
@@ -99,15 +95,11 @@ const handleCalendarOpen = (date: any) => {
   }
 }
 const Earliest = () => {
-  ETDDate.value[0] = dayjs('Oct-05-2009')
-  const date1 = dayjs(String(ETDDate.value[0])).format(valueFormatDate)
-  DateList.value[0] = date1
+  DateList.value[0] = dayjs('Oct-05-2009').format(valueFormatDate)
   daterange(DateList.value[1])
 }
 const Latest = () => {
-  ETDDate.value[1] = dayjs()
-  const date1 = dayjs(String(ETDDate.value[1])).format(valueFormatDate)
-  DateList.value[1] = date1
+  DateList.value[1] = dayjs().format(valueFormatDate)
   daterange(DateList.value[0])
 }
 const changeRangeData = (value: any) => {
@@ -128,10 +120,6 @@ const handlePanelChange = (value: any, mode: any) => {
     isShowExtra.value = true
   }
 }
-// 判断失焦时是否两个都有值
-const isTwoDate = (date: any) => {
-  console.log(date)
-}
 </script>
 <template>
   <div>
@@ -143,7 +131,7 @@ const isTwoDate = (date: any) => {
         width: props.CalendarWidth,
         backgroundColor: props.isType ? 'var(--more-type-bg-color)' : 'var(--management-bg-color)'
       }"
-      :popupClassName="{ 'th-color': props.isShowPopupClass }"
+      :popupClassName="props.isShowPopupClass ? 'th-color' : ''"
       :open="open"
       :disabled="Disabled"
       @change="changeRangeData"

+ 33 - 18
src/components/TransportMode/src/TransportMode.vue

@@ -2,6 +2,7 @@
 import { ref, onMounted, onBeforeMount, watch, computed } from 'vue'
 import type { DropdownInstance } from 'element-plus'
 import emitter from '@/utils/bus'
+import { cloneDeep } from 'lodash'
 
 interface ListItem {
   name: string
@@ -16,22 +17,24 @@ interface Props {
 }
 const props = withDefaults(defineProps<Props>(), {})
 const TransportList = ref(props.TransportListItem)
+const updateTransportList = (data: any) => {
+  TransportList.value = cloneDeep(data)
+  TransportList.value.forEach((item: any) => {
+    if (item.checked) {
+      checkedCount.push(item.sname)
+      const map = new Map()
+      checkedCount.forEach((item) => map.set(item, true))
+      checkedCount = [...map.keys()]
+    }
+    if (checkedCount.length == TransportList.value.length) {
+      checkAll.value = true
+    }
+  })
+}
 watch(
   () => props.TransportListItem,
   (current) => {
-    console.log(current)
-    TransportList.value = current
-    TransportList.value.forEach((item: any) => {
-      if (item.checked) {
-        checkedCount.push(item.sname)
-        const map = new Map()
-        checkedCount.forEach((item) => map.set(item, true))
-        checkedCount = [...map.keys()]
-      }
-      if (checkedCount.length == TransportList.value.length) {
-        checkAll.value = true
-      }
-    })
+    updateTransportList(current)
   }
 )
 
@@ -49,7 +52,7 @@ onBeforeMount(() => {
 })
 
 const checkAll = ref(false)
-const dropdown1 = ref<DropdownInstance>()
+const dropdownVisible = ref<DropdownInstance>()
 let checkedCount: any[] = []
 const TotalAll = computed(() => {
   var total_sum = 0
@@ -120,11 +123,11 @@ const TransportSearch = (visible: any) => {
   }
   TransportData.data = changedata.value
   emit('TransportSearch', TransportData)
-  if (!dropdown1.value) return
+  if (!dropdownVisible.value) return
   if (visible) {
-    dropdown1.value.handleClose()
+    dropdownVisible.value.handleClose()
   } else {
-    dropdown1.value.handleOpen()
+    dropdownVisible.value.handleOpen()
   }
 }
 const searchTableQeury = ref()
@@ -201,10 +204,22 @@ const defaultTransport = () => {
     emit('defaultTransport', TransportData, searchTableQeury.value)
   }
 }
+
+// 每次打开时都应该重新赋值
+const handleDropdownVisibleChange = (visible: boolean) => {
+  if (visible) {
+    updateTransportList(props.TransportListItem)
+  }
+}
 </script>
 <template>
   <div class="select">
-    <el-dropdown ref="dropdown1" trigger="click" :hide-on-click="false">
+    <el-dropdown
+      ref="dropdownVisible"
+      trigger="click"
+      :hide-on-click="false"
+      @visible-change="handleDropdownVisibleChange"
+    >
       <div class="el-dropdown-link">
         <div class="select_title">Transport Mode</div>
         <span class="iconfont_icon">

+ 5 - 1
src/utils/table.ts

@@ -6,7 +6,7 @@ import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
  * @param grid 表格实例
  * @returns
  */
-export const autoWidth = (tableData: VxeGridProps, grid: VxeGridInstance) => {
+export const autoWidth = (tableData: VxeGridProps, grid: VxeGridInstance, customizeWidth?: { [key: string]: number }) => {
   const columns = tableData.columns
   const data = tableData.data
   const columnsWidth: { width: number; field: any }[] = []
@@ -47,6 +47,10 @@ export const autoWidth = (tableData: VxeGridProps, grid: VxeGridInstance) => {
       if (field === 'Mode') {
         width = 80
       }
+      // 如果有自定义宽度,则使用自定义宽度
+      if (customizeWidth && customizeWidth[field]) {
+        width = customizeWidth[field]
+      }
 
       columnsWidth.push({
         width,

+ 65 - 28
src/views/Booking/src/BookingView.vue

@@ -7,6 +7,12 @@ import DateRange from '@/components/DateRange'
 import MoreFilters from '@/components/MoreFilters'
 import { ref, reactive } from 'vue'
 import { useCalculatingHeight } from '@/hooks/calculatingHeight'
+import { useUserStore } from '@/stores/modules/user'
+import dayjs from 'dayjs'
+
+const userStore = useUserStore()
+const formatDate = userStore.dateFormat
+const valueFormatDate = 'MM/DD/YYYY'
 
 const filterRef: Ref<HTMLElement | null> = ref(null)
 
@@ -21,7 +27,7 @@ const filterData = reactive({
   daterangeData: [] as Array<string>,
   morefiltersData: [] as Array<string>
 })
-onMounted(() => {})
+
 const tagsData: any = ref([])
 const handleClose = (tag: any) => {
   emitter.emit('clearTag', tag)
@@ -111,18 +117,13 @@ const defaultTransport = (val: any, value: any) => {
   renderTagsData()
 }
 // defaultDate
-const defaultDate = (val: any, value: any, data: any) => {
-  filterData.daterangeData = []
-  if (Object.keys(val).length) {
-    for (const key in val) {
-      let str = `${key}:${val[key]}`
-      filterData.daterangeData.push(str)
-    }
-  }
+const defaultDate = (dateRangeData: any, data: any) => {
+  setFilterData(dateRangeData)
+
   if (sessionStorage.getItem('searchTableQeury') == null) {
-    for (const key in value) {
-      searchTableQeury.f_etd_start = value[key].data[0]
-      searchTableQeury.f_etd_end = value[key].data[1]
+    for (const key in dateRangeData) {
+      searchTableQeury.f_etd_start = dateRangeData[key].data[0]
+      searchTableQeury.f_etd_end = dateRangeData[key].data[1]
     }
   } else {
     searchTableQeury = data
@@ -133,16 +134,20 @@ const defaultDate = (val: any, value: any, data: any) => {
   getbookingdata()
   renderTagsData()
 }
-//DateRangeSearch
-const DateRangeSearch = (val: any, value: any) => {
+
+const setFilterData = (dateRangeData: any) => {
   filterData.daterangeData = []
-  if (Object.keys(val).length) {
-    for (const key in val) {
-      let str = `${key}:${val[key]}`
-      filterData.daterangeData.push(str)
-    }
+  for (const key in dateRangeData) {
+    const startEnd = dateRangeData[key].data[0] + ' To ' + dateRangeData[key].data[1]
+    let str = `${key}:${startEnd}`
+    filterData.daterangeData.push(str)
   }
-  if (Object.keys(value).length == 0) {
+}
+//DateRangeSearch
+const DateRangeSearch = (dateRangeData: any) => {
+  setFilterData(dateRangeData)
+
+  if (Object.keys(dateRangeData).length == 0) {
     delete searchTableQeury.f_etd_start
     delete searchTableQeury.f_etd_end
     delete searchTableQeury.m_eta_start
@@ -150,16 +155,31 @@ const DateRangeSearch = (val: any, value: any) => {
     delete searchTableQeury.created_time_start
     delete searchTableQeury.created_time_end
   }
-  for (const key in value) {
+  const fieldList = [
+    {
+      title: 'ETD',
+      keys: ['f_etd_start', 'f_etd_end']
+    },
+    { title: 'ETA', keys: ['m_eta_start', 'm_eta_end'] },
+    { title: 'Creation Time', keys: ['created_time_start', 'created_time_end'] }
+  ]
+  fieldList.forEach((item) => {
+    if (!dateRangeData.hasOwnProperty(item.title)) {
+      // 删除不存在的字段
+      searchTableQeury[item.keys[0]] = undefined
+      searchTableQeury[item.keys[1]] = undefined
+    }
+  })
+  for (const key in dateRangeData) {
     if (key == 'ETD') {
-      searchTableQeury.f_etd_start = value[key].data[0]
-      searchTableQeury.f_etd_end = value[key].data[1]
+      searchTableQeury.f_etd_start = dateRangeData[key].data[0]
+      searchTableQeury.f_etd_end = dateRangeData[key].data[1]
     } else if (key == 'ETA') {
-      searchTableQeury.m_eta_start = value[key].data[0]
-      searchTableQeury.m_eta_end = value[key].data[1]
+      searchTableQeury.m_eta_start = dateRangeData[key].data[0]
+      searchTableQeury.m_eta_end = dateRangeData[key].data[1]
     } else {
-      searchTableQeury.created_time_start = value[key].data[0]
-      searchTableQeury.created_time_end = value[key].data[1]
+      searchTableQeury.created_time_start = dateRangeData[key].data[0]
+      searchTableQeury.created_time_end = dateRangeData[key].data[1]
     }
   }
   sessionStorage.setItem('searchTableQeury', JSON.stringify(searchTableQeury))
@@ -329,7 +349,23 @@ interface ListItem {
 const TagsList = ref<ListItem[]>([])
 const filterTag = ref(['All'])
 const isShowAlertIcon = ref(false)
+const setSearchQeury = () => {}
 const getbookingdata = () => {
+  const dateRangeKeys = [
+    'f_etd_start',
+    'f_etd_end',
+    'm_eta_start',
+    'm_eta_end',
+    'created_time_start',
+    'created_time_end'
+  ]
+  const curRangeData: any = {}
+  for (const key of dateRangeKeys) {
+    if (searchTableQeury[key] !== undefined) {
+      curRangeData[key] = dayjs(searchTableQeury[key], formatDate).format(valueFormatDate)
+    }
+  }
+
   tableLoadingTableData.value = true
   BookingTable_ref.value.getLoadingData(tableLoadingTableData.value)
   $api
@@ -338,7 +374,8 @@ const getbookingdata = () => {
       ps: BookingTable_ref.value.pageInfo.pageSize,
       rc: -1,
       other_filed: '',
-      ...searchTableQeury
+      ...searchTableQeury,
+      ...curRangeData
     })
     .then((res: any) => {
       if (res.code === 200) {

+ 6 - 2
src/views/Booking/src/components/BookingTable/src/BookingTable.vue

@@ -397,7 +397,11 @@ const handleCustomizeColumns = () => {
       model_name: 'Booking_Search'
     }
   }
-  CustomizeColumnsRef.value.openDialog(params, -220)
+  CustomizeColumnsRef.value.openDialog(
+    params,
+    -220,
+    'Drag item over to this selection or click "add" icon to show the column on your booking list'
+  )
 }
 // 定制表格
 const customizeColumns = async () => {
@@ -422,13 +426,13 @@ const handleLinkClick = (row: any, column: any) => {
       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 }
     })
   }
+  visitedRowState.setBookingTableData(row['__serial_no'])
 }
 
 const selectedNumber = ref(0)

+ 28 - 20
src/views/Dashboard/src/DashboardView.vue

@@ -141,7 +141,7 @@ const GetKpiData = (val: any) => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        KPIobj.ETD_Title = `{a|${res.data.title1}}{b|${res.data.title2}}`
+        KPIobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
         KPIobj.ETDList = res.data.ETDList
         KPIobj.ETD_Radius = res.data.ETD_Radius
         KPIobj.download_name = res.data.download_name
@@ -158,7 +158,7 @@ const GetKpiData = (val: any) => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        Arrivalobj.ETD_Title = `{a|${res.data.title1}}{b|${res.data.title2}}`
+        Arrivalobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
         Arrivalobj.ETDList = res.data.ETDList
         Arrivalobj.ETD_Radius = res.data.ETD_Radius
         Arrivalobj.download_name = res.data.download_name
@@ -193,7 +193,7 @@ const GetPendingEcharts = (val: any) => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        Pendingobj.ETD_Title = `{a|${res.data.title1}}{b|${res.data.title2}}`
+        Pendingobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
         Pendingobj.ETDList = res.data.ETDList
         Pendingobj.ETD_Radius = res.data.ETD_Radius
         Pendingobj.download_name = res.data.download_name
@@ -210,7 +210,7 @@ const GetPendingEcharts = (val: any) => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        PendingArrivalobj.ETD_Title = `{a|${res.data.title1}}{b|${res.data.title2}}`
+        PendingArrivalobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
         PendingArrivalobj.ETDList = res.data.ETDList
         PendingArrivalobj.ETD_Radius = res.data.ETD_Radius
         PendingArrivalobj.download_name = res.data.download_name
@@ -582,11 +582,7 @@ const ClickParams = (val: any) => {
   }
   //  PendingArrival点击跳转
   else if (val == 'Pending1') {
-    handleTurnData(
-      dashboardObj.PendingDefaultData.date_start,
-      dashboardObj.PendingDefaultData.date_end,
-      ''
-    )
+    handleTurnData('', '', '') // 因为Pending没有时间筛选,所以传空
     reportList._reportRef = pie_chart_pending_arrival.value[0].paramsdata.name
     reportList._reportType = 'r3'
     handlereportlist(
@@ -606,11 +602,7 @@ const ClickParams = (val: any) => {
   }
   // PendingDeparture点击跳转
   else if (val == 'Pending0') {
-    handleTurnData(
-      dashboardObj.PendingDefaultData.date_start,
-      dashboardObj.PendingDefaultData.date_end,
-      ''
-    )
+    handleTurnData('', '', '') // 因为Pending没有时间筛选,所以传空
     reportList._reportType = 'r4'
     reportList._reportRef = pie_chart_pending_departure.value[0].paramsdata.name
     handlereportlist(
@@ -659,7 +651,7 @@ const ClickParams = (val: any) => {
       dashboardObj.KPIDefaulteData.date_end,
       ''
     )
-    reportList._reportRef = pie_chart_kpi_arrival.value[0].paramsdata.name
+    reportList._reportRef = pie_chart_kpi_arrival.value[0]?.paramsdata?.name || ''
     reportList._reportType = 'ata_r3'
     handlereportlist(
       dashboardObj.KPIDefaulteData.transportation,
@@ -670,7 +662,7 @@ const ClickParams = (val: any) => {
     sessionStorage.setItem('reportList', JSON.stringify(reportList))
     let obj: any = {}
     obj.title = 'KPI Arrival'
-    obj.name = pie_chart_kpi_arrival.value[0].paramsdata.name
+    obj.name = pie_chart_kpi_arrival.value[0]?.paramsdata?.name || ''
     sessionStorage.setItem('tagsList', JSON.stringify(obj))
     router.push({
       path: '/tracking'
@@ -880,10 +872,21 @@ function handleImageClick(event) {
             <div class="management_content" v-for="(item, index) in Management" :key="index">
               <div class="management_flex">
                 <div class="content_title">{{ item.title }}</div>
-                <div><el-switch v-model="item.switchValue" :disabled="item.isRevenueDisplay != undefined && item.isRevenueDisplay == false" /></div>
+                <div>
+                  <el-switch
+                    v-model="item.switchValue"
+                    :disabled="item.isRevenueDisplay != undefined && item.isRevenueDisplay == false"
+                  />
+                </div>
               </div>
               <div class="content_text">{{ item.text }}</div>
-              <div class="content_text_warining" v-if="item.isRevenueDisplay != undefined && item.isRevenueDisplay == false">*To ensure the accuracy of the data display, this report needs to be configured and displayed after communicating clearly with Sales.</div>
+              <div
+                class="content_text_warining"
+                v-if="item.isRevenueDisplay != undefined && item.isRevenueDisplay == false"
+              >
+                *To ensure the accuracy of the data display, this report needs to be configured and
+                displayed after communicating clearly with Sales.
+              </div>
             </div>
             <el-divider />
             <div class="tips">
@@ -1167,6 +1170,7 @@ function handleImageClick(event) {
                   v-vloading="containerLoading"
                   style="height: 300px"
                   :isRevenue="true"
+                  save-image-name="Container Count"
                   :barHeight="{ height: '300px' }"
                 ></BarChart>
               </template>
@@ -1212,6 +1216,7 @@ function handleImageClick(event) {
                       :SellerData="Top10Obj.OriginData"
                       v-vloading="TopOriginLoading"
                       :Interval="Top1OInterval"
+                      saveImageName="Top 10 Origin"
                     ></SellerChart>
                   </div>
                   <div class="map">
@@ -1229,10 +1234,11 @@ function handleImageClick(event) {
                       :SellerData="Top10Obj.DestinationData"
                       :Interval="Top1OInterval_dest"
                       v-vloading="TopOriginLoading"
-                      style="height: 272px"
+                      saveImageName="Top 10 Destination"
+                      style="height: 310px"
                     ></SellerChart>
                   </div>
-                  <div class="map" style="height: 272px">
+                  <div class="map" style="height: 310px">
                     <!-- <TopMap :obj="dashboardObj.Top10faultData" ref="Top10Destinationref"></TopMap> -->
                     <TopMap ref="Top10Destinationref"></TopMap>
                   </div>
@@ -1267,6 +1273,7 @@ function handleImageClick(event) {
                 <BarChart
                   ref="seller_chart_CO2_origin"
                   :BarData="EmissionObj"
+                  save-image-name="CO2e Emission by Origin (Top 10)"
                   @clickParams="ClickParams(item.title)"
                   v-vloading="EmissionLoading"
                   style="height: 250px"
@@ -1301,6 +1308,7 @@ function handleImageClick(event) {
                   v-vloading="DestinationLoading"
                   style="height: 250px"
                   :isRevenue="true"
+                  save-image-name="CO2e Emission by Destination (Top 10)"
                   @clickParams="ClickParams(item.title)"
                   :barHeight="{ height: '250px' }"
                 ></BarChart>

+ 49 - 15
src/views/Dashboard/src/components/BarChart.vue

@@ -7,7 +7,8 @@ import { formatNumber } from '@/utils/tools'
 const themeStore = useThemeStore()
 const props = defineProps({
   BarData: Object,
-  barHeight: Object
+  barHeight: Object,
+  saveImageName: String
 })
 const bar_data = ref(props.BarData)
 const bar_ref = ref()
@@ -21,7 +22,9 @@ watch(
     initOption.yAxis.max = Max.value
     initOption.yAxis.interval = interval.value
     initOption.title.text = bar_title.value
-    initChart()
+    nextTick(() => {
+      barChart.value.setOption(initOption)
+    })
   },
   {
     deep: true
@@ -62,7 +65,7 @@ const Name = computed(() => {
 const initOption = reactive({
   //标题
   title: {
-    text: bar_title.value || 'Total:', //主标题
+    text: bar_title.value || '', //主标题
     left: 19,
     top: 9.5,
     textStyle: {
@@ -144,13 +147,13 @@ const initOption = reactive({
       show: true,
       lineStyle: {
         type: 'dashed',
-        color: '#eaebed'
+        color: '#3F434A'
       }
     },
     axisLine: {
       show: true,
       lineStyle: {
-        color: '#eaebed'
+        color: '#3F434A'
       }
     },
     axisLabel: {
@@ -177,24 +180,56 @@ const initOption = reactive({
       color: '#646A73'
     }
   },
+  toolbox: {
+    top: 6,
+    right: 8,
+    iconStyle: {
+      borderColor: '#2B2F36'
+    },
+    emphasis: {
+      iconStyle: {
+        borderColor: '#ff7500'
+      } // hover上去时的颜色
+    },
+    feature: {
+      saveAsImage: {
+        show: true,
+        name: bar_title.value || props.saveImageName || 'data',
+        type: 'png',
+        backgroundColor: '#fff'
+      }
+    },
+    showTitle: false
+  },
   series: bar_series.value
 })
 onMounted(() => {
   initChart()
   clickParams()
+
   watch(
     () => themeStore.theme,
     (newVal) => {
       if (newVal === 'dark') {
-        initOption.xAxis.axisLine.lineStyle.color = '#3F434A'
-        initOption.yAxis.axisLine.lineStyle.color = '#3F434A'
-        initOption.yAxis.splitLine.lineStyle.color = '#3F434A'
-        initChart()
+        initOption.title.textStyle.color = '#f0f1f3'
+        initOption.xAxis.axisLine.lineStyle.color = '#8d9095'
+        initOption.yAxis.axisLine.lineStyle.color = '#8d9095'
+        initOption.yAxis.splitLine.lineStyle.color = '#8d9095'
+        initOption.toolbox.iconStyle.borderColor = '#f0f1f3'
+        initOption.toolbox.feature.saveAsImage.backgroundColor = '#3F434A'
+        nextTick(() => {
+          barChart.value.setOption(initOption)
+        })
       } else {
+        initOption.title.textStyle.color = '#2B2F36'
         initOption.xAxis.axisLine.lineStyle.color = '#eaebed'
         initOption.yAxis.axisLine.lineStyle.color = '#eaebed'
         initOption.yAxis.splitLine.lineStyle.color = '#eaebed'
-        initChart()
+        initOption.toolbox.iconStyle.borderColor = '#2B2F36'
+        initOption.toolbox.feature.saveAsImage.backgroundColor = '#fff'
+        nextTick(() => {
+          barChart.value.setOption(initOption)
+        })
       }
     },
     {
@@ -210,21 +245,20 @@ const paramsdata = ref({
   type: ''
 })
 const clickParams = () => {
-  const bar_chart = echarts.init(bar_ref.value)
   // 监听点击事件
-  bar_chart.on('click', function (params) {
+  barChart.value.on('click', function (params) {
     paramsdata.value.name = params.name
     paramsdata.value.type = params.seriesName
     emits('ClickParams')
   })
 }
+const barChart = ref()
 const initChart = () => {
-  const bar_chart = echarts.init(bar_ref.value)
+  barChart.value = echarts.init(bar_ref.value)
   //图表响应式
   window.addEventListener('resize', () => {
-    bar_chart.resize()
+    barChart.value.resize()
   })
-  bar_chart.setOption(initOption)
 }
 
 defineExpose({

+ 74 - 39
src/views/Dashboard/src/components/PieChart.vue

@@ -4,6 +4,7 @@ import * as echarts from 'echarts'
 import { useThemeStore } from '@/stores/modules/theme'
 import { onMounted, ref, reactive, watch, computed } from 'vue'
 import { formatNumber } from '@/utils/tools'
+
 const props = defineProps({
   PieData: Object
 })
@@ -15,7 +16,9 @@ watch(
     pie_data.value = current
     initOption.title.text = pie_title.value
     initOption.toolbox.feature.saveAsImage.name = downloadName.value
-    initChart()
+    nextTick(() => {
+      pieChart.value.setOption(initOption)
+    })
   },
   {
     deep: true
@@ -46,6 +49,25 @@ const downloadName = computed(() => {
 })
 
 const initOption: any = reactive({
+  // graphic: {
+  //   elements: [
+  //     {
+  //       type: 'text',
+  //       right: '16',
+  //       bottom: '16',
+  //       style: {
+  //         text: 'Total: $12,500',
+  //         fontSize: 14,
+  //         fill: '#666'
+  //       },
+  //       // 直接设置 onclick 回调
+  //       onclick: function () {
+  //         alert('Total clicked!')
+  //         // 或者执行其他逻辑
+  //       }
+  //     }
+  //   ]
+  // },
   //标题
   title: {
     text: pie_title.value || '', //主标题
@@ -90,6 +112,8 @@ const initOption: any = reactive({
     }
   },
   toolbox: {
+    top: 6,
+    right: 8,
     iconStyle: {
       borderColor: '#2B2F36'
     },
@@ -98,10 +122,10 @@ const initOption: any = reactive({
         borderColor: '#ff7500'
       } // hover上去时的颜色
     },
-    show: false, // 显示工具箱
+    show: true, // 显示工具箱
     feature: {
-      restore: { show: true },
-      saveAsImage: { show: true, name: downloadName.value }
+      // restore: { show: true },
+      saveAsImage: { show: true, name: downloadName.value, type: 'png', backgroundColor: '#fff' }
     },
     showTitle: false
   },
@@ -143,15 +167,13 @@ const initOption: any = reactive({
       length2: 0,
       maxSurfaceAngle: 80
     },
-    labelLayout: function (params: any) {
-      const pie_chart = echarts.init(pie_ref.value)
-      const isLeft = params.labelRect.x < pie_chart.getWidth() / 2
+    labelLayout: (params) => {
+      const isLeft = params.labelRect.x < containerWidth.value / 2
       const points = params.labelLinePoints
-      // Update the end point.
-      points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width
-      return {
-        labelLinePoints: points
+      if (points?.[2]) {
+        points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width
       }
+      return { labelLinePoints: points }
     }
   },
   legend: {
@@ -168,49 +190,62 @@ const initOption: any = reactive({
     }
   }
 })
-
+const containerWidth = ref(0)
+onMounted(() => {
+  if (pie_ref.value) {
+    containerWidth.value = pie_ref.value.clientWidth
+    // 如果需要响应式 resize,可用 ResizeObserver
+  }
+})
 onMounted(() => {
   initChart()
   clickParams()
-  watch(
-    () => themeStore.theme,
-    (newVal) => {
-      if (newVal === 'dark') {
-        initOption.title.textStyle.color = '#f0f1f3'
-        initOption.series.label.rich.time.color = 'rgba(240,241,243,0.7)'
-        initOption.series.label.rich.name.color = 'rgba(240,241,243,0.7)'
-        initOption.legend.textStyle.color = 'rgba(240,241,243,0.7)'
-        initChart()
-      } else {
-        initOption.title.textStyle.color = '#2B2F36'
-        initOption.series.label.rich.time.color = '#999'
-        initOption.series.label.rich.name.color = '#646A73'
-        initOption.legend.textStyle.color = '#646A73'
-        initChart()
-      }
-    },
-    {
-      immediate: true,
-      deep: true
-    }
-  )
 })
+watch(
+  () => themeStore.theme,
+  (newVal) => {
+    if (newVal === 'dark') {
+      initOption.title.textStyle.color = '#f0f1f3'
+      initOption.series.label.rich.time.color = 'rgba(240,241,243,0.7)'
+      initOption.series.label.rich.name.color = 'rgba(240,241,243,0.7)'
+      initOption.legend.textStyle.color = 'rgba(240,241,243,0.7)'
+      initOption.toolbox.iconStyle.borderColor = '#f0f1f3'
+      initOption.toolbox.feature.saveAsImage.backgroundColor = '#2B2F36'
+      nextTick(() => {
+        pieChart.value.setOption(initOption)
+      })
+    } else {
+      initOption.title.textStyle.color = '#2B2F36'
+      initOption.series.label.rich.time.color = '#999'
+      initOption.series.label.rich.name.color = '#646A73'
+      initOption.legend.textStyle.color = '#646A73'
+      initOption.toolbox.iconStyle.borderColor = '#2B2F36'
+      initOption.toolbox.feature.saveAsImage.backgroundColor = '#fff'
+      nextTick(() => {
+        pieChart.value.setOption(initOption)
+      })
+    }
+  },
+  {
+    immediate: true,
+    deep: true
+  }
+)
 const emits = defineEmits(['ClickParams'])
 const paramsdata = ref()
+const pieChart = ref()
 const clickParams = () => {
-  const pie_chart = echarts.init(pie_ref.value)
   // 监听点击事件
-  pie_chart.on('click', function (params) {
+  pieChart.value.on('click', function (params) {
     paramsdata.value = params.data
     emits('ClickParams')
   })
 }
 const initChart = () => {
-  const pie_chart = echarts.init(pie_ref.value)
-  pie_chart.setOption(initOption)
+  pieChart.value = echarts.init(pie_ref.value)
   //图表响应式
   window.addEventListener('resize', () => {
-    pie_chart.resize()
+    pieChart.value.resize()
   })
 }
 defineExpose({

+ 0 - 1
src/views/Dashboard/src/components/RecentStatus.vue

@@ -45,7 +45,6 @@ const SubscribeShipments = (val: any) => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        console.log(res.data)
       }
     })
 }

+ 35 - 99
src/views/Dashboard/src/components/RevenueChart.vue

@@ -23,9 +23,10 @@ watch(
     initOption.xAxis.data = barName.value
     initOption.series = bar_series.value
     initOption.legend.data = Name.value
-    initOption.toolbox.feature.saveAsImage.name = downloadName.value
     initOption.toolbox.show = isShowTooltips.value
-    initChart()
+    nextTick(() => {
+      revenueChart.value.setOption(initOption)
+    })
   },
   {
     deep: true
@@ -37,7 +38,9 @@ watch(
     bar_data.value = current
     initOption.yAxis.max = Max.value
     initOption.yAxis.interval = interval.value
-    initChart()
+    nextTick(() => {
+      revenueChart.value.setOption(initOption)
+    })
   },
   {
     deep: true,
@@ -74,86 +77,10 @@ const Name = computed(() => {
     return []
   }
 })
-const downloadName = computed(() => {
-  return bar_data.value?.download_name
-})
+
 const isShowTooltips = computed(() => {
   return bar_data.value?.isShowTooltips
 })
-const exportData = ({ filename }: any) => {
-  $api
-    .RevenueDownload({
-      date_start: props.RevenueStartDate,
-      date_end: props.RevenueEndDate
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        let header: any = []
-        let data: any = []
-        let sheetname: any = []
-        let filterA = res.data.r2_cloumn.map((el: any) => {
-          return el.dataIndex
-        })
-        let titleA = res.data.r2_cloumn.map((el: any) => {
-          return el.title
-        })
-        let filterB = res.data.r3_cloumn.map((el: any) => {
-          return el.dataIndex
-        })
-        let titleB = res.data.r3_cloumn.map((el: any) => {
-          return el.title
-        })
-        let result: any = [
-          {
-            tHeader: titleA,
-            filterVal: filterA,
-            tableDatas: res.data.r2,
-            sheetName: res.data.r2_title
-          },
-          {
-            tHeader: titleB,
-            filterVal: filterB,
-            tableDatas: res.data.r3,
-            sheetName: res.data.r3_title
-          }
-        ]
-        let formatJson = (filterVal: any, jsonData: any) => {
-          return jsonData.map((v: any) => filterVal.map((j: any) => v[j]))
-        }
-        for (var i in result) {
-          header.push(result[i].tHeader)
-          sheetname.push(result[i].sheetName)
-          data.push(formatJson(result[i].filterVal, result[i].tableDatas))
-        }
-        // 将表头插入数据数组中
-        for (let i = 0; i < header.length; i++) {
-          data[i].unshift(header[i])
-        }
-        let ws_name = sheetname
-        // 创建工作簿对象
-        let wb = XLSX.utils.book_new()
-        let ws: any = []
-        // 创建每个工作表并设置列宽
-        for (let j = 0; j < header.length; j++) {
-          ws.push(XLSX.utils.aoa_to_sheet(data[j]))
-          let arr: any = []
-          header[j].forEach((val: any) => {
-            arr.push({
-              wpx: 120
-            })
-          })
-          ws[j]['!cols'] = arr
-        }
-        // 将工作表对象添加到工作簿中
-        for (let k = 0; k < header.length; k++) {
-          wb.SheetNames.push(ws_name[k])
-          wb.Sheets[ws_name[k]] = ws[k]
-        }
-        XLSX.writeFile(wb, filename + '.xlsx') // 导出文件
-      }
-    })
-    .finally(() => {})
-}
 
 // 数额
 const initOption = reactive({
@@ -284,19 +211,20 @@ const initOption = reactive({
         borderColor: '#ff7500'
       } // hover上去时的颜色
     },
-    itemSize: 25,
     show: isShowTooltips.value, // 显示工具箱
+    top: 6,
+    right: 8,
     feature: {
-      saveAsImage: { show: false, name: downloadName.value },
-      myTool1: {
-        show: true,
-        title: 'update',
-        icon: 'image://' + updateIcon,
-        onclick: function () {
-          let filename = 'Revenue Spent Details ' + barName.value[0] + '-' + barName.value[barName.value.length - 1]
-          exportData({ filename: filename })
-        }
-      }
+      saveAsImage: { show: true, name: 'Revenue Spent', type: 'png', backgroundColor: '#fff' }
+      // myTool1: {
+      //   show: true,
+      //   title: 'update',
+      //   icon: 'image://' + updateIcon,
+      //   onclick: function () {
+      //     let filename = 'Revenue Spent Details ' + barName.value[0] + '-' + barName.value[barName.value.length - 1]
+      //     exportData({ filename: filename })
+      //   }
+      // }
     },
     showTitle: false
   }
@@ -307,19 +235,27 @@ onMounted(() => {
     () => themeStore.theme,
     (newVal) => {
       if (newVal === 'dark') {
-        initOption.title.textStyle.color = '#f0f1f3'
+        initOption.title.textStyle.color = '#fff'
         initOption.xAxis.axisLine.lineStyle.color = '#3F434A'
         initOption.xAxis.axisLine.lineStyle.color = '#3F434A'
         initOption.yAxis.axisLine.lineStyle.color = '#3F434A'
         initOption.legend.textStyle.color = 'rgba(240,241,243,0.7)'
-        initChart()
+        initOption.toolbox.iconStyle.borderColor = '#f0f1f3'
+        initOption.toolbox.feature.saveAsImage.backgroundColor = '#3F434A'
+        nextTick(() => {
+          revenueChart.value.setOption(initOption)
+        })
       } else {
         initOption.title.textStyle.color = '#2B2F36'
         initOption.xAxis.axisLine.lineStyle.color = '#eaebed'
         initOption.yAxis.axisLine.lineStyle.color = '#eaebed'
         initOption.yAxis.splitLine.lineStyle.color = '#eaebed'
         initOption.legend.textStyle.color = '#646A73'
-        initChart()
+        initOption.toolbox.iconStyle.borderColor = '#2B2F36'
+        initOption.toolbox.feature.saveAsImage.backgroundColor = '#fff'
+        nextTick(() => {
+          revenueChart.value.setOption(initOption)
+        })
       }
     },
     {
@@ -329,13 +265,14 @@ onMounted(() => {
   )
 })
 
+const revenueChart = ref()
 const initChart = () => {
-  const bar_chart = echarts.init(bar_ref.value)
+  revenueChart.value = echarts.init(bar_ref.value)
   //图表响应式
   window.addEventListener('resize', () => {
-    bar_chart.resize()
+    revenueChart.value.resize()
   })
-  bar_chart.on('legendselectchanged', function (event: any) {
+  revenueChart.value.on('legendselectchanged', function (event: any) {
     const selected = event.selected
     let trueCount = 0
     let trueObj: any = {}
@@ -380,9 +317,8 @@ const initChart = () => {
       initOption.yAxis.max = max
       initOption.yAxis.interval = interval
     }
-    bar_chart.setOption(initOption)
+    revenueChart.value.setOption(initOption)
   })
-  bar_chart.setOption(initOption)
 }
 </script>
 

+ 32 - 7
src/views/Dashboard/src/components/SellerChart.vue

@@ -7,7 +7,8 @@ import { formatNumber } from '@/utils/tools'
 const themeStore = useThemeStore()
 const props = defineProps({
   SellerData: Array,
-  Interval: Object
+  Interval: Object,
+  saveImageName: String
 })
 const seller_data = ref(props.SellerData)
 const seller_interval = ref(props.Interval)
@@ -16,7 +17,9 @@ watch(
   () => props.SellerData,
   (current) => {
     seller_data.value = current
-    initChart()
+    nextTick(() => {
+      initChart()
+    })
   },
   {
     deep: true
@@ -28,7 +31,9 @@ watch(
     seller_interval.value = current
     initOption.xAxis.max = Max.value
     initOption.xAxis.interval = interval.value
-    initChart()
+    nextTick(() => {
+      initChart()
+    })
   },
   {
     deep: true
@@ -63,10 +68,10 @@ const ColorValue = computed(() => {
 const initOption = reactive({
   // 间距
   grid: {
-    top: '5%',
+    top: '12%',
     left: '3%',
     right: '6%',
-    bottom: '5%',
+    bottom: '3%',
     containLabel: true // 距离包含坐标轴上的文字
   },
   // hover时的文字显示
@@ -163,7 +168,23 @@ const initOption = reactive({
         }
       }
     }
-  ]
+  ],
+  toolbox: {
+    top: 4,
+    right: 8,
+    iconStyle: {
+      borderColor: '#ed6d00'
+    },
+    emphasis: {
+      iconStyle: {
+        borderColor: '#ff7500'
+      } // hover上去时的颜色
+    },
+    feature: {
+      saveAsImage: { show: true, name: props.saveImageName, type: 'png', backgroundColor: '#fff' }
+    },
+    showTitle: false
+  }
 })
 
 onMounted(() => {
@@ -174,9 +195,13 @@ onMounted(() => {
     (newVal) => {
       if (newVal === 'dark') {
         initOption.xAxis.splitLine.lineStyle.color = '#3F434A'
+        initOption.toolbox.iconStyle.borderColor = '#f0f1f3'
+        initOption.toolbox.feature.saveAsImage.backgroundColor = '#2B2F36'
         initChart()
       } else {
         initOption.xAxis.splitLine.lineStyle.color = '#eaebed'
+        initOption.toolbox.iconStyle.borderColor = '#2B2F36'
+        initOption.toolbox.feature.saveAsImage.backgroundColor = '#fff'
         initChart()
       }
     },
@@ -235,6 +260,6 @@ defineExpose({
 }
 #seller_chart {
   width: 100%;
-  height: 272px;
+  height: 310px;
 }
 </style>

+ 1 - 1
src/views/Dashboard/src/components/TopMap.vue

@@ -137,7 +137,7 @@ defineExpose({
 <template>
   <div
     id="map"
-    style="width: 100%; height: 272px"
+    style="width: 100%; height: 310px"
     :class="{ 'dark-mode': themeStore.theme === 'dark' }"
   ></div>
 </template>

+ 221 - 190
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/CreateNewRule.vue

@@ -42,37 +42,36 @@ const CountryCheckboxList = ref([])
 
 // 页面初始化
 const InitRuleData = () => {
-  if ( a!= undefined ) {
+  if (a != undefined) {
     $api
-    .InitCreateRule({
-      a: a
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        const { returnData } = res.data
-        KLNPLCvalue.value = returnData.KLNPLCvalue
-        selectedCountry.value = returnData.country
-        setbookingdata.value = returnData.SetBookingWindow
-        windowRadio.value = returnData.SetBookingWindow.windowradio
-        if(windowRadio.value != 1) {
-          windowBeforeDays.value = returnData.booking_window_date_start
-          windowAfterDays.value = returnData.booking_window_date_end
-        }
-        recommendRadio.value = returnData.RcommendDeliveryDate.Recommendradio
-        if(recommendRadio.value != 1) {
-          recommendCheckedList.value = returnData.RcommendDeliveryDate.RecommendCheckedList
-          recommendCheckedAirList.value = returnData.RcommendDeliveryDate.RecommendCheckedAirList
-          recommendCheckedSeaList.value = returnData.RcommendDeliveryDate.RecommendCheckedSeaList
+      .InitCreateRule({
+        a: a
+      })
+      .then((res: any) => {
+        if (res.code === 200) {
+          const { returnData } = res.data
+          KLNPLCvalue.value = returnData.KLNPLCvalue
+          selectedCountry.value = returnData.country
+          setbookingdata.value = returnData.SetBookingWindow
+          windowRadio.value = returnData.SetBookingWindow.windowradio
+          if (windowRadio.value != 1) {
+            windowBeforeDays.value = returnData.booking_window_date_start
+            windowAfterDays.value = returnData.booking_window_date_end
+          }
+          recommendRadio.value = returnData.RcommendDeliveryDate.Recommendradio
+          if (recommendRadio.value != 1) {
+            recommendCheckedList.value = returnData.RcommendDeliveryDate.RecommendCheckedList
+            recommendCheckedAirList.value = returnData.RcommendDeliveryDate.RecommendCheckedAirList
+            recommendCheckedSeaList.value = returnData.RcommendDeliveryDate.RecommendCheckedSeaList
+          }
+          countryCheckedList.value = returnData.station
+          CountryCheckboxList.value = returnData.CountryCheckedList
+          recommendata.value = returnData.RcommendDeliveryDate
         }
-        countryCheckedList.value = returnData.station
-        CountryCheckboxList.value = returnData.CountryCheckedList
-        recommendata.value = returnData.RcommendDeliveryDate
-      }
-    })
+      })
   }
 }
 
-
 const CreateRuleDisabled = computed(() => {
   // 1. 检查基本条件是否满足
   if (
@@ -82,14 +81,14 @@ const CreateRuleDisabled = computed(() => {
     recommendRadio.value === undefined ||
     KLNPLCvalue.value.length === 0
   ) {
-    return true;
+    return true
   }
 
   // 2. 处理时间窗口条件
   if (windowRadio.value !== 1) {
     // 当 windowRadio 不为 1 时,需要验证时间窗口字段
     if (windowBeforeDays.value === '' || windowAfterDays.value === '') {
-      return true;
+      return true
     }
   }
 
@@ -97,55 +96,54 @@ const CreateRuleDisabled = computed(() => {
   if (recommendRadio.value !== 1) {
     // 3.1 确保至少选择了一个运输方式
     if (recommendCheckedList.value.length === 0) {
-      return true;
+      return true
     }
 
     // 3.2 验证航空规则(如果选择了 Air)
-    console.log(recommendCheckedList.value)
     if (recommendCheckedList.value.includes('Air')) {
-      const isAirValid = recommendCheckedAirList.value.every(item => 
-        item.ports.length > 0 && 
-        item.recommended_delivery_from !== '' && 
-        item.recommended_delivery_to !== ''
-      );
-      
-      if (!isAirValid) return true;
+      const isAirValid = recommendCheckedAirList.value.every(
+        (item) =>
+          item.ports.length > 0 &&
+          item.recommended_delivery_from !== '' &&
+          item.recommended_delivery_to !== ''
+      )
+
+      if (!isAirValid) return true
     }
 
     // 3.3 验证海运规则(如果选择了 Sea)
     if (recommendCheckedList.value.includes('Sea')) {
-      const hasInvalidSeaItem = recommendCheckedSeaList.value.some(item => {
-        const hasValidDeliveryTime = 
-          item.recommended_delivery_from && 
-          item.recommended_delivery_to;
-        
-        const hasRequiredFields = item.rule_type !== 'Single Dimension'
-          ? item.ports.length > 0 && item.carrier.length > 0
-          : item.ports.length > 0 || item.carrier.length > 0;
-        
-        return !hasValidDeliveryTime || !hasRequiredFields;
-      });
-      
-      if (hasInvalidSeaItem) return true;
+      const hasInvalidSeaItem = recommendCheckedSeaList.value.some((item) => {
+        const hasValidDeliveryTime = item.recommended_delivery_from && item.recommended_delivery_to
+
+        const hasRequiredFields =
+          item.rule_type !== 'Single Dimension'
+            ? item.ports.length > 0 && item.carrier.length > 0
+            : item.ports.length > 0 || item.carrier.length > 0
+
+        return !hasValidDeliveryTime || !hasRequiredFields
+      })
+
+      if (hasInvalidSeaItem) return true
     }
   }
   // 4. 所有条件都满足,返回 false(不禁用)
-  return false;
-});
-// select country 
-const handleClickSelectCountry = (val:any) =>{
+  return false
+})
+// select country
+const handleClickSelectCountry = (val: any) => {
   selectedCountry.value = val
   countryCheckedList.value = []
 }
 // select station list
-const handleChangeStation = (val:any) =>{
+const handleChangeStation = (val: any) => {
   countryCheckedList.value = val
 }
 
 // select booking window
 const bookingWindow = ref('')
 const bookingdetail = ref('')
-const changeBookingWindow = (radio: number, beforedays:any, afterdays:any) => {
+const changeBookingWindow = (radio: number, beforedays: any, afterdays: any) => {
   windowRadio.value = radio
   windowBeforeDays.value = beforedays
   windowAfterDays.value = afterdays
@@ -169,10 +167,11 @@ const querySearchAsync = (query: string) => {
   if (query) {
     loading.value = true
     setTimeout(() => {
-      $api.getKLNEmployeeList({ 
-        term: query,
-        station: countryCheckedList.value
-      })
+      $api
+        .getKLNEmployeeList({
+          term: query,
+          station: countryCheckedList.value
+        })
         .then((res: any) => {
           if (res.code === 200) {
             loading.value = false
@@ -189,17 +188,17 @@ const querySearchAsync = (query: string) => {
 }
 // 保存
 const handleSubmitRule = () => {
-  const airlist = recommendCheckedAirList.value.map(item => {
-    const {PortList, ...rest} = item
-    if(recommendRadio.value == 2) {
+  const airlist = recommendCheckedAirList.value.map((item) => {
+    const { PortList, ...rest } = item
+    if (recommendRadio.value == 2) {
       return rest
     } else {
       return []
     }
   })
-  const seaList = recommendCheckedSeaList.value.map(item => {
-    const {PortList,CarrierList, ...rest} = item
-    if(recommendRadio.value == 2) {
+  const seaList = recommendCheckedSeaList.value.map((item) => {
+    const { PortList, CarrierList, ...rest } = item
+    if (recommendRadio.value == 2) {
       return rest
     } else {
       return []
@@ -208,39 +207,59 @@ const handleSubmitRule = () => {
   let airData = []
   let airlistInfo = {}
   let mergeData = []
-  if(windowRadio.value == 1) {
+  if (windowRadio.value == 1) {
     bookingWindow.value = 'No_Restrictions'
     bookingdetail.value = 'No Specific time restrictions for creating booking'
-  } else if(windowRadio.value == 2) {
+  } else if (windowRadio.value == 2) {
     bookingWindow.value = 'Restrictions_ETD_ATD'
-    bookingdetail.value = 'ETD/ATD: ' + windowBeforeDays.value + ' days before to ' + windowAfterDays.value + ' days after'
-  } else if(windowRadio.value == 3) {
+    bookingdetail.value =
+      'ETD/ATD: ' +
+      windowBeforeDays.value +
+      ' days before to ' +
+      windowAfterDays.value +
+      ' days after'
+  } else if (windowRadio.value == 3) {
     bookingWindow.value = 'Restrictions_ETA_ATA'
-    bookingdetail.value = 'ETA/ATA: ' + windowBeforeDays.value + ' days before to ' + windowAfterDays.value + ' days after'
+    bookingdetail.value =
+      'ETA/ATA: ' +
+      windowBeforeDays.value +
+      ' days before to ' +
+      windowAfterDays.value +
+      ' days after'
   }
-  if(recommendRadio.value == 1) {
+  if (recommendRadio.value == 1) {
     recommendDelivery.value = 'No_Recommended'
     recommenddetail.value = 'No Specific recommended time for choosing delivery date'
   } else {
     recommendDelivery.value = 'Delivery_ETA_ATA'
-    if(recommendCheckedList.value.includes('Air')) {
-      recommenddetail.value += 'Air:\nDefault Rule- Air Port: ALL,\nRecommend Delivery Date: ETA/ATA+' + airlist[0].recommended_delivery_from + ' Days to ETA/ATA+'+ airlist[0].recommended_delivery_to + ' Days;\n'
+    if (recommendCheckedList.value.includes('Air')) {
+      recommenddetail.value +=
+        'Air:\nDefault Rule- Air Port: ALL,\nRecommend Delivery Date: ETA/ATA+' +
+        airlist[0].recommended_delivery_from +
+        ' Days to ETA/ATA+' +
+        airlist[0].recommended_delivery_to +
+        ' Days;\n'
       airlist.forEach((item) => {
         item.ports = item.ports.join(',')
         item.carrier = ''
       })
       mergeData = [...airlist]
     }
-    if(recommendCheckedList.value.includes('Sea')) {
-      recommenddetail.value += 'Sea:\nDefault Rule- ort: ALL, Carrier: ALL,\nRecommend Delivery Date: ETA/ATA+' + seaList[0].recommended_delivery_from + ' Days to ETA/ATA+'+ seaList[0].recommended_delivery_to + ' Days;' 
+    if (recommendCheckedList.value.includes('Sea')) {
+      recommenddetail.value +=
+        'Sea:\nDefault Rule- ort: ALL, Carrier: ALL,\nRecommend Delivery Date: ETA/ATA+' +
+        seaList[0].recommended_delivery_from +
+        ' Days to ETA/ATA+' +
+        seaList[0].recommended_delivery_to +
+        ' Days;'
       seaList.forEach((item) => {
         item.ports = item.ports.join(',')
         item.carrier = item.carrier.join(',')
       })
-      mergeData = [...mergeData , ...seaList]
+      mergeData = [...mergeData, ...seaList]
     }
   }
-  if(seaList.length != 0) {
+  if (seaList.length != 0) {
     airData = Object.keys(seaList?.[0])
     airData.forEach((item) => {
       Object.assign(airlistInfo, {
@@ -248,36 +267,37 @@ const handleSubmitRule = () => {
       })
     })
   }
-  $api.handelSaveRule({
-    serial_no: a != undefined ? a: '',
-    country: selectedCountry.value,
-    station: countryCheckedList.value,
-    booking_window: bookingWindow.value,
-    booking_window_date_start: windowBeforeDays.value,
-    booking_window_date_end: windowAfterDays.value,
-    recommended_delivery: recommendDelivery.value,
-    booking_window_desc: bookingdetail.value,
-    kln_pic: KLNPLCvalue.value,
-    recommended_delivery_date_desc: recommenddetail.value,
-    ...airlistInfo
-  }).then((res: any) => {
-    if (res.code === 200 && res.data.msg == 'success') {
-      SaveedVisible.value = true
-      setTimeout(() => {
-        SaveedVisible.value = false
-        router.push({ name: 'Configurations'})
-      }, 3000)
-    } else {
+  $api
+    .handelSaveRule({
+      serial_no: a != undefined ? a : '',
+      country: selectedCountry.value,
+      station: countryCheckedList.value,
+      booking_window: bookingWindow.value,
+      booking_window_date_start: windowBeforeDays.value,
+      booking_window_date_end: windowAfterDays.value,
+      recommended_delivery: recommendDelivery.value,
+      booking_window_desc: bookingdetail.value,
+      kln_pic: KLNPLCvalue.value,
+      recommended_delivery_date_desc: recommenddetail.value,
+      ...airlistInfo
+    })
+    .then((res: any) => {
+      if (res.code === 200 && res.data.msg == 'success') {
+        SaveedVisible.value = true
+        setTimeout(() => {
+          SaveedVisible.value = false
+          router.push({ name: 'Configurations' })
+        }, 3000)
+      } else {
         UnableSaveVisible.value = true
         missingmessage.value = res.data.msg
-    }
-  })
+      }
+    })
 }
 
 onMounted(() => {
   InitRuleData()
 })
-
 </script>
 
 <template>
@@ -286,11 +306,20 @@ onMounted(() => {
       <div v-if="a != undefined">Modify Rule</div>
       <div v-else>Create New Rule</div>
       <div class="operator">
-        <el-button @click="CancelRulesVisible = true" style="height: 40px; width: 115px" type="default">
+        <el-button
+          @click="CancelRulesVisible = true"
+          style="height: 40px; width: 115px"
+          type="default"
+        >
           <span style="margin-right: 4px" class="font_family icon-icon_return_b"></span>
           <span style="font-weight: 400">Cancel</span></el-button
         >
-        <el-button style="height: 40px; width: 120px" class="el-button--main el-button--pain-theme" :disabled="CreateRuleDisabled" @click="handleSubmitRule">
+        <el-button
+          style="height: 40px; width: 120px"
+          class="el-button--main el-button--pain-theme"
+          :disabled="CreateRuleDisabled"
+          @click="handleSubmitRule"
+        >
           <span
             style="
               display: inline-block;
@@ -355,7 +384,9 @@ onMounted(() => {
         </el-dialog>
         <!-- 保存成功 -->
         <el-dialog v-model="SaveedVisible" width="320" style="height: 212px">
-          <div style="text-align: center"><el-image :src="submitsucessful" style="width: 64px;" /></div>
+          <div style="text-align: center">
+            <el-image :src="submitsucessful" style="width: 64px" />
+          </div>
           <div style="text-align: center; margin-top: 20px">Saved successfully</div>
         </el-dialog>
       </div>
@@ -364,107 +395,107 @@ onMounted(() => {
       <div class="setting-top-title">Setting</div>
       <el-collapse v-model="activeRules" @change="IsFirstActive = !IsFirstActive">
         <el-collapse-item name="SelectStation">
-            <template #title>
-              <div class="Rules_Title">
-                <span class="iconfont_icon icon_dark">
-                  <svg class="iconfont" aria-hidden="true">
-                    <use
-                      :xlink:href="IsFirstActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
-                    ></use>
-                  </svg>
-                </span>
-                <span class="stars_red">*</span>Select Station (Enable Booking)
-              </div>
-            </template>
-            <div>
-              <SelectStation
+          <template #title>
+            <div class="Rules_Title">
+              <span class="iconfont_icon icon_dark">
+                <svg class="iconfont" aria-hidden="true">
+                  <use
+                    :xlink:href="IsFirstActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
+                  ></use>
+                </svg>
+              </span>
+              <span class="stars_red">*</span>Select Station (Enable Booking)
+            </div>
+          </template>
+          <div>
+            <SelectStation
               @handleClickSelectCountry="handleClickSelectCountry"
               @handleChangeStation="handleChangeStation"
               :CheckboxList="CountryCheckboxList"
               :CheckedList="countryCheckedList"
               :SelectCountry="selectedCountry"
-              ></SelectStation>
-            </div>
-          </el-collapse-item>
+            ></SelectStation>
+          </div>
+        </el-collapse-item>
       </el-collapse>
       <el-collapse v-model="activeRules" @change="IsTwoActive = !IsTwoActive">
         <el-collapse-item name="SelectBooking">
-            <template #title>
-              <div class="Rules_Title">
-                <span class="iconfont_icon icon_dark">
-                  <svg class="iconfont" aria-hidden="true">
-                    <use
-                      :xlink:href="IsTwoActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
-                    ></use>
-                  </svg>
-                </span>
-                <span class="stars_red">*</span>Set Booking Window
-              </div>
-            </template>
-            <div>
-              <SetBookingWindow
-                :setbookingdata="setbookingdata"
-                @changeBookingWindow="changeBookingWindow"
-              ></SetBookingWindow>
+          <template #title>
+            <div class="Rules_Title">
+              <span class="iconfont_icon icon_dark">
+                <svg class="iconfont" aria-hidden="true">
+                  <use
+                    :xlink:href="IsTwoActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
+                  ></use>
+                </svg>
+              </span>
+              <span class="stars_red">*</span>Set Booking Window
             </div>
-          </el-collapse-item>
+          </template>
+          <div>
+            <SetBookingWindow
+              :setbookingdata="setbookingdata"
+              @changeBookingWindow="changeBookingWindow"
+            ></SetBookingWindow>
+          </div>
+        </el-collapse-item>
       </el-collapse>
       <el-collapse v-model="activeRules" @change="IsThreeActive = !IsThreeActive">
         <el-collapse-item name="RecommendDeliveryDate">
-            <template #title>
-              <div class="Rules_Title">
-                <span class="iconfont_icon icon_dark">
-                  <svg class="iconfont" aria-hidden="true">
-                    <use
-                      :xlink:href="IsThreeActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
-                    ></use>
-                  </svg>
-                </span>
-                <span class="stars_red">*</span>Recommend Delivery Date 
-              </div>
-            </template>
-            <div>
-              <RecommendDate
-                :recommendata="recommendata"
-                @chackchangerecommend="checkRecommend"
-              ></RecommendDate>
+          <template #title>
+            <div class="Rules_Title">
+              <span class="iconfont_icon icon_dark">
+                <svg class="iconfont" aria-hidden="true">
+                  <use
+                    :xlink:href="IsThreeActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
+                  ></use>
+                </svg>
+              </span>
+              <span class="stars_red">*</span>Recommend Delivery Date
             </div>
-          </el-collapse-item>
+          </template>
+          <div>
+            <RecommendDate
+              :recommendata="recommendata"
+              @chackchangerecommend="checkRecommend"
+            ></RecommendDate>
+          </div>
+        </el-collapse-item>
       </el-collapse>
       <el-collapse v-model="activeRules" @change="IsFourActive = !IsFourActive">
         <el-collapse-item name="KLNPLC">
-            <template #title>
-              <div class="Rules_Title">
-                <span class="iconfont_icon icon_dark">
-                  <svg class="iconfont" aria-hidden="true">
-                    <use
-                      :xlink:href="IsFourActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
-                    ></use>
-                  </svg>
-                </span>
-                <span class="stars_red">*</span>KLN PIC
-              </div>
-            </template>
-            <div>
-              <el-select
-                v-model="KLNPLCvalue"
-                filterable
-                remote
-                multiple
-                placeholder="Select Employee Account"
-                :remote-method="querySearchAsync"
-                :loading="loading"
-                style="width: 400px;margin-bottom: 5px;"
-              >
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value"
-                />
-              </el-select>
+          <template #title>
+            <div class="Rules_Title">
+              <span class="iconfont_icon icon_dark">
+                <svg class="iconfont" aria-hidden="true">
+                  <use
+                    :xlink:href="IsFourActive ? '#icon-icon_dropdown_b' : '#icon-icon_up_b'"
+                  ></use>
+                </svg>
+              </span>
+              <span class="stars_red">*</span>KLN PIC
             </div>
-          </el-collapse-item>
+          </template>
+          <div>
+            <el-select
+              v-model="KLNPLCvalue"
+              filterable
+              remote
+              multiple
+              placeholder="Select Employee Account"
+              :remote-method="querySearchAsync"
+              :loading="loading"
+              style="width: 400px; margin-bottom: 5px"
+            >
+              <el-option
+                v-for="item in options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </div>
+        </el-collapse-item>
       </el-collapse>
     </div>
   </div>
@@ -550,7 +581,7 @@ onMounted(() => {
   box-shadow: none;
   border: 1px solid var(--color-theme);
 }
-:deep(.el-select__wrapper.is-focused ){
+:deep(.el-select__wrapper.is-focused) {
   box-shadow: none;
   border: 1px solid var(--color-theme);
 }
@@ -580,4 +611,4 @@ onMounted(() => {
 :deep(.el-dialog__body) {
   font-weight: 400;
 }
-</style>
+</style>

+ 245 - 150
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/RecommendDate.vue

@@ -1,11 +1,12 @@
 <script setup lang="ts">
 import SelectValue from './SelectValue.vue'
 import { ref } from 'vue'
+import { cloneDeep } from 'lodash'
 
 // 定义类型接口
 interface RuleOption {
-  label: string;
-  value: string;
+  label: string
+  value: string
 }
 interface PortOption {
   value: string
@@ -13,21 +14,20 @@ interface PortOption {
   checked: boolean
 }
 
-
 interface RuleItem {
-  priority: string;
-  rule_type: string;
-  mode_type: string;
-  ports?: string[];
-  carrier?: string[];
-  PortList?:PortOption[];
-  CarrierList?:PortOption[];
-  recommended_delivery_from: string;
-  recommended_delivery_to: string;
+  priority: string
+  rule_type: string
+  mode_type: string
+  ports?: string[]
+  carrier?: string[]
+  PortList?: PortOption[]
+  CarrierList?: PortOption[]
+  recommended_delivery_from: string
+  recommended_delivery_to: string
 }
 
 // 定义 RuleItem 中数组字段的类型
-type ArrayFields = 'ports' | 'carrier';
+type ArrayFields = 'ports' | 'carrier'
 
 const props = defineProps({
   recommendata: {
@@ -45,9 +45,7 @@ const isAir = ref(false)
 const isSea = ref(false)
 const RecommendCheckedList = ref<string[]>([])
 // 选项配置
-const AirRuleTypeoptions = ref<RuleOption[]>([
-  { label: 'Specific Rule', value: 'Specific Rule' }
-])
+const AirRuleTypeoptions = ref<RuleOption[]>([{ label: 'Specific Rule', value: 'Specific Rule' }])
 
 const RuleTypeoptions = ref<RuleOption[]>([
   { label: 'Specific Rule', value: 'Specific Rule' },
@@ -63,7 +61,7 @@ const AirContentList = ref<RuleItem[]>([
     recommended_delivery_from: '',
     recommended_delivery_to: '',
     mode_type: 'air',
-    PortList:[]
+    PortList: []
   }
 ])
 const SeaContentList = ref<RuleItem[]>([
@@ -75,36 +73,39 @@ const SeaContentList = ref<RuleItem[]>([
     recommended_delivery_from: '',
     recommended_delivery_to: '',
     mode_type: 'sea',
-    PortList:[],
+    PortList: [],
     CarrierList: []
   }
 ])
 
-const recommendata = ref(props.recommendata)
+const recommendata = ref()
 
 const initRecommendData = () => {
-  if(recommendata.value) {
+  if (recommendata.value) {
     Recommendradio.value = recommendata.value.Recommendradio
-    if(Recommendradio.value == 2) {
+    if (Recommendradio.value == 2) {
       isRecommendETA.value = true
       RecommendCheckedList.value = recommendata.value.RecommendCheckedList
-      if(RecommendCheckedList.value.includes('Air')) {
+      if (RecommendCheckedList.value.includes('Air')) {
         isAir.value = true
       }
-      if(RecommendCheckedList.value.includes('Sea')) {
+      if (RecommendCheckedList.value.includes('Sea')) {
         isSea.value = true
       }
       AirContentList.value = recommendata.value.RecommendCheckedAirList
       SeaContentList.value = recommendata.value.RecommendCheckedSeaList
     }
-    }
+  }
 }
 
-watch(() => props.recommendata, (val) => { 
-  recommendata.value = val
-  initRecommendData()
-}, { immediate: true, deep: true })
-
+watch(
+  () => props.recommendata,
+  (val) => {
+    recommendata.value = cloneDeep(val)
+    initRecommendData()
+  },
+  { immediate: true, deep: true }
+)
 
 // 创建规则项的工厂函数
 function createRuleItem(type: 'Air' | 'Sea', ruleType: string): RuleItem {
@@ -112,13 +113,13 @@ function createRuleItem(type: 'Air' | 'Sea', ruleType: string): RuleItem {
     priority: 'P1',
     rule_type: ruleType,
     recommended_delivery_from: '',
-    recommended_delivery_to: '',
+    recommended_delivery_to: ''
   }
   if (type === 'Air') {
     return {
       ...baseItem,
       ports: ruleType === '*Default Rule' ? ['ALL'] : [],
-      mode_type: 'air',
+      mode_type: 'air'
       // PortList: JSON.parse(JSON.stringify(AirPorList.value))
     }
   }
@@ -126,7 +127,7 @@ function createRuleItem(type: 'Air' | 'Sea', ruleType: string): RuleItem {
     ...baseItem,
     ports: ruleType === '*Default Rule' ? ['ALL'] : [],
     carrier: ruleType === '*Default Rule' ? ['ALL'] : [],
-    mode_type: 'sea',
+    mode_type: 'sea'
     // PortList: JSON.parse(JSON.stringify(SeaPortList.value)),
     // CarrierList: JSON.parse(JSON.stringify(SeaCarrierList.value))
   }
@@ -149,56 +150,68 @@ const CheckChange = (val: string[]) => {
 
 const handleCheckboxClick = (event: Event) => {
   const target = event.target as HTMLElement
-  const isCheckboxInput = target.closest('.el-checkbox__inner')
+  const isCheckboxInput = target.closest('.el-checkbox__input')
   const isCheckboxTitle = target.closest('.titlecheckbox')
   if (!isCheckboxInput && !isCheckboxTitle) {
     event.preventDefault()
   }
 }
+
 // 选择booking window
 const ChangeFrequency = (val: number) => {
   isRecommendETA.value = val === 2
-  emits('chackchangerecommend', RecommendCheckedList.value, AirContentList.value, SeaContentList.value, Recommendradio.value)
+  emits(
+    'chackchangerecommend',
+    RecommendCheckedList.value,
+    AirContentList.value,
+    SeaContentList.value,
+    Recommendradio.value
+  )
 }
 // 修复后的 handleInput 函数
-const handleInput = (val: string, index: number, type: 'recommended_delivery_from' | 'recommended_delivery_to', list: RuleItem[]) => {
+const handleInput = (
+  val: string,
+  index: number,
+  type: 'recommended_delivery_from' | 'recommended_delivery_to',
+  list: RuleItem[]
+) => {
   // 移除非数字字符
-  const numStr = val.replace(/[^\d]/g, '');
+  const numStr = val.replace(/[^\d]/g, '')
   // 处理空值情况
   if (numStr === '') {
-    list[index][type] = '';
-    return;
+    list[index][type] = ''
+    return
   }
-  
+
   // 转换为数字以进行范围检查
-  const num = parseInt(numStr, 10);
-  
+  const num = parseInt(numStr, 10)
+
   // 确保最小值为1(但保持为字符串形式)
   if (num < 1) {
-    list[index][type] = '1';
+    list[index][type] = '1'
   } else {
     // 保持为字符串形式
-    list[index][type] = numStr;
+    list[index][type] = numStr
   }
-};
+}
 // 删除数据
 const handleDelete = (index: number, list: RuleItem[], type: 'Air' | 'Sea') => {
-  list.splice(index, 1);
+  list.splice(index, 1)
   if (list.length === 0) {
     if (type === 'Air') {
       isAir.value = false
-      RecommendCheckedList.value = RecommendCheckedList.value.filter(item => item !== 'Air')
+      RecommendCheckedList.value = RecommendCheckedList.value.filter((item) => item !== 'Air')
     } else {
       isSea.value = false
-      RecommendCheckedList.value = RecommendCheckedList.value.filter(item => item !== 'Sea')
+      RecommendCheckedList.value = RecommendCheckedList.value.filter((item) => item !== 'Sea')
     }
   }
   updatePriorities()
-};
+}
 // 添加数据
 const AddRuleItem = (list: RuleItem[], type: 'Air' | 'Sea') => {
   // 检查是否已存在默认规则
-  const hasDefaultRule = list.some(item => item.rule_type === '*Default Rule')
+  const hasDefaultRule = list.some((item) => item.rule_type === '*Default Rule')
   // 如果已经有默认规则,则创建特定规则
   const ruleType = hasDefaultRule ? 'Specific Rule' : '*Default Rule'
   list.push(createRuleItem(type, ruleType))
@@ -206,15 +219,21 @@ const AddRuleItem = (list: RuleItem[], type: 'Air' | 'Sea') => {
 }
 // 根据RuleType的值来修改Priority的值
 const updatePriorities = () => {
-  emits('chackchangerecommend', RecommendCheckedList.value, AirContentList.value, SeaContentList.value,Recommendradio.value)
+  emits(
+    'chackchangerecommend',
+    RecommendCheckedList.value,
+    AirContentList.value,
+    SeaContentList.value,
+    Recommendradio.value
+  )
   updateListPriorities(AirContentList.value, 'Air')
   updateListPriorities(SeaContentList.value, 'Sea')
-};
+}
 // 统一更新列表优先级
 const updateListPriorities = (list: RuleItem[], type: 'Air' | 'Sea') => {
   const length = list.length
   // 保护默认规则的数据
-  list.forEach(item => {
+  list.forEach((item) => {
     if (item.rule_type === '*Default Rule') {
       if (type === 'Air') {
         item.ports = ['ALL']
@@ -234,40 +253,43 @@ const updateListPriorities = (list: RuleItem[], type: 'Air' | 'Sea') => {
 }
 // 处理长度为1
 const handleLengthOne = (list: RuleItem[], type: string) => {
-  list.forEach(item => item.priority = 'P1')
-};
+  list.forEach((item) => (item.priority = 'P1'))
+}
 // 处理长度为2
 const handleLengthTwo = (list: RuleItem[], type: string) => {
-  const types = new Set(list.map(i => i.rule_type))
+  const types = new Set(list.map((i) => i.rule_type))
   // 两个都是 *Default Rule
   if (types.size === 1 && types.has('*Default Rule')) {
-    list.forEach(item => item.priority = 'P1')
+    list.forEach((item) => (item.priority = 'P1'))
     return
   }
   // 包含 *Default Rule 和其他类型
   if (types.has('*Default Rule')) {
-    list.forEach(item => {
+    list.forEach((item) => {
       item.priority = item.rule_type === '*Default Rule' ? 'P2' : 'P1'
     })
     return
   }
   // 同时存在 Specific Rule 和 Single Dimension
   if (types.has('Specific Rule') && types.has('Single Dimension')) {
-    list.forEach(item => {
+    list.forEach((item) => {
       item.priority = item.rule_type === 'Specific Rule' ? 'P1' : 'P2'
     })
     return
   }
   // 其他情况
-  list.forEach(item => item.priority = 'P1')
-};
+  list.forEach((item) => (item.priority = 'P1'))
+}
 // 处理长度≥3
 const handleLengthThreePlus = (list: RuleItem[], type: string) => {
   // 统计各类型数量
-  const counts = list.reduce((acc, cur) => {
-    acc[cur.rule_type] = (acc[cur.rule_type] || 0) + 1
-    return acc
-  }, {} as Record<string, number>)
+  const counts = list.reduce(
+    (acc, cur) => {
+      acc[cur.rule_type] = (acc[cur.rule_type] || 0) + 1
+      return acc
+    },
+    {} as Record<string, number>
+  )
   // 获取所有存在的类型
   const existingTypes = Object.keys(counts)
   // 三个不同类型都存在
@@ -281,28 +303,30 @@ const handleLengthThreePlus = (list: RuleItem[], type: string) => {
       'Single Dimension': 'P2',
       '*Default Rule': 'P3'
     }
-    list.forEach(item => {
+    list.forEach((item) => {
       item.priority = priorityMap[item.rule_type]
     })
     return
   }
   // 全为同一种类型的情况
   if (existingTypes.length === 1) {
-    list.forEach(item => item.priority = 'P1')
+    list.forEach((item) => (item.priority = 'P1'))
     return
   }
   // 处理 Specific + Default 组合
-  if (existingTypes.length === 2 && 
-      existingTypes.includes('Specific Rule') && 
-      existingTypes.includes('*Default Rule')) {
-    list.forEach(item => {
+  if (
+    existingTypes.length === 2 &&
+    existingTypes.includes('Specific Rule') &&
+    existingTypes.includes('*Default Rule')
+  ) {
+    list.forEach((item) => {
       item.priority = item.rule_type === 'Specific Rule' ? 'P1' : 'P2'
     })
     return
   }
   // 存在两个Default Rule
   if (counts['*Default Rule'] === 2 && existingTypes.length === 2) {
-    list.forEach(item => {
+    list.forEach((item) => {
       item.priority = item.rule_type === '*Default Rule' ? 'P2' : 'P1'
     })
     return
@@ -311,12 +335,12 @@ const handleLengthThreePlus = (list: RuleItem[], type: string) => {
   if (counts['Single Dimension'] === 2) {
     if (existingTypes.includes('*Default Rule')) {
       // 两个Single + 一个Default
-      list.forEach(item => {
+      list.forEach((item) => {
         item.priority = item.rule_type === '*Default Rule' ? 'P2' : 'P1'
       })
     } else if (existingTypes.includes('Specific Rule')) {
       // 两个Single + 一个Specific
-      list.forEach(item => {
+      list.forEach((item) => {
         item.priority = item.rule_type === 'Specific Rule' ? 'P1' : 'P2'
       })
     }
@@ -328,33 +352,39 @@ const handleLengthThreePlus = (list: RuleItem[], type: string) => {
     'Single Dimension': 'P2',
     '*Default Rule': 'P3'
   }
-  list.forEach(item => {
+  list.forEach((item) => {
     item.priority = defaultPriorityMap[item.rule_type] || 'P3'
   })
 }
 // 修复:改变选项值 - 使用类型保护
-const changeSelectedValue = (val: string[], index: number, field: ArrayFields, list: RuleItem[]) => {
-  const item = list[index] as Record<ArrayFields, string[]>;
-  item[field] = val;
+const changeSelectedValue = (
+  val: string[],
+  index: number,
+  field: ArrayFields,
+  list: RuleItem[]
+) => {
+  const item = list[index] as Record<ArrayFields, string[]>
+  item[field] = val
   // 新增逻辑:检查是否从 Single Dimension 变为 Specific Rule
   if (item['rule_type'] != '*Default Rule') {
     if (item['mode_type'] === 'air') {
       // Air 规则:只检查 ports
       if (item.ports && item.ports.length > 0 && !item.ports.includes('ALL')) {
-        item['rule_type'] = 'Specific Rule';
-        updatePriorities();
+        item['rule_type'] = 'Specific Rule'
+        updatePriorities()
       }
     } else if (item['mode_type'] === 'sea') {
       // Sea 规则:检查 ports 和 carrier
-      const portsSelected = item.ports && item.ports.length > 0 && !item.ports.includes('ALL');
-      const carrierSelected = item.carrier && item.carrier.length > 0 && !item.carrier.includes('ALL');
-      
+      const portsSelected = item.ports && item.ports.length > 0 && !item.ports.includes('ALL')
+      const carrierSelected =
+        item.carrier && item.carrier.length > 0 && !item.carrier.includes('ALL')
+
       if (portsSelected && carrierSelected) {
-        item['rule_type'] = 'Specific Rule';
-        updatePriorities();
+        item['rule_type'] = 'Specific Rule'
+        updatePriorities()
       } else {
-        item['rule_type'] = 'Single Dimension';
-        updatePriorities();
+        item['rule_type'] = 'Single Dimension'
+        updatePriorities()
       }
     }
   }
@@ -387,32 +417,53 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
           <el-checkbox-group v-model="RecommendCheckedList" @change="CheckChange">
             <!-- Air 部分 -->
             <el-checkbox class="delayedType" value="Air" @click="handleCheckboxClick">
-              <div class="titlecheckbox">
+              <div class="titlecheckbox clickable-area">
                 <div>Air</div>
-                <span class="icon_grey font_family" :class="isAir ? 'icon-icon_dropdown_b' : 'icon-icon_up_b'"></span>
+                <span
+                  class="icon_grey font_family"
+                  :class="isAir ? 'icon-icon_dropdown_b' : 'icon-icon_up_b'"
+                ></span>
               </div>
-              <div v-if="isAir" class="radiocheckbox" style="margin-top: 16px">
+              <div v-if="isAir" class="radiocheckbox" style="margin-top: 16px; padding-left: 8px">
                 <div class="AirCoulumn">
-                  <div class="AicoulumnTitile" style="width: 10%;">priority</div>
-                  <div class="AicoulumnTitile" style="width: 20%;">Rule Type</div>
-                  <div class="AicoulumnTitile" style="width: 40%;">Air Port</div>
-                  <div style="display: flex;flex-direction: column;border-right: 1px solid var(--color-system-border);width: 20%;">
+                  <div class="AicoulumnTitile" style="width: 10%">priority</div>
+                  <div class="AicoulumnTitile" style="width: 20%">Rule Type</div>
+                  <div class="AicoulumnTitile" style="width: 40%">Air Port</div>
+                  <div
+                    style="
+                      display: flex;
+                      flex-direction: column;
+                      border-right: 1px solid var(--color-system-border);
+                      width: 20%;
+                    "
+                  >
                     <div class="AicoulumnTitile2">Recommended Delivery Date</div>
-                    <div style="display: flex;height: 24px;align-items: center;">
-                      <div class="datetitle" style="border-right: 1px solid var(--color-system-border);">From (ETA/ATA + Days)</div>
+                    <div style="display: flex; height: 24px; align-items: center">
+                      <div
+                        class="datetitle"
+                        style="border-right: 1px solid var(--color-system-border)"
+                      >
+                        From (ETA/ATA + Days)
+                      </div>
                       <div class="datetitle">To (ETA/ATA + Days)</div>
                     </div>
                   </div>
-                  <div class="AirCoumlulnAdd" style="width: 10%;" @click="AddRuleItem(AirContentList, 'Air')">+ Add</div>
+                  <div
+                    class="AirCoumlulnAdd"
+                    style="width: 10%"
+                    @click="AddRuleItem(AirContentList, 'Air')"
+                  >
+                    + Add
+                  </div>
                 </div>
                 <div class="AirContent" v-for="(item, index) in AirContentList" :key="index">
-                  <div class="AirCoumlumn" style="width: 10%;">{{ item.priority }}</div>
-                  <div class="AirCoumlumn" style="width: 20%;">
+                  <div class="AirCoumlumn" style="width: 10%">{{ item.priority }}</div>
+                  <div class="AirCoumlumn" style="width: 20%">
                     <el-select
                       v-model="item.rule_type"
                       disabled
-                      style="width: 100%;"
-                      @change="val => changeRuleType(val, index, AirContentList)"
+                      style="width: 100%"
+                      @change="(val) => changeRuleType(val, index, AirContentList)"
                     >
                       <el-option
                         v-for="opt in AirRuleTypeoptions"
@@ -422,35 +473,42 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
                       />
                     </el-select>
                   </div>
-                  <div class="AirCoumlumn" style="width: 40%;">
+                  <div class="AirCoumlumn" style="width: 40%">
                     <SelectValue
                       ref="AirPortRef"
                       :SelectIndex="index"
                       :SelectedValue="item.ports"
                       :typeisDisabled="item.rule_type"
                       SelectType="air"
-                      @changeSelectedValue="val => changeSelectedValue(val, index, 'ports', AirContentList)"
+                      @changeSelectedValue="
+                        (val) => changeSelectedValue(val, index, 'ports', AirContentList)
+                      "
                     />
                   </div>
-                  <div class="AirCoumlumn" style="width: 10%;">
-                    <el-input 
-                      @input="val => handleInput(val, index, 'recommended_delivery_from', AirContentList)" 
-                      placeholder="Input" 
+                  <div class="AirCoumlumn" style="width: 10%">
+                    <el-input
+                      @input="
+                        (val) =>
+                          handleInput(val, index, 'recommended_delivery_from', AirContentList)
+                      "
+                      placeholder="Input"
                       v-model="item.recommended_delivery_from"
                     />
                   </div>
-                  <div class="AirCoumlumn" style="width: 10%;">
-                    <el-input 
-                      @input="val => handleInput(val, index, 'recommended_delivery_to', AirContentList)"  
-                      placeholder="Input" 
+                  <div class="AirCoumlumn" style="width: 10%">
+                    <el-input
+                      @input="
+                        (val) => handleInput(val, index, 'recommended_delivery_to', AirContentList)
+                      "
+                      placeholder="Input"
                       v-model="item.recommended_delivery_to"
                     />
                   </div>
-                  <div class="AirDelete" style="width: 10%;">
-                    <el-button 
-                      v-if="item.rule_type !== '*Default Rule'" 
-                      @click="handleDelete(index, AirContentList, 'Air')" 
-                      class="el-button--blue" 
+                  <div class="AirDelete" style="width: 10%">
+                    <el-button
+                      v-if="item.rule_type !== '*Default Rule'"
+                      @click="handleDelete(index, AirContentList, 'Air')"
+                      class="el-button--blue"
                       style="height: 24px"
                     >
                       <span class="font_family icon-icon_delete_b"></span>
@@ -461,33 +519,54 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
             </el-checkbox>
             <!-- Sea 部分 -->
             <el-checkbox class="delayedType" value="Sea" @click="handleCheckboxClick">
-              <div class="titlecheckbox">
+              <div class="titlecheckbox clickable-area">
                 <div>Sea</div>
-                <span class="icon_grey font_family" :class="isSea ? 'icon-icon_dropdown_b' : 'icon-icon_up_b'"></span>
+                <span
+                  class="icon_grey font_family"
+                  :class="isSea ? 'icon-icon_dropdown_b' : 'icon-icon_up_b'"
+                ></span>
               </div>
-              <div v-if="isSea" style="margin-top: 16px">
+              <div v-if="isSea" style="margin-top: 16px; padding-left: 8px">
                 <div class="AirCoulumn">
-                  <div class="AicoulumnTitile" style="width: 10%;">priority</div>
-                  <div class="AicoulumnTitile" style="width: 14%;">Rule Type</div>
-                  <div class="AicoulumnTitile" style="width: 23%;">Port</div>
-                  <div class="AicoulumnTitile" style="width: 23%;">Carrier</div>
-                  <div style="display: flex;flex-direction: column;border-right: 1px solid var(--color-system-border);width: 20%;">
+                  <div class="AicoulumnTitile" style="width: 10%">priority</div>
+                  <div class="AicoulumnTitile" style="width: 14%">Rule Type</div>
+                  <div class="AicoulumnTitile" style="width: 23%">Port</div>
+                  <div class="AicoulumnTitile" style="width: 23%">Carrier</div>
+                  <div
+                    style="
+                      display: flex;
+                      flex-direction: column;
+                      border-right: 1px solid var(--color-system-border);
+                      width: 20%;
+                    "
+                  >
                     <div class="AicoulumnTitile2">Recommended Delivery Date</div>
-                    <div style="display: flex;height: 24px;align-items: center;">
-                      <div class="datetitle" style="border-right: 1px solid var(--color-system-border);">From (ETA/ATA + Days)</div>
+                    <div style="display: flex; height: 24px; align-items: center">
+                      <div
+                        class="datetitle"
+                        style="border-right: 1px solid var(--color-system-border)"
+                      >
+                        From (ETA/ATA + Days)
+                      </div>
                       <div class="datetitle">To (ETA/ATA + Days)</div>
                     </div>
                   </div>
-                  <div class="AirCoumlulnAdd" style="width: 10%;" @click="AddRuleItem(SeaContentList, 'Sea')">+ Add</div>
+                  <div
+                    class="AirCoumlulnAdd"
+                    style="width: 10%"
+                    @click="AddRuleItem(SeaContentList, 'Sea')"
+                  >
+                    + Add
+                  </div>
                 </div>
                 <div class="AirContent" v-for="(item, index) in SeaContentList" :key="index">
-                  <div class="AirCoumlumn" style="width: 10%;">{{ item.priority }}</div>
-                  <div class="AirCoumlumn" style="width: 14%;">
+                  <div class="AirCoumlumn" style="width: 10%">{{ item.priority }}</div>
+                  <div class="AirCoumlumn" style="width: 14%">
                     <el-select
                       v-model="item.rule_type"
                       disabled
-                      style="width: 100%;"
-                      @change="val => changeRuleType(val, index, SeaContentList)"
+                      style="width: 100%"
+                      @change="(val) => changeRuleType(val, index, SeaContentList)"
                     >
                       <el-option
                         v-for="opt in RuleTypeoptions"
@@ -497,45 +576,54 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
                       />
                     </el-select>
                   </div>
-                  <div class="AirCoumlumn" style="width: 23%;">
+                  <div class="AirCoumlumn" style="width: 23%">
                     <SelectValue
                       ref="SeaPortRef"
                       :SelectIndex="index"
                       :SelectedValue="item.ports"
                       :typeisDisabled="item.rule_type"
                       SelectType="sea"
-                      @changeSelectedValue="val => changeSelectedValue(val, index, 'ports', SeaContentList)"
+                      @changeSelectedValue="
+                        (val) => changeSelectedValue(val, index, 'ports', SeaContentList)
+                      "
                     />
                   </div>
-                  <div class="AirCoumlumn" style="width: 23%;">
+                  <div class="AirCoumlumn" style="width: 23%">
                     <SelectValue
                       ref="SeaCarrierRef"
                       :SelectIndex="index"
                       :SelectedValue="item.carrier"
                       :typeisDisabled="item.rule_type"
                       SelectType="carrier"
-                      @changeSelectedValue="val => changeSelectedValue(val, index, 'carrier', SeaContentList)"
+                      @changeSelectedValue="
+                        (val) => changeSelectedValue(val, index, 'carrier', SeaContentList)
+                      "
                     />
                   </div>
-                  <div class="AirCoumlumn" style="width: 10%;">
-                    <el-input 
-                      @input="val => handleInput(val, index, 'recommended_delivery_from', SeaContentList)" 
-                      placeholder="Input" 
+                  <div class="AirCoumlumn" style="width: 10%">
+                    <el-input
+                      @input="
+                        (val) =>
+                          handleInput(val, index, 'recommended_delivery_from', SeaContentList)
+                      "
+                      placeholder="Input"
                       v-model="item.recommended_delivery_from"
                     />
                   </div>
-                  <div class="AirCoumlumn" style="width: 10%;">
-                    <el-input 
-                      @input="val => handleInput(val, index, 'recommended_delivery_to', SeaContentList)"  
-                      placeholder="Input" 
+                  <div class="AirCoumlumn" style="width: 10%">
+                    <el-input
+                      @input="
+                        (val) => handleInput(val, index, 'recommended_delivery_to', SeaContentList)
+                      "
+                      placeholder="Input"
                       v-model="item.recommended_delivery_to"
                     />
                   </div>
-                  <div class="AirDelete" style="width: 10%;">
-                    <el-button 
-                      v-if="item.rule_type !== '*Default Rule'" 
-                      @click="handleDelete(index, SeaContentList, 'Sea')" 
-                      class="el-button--blue" 
+                  <div class="AirDelete" style="width: 10%">
+                    <el-button
+                      v-if="item.rule_type !== '*Default Rule'"
+                      @click="handleDelete(index, SeaContentList, 'Sea')"
+                      class="el-button--blue"
                       style="height: 24px"
                     >
                       <span class="font_family icon-icon_delete_b"></span>
@@ -571,7 +659,7 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
 :deep(.el-radio__input.is-checked + .el-radio__label) {
   color: var(--color-neutral-1);
 }
-:deep( .el-radio__inner) {
+:deep(.el-radio__inner) {
   border: 1px solid var(--color-system-checkbox-border);
 }
 :deep(.el-radio__inner) {
@@ -583,13 +671,17 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
 }
 .oceanCheckbox {
   margin-bottom: 8px;
+  :deep(.el-checkbox__input) {
+    padding: 4px;
+  }
 }
 .delayedType {
   align-items: start;
   height: fit-content;
   margin-right: 5px;
   border-radius: 6px;
-  padding: 13px;
+  padding: 8px;
+  padding-left: 4px;
 }
 :deep(.el-checkbox) {
   width: 100%;
@@ -599,11 +691,14 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
 }
 :deep(.el-checkbox__label) {
   width: 100%;
+  padding-left: 0px;
 }
 .titlecheckbox {
   width: 100%;
   display: flex;
   justify-content: space-between;
+  padding-left: 4px;
+  padding-top: 4px;
 }
 .icon_grey {
   color: #b8bbbf;
@@ -674,4 +769,4 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
   align-items: center;
   justify-content: center;
 }
-</style>
+</style>

+ 77 - 50
src/views/DestinationDelivery/src/components/CreateNewBooking/src/CreateNewbooking.vue

@@ -27,13 +27,15 @@ const VesselName = ref([])
 const VesselNametest = ref('')
 const ShipperValue = ref('')
 const ConsigneeValue = ref('')
+const deliveryDate = ref('')
 const DeliveryReference = ref('')
 const getAddressListData = ref({})
 // const isFocused = ref(false)
 const isFocused = ref({
   Shipper: false,
   Consignee: false,
-  Vessel: false
+  Vessel: false,
+  deliveryDate: false
 })
 const isataFocused = ref(false)
 const isetaFocused = ref(false)
@@ -198,10 +200,6 @@ const showETAlabel = computed(() => {
   return ETATimeList.value != null || isetaFocused.value
 })
 
-const changeFocus = (val: boolean) => {
-  // isFocused.value = val
-}
-
 const changeFocustest = (type: any, val: boolean) => {
   isFocused.value[type] = val
 }
@@ -227,34 +225,34 @@ const querySearchCountry = (query: string) => {
   Countryloading.value = true
   setTimeout(() => {
     $api
-    .getAddressCountryCityData({
-      term: query,
-      term_type: 'country',
-      limit: CityCode.value != ''  ? CityCode.value : ''
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        Countryoptions.value = res.data
-        Countryloading.value = false
-      }
-    })
+      .getAddressCountryCityData({
+        term: query,
+        term_type: 'country',
+        limit: CityCode.value != '' ? CityCode.value : ''
+      })
+      .then((res: any) => {
+        if (res.code === 200) {
+          Countryoptions.value = res.data
+          Countryloading.value = false
+        }
+      })
   }, 1000)
 }
 const querySearchCity = (query: string) => {
   cityloading.value = true
   setTimeout(() => {
     $api
-    .getAddressCountryCityData({
-      term: query,
-      term_type: 'city',
-      limit: CountryCode.value != ''  ? CountryCode.value : ''
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        Cityoptions.value = res.data
-        cityloading.value = false
-      }
-    })
+      .getAddressCountryCityData({
+        term: query,
+        term_type: 'city',
+        limit: CountryCode.value != '' ? CountryCode.value : ''
+      })
+      .then((res: any) => {
+        if (res.code === 200) {
+          Cityoptions.value = res.data
+          cityloading.value = false
+        }
+      })
   }, 1000)
 }
 // 特殊日期样式
@@ -310,12 +308,12 @@ const AddNewAddressDelivery = () => {
 // 保存新地址
 const SaveNewAddress = () => {
   if (
-    CountryCode.value != '' &&
-    CityCode.value != '' &&
-    PostalCode.value != '' &&
-    ContactPerson.value != '' &&
-    ContactNumber.value != '' &&
-    AddressLine1.value != '' ||
+    (CountryCode.value != '' &&
+      CityCode.value != '' &&
+      PostalCode.value != '' &&
+      ContactPerson.value != '' &&
+      ContactNumber.value != '' &&
+      AddressLine1.value != '') ||
     AddressLine2.value != '' ||
     AddressLine3.value != '' ||
     AddressLine4.value != ''
@@ -464,6 +462,7 @@ const SearchShipment = () => {
     vessel: VesselNametest.value,
     consignee: ConsigneeValue.value,
     shipper: ShipperValue.value,
+    recommended_delivery_date: deliveryDate.value,
     eta_start: ETATimeList.value != null ? ETATimeList.value[0] : '',
     eta_end: ETATimeList.value != null ? ETATimeList.value[1] : '',
     ata_start: ATATimeList.value != null ? ATATimeList.value[0] : '',
@@ -616,7 +615,6 @@ const handleClickEditAddress = (val: any) => {
 // 删除地址
 const handleDeleteAddress = (val: any) => {
   const key = val.contact_type == 'Unedit' ? 'sync_key' : 'id'
-  console.log(val.contact_type)
   if (val.contact_type !== 'Add') {
     updateAddressList({ ...val, contact_type: 'Delete' })
   }
@@ -730,11 +728,10 @@ onMounted(() => {
         >
       </div>
       <div class="shipments_search" v-if="a == undefined">
-        <div class="flex">
+        <div class="left-filter-search">
           <el-input
             placeholder="Enter Booking/HBL/PO/Carrier Booking No. "
             v-model="CreateNewBOokingSearch"
-            style="width: 34%"
             class="log_input"
           >
             <template #prefix>
@@ -769,14 +766,7 @@ onMounted(() => {
             </el-input>
             <span v-if="showLabelConsignee" class="border-label">Consignee</span>
           </div>
-          <el-button
-            style="width: 108px"
-            class="el-button--dark create-button"
-            @click="SearchShipment"
-            >Search</el-button
-          >
-        </div>
-        <div class="flex" style="margin-top: 8px">
+
           <div class="input-with-label">
             <CalendarDate
               :isNeedFooter="false"
@@ -796,7 +786,26 @@ onMounted(() => {
             ></CalendarDate>
             <span v-if="showataLabel" class="border-label">ATA</span>
           </div>
+
           <div class="input-with-label" style="margin-right: 8px">
+            <!-- <AutoSelect ASPlaceholder="Input Vessel Name" :ASValue="VesselName" @changeFocus="changeFocus"></AutoSelect> -->
+            <a-date-picker
+              v-model:value="deliveryDate"
+              :showToday="false"
+              @focus="isFocused.deliveryDate = true"
+              @blur="isFocused.deliveryDate = false"
+              :format="userStore.dateFormat"
+              placeholder="Recommended Delivery Date"
+              valueFormat="MM/DD/YYYY"
+              style="width: 100%; height: 40px"
+            >
+            </a-date-picker>
+            <span v-if="isFocused.deliveryDate" class="border-label"
+              >Recommended Delivery Date</span
+            >
+          </div>
+
+          <div class="input-with-label">
             <!-- <AutoSelect ASPlaceholder="Input Vessel Name" :ASValue="VesselName" @changeFocus="changeFocus"></AutoSelect> -->
             <el-input
               placeholder="Input Vessel Name"
@@ -804,11 +813,19 @@ onMounted(() => {
               @focus="changeFocustest('Vessel', true)"
               @blur="changeFocustest('Vessel', false)"
               class="log_input"
+              style="width: 100%"
             >
             </el-input>
             <span v-if="showLabelVessel" class="border-label">Vessel Name</span>
           </div>
-          <div style="width: 108px"></div>
+        </div>
+        <div class="right-btn">
+          <el-button
+            style="width: 108px"
+            class="el-button--dark create-button"
+            @click="SearchShipment"
+            >Search</el-button
+          >
         </div>
       </div>
       <NewbookingTable
@@ -937,9 +954,14 @@ onMounted(() => {
             placeholder="Please Select Time"
           ></el-time-select>
         </div>
-        <div style="margin-left: 12px;">
+        <div style="margin-left: 12px">
           <div class="delivery_type_title">Delivery Reference</div>
-          <el-tooltip class="item" effect="dark" content="Reference to be quoted on arrival at the Warehouse/DC" placement="bottom">
+          <el-tooltip
+            class="item"
+            effect="dark"
+            content="Reference to be quoted on arrival at the Warehouse/DC"
+            placement="bottom"
+          >
             <el-input v-model="DeliveryReference" class="delivery_reference"></el-input>
           </el-tooltip>
         </div>
@@ -1431,7 +1453,14 @@ onMounted(() => {
   font-weight: 400;
 }
 .shipments_search {
-  margin: 0 0 8px 0;
+  display: flex;
+  margin-bottom: 16px;
+}
+.left-filter-search {
+  flex: 1;
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  grid-gap: 8px;
 }
 :deep(.log_input .el-input__wrapper) {
   box-shadow: 0 0 0 1px var(--color-select-border) inset;
@@ -1439,8 +1468,6 @@ onMounted(() => {
 }
 .input-with-label {
   position: relative;
-  display: inline-block;
-  width: 34%;
 }
 .border-label {
   position: absolute;

+ 129 - 4
src/views/DestinationDelivery/src/components/CreateNewBooking/src/components/NewbookingTable.vue

@@ -4,6 +4,7 @@ import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import { formatTimezone } from '@/utils/tools'
 import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
+import { autoWidth } from '@/utils/table'
 
 const router = useRouter()
 const { currentRoute } = router
@@ -61,6 +62,11 @@ const handleColumns = (columns: any) => {
           return `${formatTimezone(array[0])} - ${formatTimezone(array[1])}`
         }
       }
+    } else if (item.type === 'download') {
+      curColumn = {
+        ...curColumn,
+        slots: { default: 'download' }
+      }
     }
     return curColumn
   })
@@ -83,6 +89,11 @@ const getTableColumns = async () => {
   })
   nextTick(() => {
     tableLoadingColumn.value = false
+    tableRef.value &&
+      autoWidth(tableData.value, tableRef.value, {
+        packing_list: 190,
+        commercial_invoice: 180
+      })
   })
 }
 // 获取表格数据
@@ -103,6 +114,15 @@ const searchTableData = (val: any) => {
         tableData.value.data = res.data.data
       }
     })
+    .finally(() => {
+      nextTick(() => {
+        tableRef.value &&
+          autoWidth(tableData.value, tableRef.value, {
+            packing_list: 190,
+            commercial_invoice: 180
+          })
+      })
+    })
 }
 
 const emits = defineEmits(['selectChangeEvent'])
@@ -211,6 +231,78 @@ const selectAllChangeEvent = () => {
   }
 }
 
+function base64ToBlob(base64, mimeType) {
+  const byteString = atob(base64.split(',')[0].startsWith('data:') ? base64.split(',')[1] : base64)
+  const ab = new ArrayBuffer(byteString.length)
+  const ia = new Uint8Array(ab)
+  for (let i = 0; i < byteString.length; i++) {
+    ia[i] = byteString.charCodeAt(i)
+  }
+  return new Blob([ia], { type: mimeType })
+}
+
+const handleDownload = (serialNo: string, field: string) => {
+  const fileType = field === 'commercial_invoice' ? 'C/I' : 'Packing List'
+  $api
+    .downloadBookingTableFile({
+      serial_no: serialNo,
+      file_type: fileType
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        // 使用
+        const base64 = res.data.data // 纯 base64 字符串,不含 data: 前缀
+        const mimeType = 'application/octet-stream'
+        const fileName = res.data.filename || 'download'
+
+        const blob = base64ToBlob(base64, mimeType)
+        const url = URL.createObjectURL(blob)
+
+        const link = document.createElement('a')
+        link.href = url
+        link.download = fileName
+        document.body.appendChild(link)
+        link.click()
+        document.body.removeChild(link)
+
+        // 可选:下载完成后释放内存
+        link.onclick = () => {
+          setTimeout(() => {
+            URL.revokeObjectURL(url) // 释放对象 URL
+          }, 100)
+        }
+      }
+    })
+}
+
+const CustomizeColumnsRef = ref()
+// 打开定制表格弹窗
+const handleCustomizeColumns = () => {
+  const params = {
+    getData: {
+      action: 'destination_delivery_booking',
+      operate: 'destination_delivery_shipment_display'
+    },
+    saveData: {
+      action: 'ajax',
+      operate: 'save_setting_display',
+      model_name: 'destination_delivery_shipment_search'
+    }
+  }
+  CustomizeColumnsRef.value.openDialog(
+    params,
+    -220,
+    'Drag item over to this selection or click "add" icon to show the field on delivery booking list'
+  )
+}
+// 定制表格
+const customizeColumns = async () => {
+  await getTableColumns()
+  nextTick(() => {
+    tableRef.value && autoWidth(tableData.value, tableRef.value)
+  })
+}
+
 // 实现行点击样式
 useRowClickStyle(tableRef)
 
@@ -224,7 +316,15 @@ defineExpose({
 </script>
 
 <template>
-  <div class="SettingTable">
+  <div class="new-booking-table">
+    <el-button
+      style="width: 170px; align-self: flex-end"
+      type="default"
+      @click="handleCustomizeColumns"
+    >
+      <span style="margin-right: 6px" class="font_family icon-icon_column_b"></span>
+      Customize Columns
+    </el-button>
     <vxe-grid
       ref="tableRef"
       :style="{ border: 'none' }"
@@ -233,6 +333,16 @@ defineExpose({
       @checkbox-change="selectChangeEvent"
       @checkbox-all="selectAllChangeEvent"
     >
+      <!-- download下载的插槽 -->
+      <template #download="{ row, column }">
+        <div class="download-btn" @click="handleDownload(row.serial_no, column.field)">
+          <span class="font_family icon-icon_download_b icon-style"> </span>
+          <span
+            >{{ row.h_bol
+            }}{{ column.field === 'commercial_invoice' ? '.CI.zip' : '._PL.zip' }}</span
+          >
+        </div>
+      </template>
       <template #empty>
         <div v-if="isNotActivated" class="empty-text">
           This service isn't activated yet. Please contact our team to enable it.
@@ -240,13 +350,12 @@ defineExpose({
         <div v-else class="empty-text">No eligible shipments found to create a new booking.</div>
       </template>
     </vxe-grid>
+
+    <CustomizeColumns @customize="customizeColumns" ref="CustomizeColumnsRef" />
   </div>
 </template>
 
 <style lang="scss" scoped>
-.font_family::before {
-  color: var(--color-btn-danger-bg);
-}
 .icon_alert::before {
   color: var(--color-btn-warning-bg);
 }
@@ -274,4 +383,20 @@ defineExpose({
   color: var(--color-neutral-1);
   margin: 31px 0;
 }
+.download-btn {
+  cursor: pointer;
+
+  &:hover,
+  &:focus {
+    span,
+    .icon-style {
+      color: var(--color-theme) !important;
+    }
+  }
+}
+.new-booking-table {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
 </style>

+ 2 - 0
src/views/Layout/src/components/Menu/MenuView.vue

@@ -148,6 +148,7 @@ router.afterEach(() => {
 
 // 路由跳转函数
 const changeRouter = (path: any) => {
+  sessionStorage.removeItem('reportList')
   if (localStorage.getItem('loginAI')) {
     localStorage.removeItem('loginAI')
     emitter.emit('login-success')
@@ -165,6 +166,7 @@ const changeRouter = (path: any) => {
   }
   if (sessionStorage.getItem('searchTableQeuryTracking')) {
     sessionStorage.removeItem('searchTableQeuryTracking')
+    sessionStorage.removeItem('tagsList')
   }
   if (sessionStorage.getItem('clickParams')) {
     sessionStorage.removeItem('clickParams')

+ 150 - 82
src/views/Tracking/src/TrackingView.vue

@@ -8,6 +8,12 @@ import MoreFilters from '@/components/MoreFilters'
 import { ref, reactive, onMounted } from 'vue'
 import { useCalculatingHeight } from '@/hooks/calculatingHeight'
 import { useHeaderSearch } from '@/stores/modules/headerSearch'
+import { useUserStore } from '@/stores/modules/user'
+import dayjs from 'dayjs'
+
+const userStore = useUserStore()
+const formatDate = userStore.dateFormat
+const valueFormatDate = 'MM/DD/YYYY'
 
 const headerSearch = useHeaderSearch()
 
@@ -33,18 +39,18 @@ const handleClose = (tag: any) => {
     sessionStorage.getItem('reportList') != null ||
     sessionStorage.getItem('reportList') != '{}'
   ) {
-    const reportlist = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
+    const reportList = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
     let data = JSON.parse(sessionStorage.getItem('tagsList') as string) || {}
     if (tag.includes('Transport')) {
-      delete reportlist.transport_mode
+      delete reportList.transport_mode
     } else if (tag.includes('Day') || tag.includes('CO2e')) {
-      delete reportlist._reportRef
-      delete reportlist._reportType
-      delete reportlist._reportRefe_date
-      delete reportlist._reportRefb_date
-      delete reportlist._reportStationType
-      delete reportlist._reportDataType
-      delete reportlist._reportStationType
+      delete reportList._reportRef
+      delete reportList._reportType
+      delete reportList._reportRefe_date
+      delete reportList._reportRefb_date
+      delete reportList._reportStationType
+      delete reportList._reportDataType
+      delete reportList._reportStationType
       filterData.dashboardData = []
       data = {}
     } else if (tag.includes('ETD')) {
@@ -53,24 +59,24 @@ const handleClose = (tag: any) => {
           filterData.daterangeData.splice(index, 1)
         }
       })
-      delete reportlist.etd_start
-      delete reportlist.etd_end
+      delete reportList.etd_start
+      delete reportList.etd_end
     } else if (tag.includes('ETA')) {
       filterData.daterangeData.forEach((item: any, index: any) => {
         if (item.includes('ETA')) {
           filterData.daterangeData.splice(index, 1)
         }
       })
-      delete reportlist.eta_start
-      delete reportlist.eta_end
+      delete reportList.eta_start
+      delete reportList.eta_end
     } else if (tag.includes('Origin')) {
-      delete reportlist.shipper_city
-      delete reportlist._city_name
+      delete reportList.shipper_city
+      delete reportList._city_name
       filterData.dashboardData = []
     } else if (tag.includes('Destination')) {
-      delete reportlist.consignee_city
+      delete reportList.consignee_city
     }
-    sessionStorage.setItem('reportList', JSON.stringify(reportlist))
+    sessionStorage.setItem('reportList', JSON.stringify(reportList))
     sessionStorage.setItem('tagsList', JSON.stringify(data))
   }
   if (tag.includes('Transport')) {
@@ -142,14 +148,16 @@ const handleClose = (tag: any) => {
   } else if (tag.includes('Voyage')) {
     delete searchTableQeuryTracking['f_voyage/voyage']
   }
+
   sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
-  Gettrackingdata()
+  getTrackingData()
 }
 // 筛选框查询
 const FiltersSeach = (val: any, value: any) => {
   searchTableQeuryTracking[val] = value
+
   sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
-  Gettrackingdata()
+  getTrackingData()
 }
 //TransportSearch
 const TransportSearch = (val: any) => {
@@ -179,36 +187,33 @@ const defaultTransport = (val: any, value: any) => {
     searchTableQeuryTracking = value
   }
 }
-//defaultDate
-const defaultDate = (val: any, value: any, data: any) => {
+const setFilterData = (dateRangeData: any) => {
   filterData.daterangeData = []
-  if (Object.keys(val).length) {
-    for (const key in val) {
-      let str = `${key}:${val[key]}`
-      filterData.daterangeData.push(str)
-    }
+  for (const key in dateRangeData) {
+    const startEnd = dateRangeData[key].data[0] + ' To ' + dateRangeData[key].data[1]
+    let str = `${key}:${startEnd}`
+    filterData.daterangeData.push(str)
   }
+}
+//defaultDate
+const defaultDate = (dateRangeData: any, data: any) => {
+  setFilterData(dateRangeData)
 
   if (sessionStorage.getItem('searchTableQeuryTracking') == null) {
     if (
       sessionStorage.getItem('clickParams') === null ||
       sessionStorage.getItem('clickParams') === '{}'
     ) {
-      if (Object.keys(value).length == 0) {
+      if (Object.keys(dateRangeData).length == 0) {
         delete searchTableQeuryTracking.etd_start
         delete searchTableQeuryTracking.etd_end
       }
-      for (const key in value) {
-        searchTableQeuryTracking.etd_start = value[key].data[0]
-        searchTableQeuryTracking.etd_end = value[key].data[1]
+      for (const key in dateRangeData) {
+        searchTableQeuryTracking.etd_start = dateRangeData[key].data[0]
+
+        searchTableQeuryTracking.etd_end = dateRangeData[key].data[1]
       }
     }
-    // else {
-    //   for (const key in value) {
-    //     searchTableQeuryTracking.etd_start = value[key].data[0]
-    //     searchTableQeuryTracking.etd_end = value[key].data[1]
-    //   }
-    // }
   } else {
     searchTableQeuryTracking = data
     if (searchTableQeuryTracking._textSearch) {
@@ -221,22 +226,16 @@ const defaultDate = (val: any, value: any, data: any) => {
   if (trackingData) {
     // 根据顶部搜索框的搜索结果赋值
     initDataByHeaderSearch()
-  } else {
-    Gettrackingdata()
+  } else if (!trackingData && !sessionStorage.getItem('clickParams')) {
+    getTrackingData()
   }
 
   renderTagsData()
 }
 //DateRangeSearch
-const DateRangeSearch = (val: any, value: any) => {
-  filterData.daterangeData = []
-  if (Object.keys(val).length) {
-    for (const key in val) {
-      let str = `${key}:${val[key]}`
-      filterData.daterangeData.push(str)
-    }
-  }
-  if (Object.keys(value).length == 0) {
+const DateRangeSearch = (dateRangeData: any) => {
+  setFilterData(dateRangeData)
+  if (Object.keys(dateRangeData).length == 0) {
     delete searchTableQeuryTracking.etd_start
     delete searchTableQeuryTracking.etd_end
     delete searchTableQeuryTracking.eta_start
@@ -244,20 +243,35 @@ const DateRangeSearch = (val: any, value: any) => {
     delete searchTableQeuryTracking.created_time_start
     delete searchTableQeuryTracking.created_time_end
   }
-  for (const key in value) {
+  const fieldList = [
+    {
+      title: 'ETD',
+      keys: ['etd_start', 'etd_end']
+    },
+    { title: 'ETA', keys: ['eta_start', 'eta_end'] },
+    { title: 'Creation Time', keys: ['created_time_start', 'created_time_end'] }
+  ]
+  fieldList.forEach((item) => {
+    if (!dateRangeData.hasOwnProperty(item.title)) {
+      // 删除不存在的字段
+      searchTableQeuryTracking[item.keys[0]] = undefined
+      searchTableQeuryTracking[item.keys[1]] = undefined
+    }
+  })
+  for (const key in dateRangeData) {
     if (key == 'ETD') {
-      searchTableQeuryTracking.etd_start = value[key].data[0]
-      searchTableQeuryTracking.etd_end = value[key].data[1]
+      searchTableQeuryTracking.etd_start = dateRangeData[key].data[0]
+      searchTableQeuryTracking.etd_end = dateRangeData[key].data[1]
     } else if (key == 'ETA') {
-      searchTableQeuryTracking.eta_start = value[key].data[0]
-      searchTableQeuryTracking.eta_end = value[key].data[1]
+      searchTableQeuryTracking.eta_start = dateRangeData[key].data[0]
+      searchTableQeuryTracking.eta_end = dateRangeData[key].data[1]
     } else {
-      searchTableQeuryTracking.created_time_start = value[key].data[0]
-      searchTableQeuryTracking.created_time_end = value[key].data[1]
+      searchTableQeuryTracking.created_time_start = dateRangeData[key].data[0]
+      searchTableQeuryTracking.created_time_end = dateRangeData[key].data[1]
     }
   }
   sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
-  Gettrackingdata()
+  getTrackingData()
   renderTagsData()
 }
 //MoreFiltersSearch
@@ -325,7 +339,7 @@ const MoreFiltersSearch = (val: any, value: any) => {
     }
   }
   sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
-  Gettrackingdata()
+  getTrackingData()
   renderTagsData()
 }
 const defaultMorefilters = (val: any, value: any, data: any) => {
@@ -417,19 +431,18 @@ const clearfilters = () => {
     sessionStorage.getItem('reportList') != null ||
     sessionStorage.getItem('reportList') != '{}'
   ) {
-    let reportlist = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
-    let data = JSON.parse(sessionStorage.getItem('tagsList') as string) || {}
-    reportlist = {}
-    data = {}
-    sessionStorage.setItem('reportList', JSON.stringify(reportlist))
-    sessionStorage.setItem('tagsList', JSON.stringify(data))
-  } else {
-    searchTableQeuryTracking.filterTag = ['All']
+    // sessionStorage.removeItem('reportList')
+    sessionStorage.removeItem('tagsList')
   }
-  Gettrackingdata()
+  getTrackingData()
   renderTagsData()
 }
 const renderTagsData = () => {
+  const data = JSON.parse(sessionStorage.getItem('tagsList') as string) || {}
+  if (Object.keys(data).length != 0) {
+    let str = `${data.title}:${data.name}`
+    !filterData.dashboardData.includes(str) && filterData.dashboardData.push(str)
+  }
   tagsData.value = []
   if (filterData.transportData.length) {
     tagsData.value.push(filterData.transportData[0])
@@ -496,6 +509,7 @@ const initDataByHeaderSearch = () => {
     sessionStorage.removeItem('searchTableQeuryTracking')
     searchTableQeuryTracking._textSearch = TrackingSearch.value
     searchTableQeuryTracking.filterTag = ['All']
+
     sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
     setTimeout(() => {
       emitter.emit('clearTag', 'Shipment status')
@@ -549,7 +563,22 @@ interface ListItem {
 const TagsList = ref<ListItem[]>([])
 const filterTag = ref(['All'])
 const isShowAlertIcon = ref(false)
-const Gettrackingdata = () => {
+const getTrackingData = () => {
+  const dateRangeKeys = [
+    'etd_start',
+    'etd_end',
+    'eta_start',
+    'eta_end',
+    'created_time_start',
+    'created_time_end'
+  ]
+  const curRangeData = {}
+  for (const key of dateRangeKeys) {
+    if (searchTableQeuryTracking[key]) {
+      curRangeData[key] = dayjs(searchTableQeuryTracking[key], formatDate).format(valueFormatDate)
+    }
+  }
+
   tableLoadingTableData.value = true
   TrackingTable_ref.value.getLoadingData(tableLoadingTableData.value)
   $api
@@ -558,7 +587,8 @@ const Gettrackingdata = () => {
       ps: TrackingTable_ref.value.pageInfo.pageSize,
       rc: -1,
       other_filed: '',
-      ...searchTableQeuryTracking
+      ...searchTableQeuryTracking,
+      ...curRangeData
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -594,28 +624,64 @@ const Gettrackingdata = () => {
         }
       }
     })
+    .finally(() => {
+      sessionStorage.removeItem('clickParams')
+    })
 }
 onMounted(() => {
   if (
     sessionStorage.getItem('clickParams') != null &&
     sessionStorage.getItem('clickParams') != '{}'
   ) {
-    if (sessionStorage.getItem('searchTableQeuryTracking') != null) {
-      searchTableQeuryTracking = {}
-    }
-    const data = JSON.parse(sessionStorage.getItem('tagsList') as string) || {}
-    const reportlist = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
-    for (const key in reportlist) {
-      searchTableQeuryTracking[key] = reportlist[key]
-    }
-    if (reportlist._city_name == '' || reportlist._city_name == undefined) {
-      if (Object.keys(data).length != 0) {
-        let str = `${data.title}:${data.name}`
-        filterData.dashboardData.push(str)
+    const reportList = JSON.parse(sessionStorage.getItem('reportList') as string) || {}
+    for (const key in reportList) {
+      let str = ''
+      switch (key) {
+        case 'etd_start':
+          const startDate = dayjs(reportList['etd_start'], valueFormatDate).format(formatDate)
+          searchTableQeuryTracking['etd_start'] = startDate
+          const endDate = dayjs(reportList['etd_end'], valueFormatDate).format(formatDate)
+          searchTableQeuryTracking['etd_end'] = endDate
+          const startEnd = startDate + ' To ' + endDate
+          str = `ETD:${startEnd}`
+          // filterData.daterangeData.push(str)
+          break
+
+        case 'etd_end':
+          break
+        case 'eta_start':
+          const etaStart = dayjs(reportList['eta_start'], valueFormatDate).format(formatDate)
+          searchTableQeuryTracking['eta_start'] = etaStart
+          const etaEnd = dayjs(reportList['eta_end'], valueFormatDate).format(formatDate)
+          searchTableQeuryTracking['eta_end'] = etaEnd
+          str = `ETA:${etaStart} To ${etaEnd}`
+          // filterData.daterangeData.push(str)
+          break
+
+        case 'eta_end':
+          break
+        case 'created_time_start':
+          const createdTimeStart = dayjs(reportList['created_time_start'], valueFormatDate).format(
+            formatDate
+          )
+          searchTableQeuryTracking['created_time_start'] = createdTimeStart
+          const createdTimeEnd = dayjs(reportList['created_time_end'], valueFormatDate).format(
+            formatDate
+          )
+          searchTableQeuryTracking['created_time_end'] = createdTimeEnd
+          str = `Creation Time:${createdTimeStart} To ${createdTimeEnd}`
+          // filterData.daterangeData.push(str)
+          break
+        case 'created_time_end':
+          break
+        default:
+          searchTableQeuryTracking[key] = reportList[key]
       }
     }
+
+    // sessionStorage.removeItem('reportList')
     sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
-    Gettrackingdata()
+    getTrackingData()
   }
   renderTagsData()
 })
@@ -625,17 +691,19 @@ const changeTag = (val: any, boolean: any) => {
   let str = 'Shipment status: ' + val
   filterData.filtersTagData.push(str)
   filterTag.value = val
+
   sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
   if (boolean) {
-    Gettrackingdata()
+    getTrackingData()
   }
   renderTagsData()
 }
 // 点击search按钮
 const SearchInput = () => {
   searchTableQeuryTracking._textSearch = TrackingSearch.value
+
   sessionStorage.setItem('searchTableQeuryTracking', JSON.stringify(searchTableQeuryTracking))
-  Gettrackingdata()
+  getTrackingData()
 }
 
 import TrackingGuide from './components/TrackingGuide.vue'

+ 1 - 1
src/views/Tracking/src/components/DownloadAttachment/src/DownloadAttachment.vue

@@ -227,7 +227,7 @@ const handleDownloadAllSelectedFiles = (label?: string) => {
         })
         return
       } else if (res.data?.code === 500) {
-        ElMessageBox.alert(res.data.message, 'Prompt', {
+        ElMessageBox.alert(res.data.msg, 'Prompt', {
           confirmButtonText: 'OK',
           confirmButtonClass: 'el-button--dark'
         })

+ 0 - 1
src/views/Tracking/src/components/TrackingDetail/src/TrackingDetail.vue

@@ -140,7 +140,6 @@ const SubscribeShipments = () => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        console.log(res.data)
       }
     })
 }

+ 6 - 3
src/views/Tracking/src/components/TrackingTable/src/TrackingTable.vue

@@ -510,7 +510,11 @@ const handleCustomizeColumns = () => {
       model_name: 'Ocean_Search'
     }
   }
-  CustomizeColumnsRef.value.openDialog(params, -220)
+  CustomizeColumnsRef.value.openDialog(
+    params,
+    -220,
+    'Drag item over to this selection or click "add" icon to show the column on your shipment list'
+  )
 }
 
 // 定制表格
@@ -541,8 +545,8 @@ const handleLinkClick = (row: any, column: any) => {
       path: '/tracking/detail',
       query: { a: row.__serial_no, _schemas: row._schemas }
     })
-    visitedRowState.setTrackingTableData(row['__serial_no'])
   }
+  visitedRowState.setTrackingTableData(row['__serial_no'])
 }
 
 const selectedNumber = ref(0)
@@ -601,7 +605,6 @@ const SubscribeShipments = (row: any) => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        console.log(res.data)
       }
     })
 }