Ver Fonte

feat: 实现根据用户地区默认日期和数字格式化功能

zhouyuhao há 9 meses atrás
pai
commit
896784f655

+ 69 - 13
src/components/NotificationMessageCard/src/components/EventCard.vue

@@ -20,8 +20,8 @@ interface EventCardPropsData {
     delayTime: string
   }
   changeInfo?: {
-    eTDChangeNum?: number
-    eTAChangeNum?: number
+    etdChangeNum?: number
+    etaChangeNum?: number
     changeTime: string
   }
   changeTime?: string
@@ -33,9 +33,12 @@ const props = defineProps<{
   data: EventCardPropsData
 }>()
 
-const handleSeeAll = () => {
+const handleSeeAll = (data: any) => {
   router.push({
-    name: 'System Message Detail'
+    name: 'System Message Detail',
+    params: {
+      data: JSON.stringify(data) // 将数据转换为字符串并作为查询参数传递
+    }
   })
 }
 </script>
@@ -47,21 +50,74 @@ const handleSeeAll = () => {
       <div class="title">{{ data.title }}</div>
     </div>
     <div class="content">
-      <div class="more-tips" v-if="data.isMultiple">
+      <div
+        class="more-tips"
+        v-if="(data.type === 'milestone' || 'container') && data.numericRecords"
+      >
         <span>Latest Status Updates ({{ data.numericRecords }})</span>
-        <el-button @click="handleSeeAll" class="see-all-icon el-button--text">
+        <el-button @click="handleSeeAll(data)" class="see-all-icon el-button--text">
+          See All
+          <span class="font_family icon-icon_next_b"></span>
+        </el-button>
+      </div>
+      <div
+        class="more-tips"
+        v-if="
+          data.type === 'delay' &&
+          (data.delayInfo.departureDelayNum || data.delayInfo.arrivalDelayNum)
+        "
+      >
+        <div>
+          <span v-if="data.delayInfo.departureDelayNum"
+            >Departure Delay ({{ data.delayInfo.departureDelayNum }})</span
+          >
+          <span v-if="data.delayInfo.departureDelayNum && data.delayInfo.arrivalDelayNum">
+            &nbsp;&nbsp;|&nbsp;&nbsp;</span
+          >
+          <span v-if="data.delayInfo.arrivalDelayNum">
+            Arrival Delay ({{ data.delayInfo.arrivalDelayNum }})
+          </span>
+        </div>
+        <el-button @click="handleSeeAll(data)" class="see-all-icon el-button--text">
           See All
           <span class="font_family icon-icon_next_b"></span>
         </el-button>
       </div>
+
+      <div
+        class="more-tips"
+        v-if="
+          data.type === 'change' && (data.changeInfo.etdChangeNum || data.changeInfo.etaChangeNum)
+        "
+      >
+        <div>
+          <span v-if="data.changeInfo.etdChangeNum"
+            >ETD Change ({{ data.changeInfo.etdChangeNum }})</span
+          >
+          <span v-if="data.changeInfo.etdChangeNum && data.changeInfo.etaChangeNum">
+            &nbsp;&nbsp;|&nbsp;&nbsp;</span
+          >
+          <span v-if="data.changeInfo.etaChangeNum">
+            ETA Change ({{ data.changeInfo.etaChangeNum }})
+          </span>
+        </div>
+        <el-button @click="handleSeeAll(data)" class="see-all-icon el-button--text">
+          See All
+          <span class="font_family icon-icon_next_b"></span>
+        </el-button>
+      </div>
+
       <div class="base-info">
-        <span
-          v-if="data.type !== 'container'"
-          class="font_family"
-          :class="[`icon-${transportationMode?.[data.mode]}`]"
-        ></span>
-        <span v-else class="font_family icon-icon_container__filled_b"></span>
-        <span class="no">{{ data.no }}</span>
+        <!-- 除了container类型,其他类型都显示运输方式图标 -->
+        <div style="display: inline-block" v-if="data.type !== 'container'">
+          <span class="font_family" :class="[`icon-${transportationMode?.[data.mode]}`]"></span>
+          <span class="no">HBOL: {{ data.no }}</span>
+        </div>
+        <!-- container类型显示图标 -->
+        <div v-else>
+          <span class="font_family icon-icon_container__filled_b"></span>
+          <span class="no">Container: {{ data.no }}</span>
+        </div>
         <div class="tag" :class="{ delay: data.type === 'delay', change: data.type === 'change' }">
           <span class="dot"></span>
           <span class="text">{{ data.tag }}</span>

+ 55 - 0
src/utils/tools.ts

@@ -59,3 +59,58 @@ export const formatTimezoneByUser = (time: string, timezone?: string) => {
     return formattedTime
   }
 }
+
+/**
+ * 判断是否是欧洲地区
+ */
+export const isEuropean = () => {
+  const userLanguage = navigator.language || 'en-US'
+  const europeanLocales = ['de', 'fr', 'it', 'es', 'nl', 'pl'] // 例:德语、法语、西班牙语等
+  return europeanLocales.some((locale) => userLanguage.startsWith(locale))
+}
+
+/**
+ * 根据传入的地区 格式化数字
+ * @param number - 需要格式化的数字
+ * @param isEuropean - 是否为欧洲地区
+ */
+export const formatNumber = (number: number, isEuropean: boolean): string => {
+  const userLanguage = isEuropean ? 'de-DE' : 'zh-CN'
+
+  // 设置数字格式化的选项
+  const options: Intl.NumberFormatOptions = {
+    style: 'decimal'
+    // minimumFractionDigits: 2,
+    // maximumFractionDigits: 2
+  }
+
+  // 其他地区使用默认格式
+  return new Intl.NumberFormat(userLanguage, options).format(number)
+}
+
+/**
+ * 根据用户地区判断日期格式
+ * @returns {string} - 返回日期格式
+ */
+export const getDateFormat = () => {
+  const userLanguage = navigator.language || 'en-US' // 获取浏览器的语言设置
+  // 判断用户地区
+  if (userLanguage === 'en-US') {
+    return 'MM/DD/YYYY' // 美国使用 MM/DD/YYYY 格式
+  } else if (
+    userLanguage.startsWith('de') ||
+    userLanguage.startsWith('fr') ||
+    userLanguage.startsWith('it') ||
+    userLanguage.startsWith('es') ||
+    userLanguage.startsWith('pl') ||
+    userLanguage.startsWith('nl') ||
+    userLanguage.startsWith('pt') ||
+    userLanguage.startsWith('se')
+  ) {
+    return 'DD/MM/YYYY' // 其他欧洲国家(例:德语、法语、西班牙语等)使用 DD/MM/YYYY 格式
+  } else if (['zh-CN', 'ja-JP', 'ko-KR'].includes(userLanguage)) {
+    return 'YYYY-MM-DD' // 东亚国家(如简体中文、日语、韩语)使用 YYYY-MM-DD 格式
+  } else {
+    return 'DD/MM/YYYY' // 其他地区默认 DD/MM/YYYY 格式
+  }
+}

+ 13 - 6
src/views/SystemMessage/src/SystemMessage.vue

@@ -28,7 +28,7 @@ const setActiveItem = (item: string) => {
   activeItem.value = item
 }
 
-const activeName = ref('second')
+const activeName = ref('first')
 
 const handleClick = () => {}
 
@@ -40,7 +40,7 @@ const notificationList = [
     isRead: true,
     title: 'Milestone Update',
     mode: 'Ocean Freight',
-    no: 'HBOL: SHJN2301234',
+    no: 'SHJN2301234',
     tag: 'Booking Confirmed',
     location: 'Hong Kong',
     time: 'Jan 10, 2025 14:30 UTC+8'
@@ -49,7 +49,7 @@ const notificationList = [
     type: 'container',
     isRead: false,
     mode: '',
-    no: 'HBOL: SHJN2301234',
+    no: 'SHJN2301234',
     tag: 'Unloaded From Vessel',
     location: 'Hong Kong',
     time: 'Jan 10, 2025 14:30 UTC+8',
@@ -61,12 +61,14 @@ const notificationList = [
     isRead: false,
     title: 'Delay Daily Summary (Jan 10, 2025)',
     mode: 'Air Freight',
-    no: 'HBOL: SHJN2301234',
+    no: 'SHJN2301234',
     tag: 'Departure Delay',
     location: 'Hong Kong',
     time: 'Jan 10, 2025 14:30 UTC+8',
     delayInfo: {
-      delayTime: 'ATD: Jan 12, 16:30 (+2 days delay)'
+      delayTime: 'ATD: Jan 12, 16:30 (+2 days delay)',
+      departureDelayNum: 10,
+      arrivalDelayNum: 8
     }
   },
   {
@@ -75,8 +77,13 @@ const notificationList = [
     isRead: false,
     title: 'ETD/ETA  Change Weekly Summary (Jan 4- 10, 2025) ',
     mode: 'Air Freight',
-    no: 'HBOL: SHJN2301234',
+    no: 'SHJN2301234',
     tag: 'ETD Change',
+    changeInfo: {
+      etdChangeNum: 0,
+      etaChangeNum: 10,
+      changeTime: 'Updated ETD: Jan 17, 15:00'
+    },
     location: 'Hong Kong',
     changeTime: 'Updated ETD: Jan 17, 15:00',
     time: 'Jan 10, 2025 14:30 UTC+8'

+ 24 - 7
src/views/SystemMessage/src/components/PersonalProfile.vue

@@ -1,5 +1,7 @@
 <script setup lang="ts">
 import dayjs from 'dayjs'
+import { isEuropean, getDateFormat } from '@/utils/tools'
+import ChangePasswordDialog from '@/views/Layout/src/components/Header/components/ChangePasswordDialog.vue'
 
 const form = reactive({
   firstName: '',
@@ -14,6 +16,11 @@ const handleSegmented = (type: string) => {
   segmented.value = type
 }
 
+const changePasswordDialogRef = ref()
+const handleChangePassword = () => {
+  changePasswordDialogRef.value.openDialog()
+}
+
 const dateFormat = ref('MM/DD/YYYY')
 const selectVModel = ref('MM/DD/YYYY')
 const dateFormatExample = computed(() => {
@@ -55,10 +62,16 @@ const handleDateFormat = (value: string) => {
   selectVModel.value = dateFormatExample.value[value][0].value
 }
 
-const numbersFormat = ref('1')
-const handleNumbersFormat = (value: string) => {
-  numbersFormat.value = value
+const numbersFormat = ref()
+
+// 判断用户是否指定数字格式化,没有指定则自动判断
+const isSpecifyNumbersFormat = () => {
+  numbersFormat.value = isEuropean() ? 'European' : 'US/UK'
 }
+isSpecifyNumbersFormat()
+
+// 获取用户地区日期格式
+dateFormat.value = getDateFormat()
 </script>
 
 <template>
@@ -96,7 +109,9 @@ const handleNumbersFormat = (value: string) => {
             </p>
             <div class="password-change">
               <el-input size="large" style="width: 330px" :disabled="true" v-model="form.phone" />
-              <el-button class="el-button--main" plain size="large">Change Password</el-button>
+              <el-button @click="handleChangePassword" class="el-button--main" plain size="large"
+                >Change Password</el-button
+              >
             </div>
           </div>
         </div>
@@ -163,17 +178,17 @@ const handleNumbersFormat = (value: string) => {
       <div class="numbers-format" v-if="segmented === 'numbersFormat'">
         <div class="title">Numbers Format</div>
         <div class="content">
-          <el-radio-group v-model="numbersFormat" label="string" @change="handleNumbersFormat">
+          <el-radio-group v-model="numbersFormat" label="string">
             <el-row>
               <el-col
-                ><el-radio value="1">
+                ><el-radio value="US/UK">
                   <template #default>
                     <span>1,234.56 (US/UK)</span>
                   </template>
                 </el-radio></el-col
               >
               <el-col
-                ><el-radio value="2">
+                ><el-radio value="European">
                   <template #default>
                     <span>1.234,56 (European)</span>
                   </template>
@@ -189,6 +204,8 @@ const handleNumbersFormat = (value: string) => {
         </div>
       </div>
     </div>
+
+    <ChangePasswordDialog ref="changePasswordDialogRef"></ChangePasswordDialog>
   </div>
 </template>
 

+ 1 - 1
src/views/SystemMessage/src/components/SystemMessageDetail.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import EventCard from '@/components/NotificationMessageCard/src/components/EventCard.vue'
 
-const notificationData = {
+const notificationData: any = {
   title: 'Milestone Update Daily Summary (Jan 10, 2025)',
   numericRecords: 3,
   notificationList: [