feat(ui): finalize shared shells and loading states

This commit is contained in:
caoxiaozhu
2026-05-29 13:17:39 +08:00
parent 64cc76c970
commit e080105f9f
52 changed files with 1559 additions and 861 deletions

View File

@@ -1,4 +1,5 @@
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useSystemState } from './useSystemState.js'
import { useThemeSkin } from './useThemeSkin.js'
@@ -26,7 +27,20 @@ import {
readStoredSettings
} from '../utils/settingsModelHelper.js'
const sectionIds = new Set(SECTION_DEFINITIONS.map((section) => section.id))
function resolveSectionId(value) {
const sectionId = String(value || '').trim()
return sectionIds.has(sectionId) ? sectionId : 'profile'
}
function resolveInitialSectionId(route) {
return route.name === 'app-log-detail' ? 'systemLogs' : resolveSectionId(route.query.section)
}
export function useSettings() {
const route = useRoute()
const router = useRouter()
const { toast } = useToast()
const { companyProfile, currentUser, updateCompanyProfilePreview } = useSystemState()
const {
@@ -38,7 +52,7 @@ export function useSettings() {
const buildResolvedDefaults = () => buildDefaultState(companyProfile.value, currentUser.value)
const pageState = ref(mergeState(buildResolvedDefaults(), readStoredSettings()))
const activeSection = ref('profile')
const activeSection = ref(resolveInitialSectionId(route))
const sessionRetentionPickerOpen = ref(false)
const sessionRetentionPickerRef = ref(null)
const logoInputRef = ref(null)
@@ -55,6 +69,7 @@ export function useSettings() {
const sectionStatus = computed(() => computeSectionStatus(pageState.value))
const completedSectionCount = computed(() => Object.values(sectionStatus.value).filter(Boolean).length)
const systemLogDetailMode = computed(() => route.name === 'app-log-detail')
const activeSectionConfig = computed(
() => sections.find((section) => section.id === activeSection.value) || sections[0]
)
@@ -150,9 +165,37 @@ export function useSettings() {
}
}
function activateSection(sectionId) {
function syncActiveSectionRoute(sectionId) {
if (route.name !== 'app-settings') {
return
}
const nextQuery = { ...route.query }
if (sectionId === 'profile') {
delete nextQuery.section
} else {
nextQuery.section = sectionId
}
if (String(route.query.section || '') === String(nextQuery.section || '')) {
return
}
void router.replace({
name: 'app-settings',
query: nextQuery,
hash: route.hash
})
}
function activateSection(sectionId, options = {}) {
const nextSectionId = resolveSectionId(sectionId)
sessionRetentionPickerOpen.value = false
activeSection.value = sectionId
activeSection.value = nextSectionId
if (!options.skipRouteSync) {
syncActiveSectionRoute(nextSectionId)
}
}
function toggleBoolean(formKey, field) {
@@ -447,6 +490,10 @@ export function useSettings() {
return
}
if (activeSection.value === 'systemLogs') {
return
}
if (activeSection.value === 'rendering') {
await saveRenderingSection()
return
@@ -462,6 +509,16 @@ export function useSettings() {
loadSettingsSnapshot()
})
watch(
() => [route.name, route.query.section],
() => {
const nextSectionId = resolveInitialSectionId(route)
if (activeSection.value !== nextSectionId) {
activateSection(nextSectionId, { skipRouteSync: true })
}
}
)
onBeforeUnmount(() => {
if (typeof document !== 'undefined') {
document.removeEventListener('pointerdown', handleDocumentPointerDown)
@@ -512,6 +569,7 @@ export function useSettings() {
saveActiveSection,
sectionStatus,
sections,
systemLogDetailMode,
selectThemeSkin,
selectSessionRetentionDays,
themeSkinOptions,