3 커밋 15b82c49c4 ... 3ed9885c9d

작성자 SHA1 메시지 날짜
  Jack Zhou 3ed9885c9d Merge branch 'dev_zyh' into feat_i18n_zyh 19 시간 전
  Jack Zhou db7209ff7a feat: 解决Tracking详情页Container Status部分样式bug 1 일 전
  Jack Zhou 6a1511ed06 feat: 实现多语言功能 1 일 전

+ 7 - 2
src/components/ContainerStatus/src/ContainerStatus.vue

@@ -59,7 +59,12 @@ watch(
             <div class="step-dot-icon"></div>
             <div class="info">
               <div class="left-info">
-                <div class="title">{{ item.title }}</div>
+                <div class="title">
+                  <VEllipsisTooltip :max-width="220" :max-height="20" :line-clamp="1">{{
+                    item.title
+                  }}</VEllipsisTooltip>
+                </div>
+
                 <div class="date">{{ formatTimezone(item.date, item.timezone) }}</div>
               </div>
               <div class="right-country">{{ item.country }}</div>
@@ -159,7 +164,7 @@ watch(
     .info {
       flex: 1;
       display: flex;
-      height: 52px;
+      min-height: 52px;
       margin-top: -22px;
       background-color: var(--color-container-status-node-bg);
       border: 1px solid var(--color-border);

+ 8 - 2
src/components/VBreadcrumb/src/VBreadcrumb.vue

@@ -10,6 +10,12 @@ const themeStore = useThemeStore()
 const { t } = useI18n()
 const CancelRulesVisible = ref(false)
 
+const resolveBreadName = (routeItem: any) => {
+  if (routeItem?.breadKey) return t(routeItem.breadKey)
+  if (routeItem?.breadName) return routeItem.breadName
+  return routeItem?.label || ''
+}
+
 const handleGoBack = () => {
   const routeData = breadCrumb.getUpperRoute()
   router.push({
@@ -59,11 +65,11 @@ const jumpLinkMonitoring = () => {
     <template v-for="(routeItem, index) in breadCrumb.routeList" :key="routeItem.label">
       <template v-if="index + 1 !== breadCrumb.routeList.length">
         <span @click="jumpLink(routeItem.label, routeItem.query)" class="previous-route">{{
-          routeItem.breadName
+          resolveBreadName(routeItem)
         }}</span>
         <span class="interval">|</span>
       </template>
-      <span v-else>{{ routeItem.breadName }}</span>
+      <span v-else>{{ resolveBreadName(routeItem) }}</span>
     </template>
   </div>
   <div v-else></div>

+ 71 - 37
src/components/VEllipsisTooltip/src/VEllipsisTooltip.vue

@@ -5,6 +5,7 @@
     :popper-class="popperClass"
     :placement="placement"
     v-bind="tooltipProps"
+    :offset="20"
     ref="tooltipRef"
   >
     <div
@@ -12,20 +13,20 @@
       class="ellipsis-container"
       :class="{ 'is-clamp-multi': lineClamp > 1 }"
       :style="finalContainerStyle"
-      @mouseenter="handleMouseEnter"
+      @mouseenter.capture="handleMouseEnter"
       @mouseleave="handleMouseLeave"
     >
-      <slot>
-        <span ref="textRef" class="ellipsis-text" :style="textStyle">
-          {{ content }}
-        </span>
-      </slot>
+      <div ref="textRef" class="ellipsis-text" :style="finalTextStyle">
+        <slot>
+          <span>{{ content }}</span>
+        </slot>
+      </div>
     </div>
   </el-tooltip>
 </template>
 
 <script setup>
-import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
+import { ref, computed, onMounted, onUnmounted, onUpdated, watch, nextTick } from 'vue'
 
 const props = defineProps({
   content: String,
@@ -71,13 +72,11 @@ const tooltipRef = ref(null)
 // --- 是否应显示 tooltip ---
 const shouldShowTooltip = ref(false)
 
-// --- 动态计算样式类 ---
-const containerClasses = computed(() => ({
-  'is-clamp-multi': props.lineClamp > 1
-}))
+// --- 插槽文案(无 content prop 时从 DOM 读取,供 tooltip 使用)---
+const slotTooltipText = ref('')
 
 // --- 实际用于 Tooltip 显示的内容 ---
-const tooltipContent = computed(() => props.content || '')
+const tooltipContent = computed(() => props.content || slotTooltipText.value)
 
 // --- 容器样式(max-width / max-height)---
 const finalContainerStyle = computed(() => ({
@@ -114,31 +113,51 @@ const finalTextStyle = computed(() => {
   }
 })
 
-// --- 检查是否溢出 ---
-const checkOverflow = async () => {
-  await nextTick() // 确保 DOM 更新
-  const container = containerRef.value
-  const textEl = textRef.value || container?.querySelector('.ellipsis-text')
+// --- 实际发生省略的测量节点:插槽包一层 div/span 时,溢出体现在子节点 scrollWidth 上 ---
+const getMeasureEl = (textEl) => {
+  if (!textEl) return null
+  const { children } = textEl
+  if (children.length === 1) {
+    return children[0]
+  }
+  return textEl
+}
 
-  if (!container || !textEl) return
+// --- 同步测量(mouseenter 必须用同步,否则 el-tooltip 先看到 disabled=true 不会弹出)---
+const measureOverflow = () => {
+  const textEl = textRef.value
 
-  let isOverflowing = false
+  if (!textEl) return
+
+  slotTooltipText.value = (textEl.textContent || '').trim()
+
+  const measureEl = getMeasureEl(textEl)
+  if (!measureEl) return
 
   if (props.lineClamp <= 1) {
-    isOverflowing = textEl.scrollWidth > container.clientWidth
+    // 与 clientWidth 比较;子像素取整可能导致相等,故留 1px 容差
+    shouldShowTooltip.value = measureEl.scrollWidth > measureEl.clientWidth + 1
   } else {
-    // 多行看高度是否溢出(line-clamp 截断)
-    isOverflowing = textEl.scrollHeight > container.clientHeight
+    shouldShowTooltip.value = measureEl.scrollHeight > measureEl.clientHeight + 1
   }
+}
 
-  shouldShowTooltip.value = isOverflowing
+// --- 检查是否溢出(DOM 更新后)---
+const checkOverflow = async () => {
+  await nextTick()
+  measureOverflow()
 }
 
-// --- 鼠标事件用于手动触发检查(防抖)---
+// --- 捕获阶段先更新 shouldShowTooltip,再交给 el-tooltip 处理悬停 ---
 let resizeTimer
 const handleMouseEnter = () => {
   clearTimeout(resizeTimer)
-  resizeTimer = setTimeout(checkOverflow, 50)
+  measureOverflow()
+  resizeTimer = setTimeout(measureOverflow, 50)
+}
+
+const handleMouseLeave = () => {
+  clearTimeout(resizeTimer)
 }
 
 // 可选:也可监听 resize
@@ -147,6 +166,11 @@ onMounted(() => {
   checkOverflow()
 })
 
+// 插槽内容变化(如 v-for 文案)不会触发 props watch,需在更新后重算溢出
+onUpdated(() => {
+  nextTick(checkOverflow)
+})
+
 onUnmounted(() => {
   window.removeEventListener('resize', checkOverflow)
   clearTimeout(resizeTimer)
@@ -165,30 +189,35 @@ watch(
 <style lang="scss" scoped>
 .ellipsis-container {
   display: inline-block;
+  box-sizing: border-box;
+  width: 100%;
   max-width: v-bind('finalContainerStyle.maxWidth');
   max-height: v-bind('finalContainerStyle.maxHeight');
+  min-width: 0;
   overflow: hidden;
   vertical-align: top;
-  line-height: 32px;
+  /* 不固定行高:否则在继承较小字号时行盒约 13px,会裁掉加粗/降部笔画 */
+  line-height: normal;
+  font: inherit;
 }
 
 .ellipsis-text {
-  width: 100%; // 利用父容器宽度
-}
-.ellipsis-container {
-  display: inline-block;
-  max-width: v-bind('finalContainerStyle.maxWidth');
-  max-height: v-bind('finalContainerStyle.maxHeight');
+  width: 100%;
+  min-width: 0;
+  display: block;
   overflow: hidden;
-  line-height: 1.5;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  line-height: inherit;
 }
 
-.ellipsis-text {
-  width: 100%;
-  display: block;
+/* 插槽根节点常为 div(如 .title),省略与 nowrap 需作用在真正承载文字的节点上 */
+.ellipsis-container:not(.is-clamp-multi) .ellipsis-text > :deep(*) {
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
+  min-width: 0;
+  max-width: 100%;
 }
 
 .ellipsis-container.is-clamp-multi .ellipsis-text {
@@ -199,12 +228,17 @@ watch(
   white-space: normal;
   word-break: break-all;
 }
+
+.ellipsis-container.is-clamp-multi .ellipsis-text > :deep(*) {
+  white-space: normal;
+  word-break: break-all;
+}
 </style>
 
 <!-- 全局样式建议提取到全局 SCSS 文件 -->
 <style>
 .ellipsis-tooltip {
-  max-width: 200px;
+  max-width: 260px;
   word-break: break-word;
   white-space: pre-line;
   margin-bottom: -15px;

+ 5 - 2
src/locales/en.json

@@ -1046,7 +1046,7 @@
     "transportMode": "Transport Mode",
     "shipmentStatus": "Shipment Status",
     "bookingListEmptyTipLine1": "We support the following references number to find bookings: Booking No./HAWB No./MAWB No./PO No./Carrier Booking No./Contract No./File No./Quote No.",
-    "bookingListEmptyTipLine2": "",
+    
     "etd": "ETD",
     "textSearch": "text search",
     "bookingNo": "Booking No.",
@@ -1148,7 +1148,10 @@
     "time": "Time",
     "places": "Places",
     "transportation": "Transportation",
-    "others": "Others"
+    "others": "Others",
+
+
+    "bookingListEmptyTipLine2": ""
   },
   "destinationDelivery": {
     "title": "Destination Delivery",

+ 57 - 2
src/locales/index.ts

@@ -14,6 +14,48 @@ const messages: any = {
 }
 messages.en_US.vxe.table.seqTitle = 'seq'
 
+type CachedLocalePayload = {
+  fetchedAt: number
+  messages: Record<string, any>
+}
+
+const I18N_CACHE_PREFIX = 'i18n_cache_v1'
+// 默认 6 小时内刷新页面不重复拉取“语言文件”
+const DEFAULT_CACHE_TTL_MS = 6 * 60 * 60 * 1000
+
+const getCacheKey = (locale: string) => `${I18N_CACHE_PREFIX}:${locale}`
+
+const safeJsonParse = <T>(raw: string | null): T | null => {
+  if (!raw) return null
+  try {
+    return JSON.parse(raw) as T
+  } catch {
+    return null
+  }
+}
+
+const readCachedLocale = (locale: string): CachedLocalePayload | null => {
+  return safeJsonParse<CachedLocalePayload>(localStorage.getItem(getCacheKey(locale)))
+}
+
+const writeCachedLocale = (locale: string, payload: CachedLocalePayload) => {
+  try {
+    localStorage.setItem(getCacheKey(locale), JSON.stringify(payload))
+  } catch {
+    // ignore quota / private mode
+  }
+}
+
+export const clearLocaleCache = (locale?: string) => {
+  if (locale) {
+    localStorage.removeItem(getCacheKey(locale))
+    return
+  }
+  Object.keys(localStorage).forEach((k) => {
+    if (k.startsWith(`${I18N_CACHE_PREFIX}:`)) localStorage.removeItem(k)
+  })
+}
+
 const i18n = createI18n({
   legacy: false, // 使用 Composition API 模式,则需要将其设置为false
   globalInjection: true, //全局生效$t
@@ -83,16 +125,29 @@ export const loadLocaleMessages = async (locale: string) => {
   if (!langkey) return
 
   try {
+    // 1) 优先命中本地缓存(避免刷新就重复请求语言文件)
+    const cached = readCachedLocale(locale)
+    const now = Date.now()
+    const isCacheFresh = !!cached && now - cached.fetchedAt < DEFAULT_CACHE_TTL_MS
+    if (cached?.messages) {
+      i18n.global.setLocaleMessage(locale, cached.messages)
+      loadedLocaleSet.add(locale)
+      if (isCacheFresh) return
+      // cache 过期:继续走下面的远端拉取刷新缓存(同一次启动只会拉一次)
+    }
+
     // Lazy import avoids circular-init issues while still using API module method.
     const { getMultilingualJsonFile } = await import('@/api/module/multilingual')
     const res = await getMultilingualJsonFile({ langkey }, {})
     const normalized = normalizeApiMessages(res?.data || res)
-    i18n.global.setLocaleMessage(locale, {
+    const mergedMessages = {
       ...en,
       ...normalized,
       ...enUS
-    })
+    }
+    i18n.global.setLocaleMessage(locale, mergedMessages)
     loadedLocaleSet.add(locale)
+    writeCachedLocale(locale, { fetchedAt: now, messages: mergedMessages })
   } catch (error) {
     // keep fallback English messages when remote file fails
     console.error('loadLocaleMessages failed:', error)

+ 0 - 3
src/main.ts

@@ -24,7 +24,6 @@ import { createPinia } from 'pinia'
 
 import App from './App.vue'
 import router from './router'
-import i18n from './locales'
 import { useThemeStore } from '@/stores/modules/theme'
 import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
 
@@ -45,7 +44,6 @@ VxeUIAll.VxeUI.setConfig({
   i18n: (key, args) => i18n.global.t(key, args)
 })
 
-app.use(createPinia())
 const pinia = createPinia()
 pinia.use(piniaPluginPersistedstate)
 app.use(pinia)
@@ -54,7 +52,6 @@ app.use(VXETable)
 app.use(VxeUI)
 app.use(router)
 app.use(VxeUIAll)
-app.use(i18n)
 app.use(Antd)
 
 // 注册全局指令

+ 23 - 26
src/router/index.ts

@@ -3,9 +3,6 @@ import { useUserStore } from '@/stores/modules/user'
 import { useBreadCrumb } from '@/stores/modules/breadCrumb'
 import { useHeaderSearch } from '@/stores/modules/headerSearch'
 import { useFiltersStore } from '@/stores/modules/filtersList'
-import i18n from '@/locales/index'
-
-const t = i18n.global.t
 const router = createRouter({
   history: createWebHistory(`${import.meta.env.VITE_BASE_URL}`),
   routes: [
@@ -20,7 +17,7 @@ const router = createRouter({
           name: 'Dashboard',
           component: () => import('../views/Dashboard'),
           meta: {
-            breadName: t('menu.dashboard')
+            breadKey: 'menu.dashboard'
           }
         },
         {
@@ -28,7 +25,7 @@ const router = createRouter({
           name: 'Booking',
           component: () => import('../views/Booking'),
           meta: {
-            breadName: t('menu.booking')
+            breadKey: 'menu.booking'
           }
         },
         {
@@ -36,7 +33,7 @@ const router = createRouter({
           name: 'Report Management',
           component: () => import('../views/Report'),
           meta: {
-            breadName: t('menu.reportManagement')
+            breadKey: 'menu.reportManagement'
           }
         },
         {
@@ -45,7 +42,7 @@ const router = createRouter({
           component: () => import('../views/Report/src/components/ReportDetail'),
           meta: {
             activeMenu: '/report',
-            breadName: t('menu.reportDetail')
+            breadKey: 'menu.reportDetail'
           }
         },
         {
@@ -54,7 +51,7 @@ const router = createRouter({
           component: () => import('../views/Report/src/components/ReportSchedule'),
           meta: {
             activeMenu: '/report',
-            breadName: t('menu.reportSchedule')
+            breadKey: 'menu.reportSchedule'
           }
         },
         {
@@ -63,7 +60,7 @@ const router = createRouter({
           component: () => import('../views/Booking/src/components/BookingDetail'),
           meta: {
             activeMenu: '/booking',
-            breadName: t('menu.bookingDetail')
+            breadKey: 'menu.bookingDetail'
           }
         },
         {
@@ -71,7 +68,7 @@ const router = createRouter({
           name: 'Tracking',
           component: () => import('../views/Tracking'),
           meta: {
-            breadName: t('menu.tracking')
+            breadKey: 'menu.tracking'
           }
         },
         {
@@ -80,7 +77,7 @@ const router = createRouter({
           component: () => import('../views/Tracking/src/components/TrackingDetail'),
           meta: {
             activeMenu: '/tracking',
-            breadName: t('menu.trackingDetail')
+            breadKey: 'menu.trackingDetail'
           }
         },
         {
@@ -89,7 +86,7 @@ const router = createRouter({
           component: () => import('../views/Tracking/src/components/DownloadAttachment'),
           meta: {
             activeMenu: '/tracking',
-            breadName: t('menu.trackingDownloadAttachment')
+            breadKey: 'menu.trackingDownloadAttachment'
 
           }
         },
@@ -99,7 +96,7 @@ const router = createRouter({
           component: () => import('../views/Tracking/src/components/TrackingDetail'),
           meta: {
             activeMenu: '/tracking',
-            breadName: t('menu.shipmentDetail')
+            breadKey: 'menu.shipmentDetail'
           }
         },
         {
@@ -109,7 +106,7 @@ const router = createRouter({
             import('../views/Tracking/src/components/TrackingTable/src/components/VGMView.vue'),
           meta: {
             activeMenu: '/tracking',
-            breadName: t('menu.addVGM')
+            breadKey: 'menu.addVGM'
           }
         },
         {
@@ -118,7 +115,7 @@ const router = createRouter({
           component: () => import('../views/Tracking/src/components/PublicTracking'),
           meta: {
             activeMenu: '/tracking',
-            breadName: t('menu.publicTracking')
+            breadKey: 'menu.publicTracking'
           }
         },
         {
@@ -130,7 +127,7 @@ const router = createRouter({
             ),
           meta: {
             activeMenu: '/tracking',
-            breadName: t('menu.publicTrackingDetail')
+            breadKey: 'menu.publicTrackingDetail'
 
           }
         },
@@ -140,7 +137,7 @@ const router = createRouter({
           component: () => import('../views/Login'),
           meta: {
             activeMenu: '/tracking',
-            breadName: t('menu.login')
+            breadKey: 'menu.login'
           }
         },
         {
@@ -148,7 +145,7 @@ const router = createRouter({
           name: 'Reset Password',
           component: () => import('../views/Login/src/components/ChangePasswordCard.vue'),
           meta: {
-            breadName: t('menu.resetPassword')
+            breadKey: 'menu.resetPassword'
           }
         },
         {
@@ -189,7 +186,7 @@ const router = createRouter({
           name: 'System Message',
           component: () => import('../views/SystemMessage'),
           meta: {
-            breadName: t('menu.systemMessage')
+            breadKey: 'menu.systemMessage'
           }
         },
         {
@@ -197,7 +194,7 @@ const router = createRouter({
           name: 'System Message Detail',
           component: () => import('../views/SystemMessage/src/components/SystemMessageDetail.vue'),
           meta: {
-            breadName: t('menu.systemMessageDetail'),
+            breadKey: 'menu.systemMessageDetail',
             activeMenu: '/system-message'
           },
         },
@@ -206,7 +203,7 @@ const router = createRouter({
           name: 'System Settings',
           component: () => import('../views/SystemSettings'),
           meta: {
-            breadName: t('menu.systemSettings')
+            breadKey: 'menu.systemSettings'
           }
         },
         {
@@ -215,7 +212,7 @@ const router = createRouter({
           component: () => import('../views/SystemSettings/src/components/CreateNewrule'),
           meta: {
             activeMenu: '/system-settings',
-            breadName: t('menu.createNewRule')
+            breadKey: 'menu.createNewRule'
           }
         },
         {
@@ -228,7 +225,7 @@ const router = createRouter({
           name: 'Destination Delivery',
           component: () => import('../views/DestinationDelivery'),
           meta: {
-            breadName: t('menu.destinationDelivery')
+            breadKey: 'menu.destinationDelivery'
           }
 
         },
@@ -237,7 +234,7 @@ const router = createRouter({
           name: 'Create New Booking',
           component: () => import('../views/DestinationDelivery/src/components/CreateNewBooking'),
           meta: {
-            breadName: t('menu.createNewBooking'),
+            breadKey: 'menu.createNewBooking',
             activeMenu: '/destination-delivery'
           }
 
@@ -248,7 +245,7 @@ const router = createRouter({
           component: () => import('../views/DestinationDelivery/src/components/ConfiguRations'),
           meta: {
             activeMenu: '/destination-delivery',
-            breadName: t('menu.configurations')
+            breadKey: 'menu.configurations'
           }
         },
         {
@@ -260,7 +257,7 @@ const router = createRouter({
             ),
           meta: {
             activeMenu: '/destination-delivery',
-            breadName: t('menu.createNewRule')
+            breadKey: 'menu.createNewRule'
 
           }
         },

+ 17 - 14
src/stores/modules/breadCrumb.ts

@@ -1,7 +1,8 @@
 import { defineStore } from 'pinia'
 
 interface Route {
-  breadName: string
+  breadName?: string
+  breadKey?: string
   label: string
   path: string
   query?: string
@@ -44,48 +45,48 @@ export const useBreadCrumb = defineStore('breadCrumb', {
         return
       }
       if (toRoute.name === 'Destination Create New Rule') {
-        let breadName = ''
+        let breadKey = ''
         if (toRoute.query.a != undefined) {
-          breadName = 'Modify Rule'
+          breadKey = 'destinationDelivery.modifyRule'
         } else {
-          breadName = 'Create New Rule'
+          breadKey = 'destinationDelivery.createNewRule'
         }
         this.routeList = [
           {
-            breadName: 'Destination Delivery',
+            breadKey: 'menu.destinationDelivery',
             label: 'Destination Delivery',
             path: '/destination-delivery',
             query: ''
           },
           {
-            breadName: 'Configurations',
+            breadKey: 'menu.configurations',
             label: 'Configurations',
             path: '/destination-delivery/configurations',
             query: ''
           },
           {
-            breadName: breadName,
+            breadKey,
             label: toRoute.name,
             path: '/destination-delivery/create-new-rule',
             query: toRoute.query
           }
         ]
       } else if (toRoute.name === 'Create New Booking') {
-        let breadName = ''
+        let breadKey = ''
         if (toRoute.query.a != undefined) {
-          breadName = 'Modify Booking'
+          breadKey = 'destinationDelivery.modifyBooking'
         } else {
-          breadName = 'Create New Booking'
+          breadKey = 'destinationDelivery.createNewBooking'
         }
         this.routeList = [
           {
-            breadName: 'Destination Delivery',
+            breadKey: 'menu.destinationDelivery',
             label: 'Destination Delivery',
             path: '/destination-delivery',
             query: ''
           },
           {
-            breadName: breadName,
+            breadKey,
             label: toRoute.name,
             path: '/destination-delivery/create-new-booking',
             query: toRoute.query
@@ -94,7 +95,8 @@ export const useBreadCrumb = defineStore('breadCrumb', {
 
       } else if (toRoute.name && whiteList.includes(toRoute.name)) {
         this.routeList.push({
-          breadName: toRoute?.meta?.breadName || toRoute.name,
+          breadName: toRoute?.meta?.breadName,
+          breadKey: toRoute?.meta?.breadKey,
           label: toRoute.name,
           path: toRoute.path,
           query: toRoute.query
@@ -103,7 +105,8 @@ export const useBreadCrumb = defineStore('breadCrumb', {
         this.routeList = [
           {
             label: toRoute.name,
-            breadName: toRoute?.meta?.breadName || toRoute.name,
+            breadName: toRoute?.meta?.breadName,
+            breadKey: toRoute?.meta?.breadKey,
             path: toRoute.path,
             query: toRoute.query
           }

+ 1 - 1
src/views/Booking/src/components/BookingTable/src/BookingTable.vue

@@ -547,7 +547,7 @@ defineExpose({
       </template>
       <!-- Status字段的插槽 -->
       <template #status="{ row, column }">
-        <VTag :type="row[column.field]">{{ t(`booking.${row[column.field]}`) }}</VTag>
+        <VTag :type="row[column.field]">{{ row[column.field] }}</VTag>
       </template>
       <!-- Booking No字段的插槽 -->
       <template #link="{ row, column }">

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

@@ -250,7 +250,6 @@ const languageChange = async (item) => {
     await switchAppLocale(targetLocale)
     locale.value = targetLocale
   } finally {
-    window.location.reload()
     userManualLoading.value = false
     languagePopoverVisible.value = false
   }

+ 3 - 2
src/views/Layout/src/components/Header/components/KAMMapping.vue

@@ -197,7 +197,7 @@ watch(
 .kam-mapping-container {
   display: flex;
   align-items: center;
-  width: 280px;
+  // width: 280px;
   height: 32px;
   margin-left: 16px;
   margin-right: 4px;
@@ -211,7 +211,7 @@ watch(
     border-color: var(--color-theme) !important;
   }
   &.hide-mapping {
-    width: 175px;
+    // width: 175px;
     margin-left: 8px;
     margin-right: 0px;
     border: none;
@@ -219,6 +219,7 @@ watch(
   }
 }
 .select-customer {
+  min-width: 223px;
   cursor: pointer;
 }
 .customer-input {

+ 3 - 4
src/views/MultilingualConfig/src/MultilingualConfig.vue

@@ -1,7 +1,6 @@
 <script setup lang="ts">
 import { type VxeGridProps } from 'vxe-table'
 import { useCalculatingHeight } from '@/hooks/calculatingHeight'
-import FilterTabs from './components/FilterTabs.vue'
 import { cloneDeep } from 'lodash'
 import { onBeforeRouteLeave } from 'vue-router'
 
@@ -511,7 +510,7 @@ const handleTagToggle = (index: any, checked: any) => {
           v-model="selectedPage"
           placeholder="Select Page"
           @change="getMultilingualConfig()"
-          style="width: 240px; height: 32px"
+          style="width: 260px; height: 32px"
         >
           <template #label="{ label }">
             <div style="display: flex; align-items: center">
@@ -555,7 +554,7 @@ const handleTagToggle = (index: any, checked: any) => {
             <span class="font_family icon-icon_search_b"></span>
           </template>
         </el-input>
-        <el-button type="primary" @click="saveMultilingualConfig">Save</el-button>
+        <!-- <el-button type="primary" @click="saveMultilingualConfig">Save</el-button> -->
       </div>
     </div>
 
@@ -579,7 +578,7 @@ const handleTagToggle = (index: any, checked: any) => {
         </template>
 
         <template #key="{ row }">
-          <div>{{ row.originEnglish }}</div>
+          <div style="margin-bottom: 4px">{{ row.originEnglish }}</div>
           <span>{{ row.key }}</span>
         </template>
         <template #cell="{ row, column, rowIndex }">