فهرست منبع

feat:修改log下载,修改date range组件,添加查询结果不存在时的提示

AmandaG 1 سال پیش
والد
کامیت
a72839069b

+ 14 - 0
src/api/module/common.ts

@@ -80,6 +80,20 @@ export const SearchOperationLog = (params: any, config: any) => {
     config
   )
 }
+/**
+ * 日志表格下载
+ */
+export const OperationLogDownload = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'opreation_log',
+      operate: 'excel',
+      ...params
+    },
+    config
+  )
+}
 /**
  * 获取首页数据
  */

+ 1 - 2
src/auto-imports.d.ts

@@ -3,7 +3,6 @@
 // @ts-nocheck
 // noinspection JSUnusedGlobalSymbols
 // Generated by unplugin-auto-import
-// biome-ignore lint: disable
 export {}
 declare global {
   const $api: typeof import('@/api/index')['default']
@@ -69,6 +68,6 @@ declare global {
 // for type re-export
 declare global {
   // @ts-ignore
-  export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
+  export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
   import('vue')
 }

+ 0 - 1
src/components/AutoSelect/src/AutoSelect.vue

@@ -47,7 +47,6 @@ watch(
 watch(
   () => props.ASSearchObj,
   (current) => {
-    console.log(current)
     MoreFiltersObj.value = current
   }
 )

+ 5 - 3
src/components/DateRange/src/DateRange.vue

@@ -53,6 +53,10 @@ const props = defineProps({
 })
 let daterangeObj: any = {}
 const DateStart = ref()
+const DateEnd = ref()
+DateEnd.value = []
+const DateCreation = ref()
+DateCreation.value = []
 const searchTableQeury = ref()
 const searchTableQeuryTracking = ref()
 // 查询默认日期
@@ -188,8 +192,6 @@ const defaultDate = () => {
     emit('defaultDate', daterangeObj, daterangeObj2, searchTableQeury.value)
   }
 }
-const DateEnd = ref()
-const DateCreation = ref()
 const daterangedata = ref()
 daterangedata.value = []
 let daterangeObj2: any = {}
@@ -263,7 +265,7 @@ const clearDaterangeObj = () => {
   <div class="select">
     <el-popover trigger="click" :width="400" :visible="Date_visible">
       <template #reference>
-        <div class="Date_Range" @click="Date_visible = !Date_visible">
+        <div class="Date_Range" @blur="Date_visible = false" @click="Date_visible = !Date_visible">
           <div class="select_title">Date Range</div>
           <span class="iconfont_icon">
             <svg class="iconfont" aria-hidden="true">

+ 30 - 4
src/components/DateRange/src/components/CalendarDate.vue

@@ -1,6 +1,7 @@
 <script lang="ts" setup>
 import dayjs, { Dayjs } from 'dayjs'
 import { ref, watch } from 'vue'
+import moment from 'moment'
 
 // type RangeValue = [Dayjs, Dayjs]
 // const ETDDate = ref<RangeValue>()
@@ -28,28 +29,53 @@ const open = ref(false)
 const Disabled = ref([false, false])
 const isShowExtra = ref(true)
 
+const DateList = ref()
+DateList.value = []
+const daterange = (val: any) => {
+  if (DateList.value.length == 2 && val != undefined) {
+    const rangedata = {
+      title: props.CalendarTitle,
+      data: DateList.value
+    }
+    emit('DateRangeChange', rangedata)
+  }
+}
 const ChangeToday = (val: any) => {
   if (val == 'Earliest') {
     // ETDDate.value = [dayjs(), dayjs()]
     ETDDate.value[0] = dayjs()
     open.value = false
+    const date1 = moment(String(ETDDate.value[0])).format('MM/DD/YYYY')
+    DateList.value[0] = date1
+    daterange(DateList.value[1])
   } else {
     ETDDate.value[1] = dayjs()
     open.value = false
-    // ETDDate.value = [dayjs(), dayjs()]
+    const date1 = moment(String(ETDDate.value[1])).format('MM/DD/YYYY')
+    open.value = false
+    DateList.value[1] = date1
+    daterange(DateList.value[0])
   }
 }
 const handleCalendarOpen = () => {
   open.value = !open.value
 }
 const Earliest = () => {
-  Disabled.value = [true, false]
-  ETDDate.value = [dayjs('Oct-05-2009'), dayjs()]
+  ETDDate.value[0] = dayjs('Oct-05-2009')
+  const date1 = moment(String(ETDDate.value[0])).format('MM/DD/YYYY')
+  DateList.value[0] = date1
+  daterange(DateList.value[1])
+  open.value = false
 }
 const Latest = () => {
-  Disabled.value = [false, true]
+  ETDDate.value[1] = dayjs()
+  const date1 = moment(String(ETDDate.value[1])).format('MM/DD/YYYY')
+  open.value = false
+  DateList.value[1] = date1
+  daterange(DateList.value[0])
 }
 const changeRangeData = (value: any) => {
+  DateList.value = value
   if (value != '') {
     const rangedata = {
       title: props.CalendarTitle,

+ 2 - 1
src/components/MoreFilters/src/components/SelectValue.vue

@@ -329,7 +329,8 @@ const clickSeeAll = () => {
   overflow-y: clip;
 }
 .seeall {
-  max-height: fit-content;
+  max-height: 426px;
+  overflow: scroll;
 }
 .isDisabled {
   background-color: #f5f7fa;

+ 3 - 0
src/styles/elementui.scss

@@ -702,3 +702,6 @@ div .el-space {
 div .el-loading-spinner .path {
   stroke: var(--color-theme);
 }
+div .ShowAlerIcon {
+  width: 342px;
+}

+ 35 - 0
src/views/Booking/src/BookingView.vue

@@ -125,6 +125,9 @@ const defaultDate = (val: any, value: any, data: any) => {
     }
   } else {
     searchTableQeury = data
+    if (searchTableQeury._textSearch) {
+      BookingSearch.value = searchTableQeury._textSearch
+    }
   }
   BookingTable_ref.value.searchTableData(searchTableQeury)
   getbookingdata()
@@ -253,6 +256,7 @@ const defaultMorefilters = (val: any, value: any, data: any) => {
   renderTagsData()
 }
 const clearfilters = () => {
+  BookingSearch.value = ''
   tagsData.value = []
   filterData.transportData = []
   filterData.daterangeData = []
@@ -317,6 +321,7 @@ interface ListItem {
 }
 const TagsList = ref<ListItem[]>([])
 const filterTag = ref(['All'])
+const isShowAlertIcon = ref(false)
 const getbookingdata = () => {
   $api
     .getBookingTableData({
@@ -330,6 +335,13 @@ const getbookingdata = () => {
       if (res.code === 200) {
         TransportListItem.value = res.data.TransportList
         TagsList.value = res.data.tagsList
+        if (BookingSearch.value != '') {
+          if (res.data.searchData.length == 0) {
+            isShowAlertIcon.value = true
+          }
+        } else {
+          isShowAlertIcon.value = false
+        }
       }
     })
 }
@@ -366,6 +378,22 @@ const SearchInput = () => {
               </svg>
             </span>
           </template>
+          <template #suffix>
+            <el-tooltip
+              v-if="isShowAlertIcon"
+              :offset="6"
+              popper-class="ShowAlerIcon"
+              effect="dark"
+              content="We support the following references number to find bookings:· Booking No./HAWB No./MAWB No./PO No./Carrier Booking No./Contract No./File No./Quote No."
+              placement="bottom"
+            >
+              <span class="iconfont_icon iconfont_icon_tip">
+                <svg class="iconfont" aria-hidden="true">
+                  <use xlink:href="#icon-icon_info_b"></use>
+                </svg>
+              </span>
+            </el-tooltip>
+          </template>
         </el-input>
       </div>
       <TransportMode
@@ -462,6 +490,13 @@ const SearchInput = () => {
   font-weight: 600;
   font-size: var(--font-size-2);
 }
+.iconfont_icon_tip {
+  margin-left: 8px;
+  width: 16px;
+  height: 16px;
+  display: flex;
+  align-items: center;
+}
 @media only screen and (min-width: 1280px) {
   .search {
     width: 480px;

+ 171 - 56
src/views/OperationLog/src/components/BookingTable/src/BookingTable.vue

@@ -14,7 +14,7 @@ const props = defineProps({
 })
 
 const tableOriginColumnsField = ref()
-const handleColumns = (columns: any) => {
+const handleColumns = (columns: any, status?: string) => {
   const newColumns = columns.map((item: any) => {
     let curColumn: any = {
       title: item.title,
@@ -22,35 +22,37 @@ const handleColumns = (columns: any) => {
       sortable: true
     }
     // 设置插槽
-    if (item.type === 'status') {
+    if (item.type === 'status' && status !== 'all') {
       curColumn = {
         ...curColumn,
         slots: { default: 'status' }
       }
-    } else if (item.type === 'link') {
+    } else if (item.type === 'link' && status !== 'all') {
       curColumn = {
         ...curColumn,
-        slots: { default: 'bookingNo' }
+        slots: { default: 'link' }
       }
-    } else if (item.type === 'mode') {
+    } else if (item.type === 'mode' && status !== 'all') {
       curColumn = {
         ...curColumn,
-        slots: { default: 'mode' }
+        slots: { default: 'mode' },
+        formatter: ({ cellValue }: any) => {
+          return cellValue
+        }
       }
     }
     // 格式化
     if (item.formatter === 'date') {
       curColumn = {
         ...curColumn,
-        sortBy: ({ row, column }: any) => {
-          return dayjs(row[column.field]).unix()
-        },
-        formatter: ({ cellValue }: any) => dayjs(cellValue).format('YYYY/MM/DD ') || '--'
+        formatter: ({ cellValue }: any) =>
+          cellValue ? dayjs(cellValue).format('MMM-YYYY-DD ') : '--'
       }
     } else if (item.formatter === 'dateTime') {
       curColumn = {
         ...curColumn,
-        formatter: ({ cellValue }: any) => dayjs(cellValue).format('YYYY/MM/DD HH:mm:ss') || '--'
+        formatter: ({ cellValue }: any) =>
+          cellValue ? dayjs(cellValue).format('MMM-YYYY-DD HH:mm:ss') : '--'
       }
     }
     return curColumn
@@ -59,8 +61,8 @@ const handleColumns = (columns: any) => {
 }
 
 // 获取表格列
-const getTableColumns = async (isInit: boolean) => {
-  tableLoading.value = true
+const getTableColumns = async () => {
+  tableLoadingColumn.value = true
   await $api.getOperationTableColumns().then((res: any) => {
     if (res.code === 200) {
       bookingTable.value.columns = [
@@ -71,37 +73,60 @@ const getTableColumns = async (isInit: boolean) => {
     }
   })
   nextTick(() => {
-    !isInit && (tableLoading.value = false)
+    tableRef.value && autoWidth(bookingTable.value, tableRef.value)
+    tableLoadingColumn.value = false
+    selectedNumber.value = 0
+    selectedTableData.value = []
   })
 }
 
 const pageInfo = ref({ pageNo: 1, pageSize: 20, total: 0 })
+const tempSearch = ref()
+// 获得表格数据后赋值
+const assignTableData = (data: any) => {
+  bookingTable.value.data = data.searchData || []
+  pageInfo.value.total = Number(data.rc) || 0
+  tempSearch.value = data.tmp_search
+  // 拥有所有字段的表格
+  setTimeout(() => {
+    allTable.value.columns = handleColumns(bookingTable.value.columns, 'all')
+    allTable.value.data = data.searchData || []
+    // 为了让导出的表格列宽度自适应
+    nextTick(() => {
+      allTableRef.value && autoWidth(allTable.value, allTableRef.value)
+    })
+  }, 1000)
+}
 
 let searchdata: any = {}
 // 获取表格数据
-const getTableData = async (isInit: boolean, isPageChange?: boolean) => {
+const getTableData = async (isPageChange?: boolean) => {
   const rc = isPageChange ? pageInfo.value.total : -1
-  tableLoading.value = true
+  tableLoadingTableData.value = true
   await $api
     .SearchOperationLog({
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
-      rc,
+      rc: -1,
       ...searchdata
     })
     .then((res: any) => {
       if (res.code === 200) {
-        bookingTable.value.data = res.data.searchData
-        pageInfo.value.total = Number(res.data.rc)
+        assignTableData(res.data)
       }
     })
-  nextTick(() => {
-    !isInit && (tableLoading.value = false)
-  })
+    .finally(() => {
+      selectedNumber.value = 0
+      selectedTableData.value = []
+      nextTick(() => {
+        tableRef.value && autoWidth(bookingTable.value, tableRef.value)
+        tableLoadingTableData.value = false
+      })
+    })
 }
 const SearchOperationLog = (val: any) => {
   searchdata = val
-  tableLoading.value = true
+  tableLoadingTableData.value = true
   $api
     .SearchOperationLog({
       cp: pageInfo.value.pageNo,
@@ -111,16 +136,20 @@ const SearchOperationLog = (val: any) => {
     })
     .then((res: any) => {
       if (res.code === 200) {
-        bookingTable.value.data = res.data.searchData
-        pageInfo.value.total = Number(res.data.rc)
-        tableLoading.value = false
+        assignTableData(res.data)
       }
     })
+    .finally(() => {
+      selectedNumber.value = 0
+      selectedTableData.value = []
+      nextTick(() => {
+        tableRef.value && autoWidth(bookingTable.value, tableRef.value)
+        tableLoadingTableData.value = false
+      })
+    })
 }
 onMounted(() => {
-  tableLoading.value = true
-  Promise.all([getTableColumns(true), getTableData(true)]).finally(() => {
-    tableLoading.value = false
+  Promise.all([getTableColumns(), getTableData()]).finally(() => {
     nextTick(() => {
       tableRef.value && autoWidth(bookingTable.value, tableRef.value)
     })
@@ -196,37 +225,117 @@ const bookingTable = ref<VxeGridProps<any>>({
     modes: ['current', 'selected', 'all']
   }
 })
+const allTableRef = ref<VxeGridInstance>()
+const allTable = ref<VxeGridProps<any>>({
+  columns: [],
+  data: [],
+  showHeaderOverflow: true,
+  showOverflow: true,
+  scrollY: { enabled: true, oSize: 5, gt: 2 },
+  scrollX: { enabled: true, gt: 2 },
+  exportConfig: {
+    types: ['csv', 'html', 'txt', 'xlsx'],
+    modes: ['current', 'selected', 'all']
+  }
+})
 
 // 实现行点击样式
 useRowClickStyle(tableRef)
 
 const downloadDialogRef = ref()
 const handleDownload = () => {
-  downloadDialogRef.value.openDialog()
+  const curSelectedColumns: string[] = []
+  tableRef.value?.columns?.forEach((item: any) => {
+    if (item.field) {
+      curSelectedColumns.push(item.title)
+    }
+  })
+  downloadDialogRef.value.openDialog(
+    curSelectedColumns,
+    selectedNumber.value || pageInfo.value.total
+  )
 }
 
-// 导出表格
-const exportTable = () => {
-  tableRef.value?.exportData({
+const exportLoading = ref(false)
+// 获取导出表格数据
+const getExportTableData = (status: number) => {
+  // 如果有选中表格行数据,那么只到处选中的数据
+  if (selectedNumber.value > 0) {
+    exportTable(status)
+    return
+  }
+  exportLoading.value = true
+  const buildColumnString = (columns: any[]): string => {
+    return columns
+      .filter((item) => item.field)
+      .map((item) => item.title)
+      .join(',')
+  }
+
+  let column = ''
+  if (status === 1) {
+    column = buildColumnString(bookingTable.value.columns)
+  } else {
+    column = buildColumnString(allTable.value.columns)
+  }
+  $api
+    .OperationLogDownload({
+      selected_fields: column,
+      tmp_search: tempSearch.value
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        allTable.value.data = res.data.Data || []
+        nextTick(() => {
+          exportLoading.value = false
+          // 导出数据
+          exportTable(status)
+        })
+      }
+    })
+    .finally(() => {
+      exportLoading.value = false
+    })
+}
+// 导出表格 status: 1 导出当前表格 2 导出所有字段表格
+const exportTable = (status: number) => {
+  const exportConfig: any = {
     type: 'xlsx',
     message: false,
-    filename: `Booking List_${dayjs().format('YYYYMMDDHH[h]mm[m]ss[s]')}`,
-    columnFilterMethod: ({ column }: any) => {
-      // 筛选选中导出的列
-      return column.field
+    filename: `Opeartion Log_${dayjs().format('YYYYMMDDHH[h]mm[m]ss[s]')}`
+  }
+  if (status === 1) {
+    exportConfig.columnFilterMethod = ({ column }: any) => {
+      const index = bookingTable.value.columns.findIndex((item: any) => item.field === column.field)
+      // 排除复选框列
+      return column.field && index !== -1
     }
-  })
+    exportConfig.columns = bookingTable.value.columns
+  }
+  if (selectedNumber.value > 0) {
+    exportConfig.dataFilterMethod = ({ row }: any) => {
+      const index = selectedTableData.value.findIndex(
+        (item: any) => item._X_ROW_KEY === row._X_ROW_KEY
+      )
+      return index !== -1
+    }
+  }
+  allTableRef.value?.exportData(exportConfig)
 }
 
-const tableLoading = ref(false)
+const tableLoadingColumn = ref(false)
+const tableLoadingTableData = ref(false)
 
 const selectedNumber = ref(0)
+const selectedTableData = ref([])
 // 复选框选中事件
 const handleCheckboxChange = ({ records }: any) => {
   selectedNumber.value = records.length
+  selectedTableData.value = records
 }
 const handleCheckAllChange = ({ records }: any) => {
   selectedNumber.value = records.length
+  selectedTableData.value = records
 }
 defineExpose({
   SearchOperationLog
@@ -234,7 +343,12 @@ defineExpose({
 </script>
 
 <template>
-  <div style="padding: 0px 20px">
+  <div
+    style="padding: 0px 20px"
+    class="booking-table"
+    v-loading.fullscreen.lock="exportLoading"
+    element-loading-background="rgb(43, 47, 54, 0.7)"
+  >
     <div class="table-tools">
       <div class="left-total-records">{{ selectedNumber }} Selected</div>
       <div class="right-tools-btn">
@@ -246,7 +360,7 @@ defineExpose({
     </div>
     <vxe-grid
       ref="tableRef"
-      v-vloading="tableLoading"
+      v-vloading="tableLoadingTableData || tableLoadingColumn"
       :height="props.height"
       :style="{ border: 'none' }"
       v-bind="bookingTable"
@@ -254,9 +368,9 @@ defineExpose({
       @checkbox-all="handleCheckAllChange"
     >
       <!-- 空数据时的插槽 -->
-      <template #suggestion>
+      <template #empty v-if="!tableLoadingTableData && bookingTable.data.length === 0">
         <VEmpty>
-          <template #default>
+          <template #suggestion>
             <p style="color: var(--color-neutral-3)">
               We support the following references number to find booking:
             </p>
@@ -267,17 +381,8 @@ defineExpose({
           </template>
         </VEmpty>
       </template>
-      <!-- Transportation Mode字段的插槽 -->
-      <template #mode>
-        <div>
-          <span class="font_family icon-icon_ocean_b" style="font-size: 24px"></span>
-        </div>
-      </template>
-      <!-- Status字段的插槽 -->
-      <template #status="{ row, column }">
-        <VTag :type="row[column.field]">{{ row[column.field] }}</VTag>
-      </template>
     </vxe-grid>
+    <vxe-grid :height="10" ref="allTableRef" class="all-table" v-bind="allTable"> </vxe-grid>
     <div class="bottom-pagination">
       <div class="left-total-records">Total {{ pageInfo.total }}</div>
       <div class="right-pagination">
@@ -289,12 +394,12 @@ defineExpose({
           background
           layout="sizes, prev, pager, next"
           :total="pageInfo.total"
-          @size-change="getTableData(false, true)"
-          @current-change="getTableData(false, true)"
+          @size-change="getTableData(true)"
+          @current-change="getTableData(true)"
         />
       </div>
     </div>
-    <DownloadDialog @export="exportTable" ref="downloadDialogRef" />
+    <DownloadDialog @export="getExportTableData" ref="downloadDialogRef" />
   </div>
 </template>
 
@@ -331,4 +436,14 @@ defineExpose({
     align-items: center;
   }
 }
+.booking-table {
+  position: relative;
+  overflow: hidden;
+
+  .all-table {
+    position: absolute;
+    top: -100000px;
+    width: 20px;
+  }
+}
 </style>

+ 18 - 38
src/views/OperationLog/src/components/BookingTable/src/components/DownloadDialog.vue

@@ -1,37 +1,29 @@
 <script setup lang="ts">
 const dialogVisible = ref(false)
 
-const openDialog = () => {
+const openDialog = (selectedColumns: string[], slectedDataNumber: number) => {
+  selectedDataNumber.value = slectedDataNumber
+  columns.value = selectedColumns
   dialogVisible.value = true
 }
 
 const isShowSelectColumn = ref(false)
 
 const downloadFilter = ref(1)
+const selectedDataNumber = ref(0)
 
-const listData = [
-  'Transport Mode: Air, Ocean',
-  'Creation Date: 2024/05/01 To 2024/05/31',
-  'Incoterms: FOB'
-]
-
-const columns = [
-  'Booking No.',
-  'HBOL',
-  'Container No.',
-  'Status',
-  'Shipper',
-  'Consignee',
-  'ETD',
-  'ETA',
-  'Origin',
-  'Destination'
-]
-
-const emits = defineEmits<{ export: [] }>()
+const columns = ref()
+
+const emits = defineEmits<{ export: [number] }>()
 const handleDownload = () => {
-  emits('export')
+  emits('export', downloadFilter.value)
+}
+
+const clearData = () => {
+  isShowSelectColumn.value = false
+  downloadFilter.value = 1
 }
+
 defineExpose({
   openDialog,
   handleDownload
@@ -40,16 +32,15 @@ defineExpose({
 
 <template>
   <div>
-    <el-dialog v-model="dialogVisible" title="Download File" width="480">
+    <el-dialog @close="clearData" v-model="dialogVisible" title="Download File" width="480">
       <div class="download-dialog">
         <div class="select-data">
           <div style="display: inline-block">
-            Select data on your shipment list:<span style="color: var(--color-theme)">1330</span>
+            Select data on your Opeartion Log list:<span style="color: var(--color-theme)">{{
+              selectedDataNumber
+            }}</span>
           </div>
         </div>
-        <div class="data-filter">
-          <div class="filter-item" v-for="item in listData" :key="item">{{ item }}</div>
-        </div>
         <div class="download-filter">
           <el-radio-group v-model="downloadFilter">
             <el-radio :value="1"
@@ -147,17 +138,6 @@ defineExpose({
       font-size: 12px;
     }
 
-    .el-icon {
-      margin-left: 4px;
-      color: var(--color-theme);
-      transform: rotate(0deg);
-      transition: all 0.3s;
-
-      &.is-rotate {
-        transform: rotate(180deg);
-      }
-    }
-
     .select-columns {
       padding: 8px;
       margin-top: 8px;

+ 11 - 1
src/views/Tracking/src/TrackingView.vue

@@ -325,6 +325,7 @@ const defaultMorefilters = (val: any, value: any, data: any) => {
   renderTagsData()
 }
 const clearfilters = () => {
+  TrackingSearch.value = ''
   tagsData.value = []
   filterData.transportData = []
   filterData.daterangeData = []
@@ -630,7 +631,16 @@ const SearchInput = () => {
         @close="handleClose(tag)"
         color="#EFEFF0"
       >
-        {{ tag }}
+        <el-tooltip
+          class="box-item"
+          effect="dark"
+          :content="tag"
+          placement="top"
+          v-if="tag.length > 39"
+        >
+          {{ tag.length > 39 ? tag.substr(0, 39) + '...' : tag }}
+        </el-tooltip>
+        <div v-else>{{ tag }}</div>
       </el-tag>
       <div class="text_button" @click="clearfilters">Clear Filters</div>
     </div>