refactor: standardize floating action buttons with a compact stack layout and migrate menu items to key-based i18n resolution

This commit is contained in:
jxxghp
2026-04-19 13:00:04 +08:00
parent e9b214cff8
commit 20bdb940cd
11 changed files with 276 additions and 151 deletions

View File

@@ -17,7 +17,7 @@ import { usePWA } from '@/composables/usePWA'
import { useDynamicHeaderTab } from '@/composables/useDynamicHeaderTab'
// 国际化
const { t, locale } = useI18n()
const { t } = useI18n()
const route = useRoute()
@@ -908,14 +908,12 @@ const showNewFolderAction = computed(() => activeTab.value === 'installed' && !c
const showMarketSettingAction = computed(() => activeTab.value === 'market')
const pluginDynamicMenuItems = computed(() => {
locale.value
if (!appMode.value) return undefined
if (!showSearchAction.value) return undefined
const items = [
{
title: t('plugin.searchPlugins'),
titleKey: 'plugin.searchPlugins',
icon: 'mdi-magnify',
action: openPluginSearchDialog,
},
@@ -923,7 +921,7 @@ const pluginDynamicMenuItems = computed(() => {
if (showNewFolderAction.value) {
items.push({
title: t('plugin.newFolder'),
titleKey: 'plugin.newFolder',
icon: 'mdi-folder-plus',
action: showNewFolderDialog,
})
@@ -931,7 +929,7 @@ const pluginDynamicMenuItems = computed(() => {
if (showMarketSettingAction.value) {
items.push({
title: t('components.pluginMarketSetting.title'),
titleKey: 'dialog.pluginMarketSetting.title',
icon: 'mdi-store-cog',
action: openMarketSettingDialog,
})
@@ -1609,41 +1607,32 @@ function onDragStartPlugin(evt: any) {
<!-- 插件搜索图标 -->
<Teleport to="body" v-if="route.path === '/plugins'">
<div v-if="isRefreshed && !appMode && showSearchAction">
<VFab
icon="mdi-magnify"
color="info"
location="bottom"
size="x-large"
fixed
app
appear
@click="openPluginSearchDialog"
/>
<VFab
v-if="showNewFolderAction"
icon="mdi-folder-plus"
color="primary"
location="bottom"
size="x-large"
fixed
app
appear
class="mb-16"
@click="showNewFolderDialog"
/>
<div v-if="isRefreshed && !appMode && showSearchAction" class="compact-fab-stack">
<VFab
v-if="showMarketSettingAction"
icon="mdi-store-cog"
color="warning"
location="bottom"
size="x-large"
fixed
app
variant="tonal"
appear
class="mb-16"
class="compact-fab compact-fab--secondary"
@click="openMarketSettingDialog"
/>
<VFab
v-if="showNewFolderAction"
icon="mdi-folder-plus"
color="success"
variant="tonal"
appear
class="compact-fab compact-fab--secondary"
@click="showNewFolderDialog"
/>
<VFab
icon="mdi-magnify"
color="primary"
appear
class="compact-fab compact-fab--primary"
@click="openPluginSearchDialog"
/>
</div>
</Teleport>
<!-- 插件市场设置窗口 -->

View File

@@ -18,7 +18,7 @@ import { useBackgroundOptimization } from '@/composables/useBackgroundOptimizati
import { useGlobalSettingsStore } from '@/stores'
// i18n
const { t, locale } = useI18n()
const { t } = useI18n()
// 全局设置
const globalSettingsStore = useGlobalSettingsStore()
@@ -643,27 +643,25 @@ const toggleGroupSelection = (checked: boolean | null, items: readonly any[]) =>
const historyDynamicIcon = computed(() => (selected.value.length > 0 ? 'mdi-chevron-up' : 'mdi-timer-sand-paused'))
const historyDynamicMenuItems = computed(() => {
locale.value
if (selected.value.length === 0) return undefined
return [
{
title: t('components.transferQueue.title'),
titleKey: 'dialog.transferQueue.title',
icon: 'mdi-timer-sand-paused',
action: () => {
transferQueueDialog.value = true
},
},
{
title: t('transferHistory.actions.batchRedo'),
titleKey: 'transferHistory.actions.batchRedo',
icon: 'mdi-redo-variant',
action: () => {
retransferBatch()
},
},
{
title: t('transferHistory.actions.batchDelete'),
titleKey: 'transferHistory.actions.batchDelete',
icon: 'mdi-trash-can-outline',
color: 'error',
action: () => {
@@ -980,40 +978,31 @@ onUnmounted(() => {
<!-- app 模式下的 FAB 按钮 -->
<Teleport to="body" v-if="!appMode && route.path === '/history'">
<div v-if="isRefreshed">
<VFab
icon="mdi-timer-sand-paused"
color="info"
location="bottom"
size="x-large"
fixed
app
appear
@click="transferQueueDialog = true"
/>
<VFab
v-if="selected.length > 0"
class="mb-16"
icon="mdi-redo-variant"
color="primary"
location="bottom"
size="x-large"
fixed
app
appear
@click="retransferBatch"
/>
<div v-if="isRefreshed" class="compact-fab-stack compact-fab-stack--history">
<VFab
v-if="selected.length > 0"
icon="mdi-trash-can-outline"
color="error"
location="bottom"
size="x-large"
fixed
app
color="warning"
variant="tonal"
appear
class="compact-fab compact-fab--secondary"
@click="removeHistoryBatch"
class="mb-32"
/>
<VFab
v-if="selected.length > 0"
icon="mdi-redo-variant"
color="success"
variant="tonal"
appear
class="compact-fab compact-fab--secondary"
@click="retransferBatch"
/>
<VFab
icon="mdi-timer-sand-paused"
color="primary"
appear
class="compact-fab compact-fab--primary"
@click="transferQueueDialog = true"
/>
</div>
</Teleport>

View File

@@ -393,17 +393,15 @@ useDynamicButton({
/>
<!-- 新增站点按钮 -->
<Teleport to="body" v-if="route.path === '/site'">
<VFab
v-if="isRefreshed && !appMode"
icon="mdi-web-plus"
location="bottom"
size="x-large"
fixed
app
appear
@click="siteAddDialog = true"
:class="{ 'mb-12': appMode }"
/>
<div v-if="isRefreshed && !appMode" class="compact-fab-stack">
<VFab
icon="mdi-web-plus"
color="primary"
appear
class="compact-fab compact-fab--primary"
@click="siteAddDialog = true"
/>
</div>
</Teleport>
<!-- 新增站点弹窗 -->
<SiteAddEditDialog

View File

@@ -99,17 +99,15 @@ useDynamicButton({
<!-- 新增用户按钮 -->
<Teleport to="body" v-if="route.path === '/user'">
<VFab
v-if="isRefreshed && !appMode"
icon="mdi-account-plus"
location="bottom"
size="x-large"
fixed
app
appear
@click="openAddUserDialog"
:class="{ 'mb-12': appMode }"
/>
<div v-if="isRefreshed && !appMode" class="compact-fab-stack">
<VFab
icon="mdi-account-plus"
color="primary"
appear
class="compact-fab compact-fab--primary"
@click="openAddUserDialog"
/>
</div>
</Teleport>
<!-- 用户添加弹窗 -->