⚡ 全面优化 2026 前端响应式体验与加载性能
完成 FileCodeBox 2026 全站桌面端、平板和移动端的视觉交互复核,补齐文件选择后的批量操作闭环,并降低公共首屏的字体与低频依赖成本。 - 为移动文件列表增加全选、已选数量、批量编辑、策略与删除固定栏,并补充详情删除和空筛选重置 - 优化设置保存栏、分区导航、发送过期控件、仪表盘日期与图表操作、分页和记录抽屉 - 为后台侧栏增加遮罩、滚动锁定、Escape 关闭和焦点返回,完善登录密码可见性与国际化 - 移除全站强制 DingTalk 字体,按需加载 JSZip、Marked 和 DOMPurify,并停止空闲提示定时器 - 已通过架构检查、Vue 类型检查、ESLint、生产构建、48 组多视口明暗模式矩阵及核心流程回归
This commit is contained in:
@@ -3,8 +3,17 @@
|
||||
class="flex h-screen overflow-hidden flex-col transition-colors duration-300 lg:flex-row"
|
||||
:class="[isDarkMode ? 'bg-[#10191e]' : 'bg-[#dfe9eb]']"
|
||||
>
|
||||
<button
|
||||
v-if="isSidebarOpen"
|
||||
type="button"
|
||||
class="fixed inset-0 z-40 bg-black/45 backdrop-blur-[1px] lg:hidden"
|
||||
:aria-label="t('common.closeMenu')"
|
||||
@click="closeSidebar"
|
||||
/>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<aside
|
||||
ref="sidebarRef"
|
||||
class="fixed inset-y-0 left-0 z-50 flex h-full w-64 shrink-0 transform flex-col border-r lg:relative lg:h-screen lg:translate-x-0"
|
||||
:class="[
|
||||
isDarkMode
|
||||
@@ -38,7 +47,7 @@
|
||||
{{ t('common.appName') }}
|
||||
</h1>
|
||||
</div>
|
||||
<button type="button" :aria-label="t('common.closeMenu')" :title="t('common.closeMenu')" @click="toggleSidebar" class="flex h-11 w-11 items-center justify-center rounded-lg lg:hidden">
|
||||
<button type="button" :aria-label="t('common.closeMenu')" :title="t('common.closeMenu')" @click="closeSidebar" class="flex h-11 w-11 items-center justify-center rounded-lg lg:hidden">
|
||||
<XIcon class="w-6 h-6" :class="[isDarkMode ? 'text-gray-400' : 'text-gray-600']" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -93,7 +102,7 @@
|
||||
:class="[isDarkMode ? 'bg-[#1a2930] border-[#31454d]' : 'bg-[#f2f6f5] border-[#c8d7da]']"
|
||||
>
|
||||
<div class="flex h-14 items-center justify-between px-4">
|
||||
<button type="button" :aria-label="t('common.openMenu')" :title="t('common.openMenu')" @click="toggleSidebar" class="flex h-11 w-11 items-center justify-center rounded-lg lg:hidden">
|
||||
<button ref="menuButtonRef" type="button" :aria-label="t('common.openMenu')" :title="t('common.openMenu')" :aria-expanded="isSidebarOpen" @click="openSidebar" class="flex h-11 w-11 items-center justify-center rounded-lg lg:hidden">
|
||||
<MenuIcon class="w-6 h-6" :class="[isDarkMode ? 'text-gray-400' : 'text-gray-600']" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -111,7 +120,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, inject, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, inject, nextTick, onMounted, onUnmounted, watch } from 'vue'
|
||||
import {
|
||||
BoxIcon,
|
||||
MenuIcon,
|
||||
@@ -160,16 +169,36 @@ const menuItems: MenuItem[] = [
|
||||
]
|
||||
|
||||
const isSidebarOpen = ref(true)
|
||||
const toggleSidebar = () => {
|
||||
isSidebarOpen.value = !isSidebarOpen.value
|
||||
const sidebarRef = ref<HTMLElement | null>(null)
|
||||
const menuButtonRef = ref<HTMLButtonElement | null>(null)
|
||||
|
||||
const openSidebar = async () => {
|
||||
isSidebarOpen.value = true
|
||||
await nextTick()
|
||||
sidebarRef.value?.querySelector<HTMLElement>('button, a[href]')?.focus()
|
||||
}
|
||||
const closeSidebar = async () => {
|
||||
isSidebarOpen.value = false
|
||||
await nextTick()
|
||||
menuButtonRef.value?.focus()
|
||||
}
|
||||
|
||||
const closeSidebarForMobile = () => {
|
||||
if (window.innerWidth < 1024) {
|
||||
isSidebarOpen.value = false
|
||||
void closeSidebar()
|
||||
}
|
||||
}
|
||||
|
||||
const handleEscape = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape' && window.innerWidth < 1024 && isSidebarOpen.value) {
|
||||
void closeSidebar()
|
||||
}
|
||||
}
|
||||
|
||||
watch(isSidebarOpen, (open) => {
|
||||
if (window.innerWidth < 1024) document.body.style.overflow = open ? 'hidden' : ''
|
||||
})
|
||||
|
||||
// 响应式处理
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth >= 1024) {
|
||||
@@ -182,6 +211,7 @@ const handleResize = () => {
|
||||
onMounted(() => {
|
||||
handleResize()
|
||||
window.addEventListener('resize', handleResize)
|
||||
window.addEventListener('keydown', handleEscape)
|
||||
void verifySession().then((isValid) => {
|
||||
if (!isValid) {
|
||||
void router.push(ROUTES.LOGIN)
|
||||
@@ -191,6 +221,8 @@ onMounted(() => {
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
window.removeEventListener('keydown', handleEscape)
|
||||
document.body.style.overflow = ''
|
||||
})
|
||||
|
||||
// 登出处理
|
||||
|
||||
Reference in New Issue
Block a user