Pārlūkot izejas kodu

feat:添加delivery接口

AmandaG 4 mēneši atpakaļ
vecāks
revīzija
4b988994c2

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

@@ -44,4 +44,60 @@ export const getKLNEmployeeList = (params: any, config: any) => {
     },
     config
   )
+}
+/**
+ * Port List
+ */
+export const getPortList = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_load',
+      operate: 'ports',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * Carrier List
+ */
+export const getCarrierList = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_load',
+      operate: 'carrier',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * Save rule
+ */
+export const handelSaveRule = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_config',
+      operate: 'save',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * Configuration table list
+ */
+export const getConfigurationList = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'destination_delivery_config',
+      operate: 'search',
+      ...params
+    },
+    config
+  )
 }

+ 8 - 13
src/views/DestinationDelivery/src/components/ConfiguRations/src/ConfiguRations.vue

@@ -6,30 +6,25 @@ const filterRef: Ref<HTMLElement | null> = ref(null)
 
 const AddRulesTableColumns = ref([
   {
-    field: 'Event',
-    title: 'Event',
+    field: 'Country',
+    title: 'Country',
     type: 'normal',
     formatter: ''
   },
   {
-    field: 'Shipment Range',
-    title: 'Shipment Range',
+    field: 'Stations',
+    title: 'Stations',
     type: 'normal',
     formatter: ''
   },{
-    field: 'Event Details',
-    title: 'Event Details',
+    field: 'Booking Window',
+    title: 'Booking Window',
     type: 'normal',
     formatter: ''
   },
   {
-    field: 'Frequency',
-    title: 'Frequency',
-    type: 'normal',
-    formatter: ''
-  },{
-    field: 'Method',
-    title: 'Method',
+    field: 'Reecommended Delivery Date',
+    title: 'Reecommended Delivery Date',
     type: 'normal',
     formatter: ''
   }

+ 12 - 6
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/ConfigurationsTable.vue

@@ -73,8 +73,15 @@ const getTableColumns = async () => {
   })
 }
 // 获取表格数据
-const getTableData = (val: any) => {
-  tableData.value.data = val.setTrackingTableData
+const getTableData = () => {
+  $api
+    .getConfigurationList({
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        tableData.value.data = res.data.searchData
+      }
+    })
 }
 
 // 实现行点击样式
