Files
meiandClaude Fable 5 f8c6115737 feat(web): 移动端适配
- 侧边栏在窄屏改为抽屉:汉堡按钮唤起、遮罩点击关闭、切换路由自动收起
- 页头纵向排列,操作按钮与筛选控件撑满一行
- 对话框改用视口百分比宽度,表单标签改为顶部对齐,内容区限高可滚动
- 表格隐藏次要列并把操作列固定在右侧,仍可横向滚动查看全部
- 仪表盘倒计时环与信息上下排列,统计卡改两列
- 分页器在窄屏收缩为精简布局
- 输入框字号提到 16px,避免 iOS Safari 聚焦时自动缩放
- 新增 useIsMobile composable 处理 CSS 覆盖不到的部分

顺带修复汉堡按钮在桌面端未隐藏:.menu-btn 与后声明的 .icon-btn
特异性相同被覆盖,改用 .icon-btn.menu-btn 复合选择器。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 22:57:52 +08:00

37 lines
1.1 KiB
TypeScript

import { onUnmounted, ref } from 'vue'
/** 移动端断点,与 main.css 中的媒体查询保持一致 */
export const MOBILE_BREAKPOINT = 768
/**
* 响应式的移动端判断。
*
* 用于那些光靠 CSS 改不了的地方,比如表格列的显隐、分页器布局、表单标签位置。
*
* 除了监听 matchMedia 的 change,额外挂一个 resize 兜底:
* 某些环境(内嵌 WebView、开发者工具的设备模拟)改视口时不会派发 change,
* 只靠 change 会导致旋转屏幕后布局不跟着变。
*/
export function useIsMobile() {
const query = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT}px)`)
const isMobile = ref(query.matches)
const sync = () => {
if (isMobile.value !== query.matches) {
isMobile.value = query.matches
}
}
query.addEventListener('change', sync)
window.addEventListener('resize', sync, { passive: true })
window.addEventListener('orientationchange', sync)
onUnmounted(() => {
query.removeEventListener('change', sync)
window.removeEventListener('resize', sync)
window.removeEventListener('orientationchange', sync)
})
return isMobile
}