Bladeren bron

feat:monitoring表格

AmandaG 9 maanden geleden
bovenliggende
commit
cfd1a9c142
24 gewijzigde bestanden met toevoegingen van 3008 en 174 verwijderingen
  1. BIN
      dist.rar
  2. 57 1
      src/api/module/system.ts
  3. 1 122
      src/components/AddRules/src/AddRules.vue
  4. 5 1
      src/components/AddRules/src/components/NotiFrequency.vue
  5. 6 2
      src/components/AddRules/src/components/NotiMethods.vue
  6. 1 0
      src/components/CreateAddRules/index.ts
  7. 1215 0
      src/components/CreateAddRules/src/CreateAddRules.vue
  8. 78 0
      src/components/CreateAddRules/src/components/AddedrluesTag.vue
  9. 279 0
      src/components/CreateAddRules/src/components/DelayedType.vue
  10. 341 0
      src/components/CreateAddRules/src/components/ETDShipments.vue
  11. 398 0
      src/components/CreateAddRules/src/components/NotiFrequency.vue
  12. 92 0
      src/components/CreateAddRules/src/components/NotiMethods.vue
  13. 83 0
      src/components/CreateAddRules/src/components/RulesShipments.vue
  14. 197 0
      src/components/CreateAddRules/src/components/ShipmentRange.vue
  15. BIN
      src/components/CreateAddRules/src/images/icon_collapse.png
  16. BIN
      src/components/CreateAddRules/src/images/icon_expand.png
  17. BIN
      src/components/CreateAddRules/src/images/illustration_email@2x.png
  18. BIN
      src/components/CreateAddRules/src/images/illustration_system massage@2x.png
  19. BIN
      src/components/CreateAddRules/src/images/submit_successful.png
  20. 1 0
      src/views/Layout/src/components/Header/components/LogoutDialog.vue
  21. 1 0
      src/views/Login/src/loginView.vue
  22. 37 2
      src/views/SystemSettings/src/SystemSettings.vue
  23. 123 11
      src/views/SystemSettings/src/components/CreateNewrule/src/CreateNewrule.vue
  24. 93 35
      src/views/SystemSettings/src/components/MonitoringTable/src/MonitoringTable.vue

BIN
dist.rar


+ 57 - 1
src/api/module/system.ts

@@ -75,7 +75,7 @@ export const SubscribePagination = (params: any, config: any) => {
   )
 }
 /**
- * 收藏表格分页切换
+ * 初始化数据
  */
 export const MonitoringInit = (params: any, config: any) => {
   return HttpAxios.get(
@@ -87,4 +87,60 @@ export const MonitoringInit = (params: any, config: any) => {
     },
     config
   )
+}
+/**
+ * Monitoring保存数据
+ */
+export const MonitoringSave = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'monitoring_setting',
+      operate: 'monitoring_rules_do',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * Monitoring表格数据
+ */
+export const MonitoringTable = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'monitoring_setting',
+      operate: 'monitoring_rules_search',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 删除Monitoring表格数据
+ */
+export const deleteMonitoringTable = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'monitoring_setting',
+      operate: 'monitoring_rules_delete',
+      ...params
+    },
+    config
+  )
+}
+/**
+ * 编辑Monitoring表格数据
+ */
+export const EditMonitoringTable = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'monitoring_setting',
+      operate: 'monitoring_rules_edit',
+      ...params
+    },
+    config
+  )
 }

+ 1 - 122
src/components/AddRules/src/AddRules.vue

@@ -5,7 +5,6 @@ import AddedrluesTag from './components/AddedrluesTag.vue'
 import DelayedType from './components/DelayedType.vue'
 import ETDShipments from './components/ETDShipments.vue'
 import NotiFrequency from './components/NotiFrequency.vue'