@@ -108,9 +115,7 @@ const handleLinkClick = (row: any) => {
 
 onMounted(() => {
   getTableColumns()
-})
-defineExpose({
-  getTableData
+  getTableData()
 })
 
 const clickAddNewRule = () => {
@@ -121,10 +126,11 @@ const clickAddNewRule = () => {
 }
 const getpaginationTableData = () => {
   $api
-    .SubscribePagination({
+    .getConfigurationList({
     })
     .then((res: any) => {
       if (res.code === 200) {
+        console.log(res.data)
         tableData.value.data = res.data.tableData
       }
     })

+ 173 - 19
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/CreateNewRule.vue

@@ -3,6 +3,7 @@ import SelectStation from './SelectStation.vue'
 import SetBookingWindow from './SetBookingWindow.vue'
 import RecommendDate from './RecommendDate.vue'
 import { useRouter } from 'vue-router'
+import submitsucessful from '../images/icon_success_big@2x.png'
 
 const router = useRouter()
 
@@ -19,6 +20,8 @@ const recommendCheckedSeaList = ref([])
 const IsTwoActive = ref(true)
 const IsFourActive = ref(true)
 const IsThreeActive = ref(true)
+const CancelRulesVisible = ref(false)
+const SaveedVisible = ref(false)
 const KLNPLCvalue = ref('')
 interface KLNItem {
   value: string
@@ -65,9 +68,9 @@ const CreateRuleDisabled = computed(() => {
     // 3.2 验证航空规则(如果选择了 Air)
     if (recommendCheckedList.value.includes('Air')) {
       const isAirValid = recommendCheckedAirList.value.every(item => 
-        item.AirPort.length > 0 && 
-        item.FormDate !== '' && 
-        item.ToDate !== ''
+        item.ports.length > 0 && 
+        item.recommended_delivery_from !== '' && 
+        item.recommended_delivery_to !== ''
       );
       
       if (!isAirValid) return true;
@@ -76,10 +79,10 @@ const CreateRuleDisabled = computed(() => {
     // 3.3 验证海运规则(如果选择了 Sea)
     if (recommendCheckedList.value.includes('Sea')) {
       const isSeaValid = recommendCheckedSeaList.value.every(item => 
-        item.Port.length > 0 && 
-        item.Carrier.length > 0 && 
-        item.FormDate !== '' && 
-        item.ToDate !== ''
+        item.ports.length > 0 && 
+        item.carrier.length > 0 && 
+        item.recommended_delivery_from != '' && 
+        item.recommended_delivery_to != ''
       );
       
       if (!isSeaValid) return true;
@@ -101,22 +104,47 @@ const handleChangeStation = (val:any) =>{
 }
 
 // select booking window
-const changeBookingWindow = (radio: number, beforedays:any, afterdays:any) => {
+const bookingWindow = ref('')
+const bookingdetail = ref('')
+const changeBookingWindow = (radio: number, beforedays:any, afterdays:any, details: any) => {
   windowRadio.value = radio
-  windowBeforeDays.value = beforedays
-  windowAfterDays.value = afterdays
-}
-const handleCancel = () => {
-  // Logic to handle cancel action
-  router.push({ name: 'Configurations' })
+  bookingdetail.value = details
+  if(radio == 1) {
+    bookingWindow.value = 'No_Restrictions'
+    windowBeforeDays.value = ''
+    windowAfterDays.value = ''
+  } else if(radio == 2) {
+    bookingWindow.value = 'Restrictions_ETD_ATD'
+    windowBeforeDays.value = beforedays
+    windowAfterDays.value = afterdays
+  } else if(radio == 3) {
+    bookingWindow.value = 'Restrictions_ETA_ATA'
+    windowBeforeDays.value = beforedays
+    windowAfterDays.value = afterdays
+  }
 }
 
 // select recommend date
+const recommendDelivery = ref('')
+const recommenddetail = ref('')
 const checkRecommend = (checked: any, airlist: any, sealist: any, radio: number) => {
+  recommenddetail.value = ''
   recommendCheckedList.value = checked
   recommendCheckedAirList.value = airlist
   recommendCheckedSeaList.value = sealist
   recommendRadio.value = radio
+  if(radio == 1) {
+    recommendDelivery.value = 'No_Recommended'
+    recommenddetail.value = 'No Specific recommended time for choosing delivery date'
+  } else {
+    recommendDelivery.value = 'Delivery_ETA_ATA'
+    if(checked.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;' 
+    }
+    if(checked.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;' 
+    }
+  }
 }
 
 // 获取KLN列表
@@ -138,13 +166,22 @@ const getKLNList = (): Promise<KLNItem[]> => {
 };
 // 自动查询KLN
 let timeout: ReturnType<typeof setTimeout>
+const isNodata = ref([])
 const querySearchAsync = (queryString: string, cb: (arg: any) => void) => {
   const results = queryString
     ? KLNLists.value.filter(createFilter(queryString))
     : KLNLists.value
+  isNodata.value = results
   clearTimeout(timeout)
   timeout = setTimeout(() => {
-    cb(results)
+    if(results.length == 0) {
+      cb([{ 
+        isNoData: true, 
+        value: '无搜索结果' 
+      }]);
+    } else {
+      cb(results)
+    }
   }, 1000 * Math.random())
 }
 const createFilter = (queryString: string) => {
@@ -161,6 +198,46 @@ const handleSelectKLN = (item: Record<string, any>) => {
 onMounted(() => {
   getKLNList()
 })
+
+// 保存
+const handleSubmitRule = () => {
+  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) {
+      return rest
+    } else {
+      return []
+    }
+  })
+  $api.handelSaveRule({ 
+    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,
+    recommended_delivery_date_desc: recommenddetail.value,
+    ...airlist,
+    ...seaList
+  }).then((res: any) => {
+    if (res.code === 200) {
+      SaveedVisible.value = true
+      setTimeout(() => {
+        SaveedVisible.value = false
+        router.push({ name: 'Configurations'})
+      }, 3000)
+    }
+  })
+}
 </script>
 
 <template>
@@ -168,11 +245,11 @@ onMounted(() => {
     <div class="Title">
       Create New Rule
       <div class="operator">
-        <el-button @click="handleCancel" 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">
+        <el-button style="height: 40px; width: 120px" class="el-button--main el-button--pain-theme" :disabled="CreateRuleDisabled" @click="handleSubmitRule">
           <span
             style="
               display: inline-block;
@@ -184,6 +261,62 @@ onMounted(() => {
           ></span>
           <span style="font-weight: 400">Submit</span>
         </el-button>
+        <!-- 取消保存 -->
+        <el-dialog v-model="CancelRulesVisible" width="480">
+          <div style="font-weight: 400">You have unsaved changes.</div>
+          <div style="font-weight: 400">Are you sure you want to leave this page?</div>
+          <template #footer>
+            <div class="dialog-footer">
+              <el-button type="default" @click="CancelRulesVisible = false" style="width: 100px"
+                >Cancel</el-button
+              >
+              <el-button class="el-button--warning" @click="router.back()" style="width: 100px">
+                OK
+              </el-button>
+            </div>
+          </template>
+          <template #header>
+            <div class="cancel_header">
+              <span class="iconfont_icon iconfont_warning">
+                <svg class="iconfont icon_warning" aria-hidden="true">
+                  <use xlink:href="#icon-icon_tipsfilled_b"></use>
+                </svg>
+              </span>
+              Unsaved Changes
+            </div>
+          </template>
+        </el-dialog>
+        <!-- 保存失败 -->
+        <!-- <el-dialog v-model="UnableSaveVisible" width="480">
+          <div>{{ missingmessage }} missing.</div>
+          <div>Please complete all required fields.</div>
+          <template #footer>
+            <div class="dialog-footer">
+              <el-button
+                class="el-button--danger"
+                @click="UnableSaveVisible = false"
+                style="width: 100px"
+              >
+                OK
+              </el-button>
+            </div>
+          </template>
+          <template #header>
+            <div class="cancel_header">
+              <span class="iconfont_icon iconfont_warning">
+                <svg class="iconfont icon_danger" aria-hidden="true">
+                  <use xlink:href="#icon-icon_fail_fill_b"></use>
+                </svg>
+              </span>
+              Unable to Save
+            </div>
+          </template>
+        </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; margin-top: 20px">Saved successfully</div>
+        </el-dialog>
       </div>
     </div>
     <div class="setting-content">
@@ -250,7 +383,7 @@ onMounted(() => {
             <div>
               <RecommendDate
                 :recommendRadio="recommendRadio"
-                @checkRecommend="checkRecommend"
+                @chackchangerecommend="checkRecommend"
               ></RecommendDate>
             </div>
           </el-collapse-item>
@@ -276,7 +409,16 @@ onMounted(() => {
                 placeholder="Select Employee Account"
                 :fetch-suggestions="querySearchAsync"
                 @select="handleSelectKLN"
-              />
+              >
+                <template #default="{ item }">
+                  <div :class="[
+                    'suggestion-item',
+                    { 'no-data-item': item.isNoData }
+                  ]">
+                    {{ item.value }}
+                  </div>
+                </template>
+              </el-autocomplete>
             </div>
           </el-collapse-item>
       </el-collapse>
@@ -366,4 +508,16 @@ onMounted(() => {
   box-shadow: none;
   border: 1px solid var(--color-theme);
 }
+.no-data-item {
+  color: var(--color-neutral-2);
+  text-align: center;
+  padding: 20px;
+  cursor: default;
+  &:hover {
+    background-color: transparent !important;
+  }
+}
+.suggestion-item {
+  padding: 5px 20px;
+}
 </style>

+ 155 - 87
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/RecommendDate.vue

@@ -7,19 +7,27 @@ interface RuleOption {
   label: string;
   value: string;
 }
+interface PortOption {
+  value: string
+  label: string
+  checked: boolean
+}
+
 
 interface RuleItem {
-  Priority: string;
-  RuleType: string;
-  AirPort?: string[];
-  Port?: string[];
-  Carrier?: string[];
-  FromDate: string | number;
-  ToDate: string | number;
+  priority: string;
+  rule_type: string;
+  mode_type: string;
+  ports?: string[];
+  carrier?: string[];
+  PortList?:PortOption[];
+  CarrierList?:PortOption[];
+  recommended_delivery_from: string | number;
+  recommended_delivery_to: string | number;
 }
 
 // 定义 RuleItem 中数组字段的类型
-type ArrayFields = 'AirPort' | 'Port' | 'Carrier';
+type ArrayFields = 'ports' | 'carrier';
 
 const props = defineProps({
   Recommendradio: {
@@ -52,42 +60,52 @@ const RuleTypeoptions = ref<RuleOption[]>([
 // 规则数据
 const AirContentList = ref<RuleItem[]>([
   {
-    Priority: 'P1',
-    RuleType: '*Default Rule',
-    AirPort: ['All'],
-    FromDate: '',
-    ToDate: ''
+    priority: 'P1',
+    rule_type: '*Default Rule',
+    ports: ['All'],
+    recommended_delivery_from: '',
+    recommended_delivery_to: '',
+    mode_type: 'air',
+    PortList:[]
   }
 ])
 const SeaContentList = ref<RuleItem[]>([
   {
-    Priority: 'P1',
-    RuleType: '*Default Rule',
-    Port: ['All'],
-    Carrier: ['All'],
-    FromDate: '',
-    ToDate: ''
+    priority: 'P1',
+    rule_type: '*Default Rule',
+    ports: ['All'],
+    carrier: ['All'],
+    recommended_delivery_from: '',
+    recommended_delivery_to: '',
+    mode_type: 'sea',
+    PortList:[],
+    CarrierList: []
   }
 ])
 
 // 创建规则项的工厂函数
 function createRuleItem(type: 'Air' | 'Sea', ruleType: string): RuleItem {
   const baseItem = {
-    Priority: 'P1',
-    RuleType: ruleType,
-    FromDate: '',
-    ToDate: ''
+    priority: 'P1',
+    rule_type: ruleType,
+    recommended_delivery_from: '',
+    recommended_delivery_to: '',
   }
   if (type === 'Air') {
     return {
       ...baseItem,
-      AirPort: ruleType === '*Default Rule' ? ['All'] : []
+      ports: ruleType === '*Default Rule' ? ['All'] : [],
+      mode_type: 'air',
+      PortList: JSON.parse(JSON.stringify(AirPorList.value))
     }
   }
   return {
     ...baseItem,
-    Port: ruleType === '*Default Rule' ? ['All'] : [],
-    Carrier: ruleType === '*Default Rule' ? ['All'] : []
+    ports: ruleType === '*Default Rule' ? ['All'] : [],
+    carrier: ruleType === '*Default Rule' ? ['All'] : [],
+    mode_type: 'sea',
+    PortList: JSON.parse(JSON.stringify(SeaPortList.value)),
+    CarrierList: JSON.parse(JSON.stringify(SeaCarrierList.value))
   }
 }
 
@@ -120,7 +138,7 @@ const ChangeFrequency = (val: number) => {
   emits('chackchangerecommend', RecommendCheckedList.value, AirContentList.value, SeaContentList.value, Recommendradio.value)
 }
 // 修复后的 handleInput 函数
-const handleInput = (val: string, index: number, type: 'FromDate' | 'ToDate', list: RuleItem[]) => {
+const handleInput = (val: string, index: number, type: 'recommended_delivery_from' | 'recommended_delivery_to', list: RuleItem[]) => {
   // 移除非数字字符
   const numStr = val.replace(/[^\d]/g, '');
   // 转换为整数,处理NaN情况
@@ -147,7 +165,7 @@ const handleDelete = (index: number, list: RuleItem[], type: 'Air' | 'Sea') => {
 // 添加数据
 const AddRuleItem = (list: RuleItem[], type: 'Air' | 'Sea') => {
   // 检查是否已存在默认规则
-  const hasDefaultRule = list.some(item => item.RuleType === '*Default Rule')
+  const hasDefaultRule = list.some(item => item.rule_type === '*Default Rule')
   // 如果已经有默认规则,则创建特定规则
   const ruleType = hasDefaultRule ? 'Specific Rule' : '*Default Rule'
   list.push(createRuleItem(type, ruleType))
@@ -164,12 +182,12 @@ const updateListPriorities = (list: RuleItem[], type: 'Air' | 'Sea') => {
   const length = list.length
   // 保护默认规则的数据
   list.forEach(item => {
-    if (item.RuleType === '*Default Rule') {
+    if (item.rule_type === '*Default Rule') {
       if (type === 'Air') {
-        item.AirPort = ['All']
+        item.ports = ['All']
       } else {
-        item.Port = ['All']
-        item.Carrier = ['All']
+        item.ports = ['All']
+        item.carrier = ['All']
       }
     }
   })
@@ -183,38 +201,38 @@ 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.RuleType))
+  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 => {
-      item.Priority = item.RuleType === '*Default Rule' ? 'P2' : 'P1'
+      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 => {
-      item.Priority = item.RuleType === 'Specific Rule' ? 'P1' : 'P2'
+      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.RuleType] = (acc[cur.RuleType] || 0) + 1
+    acc[cur.rule_type] = (acc[cur.rule_type] || 0) + 1
     return acc
   }, {} as Record<string, number>)
   // 获取所有存在的类型
@@ -231,13 +249,13 @@ const handleLengthThreePlus = (list: RuleItem[], type: string) => {
       '*Default Rule': 'P3'
     }
     list.forEach(item => {
-      item.Priority = priorityMap[item.RuleType]
+      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 组合
@@ -245,14 +263,14 @@ const handleLengthThreePlus = (list: RuleItem[], type: string) => {
       existingTypes.includes('Specific Rule') && 
       existingTypes.includes('*Default Rule')) {
     list.forEach(item => {
-      item.Priority = item.RuleType === 'Specific Rule' ? 'P1' : 'P2'
+      item.priority = item.rule_type === 'Specific Rule' ? 'P1' : 'P2'
     })
     return
   }
   // 存在两个Default Rule
   if (counts['*Default Rule'] === 2 && existingTypes.length === 2) {
     list.forEach(item => {
-      item.Priority = item.RuleType === '*Default Rule' ? 'P2' : 'P1'
+      item.priority = item.rule_type === '*Default Rule' ? 'P2' : 'P1'
     })
     return
   }
@@ -261,12 +279,12 @@ const handleLengthThreePlus = (list: RuleItem[], type: string) => {
     if (existingTypes.includes('*Default Rule')) {
       // 两个Single + 一个Default
       list.forEach(item => {
-        item.Priority = item.RuleType === '*Default Rule' ? 'P2' : 'P1'
+        item.priority = item.rule_type === '*Default Rule' ? 'P2' : 'P1'
       })
     } else if (existingTypes.includes('Specific Rule')) {
       // 两个Single + 一个Specific
       list.forEach(item => {
-        item.Priority = item.RuleType === 'Specific Rule' ? 'P1' : 'P2'
+        item.priority = item.rule_type === 'Specific Rule' ? 'P1' : 'P2'
       })
     }
     return
@@ -278,7 +296,7 @@ const handleLengthThreePlus = (list: RuleItem[], type: string) => {
     '*Default Rule': 'P3'
   }
   list.forEach(item => {
-    item.Priority = defaultPriorityMap[item.RuleType] || 'P3'
+    item.priority = defaultPriorityMap[item.rule_type] || 'P3'
   })
 }
 // 修复:改变选项值 - 使用类型保护
@@ -291,20 +309,64 @@ const changeSelectedValue = (val: string[], index: number, field: ArrayFields, l
 const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
   const item = list[index]
   // 保护默认规则
-  if (item.RuleType === '*Default Rule' && val !== '*Default Rule') {
+  if (item.rule_type === '*Default Rule' && val !== '*Default Rule') {
     // 从默认规则切换到其他规则时重置选项
-    if ('AirPort' in item) item.AirPort = []
-    if ('Port' in item) item.Port = []
-    if ('Carrier' in item) item.Carrier = []
+    if ('ports' in item) item.ports = []
+    if ('carrier' in item) item.carrier = []
   } else if (val === '*Default Rule') {
     // 切换到默认规则时设置默认值
-    if ('AirPort' in item) item.AirPort = ['All']
-    if ('Port' in item) item.Port = ['All']
-    if ('Carrier' in item) item.Carrier = ['All']
+    if ('ports' in item) item.ports = ['All']
+    if ('carrier' in item) item.carrier = ['All']
   }
-  item.RuleType = val
+  item.rule_type = val
   updatePriorities()
 }
+
+// 获取Air Port/Port/Carrier的值
+const AirPorList = ref([])
+const SeaPortList = ref([])
+const SeaCarrierList = ref([])
+const getPortList = (type: any) => {
+  $api.getPortList({ 
+    term: '',
+    mode: type
+  }).then((res: any) => {
+    if (res.code === 200) {
+      if(type === 'air') {
+        AirPorList.value = res.data
+        // 更新现有行的列表
+        AirContentList.value.forEach(item => {
+          item.PortList = JSON.parse(JSON.stringify(res.data))
+        })
+      }
+      if(type === 'sea') {
+        SeaPortList.value = res.data
+        // 更新现有行的列表
+        SeaContentList.value.forEach(item => {
+          item.PortList = JSON.parse(JSON.stringify(res.data))
+        })
+      }
+    }
+  })
+}
+
+// 获取Carrier列表
+const getCarrierList = () => {
+  $api.getCarrierList({ 
+    term: '',
+  }).then((res: any) => {
+    if (res.code === 200) {
+      SeaCarrierList.value = res.data
+      // 更新现有行的列表
+      SeaContentList.value.forEach(item => {
+        item.CarrierList = JSON.parse(JSON.stringify(res.data))
+      })
+    }
+  })
+}
+getPortList('air')
+getPortList('sea')
+getCarrierList()
 </script>
 
 <template>
@@ -323,7 +385,7 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
               </div>
               <div v-if="isAir" class="radiocheckbox" style="margin-top: 16px">
                 <div class="AirCoulumn">
-                  <div class="AicoulumnTitile" style="width: 10%;">Priority</div>
+                  <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%;">
@@ -336,11 +398,11 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
                   <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: 10%;">{{ item.priority }}</div>
                   <div class="AirCoumlumn" style="width: 20%;">
                     <el-select
-                      v-model="item.RuleType"
-                      :disabled="item.RuleType === '*Default Rule'"
+                      v-model="item.rule_type"
+                      :disabled="item.rule_type === '*Default Rule'"
                       style="width: 100%;"
                       @change="val => changeRuleType(val, index, AirContentList)"
                     >
@@ -355,28 +417,30 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
                   <div class="AirCoumlumn" style="width: 40%;">
                     <SelectValue
                       :SelectIndex="index"
-                      :SelectedValue="item.AirPort"
-                      :typeisDisabled="item.RuleType"
-                      @changeSelectedValue="val => changeSelectedValue(val, index, 'AirPort', AirContentList)"
+                      :SelectedValue="item.ports"
+                      :typeisDisabled="item.rule_type"
+                      :PortList="item.PortList"
+                      SelectType="Air"
+                      @changeSelectedValue="val => changeSelectedValue(val, index, 'ports', AirContentList)"
                     />
                   </div>
                   <div class="AirCoumlumn" style="width: 10%;">
                     <el-input 
-                      @input="val => handleInput(val, index, 'FromDate', AirContentList)" 
+                      @input="val => handleInput(val, index, 'recommended_delivery_from', AirContentList)" 
                       placeholder="Input" 
-                      v-model="item.FromDate"
+                      v-model="item.recommended_delivery_from"
                     />
                   </div>
                   <div class="AirCoumlumn" style="width: 10%;">
                     <el-input 
-                      @input="val => handleInput(val, index, 'ToDate', AirContentList)"  
+                      @input="val => handleInput(val, index, 'recommended_delivery_to', AirContentList)"  
                       placeholder="Input" 
-                      v-model="item.ToDate"
+                      v-model="item.recommended_delivery_to"
                     />
                   </div>
                   <div class="AirDelete" style="width: 10%;">
                     <el-button 
-                      v-if="item.RuleType !== '*Default Rule'" 
+                      v-if="item.rule_type !== '*Default Rule'" 
                       @click="handleDelete(index, AirContentList, 'Air')" 
                       class="el-button--blue" 
                       style="height: 24px"
@@ -395,10 +459,10 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
               </div>
               <div v-if="isSea" style="margin-top: 16px">
                 <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: 20%;">Port</div>
-                  <div class="AicoulumnTitile" style="width: 20%;">Carrier</div>
+                  <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;">
@@ -409,11 +473,11 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
                   <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: 20%;">
+                  <div class="AirCoumlumn" style="width: 10%;">{{ item.priority }}</div>
+                  <div class="AirCoumlumn" style="width: 14%;">
                     <el-select
-                      v-model="item.RuleType"
-                      :disabled="item.RuleType === '*Default Rule'"
+                      v-model="item.rule_type"
+                      :disabled="item.rule_type === '*Default Rule'"
                       style="width: 100%;"
                       @change="val => changeRuleType(val, index, SeaContentList)"
                     >
@@ -425,39 +489,43 @@ const changeRuleType = (val: string, index: number, list: RuleItem[]) => {
                       />
                     </el-select>
                   </div>
-                  <div class="AirCoumlumn" style="width: 20%;">
+                  <div class="AirCoumlumn" style="width: 23%;">
                     <SelectValue
                       :SelectIndex="index"
-                      :SelectedValue="item.Port"
-                      :typeisDisabled="item.RuleType"
-                      @changeSelectedValue="val => changeSelectedValue(val, index, 'Port', SeaContentList)"
+                      :SelectedValue="item.ports"
+                      :typeisDisabled="item.rule_type"
+                      :PortList="item.PortList"
+                      SelectType="Sea"
+                      @changeSelectedValue="val => changeSelectedValue(val, index, 'ports', SeaContentList)"
                     />
                   </div>
-                  <div class="AirCoumlumn" style="width: 20%;">
+                  <div class="AirCoumlumn" style="width: 23%;">
                     <SelectValue
                       :SelectIndex="index"
-                      :SelectedValue="item.Carrier"
-                      :typeisDisabled="item.RuleType"
-                      @changeSelectedValue="val => changeSelectedValue(val, index, 'Carrier', SeaContentList)"
+                      :SelectedValue="item.carrier"
+                      :typeisDisabled="item.rule_type"
+                      :PortList="item.CarrierList"
+                      SelectType="Sea"
+                      @changeSelectedValue="val => changeSelectedValue(val, index, 'carrier', SeaContentList)"
                     />
                   </div>
                   <div class="AirCoumlumn" style="width: 10%;">
                     <el-input 
-                      @input="val => handleInput(val, index, 'FromDate', SeaContentList)" 
+                      @input="val => handleInput(val, index, 'recommended_delivery_from', SeaContentList)" 
                       placeholder="Input" 
-                      v-model="item.FromDate"
+                      v-model="item.recommended_delivery_from"
                     />
                   </div>
                   <div class="AirCoumlumn" style="width: 10%;">
                     <el-input 
-                      @input="val => handleInput(val, index, 'ToDate', SeaContentList)"  
+                      @input="val => handleInput(val, index, 'recommended_delivery_to', SeaContentList)"  
                       placeholder="Input" 
-                      v-model="item.ToDate"
+                      v-model="item.recommended_delivery_to"
                     />
                   </div>
                   <div class="AirDelete" style="width: 10%;">
                     <el-button 
-                      v-if="item.RuleType !== '*Default Rule'" 
+                      v-if="item.rule_type !== '*Default Rule'" 
                       @click="handleDelete(index, SeaContentList, 'Sea')" 
                       class="el-button--blue" 
                       style="height: 24px"

+ 8 - 8
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/SelectStation.vue

@@ -110,14 +110,14 @@ onMounted(() => {
       :fetch-suggestions="querySearchAsync"
       @select="handleSelect"
     >
-    <template #default="{ item }">
-      <div :class="[
-        'suggestion-item',
-        { 'no-data-item': item.isNoData }
-      ]">
-        {{ item.value }}
-      </div>
-    </template>
+      <template #default="{ item }">
+        <div :class="[
+          'suggestion-item',
+          { 'no-data-item': item.isNoData }
+        ]">
+          {{ item.value }}
+        </div>
+      </template>
     </el-autocomplete>
     <div class="station-list">
       <div class="station-list-title">Station List</div>

+ 34 - 43
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/SelectValue.vue

@@ -1,6 +1,12 @@
 <script setup lang="ts">
 import { ref, watch } from 'vue'
 
+interface PortOption {
+  value: string
+  label: string
+  checked: boolean
+}
+
 const props = defineProps({
   SelectedValue: {
     type: Array as () => string[],
@@ -13,12 +19,21 @@ const props = defineProps({
   typeisDisabled: {
     type: String,
     default: ''
+  },
+  SelectType: {
+    type: String,
+    default: ''
+  },
+  PortList: {
+    type: Array as () => PortOption[],
+    default: () => []
   }
 })
 const checkAll = ref(false)
 const value = ref<string[]>(props.SelectedValue)
 const SelectNumber = ref(props.SelectIndex)
 const typeisDisabled = ref(props.typeisDisabled)
+const PortList = ref(props.PortList)
 
 watch(
   () => props.SelectedValue,
@@ -26,46 +41,19 @@ watch(
     value.value = val
   }
 )
-
-const cities = ref([
-  {
-    value: 'Beijing',
-    label: 'Beijing',
-    checked: false
-  },
-  {
-    value: 'Shanghai',
-    label: 'Shanghai',
-    checked: false
-  },
-  {
-    value: 'Nanjing',
-    label: 'Nanjing',
-    checked: false
-  },
-  {
-    value: 'Chengdu',
-    label: 'Chengdu',
-    checked: false
-  },
-  {
-    value: 'Shenzhen',
-    label: 'Shenzhen',
-    checked: false
-  },
-  {
-    value: 'Guangzhou',
-    label: 'Guangzhou',
-    checked: false
-  },
-])
+watch(
+  () => props.PortList,
+  (val) => {
+    PortList.value = val
+  }
+)
 
 const emits = defineEmits(['changeSelectedValue', 'handelremovetag'])
 
 watch(value, (val) => {
   if (val.length === 0) {
     checkAll.value = false
-  } else if (val.length === cities.value.length) {
+  } else if (val.length === PortList.value.length) {
     checkAll.value = true
     value.value = ['All']
   }else if (val.length == 1 && val[0] == 'All') {
@@ -79,24 +67,23 @@ watch(value, (val) => {
 const handleCheckAll = (val) => {
   if (val.target.checked) {
     value.value = ['All']
-    cities.value.forEach((item) => { 
+    PortList.value.forEach((item) => { 
       item.checked = true
     })
   } else {
     value.value = []
-    cities.value.forEach((item) => { 
+    PortList.value.forEach((item) => { 
       item.checked = false
     })
   }
 }
 
 const handelchangeSelect = () => {
-  value.value = cities.value.filter(item => item.checked === true).map(item => item.value)
+  value.value = PortList.value.filter(item => item.checked === true).map(item => item.value)
 }
 
 //移除tag
 const handelRemoveTag = (tag) => {
-  console.log(tag)
   // 阻止事件冒泡和默认行为
   event.stopPropagation()
   event.preventDefault()
@@ -106,20 +93,24 @@ const handelRemoveTag = (tag) => {
   emits('changeSelectedValue', newValue, SelectNumber.value)
   
   // 更新对应的城市选中状态
-  const city = cities.value.find(item => item.value === tag)
+  const city = PortList.value.find(item => item.value === tag)
   if (city) {
     city.checked = false
   }
   
   // 更新全选状态
-  checkAll.value = newValue.length === cities.value.length
+  checkAll.value = newValue.length === PortList.value.length
 }
 
+const displayNumber = computed(() => {
+  return props.SelectType === 'Air' ? 6 : 3
+})
+
 const visibleTags = computed(() => { 
-  return value.value.slice(0, 3);
+  return value.value.slice(0, displayNumber.value);
 })
 const hiddenTagsCount = computed(() => { 
-  return Math.max(value.value.length - 3, 0);
+  return Math.max(value.value.length - displayNumber.value, 0);
 })
 </script>
 <template>
@@ -154,7 +145,7 @@ const hiddenTagsCount = computed(() => {
         </el-tag>
       </template>
       <el-option
-        v-for="item in cities"
+        v-for="item in PortList"
         :key="item.value"
         :label="item.label"
         :value="item.value"

+ 48 - 11
src/views/DestinationDelivery/src/components/ConfiguRations/src/components/SetBookingWindow.vue

@@ -27,6 +27,7 @@ watch(() => props.setbookingdata, (val) => {
 // 选择booking window
 const emits = defineEmits(['changeBookingWindow'])
 const ChangeFrequency = (val: any) => {
+  let str = ''
   if(val == 1) {
     isBookingETD.value = false
     isBookingETA.value = false
@@ -34,16 +35,22 @@ const ChangeFrequency = (val: any) => {
     afterETDdays.value = ''
     beforeETAdays.value = ''
     afterETAdays.value = ''
+    str = 'No Specific time restrictions for creating booking'
+    emits('changeBookingWindow',windowradio.value, beforeETAdays.value, afterETAdays.value, str)
   } else if(val == 2) {
     isBookingETD.value = true
     isBookingETA.value = false
     beforeETAdays.value = ''
     afterETAdays.value = ''
+    str = 'ETD/ATD: ' + beforeETDdays.value + ' days before to ' + afterETDdays.value + ' days after'
+    emits('changeBookingWindow',windowradio.value, beforeETDdays.value, afterETDdays.value, str)
   } else if(val == 3) {
     isBookingETD.value = false
     isBookingETA.value = true
     beforeETDdays.value = ''
     afterETDdays.value = ''
+    str = 'ETA/ATA: ' + beforeETAdays.value + ' days before to ' + afterETAdays.value + ' days after'
+    emits('changeBookingWindow',windowradio.value, beforeETAdays.value, afterETAdays.value, str)
   } else {
     isBookingETD.value = false
     isBookingETA.value = false
@@ -52,16 +59,46 @@ const ChangeFrequency = (val: any) => {
     beforeETAdays.value = ''
     afterETAdays.value = ''
   }
-  emits('changeBookingWindow',windowradio.value, beforeETAdays.value, afterETAdays.value)
 }
 
-const changeTime = (val: any) => {
-  if(val == 'ETD') {
-    ChangeFrequency(2)
-  } else {
-    ChangeFrequency(3)
+// 处理输入值,确保只能是正整数
+const validatePositiveInteger = (value: string) => {
+  // 移除非数字字符
+  let numStr = value.replace(/[^\d]/g, '');
+  // 如果为空字符串,直接返回
+  if (numStr === '') return '';
+  // 转换为整数
+  let num = parseInt(numStr, 10);
+  // 处理NaN情况,确保最小值为1
+  if (isNaN(num) || num < 1) {
+    return '1';
   }
-}
+  // 返回数字字符串(去掉前导零)
+  return num.toString();
+};
+
+// 处理输入变化
+const handleInput = (val: string, target: 'ETD_BEFORE' | 'ETD_AFTER' | 'ETA_BEFORE' | 'ETA_AFTER') => {
+  const validatedValue = validatePositiveInteger(val);
+  switch (target) {
+    case 'ETD_BEFORE':
+      beforeETDdays.value = validatedValue;
+      ChangeFrequency(2);
+      break;
+    case 'ETD_AFTER':
+      afterETDdays.value = validatedValue;
+      ChangeFrequency(2);
+      break;
+    case 'ETA_BEFORE':
+      beforeETAdays.value = validatedValue;
+      ChangeFrequency(3);
+      break;
+    case 'ETA_AFTER':
+      afterETAdays.value = validatedValue;
+      ChangeFrequency(3);
+      break;
+  }
+};
 
 </script>
 <template>
@@ -71,18 +108,18 @@ const changeTime = (val: any) => {
       <el-radio :value="2">
         <div>Booking Window (ETD/ATD)</div>
         <div class="ETDWindow" v-if="isBookingETD">
-          <el-input style="width: 80px;height: 32px;" v-model="beforeETDdays" @input="changeTime('ETD')"></el-input>
+          <el-input style="width: 80px;height: 32px;" v-model="beforeETDdays" @input="val => handleInput(val, 'ETD_BEFORE')"></el-input>
           days before to 
-          <el-input style="width: 80px;height: 32px;" v-model="afterETDdays" @input="changeTime('ETD')"></el-input>
+          <el-input style="width: 80px;height: 32px;" v-model="afterETDdays" @input="val => handleInput(val, 'ETD_AFTER')"></el-input>
           days after
         </div>
       </el-radio>
       <el-radio :value="3">
         <div>Booking Window (ETA/ATA)</div>
         <div class="ETDWindow" v-if="isBookingETA">
-          <el-input style="width: 80px;height: 32px;" v-model="beforeETAdays" @input="changeTime('ETA')"></el-input>
+          <el-input style="width: 80px;height: 32px;" v-model="beforeETAdays" @input="val => handleInput(val, 'ETA_BEFORE')"></el-input>
           days before to 
-          <el-input style="width: 80px;height: 32px;" v-model="afterETAdays" @input="changeTime('ETA')"></el-input>
+          <el-input style="width: 80px;height: 32px;" v-model="afterETAdays" @input="val => handleInput(val, 'ETA_AFTER')"></el-input>
           days after
         </div>
       </el-radio>

BIN
src/views/DestinationDelivery/src/components/ConfiguRations/src/images/icon_success_big@2x.png