|
@@ -2,6 +2,7 @@
|
|
|
import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
|
|
import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
|
|
|
import { useRowClickStyle } from '@/hooks/rowClickStyle'
|
|
import { useRowClickStyle } from '@/hooks/rowClickStyle'
|
|
|
import { formatTimezone, formatNumber } from '@/utils/tools'
|
|
import { formatTimezone, formatNumber } from '@/utils/tools'
|
|
|
|
|
+import { autoWidth } from '@/utils/table'
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
|
data: Object
|
|
data: Object
|
|
@@ -11,40 +12,7 @@ const tableData = ref<VxeGridProps<any>>({
|
|
|
minHeight: 70,
|
|
minHeight: 70,
|
|
|
border: true,
|
|
border: true,
|
|
|
round: true,
|
|
round: true,
|
|
|
- columns: [
|
|
|
|
|
- {
|
|
|
|
|
- field: 'HBOL No.',
|
|
|
|
|
- title: 'HBOL No.',
|
|
|
|
|
- width: 120
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- field: 'Container No.',
|
|
|
|
|
- title: 'Container No.'
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- field: 'Service Type',
|
|
|
|
|
- title: 'Service Type'
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- field: 'ETA',
|
|
|
|
|
- title: 'ETA',
|
|
|
|
|
- minWidth: 100,
|
|
|
|
|
- formatter: ({ cellValue }: any) => formatTimezone(cellValue)
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
- field: 'Recommended Delivery Date',
|
|
|
|
|
- title: 'Recommended Delivery Date',
|
|
|
|
|
- width: 220,
|
|
|
|
|
- formatter: ({ cellValue }: any) => {
|
|
|
|
|
- if (!cellValue) return '--'
|
|
|
|
|
- const rangeData = cellValue.split(';')
|
|
|
|
|
- const leftDate = rangeData[0] ? formatTimezone(rangeData[0]) : '_'
|
|
|
|
|
- const rightDate = rangeData[1] ? formatTimezone(rangeData[0]) : '_'
|
|
|
|
|
- return leftDate + ' -- ' + rightDate
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
|
|
+ columns: [],
|
|
|
data: [],
|
|
data: [],
|
|
|
scrollY: { enabled: true, oSize: 20, gt: 30 },
|
|
scrollY: { enabled: true, oSize: 20, gt: 30 },
|
|
|
emptyText: ' ',
|
|
emptyText: ' ',
|
|
@@ -56,10 +24,74 @@ const tableData = ref<VxeGridProps<any>>({
|
|
|
columnConfig: { resizable: true, useKey: true },
|
|
columnConfig: { resizable: true, useKey: true },
|
|
|
rowConfig: { isHover: true }
|
|
rowConfig: { isHover: true }
|
|
|
})
|
|
})
|
|
|
|
|
+const tableLoadingColumn = ref()
|
|
|
|
|
+
|
|
|
|
|
+const handleColumns = (columns: any) => {
|
|
|
|
|
+ const newColumns = columns.map((item: any) => {
|
|
|
|
|
+ let curColumn: any = {
|
|
|
|
|
+ title: item.title,
|
|
|
|
|
+ field: item.field,
|
|
|
|
|
+ width: '150px'
|
|
|
|
|
+ }
|
|
|
|
|
+ // 格式化
|
|
|
|
|
+ if (item.formatter === 'date') {
|
|
|
|
|
+ curColumn = {
|
|
|
|
|
+ ...curColumn,
|
|
|
|
|
+ formatter: ({ cellValue }: any) => formatTimezone(cellValue)
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (item.type === 'link') {
|
|
|
|
|
+ curColumn = {
|
|
|
|
|
+ ...curColumn,
|
|
|
|
|
+ slots: { default: 'trackingNo' }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (item.type == 'recommend') {
|
|
|
|
|
+ curColumn = {
|
|
|
|
|
+ ...curColumn,
|
|
|
|
|
+ formatter: ({ cellValue }: any) => {
|
|
|
|
|
+ if (!cellValue) return '--'
|
|
|
|
|
+ const array = cellValue.split('-')
|
|
|
|
|
+ return `${formatTimezone(array[0])} -- ${formatTimezone(array[1])}`
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (item.type === 'download') {
|
|
|
|
|
+ curColumn = {
|
|
|
|
|
+ ...curColumn,
|
|
|
|
|
+ slots: { default: 'download' }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return curColumn
|
|
|
|
|
+ })
|
|
|
|
|
+ return newColumns
|
|
|
|
|
+}
|
|
|
|
|
+// 获取表格列
|
|
|
|
|
+const getTableColumns = async () => {
|
|
|
|
|
+ tableLoadingColumn.value = true
|
|
|
|
|
+ await $api.BookingTableColumn().then((res: any) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ tableData.value.columns = [...handleColumns(res.data.TrackingTableColumns)]
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ tableLoadingColumn.value = false
|
|
|
|
|
+ tableRef.value &&
|
|
|
|
|
+ autoWidth(tableData.value, tableRef.value, {
|
|
|
|
|
+ packing_list: 190,
|
|
|
|
|
+ commercial_invoice: 180
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+onMounted(() => {
|
|
|
|
|
+ getTableColumns()
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
// 获得表格数据后赋值
|
|
// 获得表格数据后赋值
|
|
|
const assignTableData = (data: any) => {
|
|
const assignTableData = (data: any) => {
|
|
|
tableData.value.data = data || []
|
|
tableData.value.data = data || []
|
|
|
|
|
+ tableRef.value &&
|
|
|
|
|
+ autoWidth(tableData.value, tableRef.value, {
|
|
|
|
|
+ packing_list: 190,
|
|
|
|
|
+ commercial_invoice: 180
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
watch(
|
|
watch(
|
|
|
() => props.data,
|
|
() => props.data,
|
|
@@ -74,25 +106,48 @@ const tableLoadingTable = ref()
|
|
|
|
|
|
|
|
let searchdata: any = {}
|
|
let searchdata: any = {}
|
|
|
|
|
|
|
|
-// 获取表格数据
|
|
|
|
|
-const getTableData = async () => {
|
|
|
|
|
- const rc = -1
|
|
|
|
|
- tableLoadingTable.value = true
|
|
|
|
|
- await $api
|
|
|
|
|
- .SearchOperationLog({
|
|
|
|
|
- cp: 1,
|
|
|
|
|
- ps: 6,
|
|
|
|
|
- rc,
|
|
|
|
|
- ...searchdata
|
|
|
|
|
|
|
+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) => {
|
|
.then((res: any) => {
|
|
|
if (res.code === 200) {
|
|
if (res.code === 200) {
|
|
|
- assignTableData(res.data)
|
|
|
|
|
|
|
+ // 使用
|
|
|
|
|
+ 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)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .finally(() => {
|
|
|
|
|
- tableLoadingTable.value = false
|
|
|
|
|
- })
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 实现行点击样式
|
|
// 实现行点击样式
|
|
@@ -109,6 +164,15 @@ useRowClickStyle(tableRef)
|
|
|
max-height="240"
|
|
max-height="240"
|
|
|
min-height="120"
|
|
min-height="120"
|
|
|
>
|
|
>
|
|
|
|
|
+ <template #download="{ row, column }">
|
|
|
|
|
+ <div class="download-btn" @click="handleDownload(row.h_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 v-if="!tableLoadingTable && tableData.data.length === 0">
|
|
<template #empty v-if="!tableLoadingTable && tableData.data.length === 0">
|
|
|
<div class="empty">No data</div>
|
|
<div class="empty">No data</div>
|
|
|
</template>
|
|
</template>
|