From 475e3577ddcd0ee71b307941671e87b8b90ce5c8 Mon Sep 17 00:00:00 2001 From: xiaomai Date: Sat, 2 May 2026 11:57:59 +0800 Subject: [PATCH] refactor(admin): redesign system wording layout with sidebar and tabs Replace module and surface dropdowns with a sidebar and tabbed interface. Improve navigation and usability in the admin wording section. --- frontend/src/styles/main.css | 125 ++++++++++++++++++++++++++++++- frontend/src/views/AdminView.vue | 121 +++++++++++++++++++----------- 2 files changed, 199 insertions(+), 47 deletions(-) diff --git a/frontend/src/styles/main.css b/frontend/src/styles/main.css index 74befc4..3cb0fdc 100644 --- a/frontend/src/styles/main.css +++ b/frontend/src/styles/main.css @@ -2409,15 +2409,98 @@ button:disabled, font-weight: 850; } -.system-wording-toolbar { - grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); +.system-wording-header { align-items: end; } +.system-wording-header__locale { + width: min(260px, 100%); +} + +.system-wording-layout { + display: grid; + grid-template-columns: minmax(180px, 240px) minmax(0, 1fr); + gap: 16px; + align-items: start; +} + +.system-wording-sidebar { + min-width: 0; + display: grid; + align-content: start; + gap: 6px; + padding: 10px; + border: 1px solid var(--line); + border-radius: var(--radius-card); + background: var(--surface-soft); +} + +.system-wording-sidebar__title { + padding: 2px 4px 4px; + color: var(--muted); + font-size: 13px; + font-weight: 900; +} + +.system-wording-sidebar__button { + width: 100%; + min-height: 44px; + display: flex; + align-items: center; + justify-content: flex-start; + padding: 9px 10px; + border: 1px solid transparent; + border-radius: var(--radius-control); + background: transparent; + color: var(--ink-soft); + font-weight: 850; + text-align: left; + overflow-wrap: anywhere; + cursor: pointer; +} + +.system-wording-sidebar__button:hover { + border-color: rgba(42, 117, 187, 0.24); + background: rgba(255, 203, 5, 0.2); + color: var(--pokemon-blue-deep); +} + +.system-wording-sidebar__button.active { + border-color: var(--line-strong); + background: var(--pokemon-blue); + color: #ffffff; + box-shadow: 0 2px 0 var(--line-strong); +} + +.system-wording-sidebar__button:disabled { + cursor: not-allowed; + opacity: 0.54; +} + +.system-wording-content { + min-width: 0; + display: grid; + gap: 12px; +} + +.system-wording-controls { + display: flex; + align-items: start; + justify-content: space-between; + gap: 12px; + flex-wrap: wrap; +} + +.system-wording-controls .tabs--component { + flex: 1 1 320px; + min-width: 0; +} + .system-wording-toolbar__check { min-height: 44px; display: flex; align-items: center; + justify-content: flex-end; } .system-wording-list li { @@ -3795,10 +3878,22 @@ button:disabled, .pokemon-profile-grid, .pokemon-profile-row, .pokemon-related-grid, + .system-wording-layout, .admin-layout { grid-template-columns: 1fr; } + .system-wording-sidebar { + display: flex; + overflow-x: auto; + } + + .system-wording-sidebar__button { + width: auto; + flex: 0 0 auto; + white-space: nowrap; + } + .coming-soon-panel { grid-template-columns: auto minmax(0, 1fr); } @@ -3884,6 +3979,32 @@ button:disabled, width: 100%; } + .system-wording-header { + align-items: stretch; + flex-direction: column; + } + + .system-wording-header__locale { + width: 100%; + } + + .system-wording-controls .tabs--component { + flex-basis: 100%; + } + + .system-wording-toolbar__check { + justify-content: flex-start; + } + + .system-wording-list li { + align-items: stretch; + flex-direction: column; + } + + .system-wording-list .row-actions { + justify-content: flex-start; + } + .life-feed__list { width: 100%; } diff --git a/frontend/src/views/AdminView.vue b/frontend/src/views/AdminView.vue index 74dfa90..7bcbe3e 100644 --- a/frontend/src/views/AdminView.vue +++ b/frontend/src/views/AdminView.vue @@ -161,6 +161,18 @@ const wordingLocaleOptions = computed(() => ] ); const wordingModules = computed(() => [...new Set(wordingRows.value.map((item) => item.module))].sort((a, b) => a.localeCompare(b))); +const wordingSurfaceTabs = computed(() => [ + { value: '', label: t('pages.admin.allSurfaces') }, + { value: 'frontend', label: t('pages.admin.surfaceFrontend') }, + { value: 'backend', label: t('pages.admin.surfaceBackend') }, + { value: 'email', label: t('pages.admin.surfaceEmail') } +]); +const activeWordingSurfaceTab = computed({ + get: () => wordingSurface.value, + set: (value: string) => { + wordingSurface.value = value === 'frontend' || value === 'backend' || value === 'email' ? value : ''; + } +}); const filteredWordingRows = computed(() => wordingRows.value.filter((item) => { if (wordingModule.value && item.module !== wordingModule.value) return false; @@ -230,6 +242,10 @@ function resetWordingForm() { wordingForm.value = { key: '', locale: wordingLocale.value || defaultLocale, value: '', defaultValue: '', placeholders: [] }; } +function selectWordingModule(module: string) { + wordingModule.value = module; +} + function openNewConfig() { resetConfigForm(); configModalOpen.value = true; @@ -817,11 +833,9 @@ onMounted(() => {
-
+

{{ t('pages.admin.wordings') }}

-
-
-
+
-
- - -
-
- - -
-
- +
+
+ + +
+
+ +
+ +
+
+
    +
  • + + {{ item.key }} + + {{ item.module }} + {{ t(`pages.admin.surface${item.surface.charAt(0).toUpperCase()}${item.surface.slice(1)}`) }} + {{ t('pages.admin.missingTranslation') }} + + {{ item.value || item.defaultValue }} + + + + +
  • +
+

{{ t('common.noRecords') }}

-
    -
  • - - {{ item.key }} - - {{ item.module }} - {{ t(`pages.admin.surface${item.surface.charAt(0).toUpperCase()}${item.surface.slice(1)}`) }} - {{ t('pages.admin.missingTranslation') }} - - {{ item.value || item.defaultValue }} - - - - -
  • -
-

{{ t('common.noRecords') }}