diff --git a/fund-admin/src/components/MobileSidebar/index.vue b/fund-admin/src/components/MobileSidebar/index.vue
new file mode 100644
index 0000000..60a187e
--- /dev/null
+++ b/fund-admin/src/components/MobileSidebar/index.vue
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
diff --git a/fund-admin/src/composables/useMobile.js b/fund-admin/src/composables/useMobile.js
new file mode 100644
index 0000000..592cbbb
--- /dev/null
+++ b/fund-admin/src/composables/useMobile.js
@@ -0,0 +1,209 @@
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+
+// 断点定义
+const BREAKPOINTS = {
+ xs: 768, // 手机
+ sm: 992, // 平板
+ md: 1200, // 小桌面
+ lg: 1920 // 大桌面
+}
+
+/**
+ * 移动端检测组合式函数
+ */
+export function useMobile() {
+ // 视口宽度
+ const width = ref(window.innerWidth)
+ const height = ref(window.innerHeight)
+
+ // 是否移动端(< 768px)
+ const isMobile = computed(() => width.value < BREAKPOINTS.xs)
+
+ // 是否平板(768px - 992px)
+ const isTablet = computed(() => width.value >= BREAKPOINTS.xs && width.value < BREAKPOINTS.sm)
+
+ // 是否桌面(>= 992px)
+ const isDesktop = computed(() => width.value >= BREAKPOINTS.sm)
+
+ // 是否小屏幕(< 992px)
+ const isSmallScreen = computed(() => width.value < BREAKPOINTS.sm)
+
+ // 当前断点
+ const breakpoint = computed(() => {
+ if (width.value < BREAKPOINTS.xs) return 'xs'
+ if (width.value < BREAKPOINTS.sm) return 'sm'
+ if (width.value < BREAKPOINTS.md) return 'md'
+ if (width.value < BREAKPOINTS.lg) return 'lg'
+ return 'xl'
+ })
+
+ // 侧边栏是否折叠
+ const sidebarCollapsed = ref(false)
+
+ // 移动端侧边栏是否打开
+ const mobileSidebarOpen = ref(false)
+
+ // 切换侧边栏
+ const toggleSidebar = () => {
+ if (isMobile.value) {
+ mobileSidebarOpen.value = !mobileSidebarOpen.value
+ } else {
+ sidebarCollapsed.value = !sidebarCollapsed.value
+ }
+ }
+
+ // 关闭移动端侧边栏
+ const closeMobileSidebar = () => {
+ mobileSidebarOpen.value = false
+ }
+
+ // 打开移动端侧边栏
+ const openMobileSidebar = () => {
+ mobileSidebarOpen.value = true
+ }
+
+ // 监听窗口大小变化
+ const handleResize = () => {
+ width.value = window.innerWidth
+ height.value = window.innerHeight
+
+ // 切换到桌面端时关闭移动端侧边栏
+ if (!isMobile.value) {
+ mobileSidebarOpen.value = false
+ }
+ }
+
+ onMounted(() => {
+ window.addEventListener('resize', handleResize)
+ handleResize()
+ })
+
+ onUnmounted(() => {
+ window.removeEventListener('resize', handleResize)
+ })
+
+ return {
+ width,
+ height,
+ isMobile,
+ isTablet,
+ isDesktop,
+ isSmallScreen,
+ breakpoint,
+ sidebarCollapsed,
+ mobileSidebarOpen,
+ toggleSidebar,
+ closeMobileSidebar,
+ openMobileSidebar
+ }
+}
+
+/**
+ * 响应式表格组合式函数
+ */
+export function useResponsiveTable() {
+ const { isMobile } = useMobile()
+
+ // 表格高度
+ const tableHeight = computed(() => {
+ if (isMobile.value) {
+ return 'auto'
+ }
+ // 桌面端:视口高度 - 头部(50) - 搜索区域(80) - 分页(50) - 边距(40)
+ return window.innerHeight - 220
+ })
+
+ // 分页大小选项
+ const pageSizeOptions = computed(() => {
+ return isMobile.value ? [10, 20] : [10, 20, 50, 100]
+ })
+
+ // 默认分页大小
+ const defaultPageSize = computed(() => {
+ return isMobile.value ? 10 : 20
+ })
+
+ return {
+ isMobile,
+ tableHeight,
+ pageSizeOptions,
+ defaultPageSize
+ }
+}
+
+/**
+ * 触摸手势支持
+ */
+export function useTouchGesture() {
+ const touchStartX = ref(0)
+ const touchEndX = ref(0)
+ const touchStartY = ref(0)
+ const touchEndY = ref(0)
+
+ // 最小滑动距离
+ const MIN_SWIPE_DISTANCE = 50
+
+ // 处理触摸开始
+ const handleTouchStart = (e) => {
+ touchStartX.value = e.touches[0].clientX
+ touchStartY.value = e.touches[0].clientY
+ }
+
+ // 处理触摸结束
+ const handleTouchEnd = (e) => {
+ touchEndX.value = e.changedTouches[0].clientX
+ touchEndY.value = e.changedTouches[0].clientY
+
+ return {
+ direction: getSwipeDirection(),
+ distance: Math.abs(touchEndX.value - touchStartX.value)
+ }
+ }
+
+ // 获取滑动方向
+ const getSwipeDirection = () => {
+ const diffX = touchEndX.value - touchStartX.value
+ const diffY = touchEndY.value - touchStartY.value
+
+ // 判断是水平滑动还是垂直滑动
+ if (Math.abs(diffX) > Math.abs(diffY)) {
+ if (Math.abs(diffX) < MIN_SWIPE_DISTANCE) return null
+ return diffX > 0 ? 'right' : 'left'
+ } else {
+ if (Math.abs(diffY) < MIN_SWIPE_DISTANCE) return null
+ return diffY > 0 ? 'down' : 'up'
+ }
+ }
+
+ return {
+ handleTouchStart,
+ handleTouchEnd,
+ getSwipeDirection
+ }
+}
+
+/**
+ * 虚拟键盘检测
+ */
+export function useVirtualKeyboard() {
+ const isKeyboardOpen = ref(false)
+ const windowHeight = ref(window.innerHeight)
+
+ const handleResize = () => {
+ const currentHeight = window.innerHeight
+ // 如果窗口高度变小超过150px,认为是虚拟键盘打开
+ isKeyboardOpen.value = windowHeight.value - currentHeight > 150
+ }
+
+ onMounted(() => {
+ window.addEventListener('resize', handleResize)
+ })
+
+ onUnmounted(() => {
+ window.removeEventListener('resize', handleResize)
+ })
+
+ return {
+ isKeyboardOpen
+ }
+}
diff --git a/fund-admin/src/styles/mobile.scss b/fund-admin/src/styles/mobile.scss
new file mode 100644
index 0000000..336f1e3
--- /dev/null
+++ b/fund-admin/src/styles/mobile.scss
@@ -0,0 +1,296 @@
+// 移动端适配样式
+// 断点定义:xs < 768px < sm < 992px < md < 1200px < lg
+
+// 移动端基础样式
+@media screen and (max-width: 768px) {
+ // 隐藏侧边栏
+ .sidebar-container {
+ transform: translateX(-100%);
+ transition: transform 0.3s;
+
+ &.mobile-open {
+ transform: translateX(0);
+ }
+ }
+
+ // 主内容区域全宽
+ .main-container {
+ margin-left: 0 !important;
+ width: 100% !important;
+ }
+
+ // 顶部导航栏适配
+ .navbar {
+ .hamburger-container {
+ display: none;
+ }
+
+ .breadcrumb-container {
+ display: none;
+ }
+
+ .right-menu {
+ .right-menu-item {
+ padding: 0 8px;
+ }
+ }
+ }
+
+ // 搜索表单改为垂直布局
+ .search-form {
+ .el-form-item {
+ margin-right: 0;
+ margin-bottom: 10px;
+ width: 100%;
+
+ .el-input,
+ .el-select {
+ width: 100% !important;
+ }
+ }
+
+ .el-button {
+ width: 100%;
+ margin-left: 0 !important;
+ margin-bottom: 10px;
+ }
+ }
+
+ // 表格操作按钮
+ .el-table {
+ .el-button--link {
+ padding: 4px 8px;
+ font-size: 12px;
+ }
+ }
+
+ // 分页器适配
+ .el-pagination {
+ .el-pagination__sizes,
+ .el-pagination__jump {
+ display: none;
+ }
+
+ .btn-prev,
+ .btn-next {
+ min-width: 28px;
+ }
+
+ .el-pager li {
+ min-width: 28px;
+ }
+ }
+
+ // 对话框全屏
+ .el-dialog {
+ width: 100% !important;
+ margin: 0 !important;
+ border-radius: 0 !important;
+ height: 100vh;
+
+ .el-dialog__body {
+ max-height: calc(100vh - 120px);
+ overflow-y: auto;
+ }
+ }
+
+ // 抽屉全屏
+ .el-drawer {
+ width: 100% !important;
+ }
+
+ // 表单单行显示
+ .el-form {
+ .el-form-item {
+ margin-bottom: 15px;
+
+ .el-form-item__label {
+ float: none;
+ display: block;
+ text-align: left;
+ margin-bottom: 5px;
+ }
+
+ .el-form-item__content {
+ margin-left: 0 !important;
+ }
+ }
+ }
+
+ // 卡片内边距减小
+ .el-card {
+ .el-card__header {
+ padding: 12px 15px;
+ }
+
+ .el-card__body {
+ padding: 15px;
+ }
+ }
+
+ // 统计卡片
+ .dashboard-card {
+ margin-bottom: 15px;
+
+ .card-icon {
+ font-size: 36px;
+ }
+
+ .card-value {
+ font-size: 20px;
+ }
+ }
+
+ // 底部固定按钮
+ .fixed-bottom-buttons {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 10px 15px;
+ background: #fff;
+ box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
+ z-index: 100;
+ display: flex;
+ gap: 10px;
+
+ .el-button {
+ flex: 1;
+ }
+ }
+
+ // 底部留白(避免被固定按钮遮挡)
+ .has-fixed-bottom {
+ padding-bottom: 60px;
+ }
+}
+
+// 平板适配
+@media screen and (min-width: 769px) and (max-width: 992px) {
+ .sidebar-container {
+ width: 54px !important;
+
+ .el-menu {
+ .el-sub-menu__title,
+ .el-menu-item {
+ padding: 0 15px !important;
+
+ span {
+ display: none;
+ }
+
+ .el-sub-menu__icon-arrow {
+ display: none;
+ }
+ }
+ }
+ }
+
+ .main-container {
+ margin-left: 54px !important;
+ }
+}
+
+// 移动端菜单按钮
+.mobile-menu-btn {
+ display: none;
+
+ @media screen and (max-width: 768px) {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 40px;
+ font-size: 20px;
+ cursor: pointer;
+ }
+}
+
+// 移动端遮罩层
+.mobile-sidebar-mask {
+ display: none;
+
+ @media screen and (max-width: 768px) {
+ display: block;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ z-index: 999;
+ opacity: 0;
+ visibility: hidden;
+ transition: all 0.3s;
+
+ &.show {
+ opacity: 1;
+ visibility: visible;
+ }
+ }
+}
+
+// 响应式工具类
+.hide-on-mobile {
+ @media screen and (max-width: 768px) {
+ display: none !important;
+ }
+}
+
+.show-on-mobile {
+ display: none !important;
+
+ @media screen and (max-width: 768px) {
+ display: block !important;
+ }
+}
+
+// 响应式表格
+.responsive-table {
+ @media screen and (max-width: 768px) {
+ .el-table {
+ &__header-wrapper {
+ display: none;
+ }
+
+ &__body-wrapper {
+ .el-table__row {
+ display: block;
+ margin-bottom: 15px;
+ border: 1px solid #ebeef5;
+ border-radius: 4px;
+ padding: 10px;
+
+ td {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border: none;
+ padding: 8px 0;
+
+ &:not(:last-child) {
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ &::before {
+ content: attr(data-label);
+ font-weight: bold;
+ color: #606266;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// 触摸优化
+@media (hover: none) {
+ .el-button:hover {
+ opacity: 1;
+ }
+
+ .el-table__row:hover > td {
+ background-color: transparent !important;
+ }
+}