|
|
@@ -0,0 +1,565 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import dayjs from 'dayjs'
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
+import { autoWidth } from '@/utils/table'
|
|
|
+import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
|
|
|
+
|
|
|
+const route = useRoute()
|
|
|
+const router = useRouter()
|
|
|
+
|
|
|
+const allData = ref<any>({})
|
|
|
+const loading = ref(false)
|
|
|
+const generalInfo = ref({
|
|
|
+ baseInfo: [
|
|
|
+ {
|
|
|
+ label: 'HBL No.',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Carrier Booking No.',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Vessel',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Voyage',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'ETD',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'ETA ',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Last Updated User',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Last Updated Time',
|
|
|
+ value: ''
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ formData: {
|
|
|
+ Submitter: '',
|
|
|
+ signature: '',
|
|
|
+ authorized_email: '',
|
|
|
+ authorized_tel: '',
|
|
|
+ is_send: false
|
|
|
+ }
|
|
|
+})
|
|
|
+const tableRef = ref<VxeGridInstance | null>(null)
|
|
|
+const tableData = ref<VxeGridProps<any>>({
|
|
|
+ minHeight: 70,
|
|
|
+ height: '330',
|
|
|
+ border: true,
|
|
|
+ round: true,
|
|
|
+ columns: [],
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ container_no: '123',
|
|
|
+ carrier_booking_no: '123',
|
|
|
+ size: '123',
|
|
|
+ vgm_weight: '123',
|
|
|
+ vgm_kg_lg: '12311111111111111111111111111',
|
|
|
+ vgm_time: '',
|
|
|
+ vgm_method: '123',
|
|
|
+ cargo_weight_kg: '123',
|
|
|
+ cargo_weight_lb: '123'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ container_no: '123',
|
|
|
+ carrier_booking_no: '123',
|
|
|
+ size: '123',
|
|
|
+ vgm_weight: '123',
|
|
|
+ vgm_kg_lg: '123',
|
|
|
+ vgm_time: '',
|
|
|
+ vgm_method: '123',
|
|
|
+ cargo_weight_kg: '123',
|
|
|
+ cargo_weight_lb: '123'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ scrollY: { enabled: true, oSize: 20, gt: 30 },
|
|
|
+ stripe: true,
|
|
|
+ emptyText: ' ',
|
|
|
+ showHeaderOverflow: true,
|
|
|
+ showOverflow: true,
|
|
|
+ headerRowStyle: {
|
|
|
+ backgroundColor: 'var(--color-table-header-bg)'
|
|
|
+ },
|
|
|
+ editConfig: {
|
|
|
+ enabled: true,
|
|
|
+ trigger: 'dblclick', // 触发编辑的方式,可以是 click 或者 dbclick
|
|
|
+ mode: 'row',
|
|
|
+ showIcon: true
|
|
|
+ },
|
|
|
+ columnConfig: { resizable: true, useKey: true },
|
|
|
+ rowConfig: { isHover: true }
|
|
|
+})
|
|
|
+const handleColumns = (columns: any) => {
|
|
|
+ const newColumns = columns.map((item: any) => {
|
|
|
+ let curColumn: any = {
|
|
|
+ title: item.title,
|
|
|
+ field: item.field
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加编辑插槽
|
|
|
+ if (item.edit_type === 'input') {
|
|
|
+ curColumn = {
|
|
|
+ ...curColumn,
|
|
|
+ editRender: {
|
|
|
+ name: 'vInput'
|
|
|
+ },
|
|
|
+ slots: {
|
|
|
+ edit: 'vInput'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (item.edit_type === 'dateTime') {
|
|
|
+ curColumn = {
|
|
|
+ ...curColumn,
|
|
|
+ editRender: {
|
|
|
+ name: 'editDate'
|
|
|
+ },
|
|
|
+ slots: {
|
|
|
+ edit: 'editDate'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (item.title === 'VGM Unit') {
|
|
|
+ curColumn = {
|
|
|
+ ...curColumn,
|
|
|
+ editRender: {
|
|
|
+ name: 'vUnitSelect'
|
|
|
+ },
|
|
|
+ slots: {
|
|
|
+ edit: 'vUnitSelect'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (item.title === 'VGM Method') {
|
|
|
+ curColumn = {
|
|
|
+ ...curColumn,
|
|
|
+ editRender: {
|
|
|
+ name: 'vMethodSelect'
|
|
|
+ },
|
|
|
+ slots: {
|
|
|
+ edit: 'vMethodSelect'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 格式化
|
|
|
+ if (item.edit_type === 'dateTime') {
|
|
|
+ curColumn = {
|
|
|
+ ...curColumn,
|
|
|
+ formatter: ({ cellValue }: any) =>
|
|
|
+ cellValue ? dayjs(cellValue).format('MMM-YYYY-DD HH:mm:ss') : '--'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return curColumn
|
|
|
+ })
|
|
|
+ return newColumns
|
|
|
+}
|
|
|
+
|
|
|
+const convertData = (data: any) => {
|
|
|
+ const handleIsSend = (value: string) => {
|
|
|
+ if (value === 'f' || value === '') {
|
|
|
+ return false
|
|
|
+ } else if (value === 't') {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ generalInfo.value = {
|
|
|
+ baseInfo: [
|
|
|
+ {
|
|
|
+ label: 'HBL No.',
|
|
|
+ value: data?.['HBL No.']
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Carrier Booking No.',
|
|
|
+ value: data?.['Carrier Booking No.']
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Vessel',
|
|
|
+ value: data.Vessel
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Voyage',
|
|
|
+ value: data.Voyage
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'ETD',
|
|
|
+ value: data.ETD
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'ETA ',
|
|
|
+ value: data.ETA
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Last Updated User',
|
|
|
+ value: data?.['Last updated User']
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: 'Last Updated Time',
|
|
|
+ value: data?.['Last updated Time']
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ formData: {
|
|
|
+ Submitter: data.Submitter,
|
|
|
+ signature: data.signature,
|
|
|
+ authorized_email: data.authorized_email,
|
|
|
+ authorized_tel: data.authorized_tel,
|
|
|
+ is_send: handleIsSend(data.is_send)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+const getData = () => {
|
|
|
+ loading.value = true
|
|
|
+ $api
|
|
|
+ .getVGMData({
|
|
|
+ a: route.query.a,
|
|
|
+ _schemas: route.query._schemas
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ allData.value = res.data
|
|
|
+ convertData(res.data?.general_information)
|
|
|
+ tableData.value.columns = handleColumns(
|
|
|
+ res.data?.detail_information?.detail_information_column
|
|
|
+ )
|
|
|
+ tableData.value.data = res.data?.detail_information?.detail_information_data
|
|
|
+ nextTick(() => {
|
|
|
+ tableRef.value && autoWidth(tableData.value, tableRef.value)
|
|
|
+ tableData.value.columns.forEach((item) => {
|
|
|
+ if (item.title === 'SN') {
|
|
|
+ item.width = 50
|
|
|
+ } else if (item.title === 'VGM Time') {
|
|
|
+ item.width = 210
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ loading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+getData()
|
|
|
+
|
|
|
+const handleGoBack = () => {
|
|
|
+ router.push({ name: 'Tracking' })
|
|
|
+}
|
|
|
+const handleSave = () => {
|
|
|
+ const generalData = {
|
|
|
+ all_carrier_booking: generalInfo.value.baseInfo['Carrier Booking No.'],
|
|
|
+ submitter: generalInfo.value.formData.Submitter,
|
|
|
+ signature: generalInfo.value.formData.signature,
|
|
|
+ authorized_email: generalInfo.value.formData.authorized_email,
|
|
|
+ authorized_tel: generalInfo.value.formData.authorized_tel,
|
|
|
+ is_send: generalInfo.value.formData.is_send
|
|
|
+ }
|
|
|
+ const tableRowData = tableData.value.data.map((item) => {
|
|
|
+ return {
|
|
|
+ ...item
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const variableList = Object.keys(tableRowData[0])
|
|
|
+ const tableInfo = {}
|
|
|
+ variableList.forEach((item) => {
|
|
|
+ if (item === '_X_ROW_KEY') return
|
|
|
+ if (item === 'vgm_date' || item === 'vgm_time') {
|
|
|
+ Object.assign(tableInfo, {
|
|
|
+ [item]: tableRowData.map((row) =>
|
|
|
+ row[item] ? dayjs(row[item]).format('YYYY-MM-DD HH:mm:ss') : ''
|
|
|
+ )
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ Object.assign(tableInfo, {
|
|
|
+ [item]: tableRowData.map((row) => row[item])
|
|
|
+ })
|
|
|
+ })
|
|
|
+ console.log({ ...tableInfo, ...generalData })
|
|
|
+ $api
|
|
|
+ .saveVGMData({
|
|
|
+ serial_no: allData.value.serial_no,
|
|
|
+ _schemas: allData.value.schemas,
|
|
|
+ ...generalData,
|
|
|
+ ...tableInfo
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ console.log(res, '数据')
|
|
|
+ if (res.code === 200) {
|
|
|
+ // router.push({ name: 'Tracking' })
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="vgm" v-vloading="loading">
|
|
|
+ <div class="header">
|
|
|
+ <div class="title">Add VGM</div>
|
|
|
+ <div class="right-option">
|
|
|
+ <el-button class="el-button--default" @click="handleGoBack"
|
|
|
+ ><span class="font_family icon-icon_return_b"></span> Cancel</el-button
|
|
|
+ >
|
|
|
+ <el-button class="el-button--main" @click="handleSave">
|
|
|
+ <span class="font_family icon-icon_save_b"></span>
|
|
|
+ Save</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="general-info">
|
|
|
+ <div class="title">
|
|
|
+ <span>General Infomation</span>
|
|
|
+ </div>
|
|
|
+ <div class="description-info">
|
|
|
+ <div class="data-info" v-for="item in generalInfo.baseInfo" :key="item.label">
|
|
|
+ <div class="label">{{ item.label }}</div>
|
|
|
+ <div class="info">{{ item.value }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form">
|
|
|
+ <div class="form-row">
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="label">Submitter <span class="require-asterisk">*</span></div>
|
|
|
+ <div class="content">
|
|
|
+ <el-input
|
|
|
+ v-model="generalInfo.formData.Submitter"
|
|
|
+ placeholder="Please enter..."
|
|
|
+ clearable
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="label">Signature <span class="require-asterisk">*</span></div>
|
|
|
+ <div class="content">
|
|
|
+ <el-input
|
|
|
+ v-model="generalInfo.formData.signature"
|
|
|
+ placeholder="Please enter..."
|
|
|
+ clearable
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="width: 130px"></div>
|
|
|
+ </div>
|
|
|
+ <div class="form-row">
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="label">Authorized Email <span class="require-asterisk">*</span></div>
|
|
|
+ <div class="content">
|
|
|
+ <el-input
|
|
|
+ v-model="generalInfo.formData.authorized_email"
|
|
|
+ placeholder="Please enter..."
|
|
|
+ clearable
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="label">
|
|
|
+ Authorized Tel
|
|
|
+ <span class="require-asterisk">*</span>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <el-input
|
|
|
+ v-model="generalInfo.formData.authorized_tel"
|
|
|
+ placeholder="Please enter..."
|
|
|
+ clearable
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item" style="flex: 0 0 130px">
|
|
|
+ <div class="label"></div>
|
|
|
+ <div class="content">
|
|
|
+ <el-checkbox v-model="generalInfo.formData.is_send" label="Is Send" size="large" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="detail-info" style="margin-top: 8px">
|
|
|
+ <div class="title">
|
|
|
+ <span>Detail Information</span>
|
|
|
+ </div>
|
|
|
+ <div class="table">
|
|
|
+ <vxe-grid ref="tableRef" class="vgm-table" v-bind="tableData">
|
|
|
+ <template #vInput="{ row, column }">
|
|
|
+ <el-input
|
|
|
+ v-model="row[column.field]"
|
|
|
+ placeholder="Please enter..."
|
|
|
+ clearable
|
|
|
+ ></el-input>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #vUnitSelect="{ row, column }">
|
|
|
+ <vxe-select v-model="row[column.field]" placeholder="Please select..." clearable>
|
|
|
+ <vxe-option label="KGS" value="KGS"></vxe-option>
|
|
|
+ <vxe-option label="LBS" value="LBS"></vxe-option>
|
|
|
+ </vxe-select>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #vMethodSelect="{ row, column }">
|
|
|
+ <vxe-select v-model="row[column.field]" placeholder="Please select..." clearable>
|
|
|
+ <vxe-option label="SM1" value="SM1"></vxe-option>
|
|
|
+ <vxe-option label="SM2" value="SM2"></vxe-option>
|
|
|
+ </vxe-select>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #editDate="{ row, column }">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="row[column.field]"
|
|
|
+ type="datetime"
|
|
|
+ style="width: 190px"
|
|
|
+ placeholder="Pick a Date"
|
|
|
+ format="MMM-DD-YYYY HH:mm:ss"
|
|
|
+ date-format="MMM-DD-YYYY"
|
|
|
+ time-format="HH:mm:ss"
|
|
|
+ />
|
|
|
+ <!-- <a-date-picker
|
|
|
+ :showNow="false"
|
|
|
+ class="test-date-picker"
|
|
|
+ placement="topLeft"
|
|
|
+ v-model:value="row[column.field]"
|
|
|
+ format="MMM-DD-YYYY HH:mm:ss"
|
|
|
+ :getPopupContainer="(target) => target.parentElement"
|
|
|
+ :show-time="{ defaultValue: dayjs('00:00:00', 'HH:mm:ss') }"
|
|
|
+ /> -->
|
|
|
+ </template>
|
|
|
+ </vxe-grid>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.vgm {
|
|
|
+ .header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ height: 72px;
|
|
|
+ padding: 0 24px;
|
|
|
+ border-bottom: 1px solid var(--color-border);
|
|
|
+ .title {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+ .right-option {
|
|
|
+ .el-button {
|
|
|
+ height: 40px;
|
|
|
+ padding: 8px 24px;
|
|
|
+ .font_family {
|
|
|
+ margin-right: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ & > .content {
|
|
|
+ padding: 8px 24px 16px;
|
|
|
+ }
|
|
|
+ .general-info,
|
|
|
+ .detail-info {
|
|
|
+ border: 1px solid var(--color-border);
|
|
|
+ border-radius: 12px;
|
|
|
+ & > .title {
|
|
|
+ height: 48px;
|
|
|
+ line-height: 48px;
|
|
|
+ span {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ & > .description-info {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ padding: 8px 16px 0;
|
|
|
+ }
|
|
|
+ .form {
|
|
|
+ padding: 16px;
|
|
|
+ border-top: 1px solid var(--color-border);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .general-info {
|
|
|
+ & > .title {
|
|
|
+ padding-left: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .detail-info {
|
|
|
+ padding: 0 16px 8px;
|
|
|
+ }
|
|
|
+ .form {
|
|
|
+ .form-row {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 16px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ .form-item {
|
|
|
+ flex: 1;
|
|
|
+ .label {
|
|
|
+ height: 16px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 16px;
|
|
|
+ color: var(--dashboard-text-color);
|
|
|
+ .require-asterisk {
|
|
|
+ margin-left: -3px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #c9353f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .content {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ height: 32px;
|
|
|
+ .el-input {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.data-info {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ width: 25%;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ .label {
|
|
|
+ margin-bottom: 8px;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 16px;
|
|
|
+ color: var(--dashboard-text-color);
|
|
|
+ }
|
|
|
+ .info {
|
|
|
+ height: 21px;
|
|
|
+ line-height: 21px;
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss">
|
|
|
+.el-checkbox__input.is-checked + .el-checkbox__label {
|
|
|
+ color: var(--color-neutral-1);
|
|
|
+}
|
|
|
+// .test-date-picker {
|
|
|
+// .ant-picker-dropdown {
|
|
|
+// // top: 40px !important;
|
|
|
+// }
|
|
|
+// .anticon svg {
|
|
|
+// color: #202020;
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// .vgm-table {
|
|
|
+// .vxe-grid .vxe-grid--table-wrapper,
|
|
|
+// div.vxe-table--body-wrapper {
|
|
|
+// overflow: visible;
|
|
|
+// }
|
|
|
+// }
|
|
|
+</style>
|