修复后台折叠状态和保存提示

This commit is contained in:
yml
2026-05-28 11:29:46 +08:00
parent ccc350cfea
commit 26d40a2c13
5 changed files with 94 additions and 12 deletions
@@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue' import { computed, onMounted, reactive, ref, watch } from 'vue'
import { showError, showSuccess } from '@/lib/feedback'
import { import {
fetchAdminCloudtentaclesOverrideRules, fetchAdminCloudtentaclesOverrideRules,
fetchAdminCloudtentaclesSkuList, fetchAdminCloudtentaclesSkuList,
@@ -142,8 +143,10 @@ async function saveOverrideRules() {
overrideRules.value = Array.isArray(response.data.rules) overrideRules.value = Array.isArray(response.data.rules)
? response.data.rules.map((rule) => normalizeEditableRule(rule)) ? response.data.rules.map((rule) => normalizeEditableRule(rule))
: [] : []
showSuccess(`商品覆盖规则已保存,共 ${overrideRules.value.length}`)
} catch (error) { } catch (error) {
overrideErrorMessage.value = error instanceof Error ? error.message : '保存 cloudtentacles 覆盖规则失败' overrideErrorMessage.value = error instanceof Error ? error.message : '保存 cloudtentacles 覆盖规则失败'
showError(overrideErrorMessage.value)
} finally { } finally {
overrideSaving.value = false overrideSaving.value = false
} }
@@ -30,9 +30,11 @@ import { formatAdminDateTime } from '@/utils/admin-time'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const sidebarStorageKey = 'admin-sidebar-collapsed' const sidebarStorageKey = 'admin-sidebar-collapsed'
const sidebarMenuOpenedsStorageKey = 'admin-sidebar-menu-openeds'
const isSidebarCollapsed = ref( const isSidebarCollapsed = ref(
typeof window !== 'undefined' && window.localStorage.getItem(sidebarStorageKey) === '1', typeof window !== 'undefined' && window.localStorage.getItem(sidebarStorageKey) === '1',
) )
const sidebarMenuOpeneds = ref(readSidebarMenuOpeneds())
const currentRole = computed(() => getAdminRole()) const currentRole = computed(() => getAdminRole())
const isAdmin = computed(() => currentRole.value === 'admin') const isAdmin = computed(() => currentRole.value === 'admin')
@@ -110,6 +112,20 @@ function toggleSidebarCollapse() {
} }
} }
function handleSidebarMenuOpen(index: string) {
const normalizedIndex = String(index || '').trim()
if (!normalizedIndex) return
sidebarMenuOpeneds.value = Array.from(new Set([...sidebarMenuOpeneds.value, normalizedIndex]))
writeSidebarMenuOpeneds(sidebarMenuOpeneds.value)
}
function handleSidebarMenuClose(index: string) {
const normalizedIndex = String(index || '').trim()
sidebarMenuOpeneds.value = sidebarMenuOpeneds.value.filter((item) => item !== normalizedIndex)
writeSidebarMenuOpeneds(sidebarMenuOpeneds.value)
}
async function submitLogout() { async function submitLogout() {
try { try {
await logoutAdmin() await logoutAdmin()
@@ -121,6 +137,34 @@ async function submitLogout() {
await router.replace('/admin/login') await router.replace('/admin/login')
} }
} }
function readSidebarMenuOpeneds(): string[] {
if (typeof window === 'undefined') {
return []
}
try {
const rawValue = window.localStorage.getItem(sidebarMenuOpenedsStorageKey)
if (!rawValue) {
return []
}
const parsed = JSON.parse(rawValue)
return Array.isArray(parsed)
? Array.from(new Set(parsed.map((item) => String(item || '').trim()).filter(Boolean)))
: []
} catch {
return []
}
}
function writeSidebarMenuOpeneds(openeds: string[]) {
if (typeof window === 'undefined') {
return
}
window.localStorage.setItem(sidebarMenuOpenedsStorageKey, JSON.stringify(openeds))
}
</script> </script>
<template> <template>
@@ -151,12 +195,14 @@ async function submitLogout() {
<el-menu <el-menu
:default-active="activeNavIndex" :default-active="activeNavIndex"
:default-openeds="['/admin/platform-shops']" :default-openeds="sidebarMenuOpeneds"
router router
class="sidebar-menu" class="sidebar-menu"
:collapse="isSidebarCollapsed" :collapse="isSidebarCollapsed"
:collapse-transition="false" :collapse-transition="false"
:ellipsis="false" :ellipsis="false"
@open="handleSidebarMenuOpen"
@close="handleSidebarMenuClose"
> >
<template v-for="item in navItems" :key="item.to"> <template v-for="item in navItems" :key="item.to">
<el-sub-menu v-if="item.children?.length" :index="item.to"> <el-sub-menu v-if="item.children?.length" :index="item.to">
@@ -52,9 +52,10 @@ type Props = {
defineProps<Props>() defineProps<Props>()
const advancedCollapseNames = useRememberedCollapse( const {
'admin:platform-config:cloudtentacles:config:collapse', activeNames: advancedCollapseNames,
) handleChange: handleAdvancedCollapseChange,
} = useRememberedCollapse('admin:platform-config:cloudtentacles:config:collapse')
</script> </script>
<template> <template>
@@ -250,7 +251,12 @@ const advancedCollapseNames = useRememberedCollapse(
</el-form> </el-form>
</div> </div>
<el-collapse v-model="advancedCollapseNames" class="advanced-collapse"> <el-collapse
:model-value="advancedCollapseNames"
class="advanced-collapse"
@update:model-value="handleAdvancedCollapseChange"
@change="handleAdvancedCollapseChange"
>
<el-collapse-item name="advanced" title="高级参数与调试字段"> <el-collapse-item name="advanced" title="高级参数与调试字段">
<el-form label-width="auto" label-position="top"> <el-form label-width="auto" label-position="top">
<div class="form-grid"> <div class="form-grid">
@@ -22,14 +22,19 @@ type Props = {
defineProps<Props>() defineProps<Props>()
const debugCollapseNames = useRememberedCollapse( const {
'admin:platform-config:cloudtentacles:debug:collapse', activeNames: debugCollapseNames,
) handleChange: handleDebugCollapseChange,
} = useRememberedCollapse('admin:platform-config:cloudtentacles:debug:collapse')
</script> </script>
<template> <template>
<el-card class="debug-card"> <el-card class="debug-card">
<el-collapse v-model="debugCollapseNames"> <el-collapse
:model-value="debugCollapseNames"
@update:model-value="handleDebugCollapseChange"
@change="handleDebugCollapseChange"
>
<el-collapse-item name="debug"> <el-collapse-item name="debug">
<template #title> <template #title>
<div class="debug-title"> <div class="debug-title">
@@ -1,8 +1,22 @@
import { ref, watch, type Ref } from 'vue' import { ref, watch, type Ref } from 'vue'
export function useRememberedCollapse(storageKey: string, defaultValue: string[] = []): Ref<string[]> { export type RememberedCollapseState = {
activeNames: Ref<string[]>
handleChange: (value: unknown) => void
}
export function useRememberedCollapse(
storageKey: string,
defaultValue: string[] = [],
): RememberedCollapseState {
const activeNames = ref<string[]>(readStoredCollapseNames(storageKey, defaultValue)) const activeNames = ref<string[]>(readStoredCollapseNames(storageKey, defaultValue))
function handleChange(value: unknown) {
const nextNames = normalizeCollapseNames(value)
activeNames.value = nextNames
writeStoredCollapseNames(storageKey, nextNames)
}
watch( watch(
activeNames, activeNames,
(names) => { (names) => {
@@ -11,7 +25,10 @@ export function useRememberedCollapse(storageKey: string, defaultValue: string[]
{ deep: true }, { deep: true },
) )
return activeNames return {
activeNames,
handleChange,
}
} }
function readStoredCollapseNames(storageKey: string, defaultValue: string[]): string[] { function readStoredCollapseNames(storageKey: string, defaultValue: string[]): string[] {
@@ -32,7 +49,7 @@ function readStoredCollapseNames(storageKey: string, defaultValue: string[]): st
} }
} }
function writeStoredCollapseNames(storageKey: string, names: string[]): void { function writeStoredCollapseNames(storageKey: string, names: unknown): void {
if (!canUseLocalStorage()) { if (!canUseLocalStorage()) {
return return
} }
@@ -45,6 +62,11 @@ function writeStoredCollapseNames(storageKey: string, names: string[]): void {
} }
function normalizeCollapseNames(value: unknown, fallback: string[] = []): string[] { function normalizeCollapseNames(value: unknown, fallback: string[] = []): string[] {
if (typeof value === 'string' || typeof value === 'number') {
const normalized = String(value || '').trim()
return normalized ? [normalized] : []
}
if (!Array.isArray(value)) { if (!Array.isArray(value)) {
return [...fallback] return [...fallback]
} }