-import ShipmentRange from './components/ShipmentRange.vue'
 import NotiMethods from './components/NotiMethods.vue'
 import submitsucessful from './images/submit_successful.png'
 interface CheckboxItem {
@@ -40,8 +39,6 @@ const DelayedDeparturedList = ref()
 const DelayedAirdList = ref()
 const ETDOceanList = ref()
 const ETDAirList = ref()
-const CreateRuleOceanCheckList = ref()
-const CreateRuleAirCheckList = ref()
 const FrequencyDataMil = ref()
 const FrequencyDataCon = ref()
 const FrequencyDataDep = ref()
@@ -162,49 +159,6 @@ const ChangeCheckAirRules = (val: any) => {
   AirCheckList.value = val
 }
 
-//选择create new rules
-const createList = ref()
-const ChangeCheckCreateRuleOceanRules = (val: any) => {
-  CreateRuleOceanCheckList.value = val
-}
-const ChangeCheckCreateRuleAirRules = (val: any) => {
-  CreateRuleAirCheckList.value = val
-}
-
-let createObj: any = {
-  Transportstr: '',
-  Timestr: ''
-}
-const changecheckCreateRules = (val: any) => {
-  createList.value = []
-  createObj.Transportstr = val
-  if (createObj.Transportstr != '') {
-    createList.value.push(createObj.Transportstr)
-  }
-  if (createObj.Timestr != '') {
-    createList.value.push(createObj.Timestr)
-  }
-}
-const ChangeCheckTimeRules = (val: any) => {
-  createList.value = []
-  createObj.Timestr = val
-  if (createObj.Transportstr != '') {
-    createList.value.push(createObj.Transportstr)
-  }
-  if (createObj.Timestr != '') {
-    createList.value.push(createObj.Timestr)
-  }
-}
-// 删除create tag
-const ShipmentRangeRef = ref()
-const handleCloseCreateRule = (val: any) => {
-  if (val.indexOf('ETD') != -1 || val.indexOf('ETA') != -1) {
-    createObj.Timestr = ''
-  } else if (val.indexOf('Transport') != -1) {
-    createObj.Transportstr = ''
-  }
-  ShipmentRangeRef.value.handleCloseCreateRule(val)
-}
 // 更改Frequency时间
 const MilFrequencyList = ref()
 const ChangeMilFrequency = (val: any, type: any) => {
@@ -637,65 +591,6 @@ defineExpose({
             </div>
           </el-collapse-item>
         </el-collapse>
-        <el-collapse
-          v-model="RulesActive"
-          @change="IsFirstActive = !IsFirstActive"
-          v-if="props.TitleType == 'CreateRule'"
-        >
-          <el-collapse-item name="SelectMilestone">
-            <template #title>
-              <div class="Rules_Title">
-                <span class="iconfont_icon">
-                  <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>Shipment Range
-              </div>
-            </template>
-            <div>
-              <ShipmentRange
-                ref="ShipmentRangeRef"
-                @ChangeCheckRules="changecheckCreateRules"
-                @ChangeCheckTimeRules="ChangeCheckTimeRules"
-              ></ShipmentRange>
-            </div>
-          </el-collapse-item>
-        </el-collapse>
-        <el-collapse
-          v-model="RulesActive"
-          @change="IsFirstActive = !IsFirstActive"
-          v-if="props.TitleType == 'CreateRule'"
-        >
-          <el-collapse-item name="SelectMilestone">
-            <template #title>
-              <div class="Rules_Title">
-                <span class="iconfont_icon">
-                  <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 Milestone
-              </div>
-            </template>
-            <div>
-              <RulesShipments
-                Title="Ocean shipments"
-                @ChangeCheckRules="ChangeCheckCreateRuleOceanRules"
-              ></RulesShipments>
-            </div>
-            <div>
-              <RulesShipments
-                Title="Air shipments"
-                @ChangeCheckRules="ChangeCheckCreateRuleAirRules"
-              ></RulesShipments>
-            </div>
-          </el-collapse-item>
-        </el-collapse>
         <el-collapse
           v-model="RulesActive"
           @change="IsFirstActive = !IsFirstActive"
@@ -820,12 +715,6 @@ defineExpose({
     </div>
     <div class="Rules_right">
       <div class="right_Title">Added Rules</div>
-      <AddedrluesTag
-        v-if="props.TitleType == 'CreateRule'"
-        :CheckedList="createList"
-        Title="Shipment Range"
-        @handleCloseRadio="handleCloseCreateRule"
-      ></AddedrluesTag>
       <AddedrluesTag
         :CheckedList="DelayedDeparturedList"
         v-if="props.TitleType == 'Departure'"
@@ -837,11 +726,6 @@ defineExpose({
         :CheckedList="OceanCheckList"
         Title="Ocean Shipments"
       ></AddedrluesTag>
-      <AddedrluesTag
-        v-if="props.TitleType == 'CreateRule'"
-        :CheckedList="CreateRuleOceanCheckList"
-        Title="Ocean Shipments"
-      ></AddedrluesTag>
       <AddedrluesTag
         v-if="props.TitleType == 'Container'"
         :CheckedList="ContainerOceanList"
@@ -859,11 +743,6 @@ defineExpose({
         @handleCloseRadio="closeAirETD"
         Title="Air Shipments"
       ></AddedrluesTag>
-      <AddedrluesTag
-        v-if="props.TitleType == 'CreateRule'"
-        :CheckedList="CreateRuleAirCheckList"
-        Title="Air Shipments"
-      ></AddedrluesTag>
       <AddedrluesTag
         :CheckedList="DelayedAirdList"
         v-if="props.TitleType == 'Departure'"
@@ -921,7 +800,7 @@ defineExpose({
       ></AddedrluesTag>
     </div>
   </div>
-  <div class="Rules_buttom" v-if="props.TitleType != 'CreateRule'">
+  <div class="Rules_buttom">
     <el-button class="el-button--dark rules_button" @click="Savesubscribe">Save</el-button>
     <el-button @click="CancelRulesVisible = true" class="rules_button" type="default"
       >Cancel</el-button

+ 5 - 1
src/components/AddRules/src/components/NotiFrequency.vue

@@ -250,6 +250,8 @@ const handleCloseRadioFrequency = () => {
   ChangeFrequency(0)
 }
 
+const user_type = localStorage.getItem('user_type')
+
 defineExpose({
   handleCloseRadioFrequency,
   FrequencyDataInit
@@ -258,7 +260,9 @@ defineExpose({
 <template>
   <div style="margin-top: 11px">
     <el-radio-group v-model="radio" @change="ChangeFrequency">
-      <el-radio :value="1">Instant notification for each update</el-radio>
+      <el-radio :value="1" v-if="user_type != null && user_type != 'customer'"
+        >Instant notification for each update</el-radio
+      >
       <el-radio :value="2">
         <div>Daily Summary</div>
         <div class="Daily" v-if="isDaily">

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

@@ -29,7 +29,6 @@ const MethodsInit = () => {
       checkMethodList.value.push('By System Message')
     }
   }
-  console.log(checkMethodList.value)
   changeMethod(checkMethodList.value)
 }
 
@@ -52,12 +51,17 @@ const changeMethod = (val: any) => {
   }
   emits('ChangeMethodsAdd', checkMethodList.value, savesubscribeobj)
 }
+const user_type = localStorage.getItem('user_type')
 </script>
 <template>
   <div style="margin-top: 11px">
     <div class="Method">
       <el-checkbox-group v-model="checkMethodList" @change="changeMethod">
-        <el-checkbox class="methodcheckbox" value="By Email">
+        <el-checkbox
+          class="methodcheckbox"
+          value="By Email"
+          v-if="user_type != null && user_type != 'customer'"
+        >
           <div>By Email</div>
           <div class="methos_image"><img src="../images/illustration_email@2x.png" /></div>
         </el-checkbox>

+ 1 - 0
src/components/CreateAddRules/index.ts

@@ -0,0 +1 @@
+export { default } from './src/CreateAddRules.vue'

+ 1215 - 0
src/components/CreateAddRules/src/CreateAddRules.vue

@@ -0,0 +1,1215 @@
+<script lang="ts" setup>
+import { ref, watch, onMounted } from 'vue'
+import RulesShipments from './components/RulesShipments.vue'
+import AddedrluesTag from './components/AddedrluesTag.vue'
+import DelayedType from './components/DelayedType.vue'
+import ETDShipments from './components/ETDShipments.vue'
+import NotiFrequency from './components/NotiFrequency.vue'
+import ShipmentRange from './components/ShipmentRange.vue'
+import NotiMethods from './components/NotiMethods.vue'
+import submitsucessful from './images/submit_successful.png'
+interface CheckboxItem {
+  value: string
+  label: string
+}
+
+interface Props {
+  SystemList: Object
+  TitleType: String
+}
+const MilestoneOceanListInit = ref<CheckboxItem[]>([])
+const MilestoneOceanListChecked = ref()
+const MilestoneAirListInit = ref<CheckboxItem[]>([])
+const MilestoneAirListChecked = ref()
+const ContainerOceanListInit = ref<CheckboxItem[]>([])
+const ContainerOceanListChecked = ref()
+const props = defineProps<Props>()
+let savesubscribeobj: any = {}
+const SystemList = ref(props.SystemList)
+const RulesActive = ref([
+  'ShipmentRange',
+  'SelectMilestone',
+  'NotificationFrequency',
+  'NotificationMethod'
+])
+const OceanCheckList = ref()
+const AirCheckList = ref()
+const ContainerOceanList = ref()
+const IsFirstActive = ref(true)
+const IsTwoActive = ref(true)
+const IsThreeActive = ref(true)
+const IsFourActive = ref(true)
+const UnableSaveVisible = ref(false)
+const SaveedVisible = ref(false)
+const DelayedDeparturedList = ref()
+const DelayedAirdList = ref()
+const ETDOceanList = ref()
+const ETDAirList = ref()
+const FrequencyDataMil = ref()
+const FrequencyDataCon = ref()
+const FrequencyDataDep = ref()
+const FrequencyDataETD = ref()
+const MethodsDataMil = ref()
+const MethodsDataCon = ref()
+const MethodsDataDep = ref()
+const MethodsDataETD = ref()
+const DelayedDataInit = ref()
+const DelayedDataInitAir = ref()
+const OceanETDInit = ref()
+const AirETDInit = ref()
+
+watch(
+  () => props.SystemList,
+  (current) => {
+    SystemList.value = current
+    FrequencyDataMil.value = current['Milestone_Update']
+    MethodsDataMil.value = current['Milestone_Update']
+    FrequencyDataCon.value = current['Container_Status_Update']
+    MethodsDataCon.value = current['Container_Status_Update']
+    FrequencyDataDep.value = current['Departure/Arrival_Delay']
+    MethodsDataDep.value = current['Departure/Arrival_Delay']
+    FrequencyDataETD.value = current['ETD/ETA_Change']
+    MethodsDataETD.value = current['ETD/ETA_Change']
+    Initdata(current)
+  }
+)
+
+const MonitoringList = ref()
+const getInitMonitoring = () => {
+  $api
+    .MonitoringInit({})
+    .then((res: any) => {
+      if (res.code === 200) {
+        MonitoringList.value = res.data
+        MilestoneOceanListInit.value = res.data.OceanCheckBoxList
+        MilestoneAirListInit.value = res.data.AirCheckBoxList
+        ContainerOceanListInit.value = res.data.CtnrCheckBoxList
+      }
+    })
+    .finally(() => {})
+}
+onMounted(() => {
+  getInitMonitoring()
+})
+// 初始赋值
+const Initdata = (val: any) => {
+  console.log(val)
+  MilestoneOceanListInit.value = val.Milestone_Update.OceanCheckBoxList
+  MilestoneOceanListChecked.value = val.Milestone_Update.OceanCheckedList
+  OceanCheckList.value = val.Milestone_Update.OceanCheckedList
+  MilestoneAirListInit.value = val.Milestone_Update.AirCheckBoxList
+  MilestoneAirListChecked.value = val.Milestone_Update.AirCheckedList
+  AirCheckList.value = val.Milestone_Update.AirCheckedList
+  ContainerOceanListInit.value = val.Container_Status_Update.CtnrCheckBoxList
+  ContainerOceanListChecked.value = val.Container_Status_Update.CtnrCheckedList
+  ContainerOceanList.value = val.Container_Status_Update.CtnrCheckedList
+  let OceanObj: any = {}
+  OceanObj.atd_etd = val['Departure/Arrival_Delay'].ocean_atd_sub_etd
+  OceanObj.atd_etd_unit = val['Departure/Arrival_Delay'].ocean_atd_sub_etd_unit
+  OceanObj.ata_eta = val['Departure/Arrival_Delay'].ocean_ata_sub_eta
+  OceanObj.ata_eta_unit = val['Departure/Arrival_Delay'].ocean_ata_sub_eta_unit
+  DelayedDataInit.value = OceanObj
+  let AirObj: any = {}
+  AirObj.atd_etd = val['Departure/Arrival_Delay'].air_atd_sub_etd
+  AirObj.atd_etd_unit = val['Departure/Arrival_Delay'].air_atd_sub_etd_unit
+  AirObj.ata_eta = val['Departure/Arrival_Delay'].air_ata_sub_eta
+  AirObj.ata_eta_unit = val['Departure/Arrival_Delay'].air_ata_sub_eta_unit
+  DelayedDataInitAir.value = AirObj
+  let OceanChange: any = {}
+  OceanChange.ETDradio = val['ETD/ETA_Change'].ocean_etd_change
+  OceanChange.etd_old_sub_new = val['ETD/ETA_Change'].ocean_etd_old_sub_new
+  OceanChange.etd_old_sub_new_unit = val['ETD/ETA_Change'].ocean_etd_old_sub_new_unit
+  OceanChange.ETAradio = val['ETD/ETA_Change'].ocean_eta_change
+  OceanChange.eta_old_sub_new = val['ETD/ETA_Change'].ocean_eta_old_sub_new
+  OceanChange.eta_old_sub_new_unit = val['ETD/ETA_Change'].ocean_eta_old_sub_new_unit
+  OceanETDInit.value = OceanChange
+  let AirChange: any = {}
+  AirChange.ETDradio = val['ETD/ETA_Change'].air_etd_change
+  AirChange.etd_old_sub_new = val['ETD/ETA_Change'].air_etd_old_sub_new
+  AirChange.etd_old_sub_new_unit = val['ETD/ETA_Change'].air_etd_old_sub_new_unit
+  AirChange.ETAradio = val['ETD/ETA_Change'].air_eta_change
+  AirChange.eta_old_sub_new = val['ETD/ETA_Change'].air_eta_old_sub_new
+  AirChange.eta_old_sub_new_unit = val['ETD/ETA_Change'].air_eta_old_sub_new_unit
+  AirETDInit.value = AirChange
+}
+
+// 给tag list赋值
+const ChangeCheckOceanRules = (val: any) => {
+  OceanCheckList.value = val
+}
+const ChangeContainerRules = (val: any) => {
+  ContainerOceanList.value = val
+}
+// delayed赋值
+const ChangeDeayedRules = (val: any) => {
+  DelayedDeparturedList.value = []
+  if (val.Departure != '') {
+    DelayedDeparturedList.value.push(val.Departure)
+    savesubscribeobj.ocean_atd_sub_etd = val.Departure.split(' ')[3]
+    savesubscribeobj.ocean_atd_sub_etd_unit = val.Departure.split(' ')[4]
+  } else {
+    delete savesubscribeobj.ocean_atd_sub_etd
+    delete savesubscribeobj.ocean_atd_sub_etd_unit
+  }
+  if (val.Arrival != '') {
+    DelayedDeparturedList.value.push(val.Arrival)
+    savesubscribeobj.ocean_ata_sub_eta = val.Arrival.split(' ')[4]
+    savesubscribeobj.ocean_ata_sub_eta_unit = val.Arrival.split(' ')[5]
+  } else {
+    delete savesubscribeobj.ocean_ata_sub_eta
+    delete savesubscribeobj.ocean_ata_sub_eta_unit
+  }
+}
+const ChangeAirRules = (val: any) => {
+  DelayedAirdList.value = []
+  if (val.Departure != '') {
+    DelayedAirdList.value.push(val.Departure)
+    savesubscribeobj.air_atd_sub_etd = val.Departure.split(' ')[3]
+    savesubscribeobj.air_atd_sub_etd_unit = val.Departure.split(' ')[4]
+  } else {
+    delete savesubscribeobj.air_atd_sub_etd
+    delete savesubscribeobj.air_atd_sub_etd_unit
+  }
+  if (val.Arrival != '') {
+    DelayedAirdList.value.push(val.Arrival)
+    savesubscribeobj.air_ata_sub_eta = val.Arrival.split(' ')[4]
+    savesubscribeobj.air_ata_sub_eta_unit = val.Arrival.split(' ')[5]
+  } else {
+    delete savesubscribeobj.air_ata_sub_eta
+    delete savesubscribeobj.air_ata_sub_eta_unit
+  }
+}
+const ChangeCheckAirRules = (val: any) => {
+  AirCheckList.value = val
+}
+
+//选择create new rules
+const createListMilestone = ref()
+const createListContainer = ref()
+const createListDeparture = ref()
+const createListETDChange = ref()
+
+let createObj: any = {
+  Transportstr: '',
+  Timestr: ''
+}
+const changecheckCreateRulesMilestone = (val: any, value: any) => {
+  createListMilestone.value = []
+  createObj.Transportstr = val
+  if (createObj.Transportstr != '') {
+    createListMilestone.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListMilestone.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_transport_mode = value
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+const ChangeCheckTimeRulesMilestone = (val: any, time: any) => {
+  createListMilestone.value = []
+  createObj.Timestr = val
+  if (val.includes('ETD')) {
+    savesubscribeobj.shipment_etd_limit = time
+    savesubscribeobj.shipment_eta_limit = ''
+  }
+  if (val.includes('ETA')) {
+    savesubscribeobj.shipment_eta_limit = time
+    savesubscribeobj.shipment_etd_limit = ''
+  }
+  if (createObj.Transportstr != '') {
+    createListMilestone.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListMilestone.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+const changecheckCreateRulesContainer = (val: any, value: any) => {
+  createListContainer.value = []
+  createObj.Transportstr = val
+  if (createObj.Transportstr != '') {
+    createListContainer.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListContainer.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_transport_mode = value
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+const ChangeCheckTimeRulesContainer = (val: any, time: any) => {
+  createListContainer.value = []
+  createObj.Timestr = val
+  if (val.includes('ETD')) {
+    savesubscribeobj.shipment_etd_limit = time
+    savesubscribeobj.shipment_eta_limit = ''
+  }
+  if (val.includes('ETA')) {
+    savesubscribeobj.shipment_eta_limit = time
+    savesubscribeobj.shipment_etd_limit = ''
+  }
+  if (createObj.Transportstr != '') {
+    createListContainer.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListContainer.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+const changecheckCreateRulesDeparture = (val: any, value: any) => {
+  createListDeparture.value = []
+  createObj.Transportstr = val
+  if (createObj.Transportstr != '') {
+    createListDeparture.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListDeparture.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_transport_mode = value
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+const ChangeCheckTimeRulesDeparture = (val: any, time: any) => {
+  createListDeparture.value = []
+  createObj.Timestr = val
+  if (val.includes('ETD')) {
+    savesubscribeobj.shipment_etd_limit = time
+    savesubscribeobj.shipment_eta_limit = ''
+  }
+  if (val.includes('ETA')) {
+    savesubscribeobj.shipment_eta_limit = time
+    savesubscribeobj.shipment_etd_limit = ''
+  }
+  if (createObj.Transportstr != '') {
+    createListDeparture.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListDeparture.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+const changecheckCreateRulesETDChange = (val: any, value: any) => {
+  createListETDChange.value = []
+  createObj.Transportstr = val
+  if (createObj.Transportstr != '') {
+    createListETDChange.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListETDChange.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_transport_mode = value
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+const ChangeCheckTimeRulesETDChange = (val: any, time: any) => {
+  createListETDChange.value = []
+  createObj.Timestr = val
+  if (val.includes('ETD')) {
+    savesubscribeobj.shipment_etd_limit = time
+    savesubscribeobj.shipment_eta_limit = ''
+  }
+  if (val.includes('ETA')) {
+    savesubscribeobj.shipment_eta_limit = time
+    savesubscribeobj.shipment_etd_limit = ''
+  }
+  if (createObj.Transportstr != '') {
+    createListETDChange.value.push(createObj.Transportstr)
+  }
+  if (createObj.Timestr != '') {
+    createListETDChange.value.push(createObj.Timestr)
+  }
+  savesubscribeobj.shipment_details = createListMilestone.value.join(';\n')
+}
+// 删除create tag
+const ShipmentRangeRef = ref()
+const handleCloseCreateRule = (val: any) => {
+  if (val.indexOf('ETD') != -1 || val.indexOf('ETA') != -1) {
+    createObj.Timestr = ''
+  } else if (val.indexOf('Transport') != -1) {
+    createObj.Transportstr = ''
+  }
+  ShipmentRangeRef.value.handleCloseCreateRule(val)
+}
+// 更改Frequency时间
+const MilFrequencyList = ref([])
+const ChangeMilFrequency = (val: any, type: any) => {
+  MilFrequencyList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+const ConFrequencyList = ref([])
+const ChangeConFrequency = (val: any, type: any) => {
+  ConFrequencyList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+const DepFrequencyList = ref([])
+const ChangeDepFrequency = (val: any, type: any) => {
+  DepFrequencyList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+const ETDFrequencyList = ref([])
+const ChangeETDFrequency = (val: any, type: any) => {
+  ETDFrequencyList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+
+// 删除 Frequency tag
+const NotiFrequencyDeleteMil = ref()
+const NotiFrequencyDeleteCon = ref()
+const NotiFrequencyDeleteDep = ref()
+const NotiFrequencyDeleteETD = ref()
+const handleCloseRadio = (val: any) => {
+  if (val == 'Mil') {
+    NotiFrequencyDeleteMil.value.handleCloseRadioFrequency()
+  } else if (val == 'Con') {
+    NotiFrequencyDeleteCon.value.handleCloseRadioFrequency()
+  } else if (val == 'Dep') {
+    NotiFrequencyDeleteDep.value.handleCloseRadioFrequency()
+  } else {
+    NotiFrequencyDeleteETD.value.handleCloseRadioFrequency()
+  }
+}
+
+// methods 切换
+const MilMethodsList = ref([])
+const ChangeMethodsAddMil = (val: any, type: any) => {
+  MilMethodsList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+const ConMethodsList = ref([])
+const ChangeMethodsAddCon = (val: any, type: any) => {
+  ConMethodsList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+const DepMethodsList = ref([])
+const ChangeMethodsAddDep = (val: any, type: any) => {
+  DepMethodsList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+const ETDMethodsList = ref([])
+const ChangeMethodsAddETD = (val: any, type: any) => {
+  ETDMethodsList.value = val
+  savesubscribeobj = { ...savesubscribeobj, ...type }
+}
+const OceanDelayed = ref()
+const AirDelayed = ref()
+
+const handleCloseDelayed = (val: any) => {
+  OceanDelayed.value.closeDelayed(val)
+}
+const handleCloseAirDelayed = (val: any) => {
+  AirDelayed.value.closeDelayed(val)
+}
+// ETD Change
+const ChangeETDOceanRules = (val: any) => {
+  ETDOceanList.value = []
+  if (val.ETD != '') {
+    if (val.ETD.indexOf('≥') != -1) {
+      savesubscribeobj.ocean_etd_change = false
+      savesubscribeobj.ocean_etd_old_sub_new = val.ETD.split(' ')[6]
+      savesubscribeobj.ocean_etd_old_sub_new_unit = val.ETD.split(' ')[7]
+    } else {
+      savesubscribeobj.ocean_etd_change = true
+    }
+    ETDOceanList.value.push(val.ETD)
+  } else {
+    delete savesubscribeobj.ocean_etd_change
+    delete savesubscribeobj.ocean_etd_old_sub_new
+    delete savesubscribeobj.ocean_etd_old_sub_new_unit
+  }
+  if (val.ETA != '') {
+    if (val.ETA.indexOf('≥') != -1) {
+      savesubscribeobj.ocean_eta_change = false
+      savesubscribeobj.ocean_eta_old_sub_new = val.ETA.split(' ')[6]
+      savesubscribeobj.ocean_eta_old_sub_new_unit = val.ETA.split(' ')[7]
+    } else {
+      savesubscribeobj.ocean_eta_change = true
+    }
+    ETDOceanList.value.push(val.ETA)
+  } else {
+    delete savesubscribeobj.ocean_eta_change
+    delete savesubscribeobj.ocean_eta_old_sub_new
+    delete savesubscribeobj.ocean_eta_old_sub_new_unit
+  }
+}
+// 删除ETD tag
+const OceanETD = ref()
+const closeOceanETD = (val: any) => {
+  OceanETD.value.closeETD(val)
+}
+// ETA Change
+const ChangeETDAirRules = (val: any) => {
+  ETDAirList.value = []
+  if (val.ETD != '') {
+    if (val.ETD.indexOf('≥') != -1) {
+      savesubscribeobj.air_etd_change = false
+      savesubscribeobj.air_etd_old_sub_new = val.ETD.split(' ')[6]
+      savesubscribeobj.air_etd_old_sub_new_unit = val.ETD.split(' ')[7]
+    } else {
+      savesubscribeobj.air_etd_change = true
+    }
+    ETDAirList.value.push(val.ETD)
+  } else {
+    delete savesubscribeobj.air_etd_change
+    delete savesubscribeobj.air_etd_old_sub_new
+    delete savesubscribeobj.air_etd_old_sub_new_unit
+  }
+  if (val.ETA != '') {
+    if (val.ETA.indexOf('≥') != -1) {
+      savesubscribeobj.air_eta_change = false
+      savesubscribeobj.air_eta_old_sub_new = val.ETA.split(' ')[6]
+      savesubscribeobj.air_eta_old_sub_new_unit = val.ETA.split(' ')[7]
+    } else {
+      savesubscribeobj.air_eta_change = true
+    }
+    ETDAirList.value.push(val.ETA)
+  } else {
+    delete savesubscribeobj.air_eta_change
+    delete savesubscribeobj.air_eta_old_sub_new
+    delete savesubscribeobj.air_eta_old_sub_new_unit
+  }
+}
+
+// 删除ETA tag
+const AirETD = ref()
+const closeAirETD = (val: any) => {
+  AirETD.value.closeETD(val)
+}
+
+const emits = defineEmits(['SavedAddedRules'])
+// 不保存修改的折叠面板
+
+// 保存subscribe配置
+const missingmessage = ref('')
+// 保存成功调用接口
+const SaveSuceessful = () => {
+  $api
+    .MonitoringSave({
+      ...savesubscribeobj
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        SaveedVisible.value = true
+        setTimeout(() => {
+          SaveedVisible.value = false
+          emits('SavedAddedRules', res.data.addedRules, savesubscribeobj.rules_type)
+        }, 3000)
+      }
+    })
+}
+const Savesubscribe = () => {
+  missingmessage.value = ''
+  let str = ''
+  if (props.TitleType == 'Milestone') {
+    savesubscribeobj.rules_type = 'Milestone_Update'
+    if (
+      OceanCheckList.value == undefined ||
+      AirCheckList.value == undefined ||
+      MilFrequencyList.value.length == 0 ||
+      MilMethodsList.value.length == 0 ||
+      createObj.Transportstr == '' ||
+      createObj.Timestr == ''
+    ) {
+      console.log(createObj)
+      if (createObj.Transportstr == '') {
+        missingmessage.value += 'Transport Mode, '
+      }
+      if (createObj.Timestr == '') {
+        missingmessage.value += 'Time, '
+      }
+      if (OceanCheckList.value == undefined) {
+        missingmessage.value += 'Ocean Shipments, '
+      }
+      if (AirCheckList.value == undefined) {
+        missingmessage.value += 'Air Shipments, '
+      }
+      if (MilFrequencyList.value.length == 0) {
+        missingmessage.value += 'Notification Frequency, '
+      }
+      if (MilMethodsList.value.length == 0) {
+        missingmessage.value += 'Notification Method, '
+      }
+      missingmessage.value = missingmessage.value.substring(0, missingmessage.value.length - 2)
+      UnableSaveVisible.value = true
+    } else {
+      savesubscribeobj.ocean_milestone = OceanCheckList.value
+      savesubscribeobj.air_milestone = AirCheckList.value
+      str =
+        'Ocean Milestones: ' +
+        OceanCheckList.value.join(',') +
+        ';\nAir Milestones: ' +
+        AirCheckList.value.join(',') +
+        ';'
+      savesubscribeobj.event_details = str
+      SaveSuceessful()
+    }
+  } else if (props.TitleType == 'Container') {
+    savesubscribeobj.rules_type = 'Container_Status_Update'
+    if (
+      ContainerOceanList.value == undefined ||
+      ConFrequencyList.value.length == 0 ||
+      ConMethodsList.value.length == 0
+    ) {
+      if (ContainerOceanList.value == undefined) {
+        missingmessage.value += 'Ocean Shipments, '
+      }
+      if (ConFrequencyList.value.length == 0) {
+        missingmessage.value += 'Notification Frequency, '
+      }
+      if (ConMethodsList.value.length == 0) {
+        missingmessage.value += 'Notification Method, '
+      }
+      missingmessage.value = missingmessage.value.substring(0, missingmessage.value.length - 2)
+      UnableSaveVisible.value = true
+    } else {
+      savesubscribeobj.ocean_ctnr_status = ContainerOceanList.value
+      str = 'Ocean Container: ' + ContainerOceanList.value.join(',')
+      savesubscribeobj.event_details = str
+      SaveSuceessful()
+    }
+  } else if (props.TitleType == 'Departure') {
+    savesubscribeobj.rules_type = 'Departure/Arrival_Delay'
+    if (
+      DelayedDeparturedList.value == undefined ||
+      DelayedAirdList.value == undefined ||
+      DepFrequencyList.value.length == 0 ||
+      DepMethodsList.value.length == 0
+    ) {
+      if (DelayedDeparturedList.value == undefined) {
+        missingmessage.value += 'Ocean Shipments, '
+      }
+      if (DelayedAirdList.value == undefined) {
+        missingmessage.value += 'Air Shipments, '
+      }
+      if (DepFrequencyList.value.length == 0) {
+        missingmessage.value += 'Notification Frequency, '
+      }
+      if (DepMethodsList.value.length == 0) {
+        missingmessage.value += 'Notification Method, '
+      }
+      missingmessage.value = missingmessage.value.substring(0, missingmessage.value.length - 2)
+      UnableSaveVisible.value = true
+    } else {
+      str = DelayedDeparturedList.value.join(';\n') + ';\n' + DelayedAirdList.value.join(';\n')
+      savesubscribeobj.event_details = str
+      SaveSuceessful()
+    }
+  } else {
+    savesubscribeobj.rules_type = 'ETD/ETA_Change'
+    if (
+      ETDOceanList.value == undefined ||
+      ETDOceanList.value.length == 0 ||
+      ETDAirList.value == undefined ||
+      ETDAirList.value.length == 0 ||
+      ETDFrequencyList.value.length == 0 ||
+      ETDMethodsList.value.length == 0
+    ) {
+      if (ETDOceanList.value == undefined) {
+        missingmessage.value += 'Ocean Shipments, '
+      }
+      if (ETDAirList.value == undefined) {
+        missingmessage.value += 'Air Shipments, '
+      }
+      if (ETDFrequencyList.value.length == 0) {
+        missingmessage.value += 'Notification Frequency, '
+      }
+      if (ETDMethodsList.value.length == 0) {
+        missingmessage.value += 'Notification Method, '
+      }
+      missingmessage.value = missingmessage.value.substring(0, missingmessage.value.length - 2)
+      UnableSaveVisible.value = true
+    } else {
+      str = ETDOceanList.value.join(';\n') + ';\n' + ETDAirList.value.join(';\n')
+      savesubscribeobj.event_details = str
+      SaveSuceessful()
+    }
+  }
+}
+
+// 删除表格数据后清空所有数据
+const clearData = (val: any) => {
+  if (val == 'Milestone') {
+    OceanCheckList.value = []
+    AirCheckList.value = []
+    MilFrequencyList.value = []
+    MilMethodsList.value = []
+    MilestoneOceanListChecked.value = []
+    MilestoneAirListChecked.value = []
+    createListMilestone.value = []
+  } else if (val == 'Container') {
+    ContainerOceanList.value = []
+    createListContainer.value = []
+    ConFrequencyList.value = []
+    ConMethodsList.value = []
+    ContainerOceanListChecked.value = []
+  } else if (val == 'Departure') {
+    DelayedDeparturedList.value = []
+    DelayedAirdList.value = []
+    DepFrequencyList.value = []
+    DepMethodsList.value = []
+    createListDeparture.value = []
+  } else {
+    ETDOceanList.value = []
+    ETDAirList.value = []
+    ETDFrequencyList.value = []
+    ETDMethodsList.value = []
+    createListETDChange.value = []
+  }
+}
+
+defineExpose({
+  clearData,
+  Savesubscribe
+})
+</script>
+<template>
+  <div class="Rules_flex">
+    <div class="Rules_left">
+      <div class="Rules_collapse">
+        <el-collapse v-model="RulesActive" @change="IsFourActive = !IsFourActive">
+          <el-collapse-item name="ShipmentRange">
+            <template #title>
+              <div class="Rules_Title">
+                <span class="iconfont_icon">
+                  <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>Shipment Range
+              </div>
+            </template>
+            <div>
+              <ShipmentRange
+                ref="ShipmentRangeRef"
+                v-if="props.TitleType == 'Milestone'"
+                @ChangeCheckRules="changecheckCreateRulesMilestone"
+                @ChangeCheckTimeRules="ChangeCheckTimeRulesMilestone"
+              ></ShipmentRange>
+              <ShipmentRange
+                ref="ShipmentRangeRef"
+                v-if="props.TitleType == 'Container'"
+                @ChangeCheckRules="changecheckCreateRulesContainer"
+                @ChangeCheckTimeRules="ChangeCheckTimeRulesContainer"
+              ></ShipmentRange>
+              <ShipmentRange
+                ref="ShipmentRangeRef"
+                v-if="props.TitleType == 'Departure'"
+                @ChangeCheckRules="changecheckCreateRulesDeparture"
+                @ChangeCheckTimeRules="ChangeCheckTimeRulesDeparture"
+              ></ShipmentRange>
+              <ShipmentRange
+                ref="ShipmentRangeRef"
+                v-if="props.TitleType == 'ETDChange'"
+                @ChangeCheckRules="changecheckCreateRulesETDChange"
+                @ChangeCheckTimeRules="ChangeCheckTimeRulesETDChange"
+              ></ShipmentRange>
+            </div>
+          </el-collapse-item>
+        </el-collapse>
+        <el-collapse
+          v-model="RulesActive"
+          @change="IsFirstActive = !IsFirstActive"
+          v-if="props.TitleType == 'Milestone'"
+        >
+          <el-collapse-item name="SelectMilestone">
+            <template #title>
+              <div class="Rules_Title">
+                <span class="iconfont_icon">
+                  <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 Milestone
+              </div>
+            </template>
+            <div>
+              <RulesShipments
+                Title="Ocean shipments"
+                @ChangeCheckRules="ChangeCheckOceanRules"
+                :CheckboxList="MilestoneOceanListInit"
+                :CheckedList="MilestoneOceanListChecked"
+              ></RulesShipments>
+            </div>
+            <div>
+              <RulesShipments
+                Title="Air shipments"
+                @ChangeCheckRules="ChangeCheckAirRules"
+                :CheckboxList="MilestoneAirListInit"
+                :CheckedList="MilestoneAirListChecked"
+              ></RulesShipments>
+            </div>
+          </el-collapse-item>
+        </el-collapse>
+        <el-collapse
+          v-model="RulesActive"
+          @change="IsFirstActive = !IsFirstActive"
+          v-if="props.TitleType == 'Container'"
+        >
+          <el-collapse-item name="SelectMilestone">
+            <template #title>
+              <div class="Rules_Title">
+                <span class="iconfont_icon">
+                  <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 Container Status
+              </div>
+            </template>
+            <div>
+              <RulesShipments
+                Title="Ocean shipments"
+                @ChangeCheckRules="ChangeContainerRules"
+                :CheckboxList="ContainerOceanListInit"
+                :CheckedList="ContainerOceanListChecked"
+              ></RulesShipments>
+            </div>
+          </el-collapse-item>
+        </el-collapse>
+        <el-collapse
+          v-model="RulesActive"
+          @change="IsFirstActive = !IsFirstActive"
+          v-if="props.TitleType == 'Departure'"
+        >
+          <el-collapse-item name="SelectMilestone">
+            <template #title>
+              <div class="Rules_Title">
+                <span class="iconfont_icon">
+                  <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 Delayed Type
+              </div>
+            </template>
+            <div>
+              <DelayedType
+                Title="Ocean shipments"
+                ref="OceanDelayed"
+                :DelayedData="DelayedDataInit"
+                @ChangeCheckRules="ChangeDeayedRules"
+              ></DelayedType>
+            </div>
+            <div>
+              <DelayedType
+                Title="Air shipments"
+                ref="AirDelayed"
+                :DelayedData="DelayedDataInitAir"
+                @ChangeCheckRules="ChangeAirRules"
+              ></DelayedType>
+            </div>
+          </el-collapse-item>
+        </el-collapse>
+        <el-collapse
+          v-model="RulesActive"
+          @change="IsFirstActive = !IsFirstActive"
+          v-if="props.TitleType == 'ETDChange'"
+        >
+          <el-collapse-item name="SelectMilestone">
+            <template #title>
+              <div class="Rules_Title">
+                <span class="iconfont_icon">
+                  <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 Delayed Type
+              </div>
+            </template>
+            <div>
+              <ETDShipments
+                Title="Ocean shipments"
+                ref="OceanETD"
+                :ETDData="OceanETDInit"
+                @ChangeCheckRules="ChangeETDOceanRules"
+              ></ETDShipments>
+            </div>
+            <div>
+              <ETDShipments
+                Title="Air shipments"
+                ref="AirETD"
+                :ETDData="AirETDInit"
+                @ChangeCheckRules="ChangeETDAirRules"
+              ></ETDShipments>
+            </div>
+          </el-collapse-item>
+        </el-collapse>
+        <el-collapse
+          style="margin-top: 17px; margin-right: 16px"
+          v-model="RulesActive"
+          @change="IsTwoActive = !IsTwoActive"
+        >
+          <el-collapse-item name="NotificationFrequency">
+            <template #title>
+              <div class="Rules_Title">
+                <span class="iconfont_icon">
+                  <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>Notification Frequency
+              </div>
+            </template>
+            <NotiFrequency
+              v-if="props.TitleType == 'Milestone'"
+              ref="NotiFrequencyDeleteMil"
+              :FrequencyData="FrequencyDataMil"
+              @ChangeFrequencyAdd="ChangeMilFrequency"
+            ></NotiFrequency>
+            <NotiFrequency
+              v-if="props.TitleType == 'Container'"
+              ref="NotiFrequencyDeleteCon"
+              :FrequencyData="FrequencyDataCon"
+              @ChangeFrequencyAdd="ChangeConFrequency"
+            ></NotiFrequency>
+            <NotiFrequency
+              v-if="props.TitleType == 'Departure'"
+              ref="NotiFrequencyDeleteDep"
+              :FrequencyData="FrequencyDataDep"
+              @ChangeFrequencyAdd="ChangeDepFrequency"
+            ></NotiFrequency>
+            <NotiFrequency
+              v-if="props.TitleType == 'ETDChange'"
+              ref="NotiFrequencyDeleteETD"
+              :FrequencyData="FrequencyDataETD"
+              @ChangeFrequencyAdd="ChangeETDFrequency"
+            ></NotiFrequency>
+          </el-collapse-item>
+        </el-collapse>
+        <el-collapse
+          style="margin: 17px 0"
+          v-model="RulesActive"
+          @change="IsThreeActive = !IsThreeActive"
+        >
+          <el-collapse-item name="NotificationMethod">
+            <template #title>
+              <div class="Rules_Title">
+                <span class="iconfont_icon">
+                  <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>Notification Method
+              </div>
+            </template>
+            <NotiMethods
+              v-if="props.TitleType == 'Milestone'"
+              :MethodsData="MethodsDataMil"
+              @ChangeMethodsAdd="ChangeMethodsAddMil"
+            ></NotiMethods>
+            <NotiMethods
+              v-if="props.TitleType == 'Container'"
+              :MethodsData="MethodsDataCon"
+              @ChangeMethodsAdd="ChangeMethodsAddCon"
+            ></NotiMethods>
+            <NotiMethods
+              v-if="props.TitleType == 'Departure'"
+              :MethodsData="MethodsDataDep"
+              @ChangeMethodsAdd="ChangeMethodsAddDep"
+            ></NotiMethods>
+            <NotiMethods
+              v-if="props.TitleType == 'ETDChange'"
+              :MethodsData="MethodsDataETD"
+              @ChangeMethodsAdd="ChangeMethodsAddETD"
+            ></NotiMethods>
+          </el-collapse-item>
+        </el-collapse>
+      </div>
+    </div>
+    <div class="Rules_right">
+      <div class="right_Title">Added Rules</div>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Milestone'"
+        :CheckedList="createListMilestone"
+        Title="Shipment Range"
+        @handleCloseRadio="handleCloseCreateRule"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Container'"
+        :CheckedList="createListContainer"
+        Title="Shipment Range"
+        @handleCloseRadio="handleCloseCreateRule"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Departure'"
+        :CheckedList="createListDeparture"
+        Title="Shipment Range"
+        @handleCloseRadio="handleCloseCreateRule"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'ETDChange'"
+        :CheckedList="createListETDChange"
+        Title="Shipment Range"
+        @handleCloseRadio="handleCloseCreateRule"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        :CheckedList="DelayedDeparturedList"
+        v-if="props.TitleType == 'Departure'"
+        @handleCloseRadio="handleCloseDelayed"
+        Title="Ocean Shipments"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Milestone'"
+        :CheckedList="OceanCheckList"
+        Title="Ocean Shipments"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Container'"
+        :CheckedList="ContainerOceanList"
+        Title="Ocean Shipments"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        :CheckedList="ETDOceanList"
+        v-if="props.TitleType == 'ETDChange'"
+        Title="Ocean Shipments"
+        @handleCloseRadio="closeOceanETD"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        :CheckedList="ETDAirList"
+        v-if="props.TitleType == 'ETDChange'"
+        @handleCloseRadio="closeAirETD"
+        Title="Air Shipments"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        :CheckedList="DelayedAirdList"
+        v-if="props.TitleType == 'Departure'"
+        @handleCloseRadio="handleCloseAirDelayed"
+        Title="Air Shipments"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Milestone'"
+        :CheckedList="AirCheckList"
+        Title="Air Shipments"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Milestone'"
+        :CheckedList="MilFrequencyList"
+        Title="Notification Frequency"
+        @handleCloseRadio="handleCloseRadio('Mil')"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Container'"
+        :CheckedList="ConFrequencyList"
+        Title="Notification Frequency"
+        @handleCloseRadio="handleCloseRadio('Con')"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Departure'"
+        :CheckedList="DepFrequencyList"
+        Title="Notification Frequency"
+        @handleCloseRadio="handleCloseRadio('Dep')"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'ETDChange'"
+        :CheckedList="ETDFrequencyList"
+        Title="Notification Frequency"
+        @handleCloseRadio="handleCloseRadio('ETD')"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Milestone'"
+        :CheckedList="MilMethodsList"
+        Title="Notification Method"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Container'"
+        :CheckedList="ConMethodsList"
+        Title="Notification Method"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'Departure'"
+        :CheckedList="DepMethodsList"
+        Title="Notification Method"
+      ></AddedrluesTag>
+      <AddedrluesTag
+        v-if="props.TitleType == 'ETDChange'"
+        :CheckedList="ETDMethodsList"
+        Title="Notification Method"
+      ></AddedrluesTag>
+    </div>
+  </div>
+  <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" /></div>
+    <div style="text-align: center; margin-top: 20px">Saved successfully</div>
+  </el-dialog>
+</template>
+
+<style lang="scss" scoped>
+.Rules_flex {
+  padding: 0 0 0 8px;
+  display: flex;
+}
+.Rules_left {
+  width: 60%;
+  border-right: 1px solid var(--color-user-config-title-bottom-border);
+}
+.Rules_right {
+  width: 40%;
+  background-color: var(--more-filters-background-color);
+}
+.right_Title {
+  color: var(--color-neutral-1);
+  padding: 9px 8px;
+  font-size: 18px;
+  font-weight: 700;
+  border-bottom: 1px solid var(--color-user-config-title-bottom-border);
+  background-color: var(--color-drawer-body-bg);
+}
+.iconfont {
+  width: 16px;
+  height: 16px;
+  margin-right: 8px;
+}
+.icon_danger {
+  fill: var(--color-btn-danger-bg);
+}
+:deep(.Rules_Title) {
+  color: var(--color-neutral-1);
+  font-size: 14px;
+  font-weight: 700;
+  height: 22px;
+  display: flex;
+  align-items: center;
+}
+.stars_red {
+  color: var(--color-danger);
+}
+:deep(.el-collapse-item__header) {
+  height: 25px !important;
+  margin: 14px 0 0 0 !important;
+  border: none !important;
+  padding: 0 !important;
+}
+:deep(.el-collapse-item__header):hover {
+  background-color: #fff !important;
+  border: none !important;
+}
+:deep(.el-collapse-item__arrow) {
+  width: 0 !important;
+  height: 0 !important;
+}
+:deep(.el-icon svg) {
+  width: 0 !important;
+}
+:deep(.el-collapse-item__header.is-active) {
+  background-color: transparent !important;
+  border-color: transparent !important;
+}
+:deep(.el-collapse-item__arrow.is-active) {
+  transform: rotate(-180deg) !important;
+}
+:deep(.Ocean_collapse .el-collapse-item__arrow) {
+  width: 16px !important;
+  height: 16px !important;
+  background-image: url('../src/images/icon_expand.png') !important;
+  background-size: contain;
+  background-repeat: no-repeat;
+  transform: rotate(0);
+}
+:deep(.Ocean_collapse .el-collapse-item__header) {
+  background-color: #fff !important;
+  padding: 0 8px !important;
+  height: 40px !important;
+}
+:deep(.Ocean_collapse .el-collapse-item) {
+  background-color: var(--color-dialog-header-bg);
+  border-radius: 12px;
+}
+:deep(.Ocean_collapse .el-collapse-item__wrap) {
+  padding: 0 8px !important;
+}
+:deep(.Ocean_collapse .el-collapse-item__header.is-active) {
+  background-color: var(--color-dialog-header-bg) !important;
+}
+:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
+  color: var(--color-neutral-1);
+}
+.Rules_buttom {
+  padding: 8px;
+  border-top: 1px solid var(--color-border-1);
+}
+.rules_button {
+  width: 100px;
+  height: 40px;
+}
+.cancel_header {
+  font-size: 18px;
+  font-weight: 700;
+  color: var(--color-neutral-1);
+  display: flex;
+  align-items: center;
+}
+.icon_warning {
+  width: 22px;
+  height: 22px;
+  margin-right: 0;
+  fill: var(--color-btn-warning-bg);
+}
+.iconfont_warning {
+  display: flex;
+  align-items: center;
+}
+:deep(header.el-dialog__header) {
+  background-color: #fff;
+}
+:deep(footer.el-dialog__footer) {
+  border-top: none;
+}
+:deep(.el-collapse) {
+  margin-right: 8px;
+}
+
+:deep(.el-radio-group) {
+  display: block;
+}
+:deep(.el-radio) {
+  display: flex;
+  min-height: 32px;
+  border: 1px solid var(--color-select-border);
+  margin-bottom: 4px;
+  border-radius: 6px;
+  padding: 0 8px;
+  margin-right: 0;
+  height: fit-content;
+  line-height: 32px;
+  align-items: center;
+}
+:deep(.el-radio__input.is-checked + .el-radio__label) {
+  color: var(--color-neutral-1);
+}
+</style>

+ 78 - 0
src/components/CreateAddRules/src/components/AddedrluesTag.vue

@@ -0,0 +1,78 @@
+<script setup lang="ts" >
+import { ref, watch } from 'vue'
+const props = defineProps({
+  CheckedList: Array,
+  Title: String
+})
+const CheckedList = ref(props.CheckedList)
+watch(
+  () => props.CheckedList,
+  (current) => {
+    CheckedList.value = current
+  }
+)
+
+const emit = defineEmits(['handleCloseRadio'])
+
+const handleClose = (tag: any) => {
+  CheckedList.value?.splice(CheckedList.value.indexOf(tag), 1)
+  emit('handleCloseRadio', tag)
+}
+</script>
+
+<template>
+  <div>
+    <el-card class="Rules_Card">
+      <div class="Card_Title">{{ props.Title }}</div>
+      <div class="right_flex">
+        <el-tag
+          class="tag"
+          v-for="(tag, index) in CheckedList"
+          :key="index"
+          closable
+          @close="handleClose(tag)"
+        >
+          {{ tag }}
+        </el-tag>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.tag {
+  border-radius: 3px;
+  margin-bottom: 4px;
+  color: var(--color-neutral-1);
+  height: 32px;
+  width: fit-content;
+  font-weight: 400;
+  font-size: 14px;
+  background-color: var(--tag-bg-color) !important;
+  border-color: var(--tag-bg-color);
+}
+.tag:last-child {
+  margin-bottom: 0;
+}
+:deep(.el-card__body) {
+  padding: 8px !important;
+  max-height: 400px;
+  overflow-y: scroll;
+}
+:deep(.el-tag .el-tag__close svg) {
+  width: 16px !important;
+}
+.right_flex {
+  display: flex;
+  flex-direction: column;
+}
+.Rules_Card {
+  margin: 8px;
+}
+.Card_Title {
+  color: var(--color-neutral-1);
+  font-size: 14px;
+  font-weight: 600;
+  margin: 9px 0 11px 0;
+}
+</style>

+ 279 - 0
src/components/CreateAddRules/src/components/DelayedType.vue

@@ -0,0 +1,279 @@
+<script lang="ts" setup>
+import { ref, computed, watch } from 'vue'
+
+const props = defineProps({
+  Title: String,
+  DelayedData: Object
+})
+const delayed_data = ref(props.DelayedData)
+watch(
+  () => props.DelayedData,
+  (current) => {
+    delayed_data.value = current
+    DelayedInit()
+  }
+)
+
+const DelayedInit = () => {
+  let array2: any = []
+  OceanCheckedList.value = []
+  if (delayed_data.value?.atd_etd != '' && delayed_data.value?.atd_etd != undefined) {
+    isDeparture.value = true
+    DepartureTime.value = delayed_data.value?.atd_etd
+    DepartureSelect.value = delayed_data.value?.atd_etd_unit
+    OceanCheckedList.value.push('Departure Delayed')
+    array2.push('Departure')
+  }
+  if (delayed_data.value?.ata_eta != '' && delayed_data.value?.ata_eta != undefined) {
+    isArrival.value = true
+    ArrivalTime.value = delayed_data.value?.ata_eta
+    ArrivalSelect.value = delayed_data.value?.ata_eta_unit
+    OceanCheckedList.value.push('Arrival Delayed (ATA-ETA)')
+    array2.push('Arrival')
+  }
+  CheckChange(OceanCheckedList.value)
+  changedeparture(array2)
+}
+const isDeparture = ref(false)
+const isArrival = ref(false)
+const OceanActive = ref(['DelayedShipments'])
+const OceanCheckedList = ref()
+const DepartureTime = ref('')
+const DepartureSelect = ref('')
+const ArrivalTime = ref('')
+const ArrivalSelect = ref('')
+const emit = defineEmits(['ChangeCheckRules', 'closeDelayed'])
+const DepartureList = ref({
+  Departure: '',
+  Arrival: ''
+})
+let Departurestr: any = ''
+let Arrivalstr: any = ''
+
+const clampedValue = computed(() => {
+  if (DepartureTime.value == '') {
+    return 0
+  } else {
+    const numericValue = DepartureTime.value.replace(/[^0-9]/g, 0) // 移除非数字字符
+    return Math.min(Math.max(parseInt(numericValue, 10), 0), 365) // 确保值在0到1000之间,但不更新原输入值仅用于显示
+  }
+})
+const clampedArrivalValue = computed(() => {
+  if (ArrivalTime.value == '') {
+    return 0
+  } else {
+    const numericValue = ArrivalTime.value.replace(/[^0-9]/g, 0) // 移除非数字字符
+    return Math.min(Math.max(parseInt(numericValue, 10), 0), 365) // 确保值在0到1000之间,但不更新原输入值仅用于显示
+  }
+})
+
+const CheckChange = (val: any) => {
+  if (val.includes('Departure Delayed')) {
+    isDeparture.value = true
+    Departurestr = 'Departure Delayed' + ' ≥ ' + clampedValue.value + ' ' + DepartureSelect.value
+    if (DepartureSelect.value != '') {
+      DepartureList.value.Departure = Departurestr
+    }
+    if (val.includes('Arrival Delayed (ATA-ETA)')) {
+      isArrival.value = true
+      Arrivalstr =
+        'Arrival Delayed (ATA-ETA)' + ' ≥ ' + clampedArrivalValue.value + ' ' + ArrivalSelect.value
+      if (ArrivalSelect.value != '') {
+        DepartureList.value.Arrival = Arrivalstr
+      }
+    } else {
+      isArrival.value = false
+      DepartureList.value.Arrival = ''
+    }
+  } else {
+    isDeparture.value = false
+    DepartureList.value.Departure = ''
+    if (val.includes('Arrival Delayed (ATA-ETA)')) {
+      isArrival.value = true
+      Arrivalstr =
+        'Arrival Delayed (ATA-ETA)' + ' ≥ ' + clampedArrivalValue.value + ' ' + ArrivalSelect.value
+      if (ArrivalSelect.value != '') {
+        DepartureList.value.Arrival = Arrivalstr
+      }
+    } else {
+      isArrival.value = false
+      DepartureList.value.Arrival = ''
+    }
+  }
+  emit('ChangeCheckRules', DepartureList.value)
+}
+const changedeparture = (val: any) => {
+  if (val == 'Departure') {
+    Departurestr = 'Departure Delayed' + ' ≥ ' + clampedValue.value + ' ' + DepartureSelect.value
+    if (DepartureSelect.value != '') {
+      DepartureList.value.Departure = Departurestr
+    }
+    if (val == 'Arrival') {
+      Arrivalstr =
+        'Arrival Delayed (ATA-ETA)' + ' ≥ ' + clampedArrivalValue.value + ' ' + ArrivalSelect.value
+      if (ArrivalSelect.value != '') {
+        DepartureList.value.Arrival = Arrivalstr
+      }
+    }
+  } else {
+    if (val == 'Arrival') {
+      Arrivalstr =
+        'Arrival Delayed (ATA-ETA)' + ' ≥ ' + clampedArrivalValue.value + ' ' + ArrivalSelect.value
+      if (ArrivalSelect.value != '') {
+        DepartureList.value.Arrival = Arrivalstr
+      }
+    }
+  }
+  emit('ChangeCheckRules', DepartureList.value)
+}
+const closeDelayed = (val: any) => {
+  if (val.includes('Departure')) {
+    OceanCheckedList.value.splice(OceanCheckedList.value.indexOf('Departure Delayed'), 1)
+    DepartureList.value.Departure = ''
+    isDeparture.value = false
+    DepartureTime.value = ''
+    DepartureSelect.value = ''
+  }
+  if (val.includes('Arrival')) {
+    OceanCheckedList.value.splice(OceanCheckedList.value.indexOf('Arrival Delayed (ATA-ETA)'), 1)
+    DepartureList.value.Arrival = ''
+    isArrival.value = false
+    ArrivalTime.value = ''
+    ArrivalSelect.value = ''
+  }
+  emit('ChangeCheckRules', DepartureList.value)
+}
+
+// 清除所有数据
+const ClearData = () => {
+  OceanCheckedList.value = []
+  DepartureList.value.Departure = ''
+  isDeparture.value = false
+  DepartureList.value.Arrival = ''
+  isArrival.value = false
+  DepartureTime.value = ''
+  DepartureSelect.value = ''
+  ArrivalTime.value = ''
+  ArrivalSelect.value = ''
+}
+
+defineExpose({
+  closeDelayed,
+  ClearData
+})
+</script>
+<template>
+  <div class="Ocean_collapse">
+    <el-collapse v-model="OceanActive">
+      <el-collapse-item name="DelayedShipments">
+        <template #title>
+          <div class="Rules_Title OceanTitle">{{ props.Title }}</div>
+        </template>
+        <div class="oceanCheckbox">
+          <el-checkbox-group @change="CheckChange" v-model="OceanCheckedList">
+            <el-checkbox class="delayedType" value="Departure Delayed">
+              <div>Departure Delayed (ATD-ETD)</div>
+              <div v-if="isDeparture" style="margin-top: 16px">
+                <span class="delayedTitle">Delayed Time</span>
+                <span class="delayedIcon">></span>
+                <el-input
+                  v-model="DepartureTime"
+                  class="input-with-select"
+                  :value="clampedValue"
+                  @input="changedeparture('Departure')"
+                >
+                  <template #append>
+                    <el-select
+                      v-model="DepartureSelect"
+                      placeholder="Select"
+                      @change="changedeparture('Departure')"
+                    >
+                      <el-option label="Day(s)" value="Day(s)" />
+                      <el-option label="Hour(s)" value="Hour(s)" />
+                    </el-select>
+                  </template>
+                </el-input>
+              </div>
+            </el-checkbox>
+            <el-checkbox class="delayedType" value="Arrival Delayed (ATA-ETA)">
+              <div>Arrival Delayed (ATA-ETA)</div>
+              <div v-if="isArrival" style="margin-top: 16px">
+                <span class="delayedTitle">Delayed Time</span>
+                <span class="delayedIcon">></span>
+                <el-input
+                  v-model="ArrivalTime"
+                  @input="changedeparture('Arrival')"
+                  :value="clampedArrivalValue"
+                  class="input-with-select"
+                >
+                  <template #append>
+                    <el-select
+                      v-model="ArrivalSelect"
+                      placeholder="Select"
+                      @change="changedeparture('Arrival')"
+                    >
+                      <el-option label="Day(s)" value="Day(s)" />
+                      <el-option label="Hour(s)" value="Hour(s)" />
+                    </el-select>
+                  </template>
+                </el-input>
+              </div>
+            </el-checkbox>
+          </el-checkbox-group>
+        </div>
+      </el-collapse-item>
+    </el-collapse>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+:deep(.el-checkbox-group) {
+  border: 1px solid var(--color-select-border);
+  border-radius: 5px;
+}
+:deep(.el-checkbox) {
+  width: 100%;
+  background-color: var(--color-drawer-body-bg);
+  border-bottom: 1px solid var(--color-select-border);
+  padding: 8px;
+}
+:deep(.el-checkbox:first-child) {
+  border-radius: 6px 6px 0 0;
+}
+:deep(.el-checkbox:last-child) {
+  border-radius: 0 0 6px 6px;
+  border-bottom: none;
+}
+.delayedType {
+  align-items: start;
+  height: fit-content;
+  margin-right: 5px;
+  border-radius: 6px;
+  padding: 8px;
+}
+.input-with-select {
+  width: 180px;
+}
+:deep(.el-input__wrapper) {
+  width: 50%;
+}
+:deep(.el-input-group__append) {
+  width: 50%;
+  padding: 0;
+  border: none;
+}
+:deep(.el-input-group--append .el-input-group__append .el-select .el-select__wrapper) {
+  padding: 5px 10px;
+  background-color: #fff;
+}
+.delayedTitle {
+  color: var(--color-neutral-2);
+  font-size: 12px;
+}
+.delayedIcon {
+  margin: 0 8px;
+}
+.oceanCheckbox {
+  margin-bottom: 8px;
+}
+</style>

+ 341 - 0
src/components/CreateAddRules/src/components/ETDShipments.vue

@@ -0,0 +1,341 @@
+<script lang="ts" setup>
+import { ref, computed, watch } from 'vue'
+
+const props = defineProps({
+  Title: String,
+  ETDData: Object
+})
+const ETD_data = ref(props.ETDData)
+watch(
+  () => props.ETDData,
+  (current) => {
+    ETD_data.value = current
+    ETDInit()
+  }
+)
+
+const ETDInit = () => {
+  OceanCheckedList.value = []
+  if (ETD_data.value?.ETDradio == 't') {
+    ETDRadio.value = '1'
+    OceanCheckedList.value.push('ETD')
+  } else {
+    if (ETD_data.value?.etd_old_sub_new != '' && ETD_data.value?.etd_old_sub_new != undefined) {
+      ETDRadio.value = '2'
+      isETD.value = true
+      ETDTime.value = ETD_data.value?.etd_old_sub_new
+      ETDSelect.value = ETD_data.value?.etd_old_sub_new_unit
+      OceanCheckedList.value.push('ETD')
+    }
+  }
+  if (ETD_data.value?.ETAradio == 't') {
+    ETARadio.value = '1'
+    OceanCheckedList.value.push('ETA')
+  } else {
+    if (ETD_data.value?.eta_old_sub_new != '' && ETD_data.value?.eta_old_sub_new != undefined) {
+      ETARadio.value = '2'
+      isETA.value = true
+      ETATime.value = ETD_data.value?.eta_old_sub_new
+      ETASelect.value = ETD_data.value?.eta_old_sub_new_unit
+      OceanCheckedList.value.push('ETA')
+    }
+  }
+  CheckChange(OceanCheckedList.value)
+  changeETDRadio(ETDRadio.value)
+  changeETARadio(ETARadio.value)
+  changedeparture(OceanCheckedList.value)
+}
+const isETD = ref(false)
+const isETA = ref(false)
+const OceanActive = ref(['ETDShipments'])
+const OceanCheckedList = ref()
+const ETDTime = ref('')
+const ETDSelect = ref('')
+const ETATime = ref('')
+const ETASelect = ref('')
+const ETDRadio = ref()
+const ETARadio = ref()
+const emit = defineEmits(['ChangeCheckRules', 'closeETD'])
+const ETDETAList = ref({
+  ETD: '',
+  ETA: ''
+})
+let ETDstr: any = ''
+let ETAstr: any = ''
+const CheckChange = (val: any) => {
+  if (val.includes('ETD')) {
+    isETD.value = true
+    if (ETDSelect.value != '') {
+      ETDETAList.value.ETD = ETDstr
+    }
+    if (val.includes('ETA')) {
+      isETA.value = true
+      if (ETASelect.value != '') {
+        ETDETAList.value.ETA = ETAstr
+      }
+    } else {
+      isETA.value = false
+      ETDETAList.value.ETA = ''
+    }
+  } else {
+    isETD.value = false
+    ETDETAList.value.ETD = ''
+    if (val.includes('ETA')) {
+      isETA.value = true
+      if (ETASelect.value != '') {
+        ETDETAList.value.ETA = ETAstr
+      }
+    } else {
+      isETA.value = false
+      ETDETAList.value.ETA = ''
+    }
+  }
+  emit('ChangeCheckRules', ETDETAList.value)
+}
+const changeETDRadio = (val: any) => {
+  if (val == 1) {
+    ETDstr = 'ETD: Notify for all changes'
+    ETDETAList.value.ETD = ETDstr
+  } else if (val == 2) {
+    ETDstr = 'ETD: Notify for all changes ≥ ' + clampedValue.value + ' ' + ETDSelect.value
+    if (ETDSelect.value != '') {
+      ETDETAList.value.ETD = ETDstr
+    } else {
+      ETDETAList.value.ETD = ''
+    }
+  }
+  emit('ChangeCheckRules', ETDETAList.value)
+}
+const changeETARadio = (val: any) => {
+  if (val == 1) {
+    ETAstr = 'ETA: Notify for all changes'
+    ETDETAList.value.ETA = ETAstr
+  } else if (val == 2) {
+    ETAstr = 'ETA: Notify for all changes ≥ ' + clampedETAValue.value + ' ' + ETASelect.value
+    if (ETASelect.value != '') {
+      ETDETAList.value.ETA = ETAstr
+    } else {
+      ETDETAList.value.ETA = ''
+    }
+  }
+  emit('ChangeCheckRules', ETDETAList.value)
+}
+const changedeparture = (val: any) => {
+  if (val == 'ETD') {
+    ETDstr = 'ETD: Notify for all changes ≥ ' + clampedValue.value + ' ' + ETDSelect.value
+    if (ETDSelect.value != '') {
+      ETDETAList.value.ETD = ETDstr
+    }
+    if (val == 'ETA') {
+      ETAstr = 'ETA: Notify for all changes ≥ ' + clampedETAValue.value + ' ' + ETASelect.value
+      if (ETASelect.value != '') {
+        ETDETAList.value.ETA = ETAstr
+      }
+    }
+  } else {
+    if (val == 'ETA') {
+      ETAstr = 'ETA: Notify for all changes ≥ ' + clampedETAValue.value + ' ' + ETASelect.value
+      if (ETASelect.value != '') {
+        ETDETAList.value.ETA = ETAstr
+      }
+    }
+  }
+  emit('ChangeCheckRules', ETDETAList.value)
+}
+const closeETD = (val: any) => {
+  if (val.includes('ETD')) {
+    OceanCheckedList.value.splice(OceanCheckedList.value.indexOf('ETD'), 1)
+    ETDETAList.value.ETD = ''
+    isETD.value = false
+    ETDTime.value = ''
+    ETDSelect.value = ''
+    ETDRadio.value = 0
+  }
+  if (val.includes('ETA')) {
+    OceanCheckedList.value.splice(OceanCheckedList.value.indexOf('ETA'), 1)
+    ETDETAList.value.ETA = ''
+    isETA.value = false
+    ETATime.value = ''
+    ETASelect.value = ''
+    ETARadio.value = 0
+  }
+  emit('ChangeCheckRules', ETDETAList.value)
+}
+
+// 清除所有数据
+const ClearData = () => {
+  OceanCheckedList.value = []
+  ETDETAList.value.ETD = ''
+  isETD.value = false
+  ETDETAList.value.ETA = ''
+  isETA.value = false
+  ETDRadio.value = 0
+  ETARadio.value = 0
+  ETDTime.value = ''
+  ETDSelect.value = ''
+  ETATime.value = ''
+  ETASelect.value = ''
+}
+
+defineExpose({
+  closeETD,
+  ClearData
+})
+
+const clampedValue = computed(() => {
+  if (ETDTime.value == '') {
+    return 0
+  } else {
+    const numericValue = ETDTime.value.replace(/[^0-9]/g, 0) // 移除非数字字符
+    return Math.min(Math.max(parseInt(numericValue, 10), 0), 365) // 确保值在0到1000之间,但不更新原输入值仅用于显示
+  }
+})
+const clampedETAValue = computed(() => {
+  if (ETATime.value == '') {
+    return 0
+  } else {
+    const numericValue = ETATime.value.replace(/[^0-9]/g, 0) // 移除非数字字符
+    return Math.min(Math.max(parseInt(numericValue, 10), 0), 365) // 确保值在0到1000之间,但不更新原输入值仅用于显示
+  }
+})
+</script>
+<template>
+  <div class="Ocean_collapse">
+    <el-collapse v-model="OceanActive">
+      <el-collapse-item name="ETDShipments">
+        <template #title>
+          <div class="Rules_Title OceanTitle">{{ props.Title }}</div>
+        </template>
+        <div class="oceanCheckbox">
+          <el-checkbox-group @change="CheckChange" v-model="OceanCheckedList">
+            <el-checkbox class="delayedType" value="ETD">
+              <div>ETD</div>
+              <div v-if="isETD" style="margin-top: 16px">
+                <el-radio-group v-model="ETDRadio" @change="changeETDRadio">
+                  <el-radio value="1">Notify for all changes</el-radio>
+                  <el-radio value="2"
+                    >Notify only when time difference
+                    <span class="delayedIcon">></span>
+                    <el-input
+                      v-model="ETDTime"
+                      :value="clampedValue"
+                      class="input-with-select"
+                      @input="changedeparture('ETD')"
+                    >
+                      <template #append>
+                        <el-select
+                          v-model="ETDSelect"
+                          placeholder="Select"
+                          @change="changedeparture('ETD')"
+                        >
+                          <el-option label="Day(s)" value="Day(s)" />
+                          <el-option label="Hour(s)" value="Hour(s)" />
+                        </el-select>
+                      </template> </el-input
+                  ></el-radio>
+                </el-radio-group>
+              </div>
+            </el-checkbox>
+            <el-checkbox class="delayedType" value="ETA">
+              <div>ETA</div>
+              <div v-if="isETA" style="margin-top: 16px">
+                <el-radio-group v-model="ETARadio" @change="changeETARadio">
+                  <el-radio value="1">Notify for all changes</el-radio>
+                  <el-radio value="2"
+                    >Notify only when time difference
+                    <span class="delayedIcon">></span>
+                    <el-input
+                      v-model="ETATime"
+                      :value="clampedETAValue"
+                      class="input-with-select"
+                      @input="changedeparture('ETA')"
+                    >
+                      <template #append>
+                        <el-select
+                          v-model="ETASelect"
+                          placeholder="Select"
+                          @change="changedeparture('ETA')"
+                        >
+                          <el-option label="Day(s)" value="Day(s)" />
+                          <el-option label="Hour(s)" value="Hour(s)" />
+                        </el-select>
+                      </template> </el-input
+                  ></el-radio>
+                </el-radio-group>
+              </div>
+            </el-checkbox>
+          </el-checkbox-group>
+        </div>
+      </el-collapse-item>
+    </el-collapse>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+:deep(.el-checkbox-group) {
+  border: 1px solid var(--color-select-border);
+  border-radius: 5px;
+}
+:deep(.el-checkbox) {
+  width: 100%;
+  background-color: var(--color-drawer-body-bg);
+  border-bottom: 1px solid var(--color-select-border);
+  padding: 8px;
+}
+:deep(.el-checkbox:first-child) {
+  border-radius: 6px 6px 0 0;
+}
+:deep(.el-checkbox:last-child) {
+  border-radius: 0 0 6px 6px;
+  border-bottom: none;
+}
+:deep(.el-radio) {
+  border: none !important;
+}
+.delayedType {
+  align-items: start;
+  height: fit-content;
+  margin-right: 5px;
+  border-radius: 6px;
+  padding: 8px;
+}
+.input-with-select {
+  width: 180px;
+}
+:deep(.el-input__wrapper) {
+  width: 50%;
+}
+:deep(.el-input-group__append) {
+  width: 50%;
+  padding: 0;
+  border: none;
+}
+:deep(.el-input-group--append .el-input-group__append .el-select .el-select__wrapper) {
+  padding: 5px 10px;
+  background-color: #fff;
+}
+.delayedIcon {
+  margin: 0 8px;
+}
+.oceanCheckbox {
+  margin-bottom: 8px;
+}
+:deep(.el-radio-group) {
+  display: block;
+}
+:deep(.el-radio) {
+  display: flex;
+  min-height: 32px;
+  border: 1px solid var(--color-select-border);
+  margin-bottom: 4px;
+  border-radius: 6px;
+  padding: 0 8px;
+  margin-right: 0;
+  height: fit-content;
+  line-height: 32px;
+  align-items: center;
+}
+:deep(.el-radio__input.is-checked + .el-radio__label) {
+  color: var(--color-neutral-1);
+}
+</style>

+ 398 - 0
src/components/CreateAddRules/src/components/NotiFrequency.vue

@@ -0,0 +1,398 @@
+<script setup lang="ts">
+import { ref, watch } from 'vue'
+import moment from 'moment-timezone'
+import { defaultTimeZone } from '@/utils/timezone'
+
+const props = defineProps({
+  FrequencyData: Object
+})
+
+const frequency_data = ref(props.FrequencyData)
+const radio = ref(0)
+const FrequencyList = ref()
+const DailyTime = ref('')
+const WeeklyTime = ref('')
+const WeeklyDay = ref('')
+const WeekDay = ref([
+  {
+    label: 'Monday',
+    value: 'Monday'
+  },
+  {
+    label: 'Tuesday',
+    value: 'Tuesday'
+  },
+  {
+    label: 'Wednesday',
+    value: 'Wednesday'
+  },
+  {
+    label: 'Thursday',
+    value: 'Thursday'
+  },
+  {
+    label: 'Friday',
+    value: 'Friday'
+  },
+  {
+    label: 'Saturday',
+    value: 'Saturday'
+  },
+  {
+    label: 'Sunday',
+    value: 'Sunday'
+  }
+])
+const TimeZone = ref([
+  {
+    label: 'UTC-08',
+    value: 'UTC-08'
+  },
+  {
+    label: 'UTC-07',
+    value: 'UTC-07'
+  },
+  {
+    label: 'UTC-06',
+    value: 'UTC-06'
+  },
+  {
+    label: 'UTC-05',
+    value: 'UTC-05'
+  },
+  {
+    label: 'UTC-04',
+    value: 'UTC-04'
+  },
+  {
+    label: 'UTC-03',
+    value: 'UTC-03'
+  },
+  {
+    label: 'UTC-02',
+    value: 'UTC-02'
+  },
+  {
+    label: 'UTC-01',
+    value: 'UTC-01'
+  },
+  {
+    label: 'UTC-00',
+    value: 'UTC-00'
+  },
+  {
+    label: 'UTC+01',
+    value: 'UTC+01'
+  },
+  {
+    label: 'UTC+02',
+    value: 'UTC+02'
+  },
+  {
+    label: 'UTC+03',
+    value: 'UTC+03'
+  },
+  {
+    label: 'UTC+04',
+    value: 'UTC+04'
+  },
+  {
+    label: 'UTC+05',
+    value: 'UTC+05'
+  },
+  {
+    label: 'UTC+05:30',
+    value: 'UTC+05:30'
+  },
+  {
+    label: 'UTC+06',
+    value: 'UTC+06'
+  },
+  {
+    label: 'UTC+07',
+    value: 'UTC+07'
+  },
+  {
+    label: 'UTC+08',
+    value: 'UTC+08'
+  },
+  {
+    label: 'UTC+09',
+    value: 'UTC+09'
+  },
+  {
+    label: 'UTC+10',
+    value: 'UTC+10'
+  },
+  {
+    label: 'UTC+11',
+    value: 'UTC+11'
+  },
+  {
+    label: 'UTC+12',
+    value: 'UTC+12'
+  }
+])
+const TimeZoneDailySelect = ref()
+const TimeZoneWeeklySelect = ref()
+TimeZoneDailySelect.value = 'UTC' + moment().tz(moment.tz.guess()).format('Z').slice(0, 3)
+TimeZoneWeeklySelect.value = 'UTC' + moment().tz(moment.tz.guess()).format('Z').slice(0, 3)
+const isDaily = ref(false)
+const isWeekly = ref(false)
+let savesubscribeobj: any = {}
+
+watch(
+  () => props.FrequencyData,
+  (current) => {
+    frequency_data.value = current
+    FrequencyDataInit()
+  }
+)
+
+const emits = defineEmits(['ChangeFrequencyAdd'])
+
+// 初始设置Frequency
+const FrequencyDataInit = () => {
+  if (frequency_data.value?.frequency_type == 'Instant') {
+    radio.value = 1
+    ChangeFrequency(1)
+  } else if (frequency_data.value?.frequency_type == 'Daily') {
+    radio.value = 2
+    DailyTime.value = frequency_data.value?.daily_time
+    TimeZoneDailySelect.value = frequency_data.value?.daily_time_zone
+    ChangeFrequency(2)
+  } else if (frequency_data.value?.frequency_type == 'Weekly') {
+    radio.value = 3
+    WeeklyDay.value = frequency_data.value?.weekly_week
+    WeeklyTime.value = frequency_data.value?.weekly_time
+    TimeZoneWeeklySelect.value = frequency_data.value?.weekly_time_zone
+    ChangeFrequency(3)
+  } else {
+    radio.value = 0
+    ChangeFrequency(0)
+  }
+}
+
+// 更改Frequency时间
+const ChangeFrequency = (val: any) => {
+  FrequencyList.value = []
+  let str: any = ''
+  if (val == 1) {
+    isDaily.value = false
+    isWeekly.value = false
+    str = 'Instant notification for each update'
+    FrequencyList.value.push(str)
+    savesubscribeobj.frequency_type = 'Instant'
+    savesubscribeobj.frequency_display = str
+  } else if (val == 2) {
+    isDaily.value = true
+    isWeekly.value = false
+    str = 'Daily, ' + DailyTime.value + ', ' + TimeZoneDailySelect.value
+    if (DailyTime.value != '' && TimeZoneDailySelect.value !== '') {
+      FrequencyList.value.push(str)
+    }
+    savesubscribeobj.frequency_type = 'Daily'
+    savesubscribeobj.daily_time = DailyTime.value
+    savesubscribeobj.daily_time_zone = TimeZoneDailySelect.value
+    savesubscribeobj.frequency_display = str
+  } else if (val == 3) {
+    isDaily.value = false
+    isWeekly.value = true
+    str = 'Weekly, ' + WeeklyDay.value + ', ' + WeeklyTime.value + ', ' + TimeZoneWeeklySelect.value
+    if (WeeklyDay.value != '' && WeeklyTime.value != '' && TimeZoneWeeklySelect.value !== '') {
+      FrequencyList.value.push(str)
+    }
+    savesubscribeobj.frequency_type = 'Weekly'
+    if (WeeklyDay.value == 'Monday') {
+      savesubscribeobj.weekly_week = 1
+    } else if (WeeklyDay.value == 'Tuesday') {
+      savesubscribeobj.weekly_week = 2
+    } else if (WeeklyDay.value == 'Wednesday') {
+      savesubscribeobj.weekly_week = 3
+    } else if (WeeklyDay.value == 'Thursday') {
+      savesubscribeobj.weekly_week = 4
+    } else if (WeeklyDay.value == 'Friday') {
+      savesubscribeobj.weekly_week = 5
+    } else if (WeeklyDay.value == 'Saturday') {
+      savesubscribeobj.weekly_week = 6
+    } else if (WeeklyDay.value == 'Sunday') {
+      savesubscribeobj.weekly_week = 0
+    }
+    savesubscribeobj.weekly_time = WeeklyTime.value
+    savesubscribeobj.weekly_time_zone = TimeZoneWeeklySelect.value
+    savesubscribeobj.frequency_display = str
+  } else {
+    isDaily.value = false
+    isWeekly.value = false
+    DailyTime.value = ''
+    WeeklyTime.value = ''
+    WeeklyDay.value = ''
+    delete savesubscribeobj.frequency_type
+    delete savesubscribeobj.daily_time
+    delete savesubscribeobj.daily_time_zone
+    delete savesubscribeobj.weekly_week
+    delete savesubscribeobj.weekly_time
+    delete savesubscribeobj.weekly_time_zone
+  }
+  emits('ChangeFrequencyAdd', FrequencyList.value, savesubscribeobj)
+}
+const changeTime = (val: any) => {
+  if (val == 'Daily') {
+    ChangeFrequency(2)
+  } else {
+    ChangeFrequency(3)
+  }
+}
+
+// 删除 Frequency tag
+const handleCloseRadioFrequency = () => {
+  radio.value = 0
+  ChangeFrequency(0)
+}
+
+const user_type = localStorage.getItem('user_type')
+
+defineExpose({
+  handleCloseRadioFrequency,
+  FrequencyDataInit
+})
+</script>
+<template>
+  <div style="margin-top: 11px">
+    <el-radio-group v-model="radio" @change="ChangeFrequency">
+      <el-radio :value="1" v-if="user_type != null && user_type != 'customer'"
+        >Instant notification for each update</el-radio
+      >
+      <el-radio :value="2">
+        <div>Daily Summary</div>
+        <div class="Daily" v-if="isDaily">
+          <div class="Daily_left" style="margin-right: 8px">
+            Select Time
+            <div>
+              <el-time-select
+                v-model="DailyTime"
+                start="00:00"
+                step="00:30"
+                end="23:30"
+                prefix-icon=""
+                @change="changeTime('Daily')"
+                placeholder="Select Time"
+              ></el-time-select>
+            </div>
+          </div>
+          <div class="Daily_left">
+            Select Time Zone
+            <div>
+              <el-select
+                v-model="TimeZoneDailySelect"
+                placeholder="Select Time Zone"
+                @change="changeTime('Daily')"
+              >
+                <el-option
+                  v-for="item in TimeZone"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                />
+              </el-select>
+            </div>
+          </div>
+        </div>
+      </el-radio>
+      <el-radio :value="3">
+        <div>Weekly Summary</div>
+        <div class="Daily" v-if="isWeekly">
+          <div class="Weekly_left">
+            Select Day
+            <div>
+              <el-select
+                v-model="WeeklyDay"
+                @change="changeTime('Weekly')"
+                placeholder="Select Day"
+              >
+                <el-option
+                  v-for="item in WeekDay"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                />
+              </el-select>
+            </div>
+          </div>
+          <div class="Weekly_left" style="margin: 0 8px">
+            Select Time
+            <div>
+              <el-time-select
+                v-model="WeeklyTime"
+                @change="changeTime('Weekly')"
+                start="00:00"
+                step="00:30"
+                end="23:30"
+                prefix-icon=""
+                placeholder="Select time"
+              ></el-time-select>
+            </div>
+          </div>
+          <div class="Weekly_left">
+            Select Time Zone
+            <div>
+              <el-select
+                v-model="TimeZoneWeeklySelect"
+                placeholder="Select Time Zone"
+                @change="changeTime('Weekly')"
+              >
+                <el-option
+                  v-for="item in TimeZone"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                />
+              </el-select>
+            </div>
+          </div>
+        </div>
+      </el-radio>
+    </el-radio-group>
+  </div>
+</template>
+<style lang="scss" scoped>
+:deep(.el-radio-group) {
+  display: block;
+}
+:deep(.el-radio) {
+  display: flex;
+  min-height: 32px;
+  border: 1px solid var(--color-select-border);
+  margin-bottom: 4px;
+  border-radius: 6px;
+  padding: 0 8px;
+  margin-right: 0;
+  height: fit-content;
+  line-height: 32px;
+  align-items: start;
+}
+:deep(.el-radio__input.is-checked + .el-radio__label) {
+  color: var(--color-neutral-1);
+}
+.Daily {
+  margin: 0 0 9px 0;
+  display: flex;
+}
+.Daily_left {
+  color: var(--color-neutral-2);
+  width: 50%;
+}
+.Weekly_left {
+  color: var(--color-neutral-2);
+  width: 33%;
+}
+:deep(.el-select__icon.el-icon svg) {
+  width: 1em !important;
+}
+:deep(.el-select__wrapper.is-filterable) {
+  padding-left: 7px;
+}
+:deep(.el-radio__inner) {
+  margin-top: 7px;
+}
+</style>

+ 92 - 0
src/components/CreateAddRules/src/components/NotiMethods.vue

@@ -0,0 +1,92 @@
+<script setup lang="ts">
+import { ref, watch } from 'vue'
+
+const checkMethodList = ref()
+checkMethodList.value = []
+let savesubscribeobj: any = {}
+const props = defineProps({
+  MethodsData: Object
+})
+
+const methods_data = ref(props.MethodsData)
+watch(
+  () => props.MethodsData,
+  (current) => {
+    methods_data.value = current
+    MethodsInit()
+  }
+)
+const emits = defineEmits(['ChangeMethodsAdd'])
+// 初始设置Methods
+const MethodsInit = () => {
+  if (methods_data.value?.method_display != undefined) {
+    if (methods_data.value?.method_display.indexOf('Email') != -1) {
+      checkMethodList.value.push('By Email')
+    }
+  }
+  if (methods_data.value?.method_display != undefined) {
+    if (methods_data.value?.method_display.indexOf('System Message') != -1) {
+      checkMethodList.value.push('By System Message')
+    }
+  }
+  changeMethod(checkMethodList.value)
+}
+
+// 选中Method
+const changeMethod = (val: any) => {
+  if (val.indexOf('By Email') != -1) {
+    savesubscribeobj.method_by_email = true
+  } else {
+    savesubscribeobj.method_by_email = false
+  }
+  if (val.indexOf('By System Message ') != -1) {
+    savesubscribeobj.method_by_message = true
+  } else {
+    savesubscribeobj.method_by_message = false
+  }
+  if (val.length != 0) {
+    savesubscribeobj.method_display = val.map((e: any) => e.replace('By ', '')).join(',')
+  } else {
+    savesubscribeobj.method_display = ''
+  }
+  emits('ChangeMethodsAdd', checkMethodList.value, savesubscribeobj)
+}
+const user_type = localStorage.getItem('user_type')
+</script>
+<template>
+  <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'"
+        >
+          <div>By Email</div>
+          <div class="methos_image"><img src="../images/illustration_email@2x.png" /></div>
+        </el-checkbox>
+        <el-checkbox class="methodcheckbox" value="By System Message">
+          <div>By System Message</div>
+          <div class="methos_image">
+            <img src="../images/illustration_system massage@2x.png" />
+          </div>
+        </el-checkbox>
+      </el-checkbox-group>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.methodcheckbox {
+  align-items: start;
+  height: fit-content;
+  width: 49%;
+  margin-right: 5px;
+  background-color: var(--color-dialog-header-bg);
+  border-radius: 6px;
+  padding: 11px 0 0 13px;
+}
+.methos_image {
+  margin: 9px 0;
+}
+</style>

+ 83 - 0
src/components/CreateAddRules/src/components/RulesShipments.vue

@@ -0,0 +1,83 @@
+<script lang="ts" setup>
+import { ref, watch } from 'vue'
+
+interface OceanCheckboxItem {
+  value: string
+  label: string
+}
+interface Props {
+  CheckboxList: OceanCheckboxItem[]
+  Title: String
+  CheckedList: Array<''>
+}
+const props = defineProps<Props>()
+
+const OceanActive = ref(['OceanShipments'])
+const CheckedList = ref(props.CheckedList)
+const CheckboxList = ref(props.CheckboxList)
+watch(
+  () => props.CheckboxList,
+  (current) => {
+    CheckboxList.value = current
+  }
+)
+watch(
+  () => props.CheckedList,
+  (current) => {
+    CheckedList.value = current
+  }
+)
+
+const emit = defineEmits(['ChangeCheckRules'])
+const CheckChange = () => {
+  console.log(CheckedList.value)
+  emit('ChangeCheckRules', CheckedList.value)
+}
+</script>
+<template>
+  <div class="Ocean_collapse">
+    <el-collapse v-model="OceanActive">
+      <el-collapse-item name="OceanShipments">
+        <template #title>
+          <div class="Rules_Title OceanTitle">{{ props.Title }}</div>
+        </template>
+        <div class="oceanCheckbox">
+          <el-checkbox-group @change="CheckChange" v-model="CheckedList">
+            <el-checkbox
+              v-for="item in CheckboxList"
+              :key="item.label"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-checkbox-group>
+        </div>
+      </el-collapse-item>
+    </el-collapse>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+:deep(.el-checkbox-group) {
+  border: 1px solid var(--color-select-border);
+  border-radius: 5px;
+}
+:deep(.el-checkbox) {
+  width: 100%;
+  background-color: var(--color-drawer-body-bg);
+  border-bottom: 1px solid var(--color-select-border);
+  padding: 8px;
+}
+:deep(.el-checkbox:first-child) {
+  border-radius: 6px 6px 0 0;
+}
+:deep(.el-checkbox:last-child) {
+  border-radius: 0 0 6px 6px;
+  border-bottom: none;
+}
+.oceanCheckbox {
+  max-height: 321px;
+  overflow-x: hidden;
+  margin-bottom: 8px;
+  overflow-y: scroll;
+}
+</style>

+ 197 - 0
src/components/CreateAddRules/src/components/ShipmentRange.vue

@@ -0,0 +1,197 @@
+<script lang="ts" setup>
+import { ref, computed } from 'vue'
+
+const OceanActive = ref(['TransportMode', 'Time'])
+const TransportCheckedList = ref([])
+interface OceanItem {
+  label: string
+  value: string
+}
+const TransportList = ref<OceanItem[]>([])
+TransportList.value = [
+  {
+    label: 'Ocean',
+    value: 'Ocean'
+  },
+  {
+    label: 'Air',
+    value: 'Air'
+  },
+  {
+    label: 'Road',
+    value: 'Road'
+  }
+]
+
+const TimeChecked = ref()
+
+const ETDTime = ref('')
+const ETATime = ref('')
+
+const clampedETDValue = computed(() => {
+  if (ETDTime.value == '') {
+    return 0
+  } else {
+    const numericValue = ETDTime.value.replace(/[^0-9]/g, 0) // 移除非数字字符
+    return Math.min(Math.max(parseInt(numericValue, 10), 0), 365) // 确保值在0到1000之间,但不更新原输入值仅用于显示
+  }
+})
+const clampedETAValue = computed(() => {
+  if (ETATime.value == '') {
+    return 0
+  } else {
+    const numericValue = ETATime.value.replace(/[^0-9]/g, 0) // 移除非数字字符
+    return Math.min(Math.max(parseInt(numericValue, 10), 0), 365) // 确保值在0到1000之间,但不更新原输入值仅用于显示
+  }
+})
+
+let Transportstr: any = ''
+let Timestr: any = ''
+const emit = defineEmits(['ChangeCheckRules', 'ChangeCheckTimeRules'])
+const CheckChange = (val: any) => {
+  if (val != '') {
+    Transportstr = 'Transport Mode: ' + val
+  } else {
+    Transportstr = ''
+  }
+  emit('ChangeCheckRules', Transportstr, TransportCheckedList.value)
+}
+
+// 输入ETD、ETA
+const changeTime = (val: any) => {
+  if (val == 1) {
+    Timestr = 'ETD within ' + clampedETDValue.value + ' Day(s)'
+  } else if (val == 2) {
+    Timestr = 'ETA within ' + clampedETAValue.value + ' Day(s)'
+  } else {
+    Timestr = ''
+  }
+  emit('ChangeCheckTimeRules', Timestr, clampedETDValue.value)
+}
+
+const handleCloseCreateRule = (val: any) => {
+  if (val.indexOf('ETD') != -1 || val.indexOf('ETA') != -1) {
+    TimeChecked.value = 0
+    ETDTime.value = ''
+    ETATime.value = ''
+  } else if (val.indexOf('Transport') != -1) {
+    TransportCheckedList.value = []
+  }
+}
+
+defineExpose({
+  handleCloseCreateRule
+})
+</script>
+<template>
+  <div class="Ocean_collapse">
+    <el-collapse v-model="OceanActive">
+      <el-collapse-item name="TransportMode">
+        <template #title>
+          <div class="Rules_Title OceanTitle">Transport Mode</div>
+        </template>
+        <div class="oceanCheckbox">
+          <el-checkbox-group @change="CheckChange" v-model="TransportCheckedList">
+            <el-checkbox
+              v-for="item in TransportList"
+              :key="item.label"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-checkbox-group>
+        </div>
+      </el-collapse-item>
+      <el-collapse-item name="Time">
+        <template #title>
+          <div class="Rules_Title OceanTitle">Time</div>
+        </template>
+        <div class="oceanCheckbox">
+          <el-radio-group v-model="TimeChecked" @change="changeTime">
+            <el-radio value="1">
+              <div class="flex">
+                <div style="width: 70px">ETD within</div>
+                <el-input
+                  @input="changeTime('1')"
+                  v-model="ETDTime"
+                  :value="clampedETDValue"
+                  class="input-with-select"
+                >
+                </el-input>
+                <div class="Days">Day(s)</div>
+              </div>
+            </el-radio>
+            <el-radio value="2">
+              <div class="flex">
+                <div style="width: 70px">ETA within</div>
+                <el-input
+                  @input="changeTime('2')"
+                  v-model="ETATime"
+                  :value="clampedETAValue"
+                  class="input-with-select"
+                >
+                </el-input>
+                <div class="Days">Day(s)</div>
+              </div>
+            </el-radio>
+          </el-radio-group>
+        </div>
+      </el-collapse-item>
+    </el-collapse>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+:deep(.el-checkbox-group) {
+  border: 1px solid var(--color-select-border);
+  border-radius: 5px;
+}
+:deep(.el-checkbox) {
+  width: 100%;
+  background-color: var(--color-drawer-body-bg);
+  border-bottom: 1px solid var(--color-select-border);
+  padding: 8px;
+}
+:deep(.el-checkbox:first-child) {
+  border-radius: 6px 6px 0 0;
+}
+:deep(.el-checkbox:last-child) {
+  border-radius: 0 0 6px 6px;
+  border-bottom: none;
+}
+.oceanCheckbox {
+  max-height: 321px;
+  overflow-x: hidden;
+  margin-bottom: 8px;
+  overflow-y: scroll;
+}
+
+.input-with-select {
+  width: 96px;
+  border-radius: 6px 0 0 6px;
+  margin-left: 8px;
+}
+:deep(.el-input__wrapper) {
+  border-radius: 6px 0 0 6px;
+  opacity: 0.8;
+  height: 28px;
+}
+.flex {
+  display: flex;
+  align-items: center;
+}
+.Days {
+  width: 64px;
+  border: 1px solid var(--color-select-border);
+  border-radius: 0 6px 6px 0;
+  background-color: var(--color-drawer-body-bg);
+  border-left: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  opacity: 0.8;
+  height: 28px;
+}
+:deep(.el-radio) {
+  background-color: var(--color-drawer-body-bg);
+}
+</style>

BIN
src/components/CreateAddRules/src/images/icon_collapse.png


BIN
src/components/CreateAddRules/src/images/icon_expand.png


BIN
src/components/CreateAddRules/src/images/illustration_email@2x.png


BIN
src/components/CreateAddRules/src/images/illustration_system massage@2x.png


BIN
src/components/CreateAddRules/src/images/submit_successful.png


+ 1 - 0
src/views/Layout/src/components/Header/components/LogoutDialog.vue

@@ -12,6 +12,7 @@ const handleLogout = () => {
   dialogVisible.value = false
   router.push('/login')
   sessionStorage.clear()
+  localStorage.removeItem('user_type')
 }
 defineExpose({
   openDialog

+ 1 - 0
src/views/Login/src/loginView.vue

@@ -243,6 +243,7 @@ const handleLoginAfterVerify = () => {
       if (res.code === 200) {
         if (isRememerPwd.value) {
           saveCredentials()
+          localStorage.setItem('user_type', res.data.user_info.user_type)
         } else {
           clearCredentials()
         }

+ 37 - 2
src/views/SystemSettings/src/SystemSettings.vue

@@ -2,6 +2,9 @@
 import { ref, onMounted } from 'vue'
 import AddRSettingTableules from './components/SettingTable'
 import MonitoringTable from './components/MonitoringTable'
+import { useRouter } from 'vue-router'
+
+const router = useRouter()
 
 const TabActive = ref('Subscribe Notifications')
 const isMilestoneChecked = ref(false)
@@ -184,6 +187,20 @@ const deleteAddedRules = (val: any) => {
   }
 }
 
+// 跳转Create New Rule页面
+const ToCreateRule = () => {
+  router.push({
+    path: '/SystemSettings/createnewrule',
+    query: {}
+  })
+  sessionStorage.setItem('activeTab', 'Monitoring Settings')
+}
+
+const tabledatalength = ref()
+const gettabledatalength = (val: any) => {
+  tabledatalength.value = val
+}
+
 onMounted(() => {
   getsubscribe()
   if (sessionStorage.getItem('activeTab') != null) {
@@ -296,8 +313,17 @@ onMounted(() => {
       ></AddRSettingTableules>
     </el-tab-pane>
     <el-tab-pane label="Monitoring Settings" name="Monitoring Settings">
-      <div class="subscribedTitle">Added Rules</div>
-      <MonitoringTable></MonitoringTable>
+      <div class="monitoring_flex">
+        <div class="subscribedTitle">Added Rules</div>
+        <el-button
+          class="el-button--main"
+          style="height: 40px"
+          v-if="tabledatalength != 0 && tabledatalength != null"
+          @click="ToCreateRule"
+          >+ Add Rule</el-button
+        >
+      </div>
+      <MonitoringTable @gettabledatalength="gettabledatalength"></MonitoringTable>
     </el-tab-pane>
   </el-tabs>
 </template>
@@ -420,4 +446,13 @@ onMounted(() => {
 :deep(.el-icon svg) {
   width: 0;
 }
+.monitoring_flex {
+  display: flex;
+  justify-content: space-between;
+  padding-right: 24px;
+  align-items: end;
+}
+.el-button--main {
+  margin-bottom: 4px;
+}
 </style>

+ 123 - 11
src/views/SystemSettings/src/components/CreateNewrule/src/CreateNewrule.vue

@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import { ref } from 'vue'
+import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 
 const router = useRouter()
@@ -8,32 +8,60 @@ const notificationvalue = ref()
 const notificationoptions = ref([
   {
     label: 'Milestone Update',
-    value: 'Milestone Update'
+    value: 'Milestone'
   },
   {
     label: 'Container Status Update',
-    value: 'Container Status Update'
+    value: 'Container'
   },
   {
     label: 'Departure/Arrival Delay',
-    value: 'Departure/Arrival Delay'
+    value: 'Departure'
   },
   {
     label: 'ETD/ETA Change',
-    value: 'ETD/ETA Change'
+    value: 'ETDChange'
   }
 ])
-
-// 退回上一页
-const CancelCreate = () => {
-  router.back()
+const CancelRulesVisible = ref()
+const ChangeRulesVisible = ref()
+// 保存
+const CreateAddRulesRef = ref()
+const saveMonitoring = () => {
+  CreateAddRulesRef.value.Savesubscribe()
+}
+let select: any = ''
+const changenotification = (val: any) => {
+  select = val
+  if (notificationvalue.value != undefined) {
+    ChangeRulesVisible.value = true
+  }
 }
+const ChangeRulesVisibleOK = () => {
+  ChangeRulesVisible.value = false
+  notificationvalue.value = select
+  CreateAddRulesRef.value.clearData(select)
+}
+const systemList = ref()
+onMounted(() => {
+  console.log(sessionStorage.getItem('CreateAddRulesSystemlist'))
+  if (sessionStorage.getItem('CreateAddRulesSystemlist') == null) {
+    systemList.value = {}
+  } else {
+    systemList.value =
+      JSON.parse(sessionStorage.getItem('CreateAddRulesSystemlist') as string) || {}
+    setTimeout(() => {
+      sessionStorage.removeItem('CreateAddRulesSystemlist')
+    }, 3000)
+  }
+  console.log(systemList.value)
+})
 </script>
 <template>
   <div class="Title">
     <div>Create New Rule</div>
     <div>
-      <el-button class="create_button" type="default" @click="CancelCreate">
+      <el-button class="create_button" type="default" @click="CancelRulesVisible = true">
         <span class="iconfont_icon">
           <svg class="iconfont" aria-hidden="true">
             <use xlink:href="#icon-icon_return_b"></use>
@@ -41,9 +69,64 @@ const CancelCreate = () => {
         </span>
         Cancel
       </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>
+      <!-- 切换select -->
+      <el-dialog v-model="ChangeRulesVisible" 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="ChangeRulesVisible = false" style="width: 100px"
+              >Cancel</el-button
+            >
+            <el-button
+              class="el-button--warning"
+              @click="ChangeRulesVisibleOK"
+              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-button
         :disabled="notificationvalue == '' || notificationvalue == undefined"
         class="el-button--main create_button"
+        @click="saveMonitoring"
       >
         <span class="iconfont_icon">
           <svg class="iconfont" aria-hidden="true">
@@ -64,6 +147,7 @@ const CancelCreate = () => {
             :key="item.value"
             :label="item.label"
             :value="item.value"
+            @mousedown="changenotification(item.value)"
           />
         </el-select>
       </div>
@@ -76,7 +160,12 @@ const CancelCreate = () => {
         EmptyTitle="Please select Notification Events first"
       ></TableEmpty>
       <div v-else>
-        <AddRules TitleType="CreateRule"></AddRules>
+        {{ systemList }}
+        <CreateAddRules
+          :SystemList="systemList"
+          ref="CreateAddRulesRef"
+          :TitleType="notificationvalue"
+        ></CreateAddRules>
       </div>
     </div>
   </div>
@@ -160,4 +249,27 @@ const CancelCreate = () => {
   align-items: center;
   background-color: transparent;
 }
+.cancel_header {
+  font-size: 18px;
+  font-weight: 700;
+  color: var(--color-neutral-1);
+  display: flex;
+  align-items: center;
+}
+.icon_warning {
+  width: 22px;
+  height: 22px;
+  margin-right: 0;
+  fill: var(--color-btn-warning-bg);
+}
+.iconfont_warning {
+  display: flex;
+  align-items: center;
+}
+:deep(header.el-dialog__header) {
+  background-color: #fff;
+}
+:deep(footer.el-dialog__footer) {
+  border-top: none;
+}
 </style>

+ 93 - 35
src/views/SystemSettings/src/components/MonitoringTable/src/MonitoringTable.vue

@@ -7,53 +7,46 @@ import { useRouter } from 'vue-router'
 
 const router = useRouter()
 
+const emits = defineEmits(['gettabledatalength'])
+
 const columnstest = ref([
   {
-    field: 'Event',
+    field: '_rules_type_display',
     title: 'Event',
     type: 'normal',
     formatter: ''
   },
   {
-    field: 'Shipment Range',
+    field: 'shipment_details',
     title: 'Shipment Range',
     type: 'normal',
     formatter: ''
   },
   {
-    field: 'Event Details',
+    field: 'event_details',
     title: 'Event Details',
     type: 'normal',
     formatter: ''
   },
   {
-    field: 'Frequency',
+    field: 'frequency_display',
     title: 'Frequency',
     type: 'normal',
     formatter: ''
   },
   {
-    field: 'Methods',
+    field: 'method_display',
     title: 'Methods',
     type: 'normal',
     formatter: ''
   }
 ])
-const datatest = ref([
-  // {
-  //   Event: '123',
-  //   ['Shipment Range']: '123',
-  //   ['Event Details']: '123',
-  //   Frequency: '123',
-  //   Methods: '123'
-  // }
-])
-const visible = ref(false)
+const datatest = ref([])
 const tableData = ref<VxeGridProps<any>>({
   border: true,
   round: true,
-  minHeight: 726,
-  maxHeight: 726,
+  minHeight: 700,
+  maxHeight: 700,
   columns: [],
   data: [],
   scrollY: { enabled: true, oSize: 20, gt: 30 },
@@ -69,6 +62,7 @@ const tableData = ref<VxeGridProps<any>>({
 })
 
 const tableRef = ref<VxeGridInstance | null>(null)
+const pageInfo = ref({ pageNo: 1, pageSize: 15, total: 0 })
 
 const handleColumns = (columns: any) => {
   const newColumns = columns.map((item: any) => {
@@ -91,30 +85,29 @@ const handleColumns = (columns: any) => {
 // 获取表格列
 const getTableColumns = async () => {
   tableData.value.columns = handleColumns(columnstest.value)
-  // await $api.getBookingTableColumns().then((res: any) => {
-  //   if (res.code === 200) {
-  //     tableData.value.columns = [
-  //       ...handleColumns(res.data.BookingTableColumns)
-  //     ]
-  tableData.value.columns.push({
+  tableData.value.columns?.push({
     title: 'Operation',
     fixed: 'right',
     width: 100,
     slots: { default: 'action' }
   })
-  //   }
-  // })
 }
 // 获取表格数据
 const getTableData = async () => {
   // 保存页长以及当前页码
   tableData.value.data = datatest.value
   $api
-    .MonitoringInit({})
+    .MonitoringTable({
+      cp: pageInfo.value.pageNo,
+      ps: pageInfo.value.pageSize
+    })
     .then((res: any) => {
       if (res.code === 200) {
-        // tableData.value.data = res.data
-        console.log(res.data)
+        pageInfo.value.total = Number(res.data.rc)
+        pageInfo.value.pageNo = res.data.cp
+        pageInfo.value.pageSize = res.data.ps
+        tableData.value.data = res.data.monitoringRules
+        emits('gettabledatalength', res.data.monitoringRules.length)
       }
     })
     .finally(() => {})
@@ -125,7 +118,7 @@ useRowClickStyle(tableRef)
 
 // 点击删除
 const handleDelete = (row: any) => {
-  row.visible.value = true
+  row.visible = true
 }
 
 // 跳转Create New Rule页面
@@ -137,6 +130,40 @@ const ToCreateRule = () => {
   sessionStorage.setItem('activeTab', 'Monitoring Settings')
 }
 
+// 删除表格数据
+const deleteMoniTable = (row: any) => {
+  row.visible = false
+  $api
+    .deleteMonitoringTable({
+      id: row.id
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        tableData.value.data = tableData.value.data?.filter((item) => item.id !== row.id)
+        emits('gettabledatalength', tableData.value.data?.length)
+      }
+    })
+}
+
+// 编辑表格数据
+const handleedit = (row: any) => {
+  $api
+    .EditMonitoringTable({
+      id: row.id,
+      rules_type: row.rules_type
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        router.push({
+          path: '/SystemSettings/createnewrule',
+          query: {}
+        })
+        sessionStorage.setItem('activeTab', 'Monitoring Settings')
+        sessionStorage.setItem('CreateAddRulesSystemlist', JSON.stringify(res.data[row.rules_type]))
+      }
+    })
+}
+
 onMounted(() => {
   getTableColumns()
   getTableData()
@@ -145,7 +172,7 @@ onMounted(() => {
 
 <template>
   <div class="SettingTable">
-    <vxe-grid class="radius-bottom" ref="tableRef" :style="{ border: 'none' }" v-bind="tableData">
+    <vxe-grid ref="tableRef" :style="{ border: 'none' }" v-bind="tableData">
       <!-- 空数据时的插槽 -->
       <template #empty v-if="tableData.data.length === 0">
         <TableEmpty EmptyTitle="Customize your shipment tracking preferences.">
@@ -155,17 +182,22 @@ onMounted(() => {
         </TableEmpty>
       </template>
       <template #action="{ row }">
-        <el-popover :visible="visible" placement="left" :width="480">
+        <el-button class="el-button--blue" style="height: 24px" @click="handleedit(row)">
+          <span class="font_family icon-icon_edit_b"></span>
+        </el-button>
+        <el-popover trigger="click" :visible="row.visible" placement="left" :width="480">
           <div class="delete_title">
             <span class="font_family icon_alert icon-icon_tipsfilled_b"></span>
             Delete Rules
           </div>
           <p class="delete_content">Are you sure to delete this notification event?</p>
           <div style="text-align: right; margin: 0; padding: 8px">
-            <el-button style="width: 100px" tupe="default" @click="visible = false"
+            <el-button style="width: 100px" class="el-button--default" @click="row.visible = false"
               >cancel</el-button
             >
-            <el-button style="width: 100px" type="warning" @click="visible = false"> OK </el-button>
+            <el-button style="width: 100px" type="warning" @click="deleteMoniTable(row)">
+              OK
+            </el-button>
           </div>
           <template #reference>
             <el-button @click="handleDelete(row)" class="el-button--blue" style="height: 24px">
@@ -176,13 +208,26 @@ onMounted(() => {
       </template>
     </vxe-grid>
   </div>
+  <div class="pagination">
+    <span>Total {{ pageInfo.total }}</span>
+    <el-pagination
+      v-model:current-page="pageInfo.pageNo"
+      v-model:page-size="pageInfo.pageSize"
+      layout="prev, pager, next"
+      :total="pageInfo.total"
+      :pager-count="5"
+      @size-change="getTableData"
+      @current-change="getTableData"
+      background
+    />
+  </div>
 </template>
 
 <style lang="scss" scoped>
 .SettingTable {
-  padding: 0 24px 20px 24px;
+  padding: 0 24px 0 24px;
 }
-.font_family::before {
+.icon-icon_delete_b::before {
   color: var(--color-btn-danger-bg);
 }
 .icon_alert::before {
@@ -200,4 +245,17 @@ onMounted(() => {
   color: var(--color-neutral-1);
   padding: 15px 0 33px 37px;
 }
+.pagination {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  border: 1px solid var(--color-border);
+  border-top: none;
+  margin: 0 24px 0 24px;
+  padding: 4px 8px;
+  border-radius: 0 0 6px 6px;
+}
+:deep(.el-icon svg) {
+  width: 1em !important;
+}
 </style>