소스 검색

feat: 完善多语言

Jack Zhou 1 주 전
부모
커밋
6e97ffcbdc
4개의 변경된 파일287개의 추가작업 그리고 52개의 파일을 삭제
  1. 2 2
      src/App.vue
  2. 2 3
      src/locales/index.ts
  3. 64 8
      src/views/Layout/src/components/Header/HeaderView.vue
  4. 219 39
      src/views/MultilingualConfig/src/MultilingualConfig.vue

+ 2 - 2
src/App.vue

@@ -17,14 +17,14 @@ const langValue = ref()
 const { locale } = useI18n() // 解构出 locale
 
 langValue.value = localStorage.getItem('lang') || 'English'
-const languageChangetest = async (label: string) => {
+const languageChange = async (label: string) => {
   const targetLocale = resolveLocaleByLangLabel(label)
   await switchAppLocale(targetLocale)
   locale.value = targetLocale
 }
 
 onMounted(() => {
-  languageChangetest(langValue.value)
+  languageChange(langValue.value)
 })
 </script>
 

+ 2 - 3
src/locales/index.ts

@@ -33,9 +33,8 @@ const localeToApiLangKey: Record<string, string> = {
 
 const langLabelToLocale: Record<string, string> = {
   English: 'en_US',
-  Chinese: 'zh_TW',
-  'Simplified Chinese': 'zh_CN',
-  'Traditional Chinese': 'zh_TW',
+  'Chinese (Simplified)': 'zh_CN',
+  'Chinese (Traditional)': 'zh_TW',
   French: 'fr_FR',
   Spanish: 'es_ES',
   Portuguese: 'pt_BR'

+ 64 - 8
src/views/Layout/src/components/Header/HeaderView.vue

@@ -211,13 +211,44 @@ const handleDemoVideo = () => {
 }
 
 const langValue = ref()
+const languageList = ref([
+  {
+    label: 'English',
+    value: 'English'
+  },
+  {
+    label: 'Chinese (Simplified)',
+    value: 'Chinese (Simplified)'
+  },
+  {
+    label: 'Chinese (Traditional)',
+    value: 'Chinese (Traditional)'
+  },
+  {
+    label: 'French',
+    value: 'French'
+  },
+  {
+    label: 'Spanish',
+    value: 'Spanish'
+  },
+  {
+    label: 'Portuguese',
+    value: 'Portuguese'
+  }
+])
 const { locale } = useI18n() // 解构出 locale
 
 langValue.value = localStorage.getItem('lang') || 'English'
-const languageChangetest = async (label: string) => {
-  const targetLocale = resolveLocaleByLangLabel(label)
+const languageChange = async (item) => {
+  userManualLoading.value = true
+  langValue.value = item.label
+  const targetLocale = resolveLocaleByLangLabel(item.value)
+  localStorage.setItem('lang', item.label)
+  console.log(targetLocale, 'value')
   await switchAppLocale(targetLocale)
   locale.value = targetLocale
+  userManualLoading.value = false
 }
 </script>
 
@@ -337,13 +368,32 @@ const languageChangetest = async (label: string) => {
           </el-tooltip>
         </template>
       </el-popover>
-      <el-button
-        style="height: 40px; width: 40px; margin-left: 0"
-        class="el-button--text"
-        @click="languageChangetest('English')"
+
+      <el-popover
+        placement="bottom-end"
+        :width="256"
+        trigger="click"
+        popper-class="user-config-popover"
       >
-        <span class="font_family icon-icon_language_b" style="font-size: 16px"></span>
-      </el-button>
+        <div class="options">
+          <div
+            class="item"
+            v-for="item in languageList"
+            :key="item.value"
+            :class="{ active: item.value === langValue }"
+            @click="languageChange(item)"
+          >
+            {{ item.label }}
+          </div>
+        </div>
+        <template #reference>
+          <el-button style="height: 40px; padding: 0 12px; margin-left: 0" class="el-button--text">
+            <span class="font_family icon-icon_language_b" style="font-size: 16px"></span>
+            {{ langValue }}
+          </el-button>
+        </template>
+      </el-popover>
+
       <el-popover
         placement="bottom-end"
         :width="256"
@@ -607,8 +657,14 @@ div.el-popover.el-popper.user-config-popover {
       &:hover {
         background-color: var(--color-mune-active-bg);
         border-radius: 6px;
+        color: var(--color-theme);
         cursor: pointer;
       }
+      &.active {
+        background-color: var(--color-mune-active-bg);
+        color: var(--color-theme);
+        border-radius: 6px;
+      }
     }
   }
 }

+ 219 - 39
src/views/MultilingualConfig/src/MultilingualConfig.vue

@@ -14,9 +14,63 @@ const languageStatusList = [
   'portugueseStatus'
 ]
 
+const allUnverifiedNumber = computed(() => {
+  return (
+    englishUnverifiedNumber.value +
+    simplifiedChineseUnverifiedNumber.value +
+    traditionalChineseUnverifiedNumber.value +
+    frenchUnverifiedNumber.value +
+    spanishUnverifiedNumber.value +
+    portugueseUnverifiedNumber.value
+  )
+})
+const englishUnverifiedNumber = computed(() => {
+  return showTableData.value.filter((item) => item.englishStatus === 0).length
+})
+const simplifiedChineseUnverifiedNumber = computed(() => {
+  return showTableData.value.filter((item) => item.simplifiedChineseStatus === 0).length
+})
+const traditionalChineseUnverifiedNumber = computed(() => {
+  return showTableData.value.filter((item) => item.traditionalChineseStatus === 0).length
+})
+const frenchUnverifiedNumber = computed(() => {
+  return showTableData.value.filter((item) => item.frenchStatus === 0).length
+})
+const spanishUnverifiedNumber = computed(() => {
+  return showTableData.value.filter((item) => item.spanishStatus === 0).length
+})
+const portugueseUnverifiedNumber = computed(() => {
+  return showTableData.value.filter((item) => item.portugueseStatus === 0).length
+})
+const curPageUnverifiedNumber = computed(() => {
+  return (
+    variableTableData.value.filter((item) =>
+      currnentTab.value.some((status) => item[status as keyof typeof item] === 0)
+    ).length || 0
+  )
+})
+
+const unverifiedNumberMap = computed(() => {
+  return {
+    all: allUnverifiedNumber.value,
+    english: englishUnverifiedNumber.value,
+    simplifiedChinese: simplifiedChineseUnverifiedNumber.value,
+    traditionalChinese: traditionalChineseUnverifiedNumber.value,
+    french: frenchUnverifiedNumber.value,
+    spanish: spanishUnverifiedNumber.value,
+    portuguese: portugueseUnverifiedNumber.value
+  }
+})
+
 const tabList = ref([
   { name: 'All', checked: true, number: 0, type: 'all', statusKey: languageStatusList },
-  { name: 'English', checked: false, number: 0, type: 'english', statusKey: 'englishStatus' },
+  {
+    name: 'English',
+    checked: false,
+    number: 0,
+    type: 'english',
+    statusKey: 'englishStatus'
+  },
   {
     name: 'Chinese (Simplified)',
     checked: false,
@@ -105,6 +159,14 @@ const columnList = computed(() => {
   return columns
 })
 
+const isCheckedTab = (type, checked) => {
+  // all类型永远是true,当选中all类型时,其他类型都为true
+  if (type === 'all' || tabList.value[0].checked || checked) {
+    return true
+  } else {
+    return false
+  }
+}
 const tabChange = (newTabList) => {
   tabList.value = cloneDeep(newTabList)
   getMultilingualConfig()
@@ -216,43 +278,6 @@ const showTableData = computed(() => {
   return arr
 })
 
-const englishUnverifiedNumber = computed(() => {
-  return showTableData.value.filter((item) => item.englishStatus === 0).length
-})
-const simplifiedChineseUnverifiedNumber = computed(() => {
-  return showTableData.value.filter((item) => item.simplifiedChineseStatus === 0).length
-})
-const traditionalChineseUnverifiedNumber = computed(() => {
-  return showTableData.value.filter((item) => item.traditionalChineseStatus === 0).length
-})
-const frenchUnverifiedNumber = computed(() => {
-  return showTableData.value.filter((item) => item.frenchStatus === 0).length
-})
-const spanishUnverifiedNumber = computed(() => {
-  return showTableData.value.filter((item) => item.spanishStatus === 0).length
-})
-const portugueseUnverifiedNumber = computed(() => {
-  return showTableData.value.filter((item) => item.portugueseStatus === 0).length
-})
-const curPageUnverifiedNumber = computed(() => {
-  return (
-    variableTableData.value.filter((item) =>
-      currnentTab.value.some((status) => item[status as keyof typeof item] === 0)
-    ).length || 0
-  )
-})
-
-const unverifiedNumberMap = computed(() => {
-  return {
-    english: englishUnverifiedNumber.value,
-    simplifiedChinese: simplifiedChineseUnverifiedNumber.value,
-    traditionalChinese: traditionalChineseUnverifiedNumber.value,
-    french: frenchUnverifiedNumber.value,
-    spanish: spanishUnverifiedNumber.value,
-    portuguese: portugueseUnverifiedNumber.value
-  }
-})
-
 const tableLoading = ref(false)
 
 const getMultilingualConfig = async () => {
@@ -388,6 +413,61 @@ onUnmounted(() => {
     clearInterval(saveInterval)
   }
 })
+
+interface ListItem {
+  name: string
+  number: number
+  type: string
+  checked: boolean
+}
+
+const getCheckedTabs = (tabList: ListItem[]) => {
+  const checkedList = tabList.filter((item) => item.checked)
+  return checkedList.map((item) => item.name)
+}
+// 判断是否除了all,其他的全选了
+const isAllExceptAllSelected = (tabList: ListItem[]) => {
+  const curCheckedTags = getCheckedTabs(tabList)
+  if (curCheckedTags.length === tabList.length - 1 && !curCheckedTags.includes('All')) {
+    return true
+  } else {
+    return false
+  }
+}
+//  点击标签 如果除了all
+const handleTagToggle = (index: any, checked: any) => {
+  // 如果点击的是all,并且当前选中也是all,那么直接返回
+  if (index === 0 && checked) return
+
+  const curTabList = cloneDeep(tabList.value)
+  if (index !== 0) {
+    const curTab = curTabList[index]
+    const curCheckedTags = getCheckedTabs(curTabList)
+    // 如果只选中了一个标签,并且这个标签不是all,那么改为选中all,取消选中当前选项
+    if (curCheckedTags.includes(curTab.name) && curCheckedTags.length === 1) {
+      curTabList[index].checked = false
+      curTabList[0].checked = true
+      tabChange(curTabList)
+      return
+    }
+    curTabList[index].checked = !checked
+    const isCheckedAll = isAllExceptAllSelected(curTabList)
+    if (isCheckedAll) {
+      curTabList[0].checked = true
+      curTabList.forEach((item, index) => {
+        index !== 0 && (item.checked = false)
+      })
+    } else {
+      curTabList[0].checked = false
+    }
+  } else if (index === 0 && !checked) {
+    curTabList[0].checked = true
+    curTabList.forEach((item, index) => {
+      index !== 0 && (item.checked = false)
+    })
+  }
+  tabChange(curTabList)
+}
 </script>
 
 <template>
@@ -397,7 +477,34 @@ onUnmounted(() => {
     </div>
     <div class="page-filter">
       <div class="language-tab">
-        <FilterTabs :tabList="tabList" @tabChange="tabChange" />
+        <!-- <FilterTabs :tabList="tabList" @tabChange="tabChange" /> -->
+
+        <div class="body">
+          <div class="TagsBox">
+            <div
+              class="list"
+              v-for="(item, index) of tabList"
+              :key="item.name"
+              :class="[item.checked ? 'checked' : '']"
+              @click="handleTagToggle(index, item.checked)"
+            >
+              {{ item.name }}
+              <div
+                :class="[
+                  'v-tag',
+                  item.type && 'v-tag__' + item.type,
+                  item.checked ? 'checked_color' : ''
+                ]"
+              >
+                {{
+                  isCheckedTab(item.type, item.checked)
+                    ? unverifiedNumberMap[item.type]
+                    : item.number
+                }}
+              </div>
+            </div>
+          </div>
+        </div>
       </div>
       <div class="top-content">
         <el-select
@@ -593,6 +700,79 @@ onUnmounted(() => {
     font-size: 10px;
   }
 }
+.language-tab {
+  .body {
+    margin-top: 8.73px;
+  }
+  .TagsBox {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  .list {
+    // min-width: 93px;
+    padding: 5.42px 16px;
+    color: var(--color-neutral-2);
+    font-size: var(--font-size-3);
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: var(--border-radius-12);
+  }
+  .v-tag {
+    min-width: 18px;
+    font-size: var(--font-size-2);
+    margin-left: 8px;
+    border-radius: 6px;
+    padding: 3px 4px;
+    text-align: center;
+  }
+  .v-tag__all {
+    font-weight: 400;
+    background-color: var(--color-tag-all-bg-color);
+    color: #e26394;
+  }
+  .v-tag__english {
+    font-weight: 400;
+    background-color: var(--color-tag-created-bg);
+    color: var(--color-tag-created);
+  }
+  .v-tag__simplifiedChinese {
+    font-weight: 400;
+    background-color: var(--color-tag-chinese-simplified-bg);
+    color: var(--color-tag-confirmed);
+  }
+  .v-tag__traditionalChinese {
+    font-weight: 400;
+    background-color: var(--color-tag-chinese-traditional-bg);
+    color: var(--color-tag-chinese-traditional);
+  }
+
+  .v-tag__french {
+    font-weight: 400;
+    background-color: var(--color-tag-cargo-received-bg);
+    color: var(--color-tag-cargo-received);
+  }
+  .v-tag__spanish {
+    font-weight: 400;
+    background-color: var(--color-tag-spanish-bg);
+    color: var(--color-tag-spanish);
+  }
+  .v-tag__portuguese {
+    font-weight: 400;
+    background-color: var(--color-tag-portuguese-bg);
+    color: var(--color-tag-portuguese-text-color);
+  }
+  .checked {
+    color: var(--color-theme);
+    font-weight: 700;
+    background: var(--color-tag-checked-bg);
+  }
+  .checked_color {
+    background-color: var(--color-tag-all-bg);
+    color: var(--color-tag-all);
+  }
+}
 .header {
   position: sticky;
   top: 0;