多体系建设信息化条统-前端
zhouwx
2026-02-10 c2b4a583f693fba8e10165d0ef706fb7683753fb
src/views/menuPage.vue
@@ -1,658 +1,185 @@
<template>
  <div class="system-select-container">
    <div class="user-info-bar">
      <div class="user-left"></div>
      <h3 class="user-details">欢迎访问多体系建设信息化系统</h3>
      <div class="avatar-container">
        <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
          <div class="avatar-wrapper" style="display: flex;align-items: center">
  <div class="multi-system-dashboard">
    <!-- 头部 -->
    <header>
      <div class="header-container">
        <div class="system-title">欢迎进入多体系建设信息化系统</div>
<!--        <div class="admin-info" @click="handleAdminClick" ref="adminInfoRef">-->
<!--          <div class="admin-icon">-->
<!--            <i class="fas fa-user-cog"></i>-->
<!--          </div>-->
<!--          <div class="admin-details">-->
<!--            <div class="admin-name">admin</div>-->
<!--            <div class="admin-role">系统管理员</div>-->
<!--          </div>-->
<!--        </div>-->
        <div class="admin-info">
          <div class="admin-icon">
            <img src="../assets/images/avator.png" class="user-avatar"  />
            <span style="font-size: 16px">{{userName}}({{userTypeName}})</span>
            <el-icon><caret-bottom /></el-icon>
          </div>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="password">
                <span>修改密码</span>
              </el-dropdown-item>
              <el-dropdown-item divided command="logout">
                <span>退出登录</span>
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </div>
    <!-- 重新布局的系统选择区域 -->
    <div class="systems-container">
      <div class="layout-container">
        <!-- 左侧列 -->
        <div class="left-column">
          <!-- 通知公告 -->
          <div class="module-card notice-module">
            <div class="module-header">
              <h3>通知公告</h3>
              <span class="more-link" @click="toNoticeMng">更多 ></span>
          <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
            <div class="admin-details">
              <div class="admin-name">{{userName}}</div>
              <div class="admin-role">{{userTypeName}}</div>
            </div>
            <div class="notice-list">
              <div class="notice-item" v-for="item in noticeList" :key="item">
                <span class="notice-title" @click="openNoticeFile(item.filePath)">{{item.content}}</span>
                <span class="notice-date">{{item.publishDate}}</span>
              </div>
            </div>
          </div>
          <!-- 流程中心 -->
          <div class="module-card process-module">
            <div class="module-header">
              <h3>流程中心</h3>
<!--              <span class="more-link">更多 ></span>-->
            </div>
            <div class="process-list" v-if="flowList && flowList.length>0">
              <div class="process-item" v-for="process in flowList" :key="process.id">
                <div class="process-info" @click="openDetail(process)">
                  <span class="process-status" :class="{processing: process.type == 1,pending: process.type == 2,success: process.type == 3,normal: process.type == 4,seal: process.type == 5}">
                    {{process.type == 1? '内审实施计划':process.type == 2? '培训计划':process.type == 3? '项目评审':process.type == 4?'年度检定计划':process.type == 5?'用章审批(申请)': '用章审批(待审批)'}}
                  </span>
                  <span class="process-name">{{process.title}}</span>
                </div>
              </div>
            </div>
            <div class="process-list" v-else>
              <span style="color: #999;font-size: 16px">暂无流程</span>
            </div>
          </div>
          <!-- 备忘录 -->
          <div class="module-card memo-module">
            <div class="module-header">
              <h3>备忘录</h3>
              <el-button @click="addMemo" type="primary">保存</el-button>
            </div>
            <div class="memo-content">
              <div class="memo-input">
                <el-input
                    v-model="memo.content"
                    placeholder="添加新的备忘录..."
                    type="textarea"
                    :autosize="{ minRows: 6, maxRows: 10}"
                >
                </el-input>
                <div class="memo-time" v-if="memo.updateTime">{{memo.updateTime}}</div>
              </div>
            </div>
          </div>
        </div>
        <!-- 右侧列 -->
        <div class="right-column">
          <!-- 快捷入口 -->
          <div class="module-card quick-access-module">
            <div class="module-header">
              <h3>快捷入口</h3>
              <div class="pagination-controls" v-if="platformList.length > 9">
                <el-button
                    :icon="ArrowLeft"
                    @click="prevPage"
                    size="small"
                    :disabled="currentPage === 0"
                    circle
                />
                <span class="page-info">{{ currentPage + 1 }}/{{ totalPages }}</span>
                <el-button
                    :icon="ArrowRight"
                    @click="nextPage"
                    size="small"
                    :disabled="currentPage === totalPages - 1"
                    circle
                />
              </div>
            </div>
            <div class="systems-grid-container">
              <div class="systems-grid">
                <div
                    v-for="(system, index) in displayedSystems"
                    :key="system.id"
                    class="system-card"
                    @mouseenter="handleCardEnter($event, system.id)"
                    @mousemove="handleCardMove($event, system.id)"
                    @mouseleave="handleCardLeave(system.id)"
                    @click="enterSystem(system.platformAddress, getActualIndex(index))"
                    :style="getCardStyle(system.id)"
                >
                  <div class="card-content">
                    <div class="system-icon">
                      <el-image v-if="getActualIndex(index) == 0" :src="system.platformPic"/>
                      <el-image v-else :src="picUrl + system.platformPic"/>
                    </div>
                    <h3>{{ system.platformName }}</h3>
                  </div>
                </div>
                <!-- 填充空白格子 -->
                <div
                    v-if="showEmptyCard && displayedSystems.length < 9"
                    class="system-card empty-card"
                    @click="openAdd('add',{})"
                >
                  <div class="card-content">
                    <div class="system-icon">
                      <el-icon><Plus /></el-icon>
                    </div>
                    <h3>新增平台</h3>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- 日历 -->
          <div class="module-card calendar-module">
            <div class="module-header">
              <h3>日历</h3>
            </div>
            <div class="calendar-header">
              <div class="lunar-info">
                <span class="lunar-date-full">{{ currentLunarDate }}</span>
                <span class="lunar-year">{{ currentLunarYear }}</span>
              </div>
              <div class="current-date-info">
                <div class="solar-date-large">{{ currentSolarDate }}</div>
                <div class="week-day">{{ currentWeekDay }}</div>
              </div>
              <div class="calendar-actions">
                <el-button-group>
                  <el-button :icon="ArrowLeft" @click="prevMonth" size="small" />
                  <el-button @click="goToday" size="small">今天</el-button>
                  <el-button :icon="ArrowRight" @click="nextMonth" size="small" />
                </el-button-group>
              </div>
            </div>
            <div class="calendar-content">
              <el-calendar v-model="currentDate" ref="calendarRef">
                <template #header>
                  <!-- 隐藏默认header -->
                  <div style="display: none;"></div>
                </template>
                <template #date-cell="{ data }">
                  <div class="calendar-date" :class="{ 'is-today': isToday(data.day), 'is-current-month': isCurrentMonth(data.day) }">
                    <div class="solar-date">{{ getSolarDate(data.day) }}</div>
                    <div class="lunar-date">{{ getLunarDate(data.day) }}</div>
                    <div v-if="hasEvent(data.day)" class="calendar-event-dot"></div>
                  </div>
                </template>
              </el-calendar>
            </div>
          </div>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="password">
                  <span>修改密码</span>
                </el-dropdown-item>
                <el-dropdown-item divided command="logout">
                  <span>退出登录</span>
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </div>
    </header>
    <!-- 主体内容 -->
    <div class="menu-container">
      <section class="welcome-section">
        <div class="welcome-decoration"></div>
        <h1 class="welcome-title">多体系建设信息化系统</h1>
        <p class="welcome-subtitle">
          本系统集成多个国际与国内管理体系标准,为企业提供全面、协同、高效的信息化管理平台。通过统一门户实现质量管理、信息安全、职业健康安全、项目管理等多体系的无缝集成与协同运作,助力企业标准化、数字化、智能化发展。
        </p>
      </section>
      <section class="systems-grid">
        <!-- 使用v-for循环渲染系统卡片 -->
        <div
            v-for="(system, index) in systems"
            :key="system.id"
            class="system-card"
            :class="`card-${index + 1}`"
            @click="handleSystemLinkClick(system.id)"
            @mouseenter="handleCardHover(system, true)"
            @mouseleave="handleCardHover(system, false)"
            ref="cardRefs"
        >
          <div class="card-decoration"></div>
          <div class="system-header">
            <div class="system-icon-container">
              <div class="system-icon" ref="iconRefs">
                <img :src="system.icon"/>
              </div>
              <h3 class="system-name">{{ system.name }}</h3>
            </div>
          </div>
          <p class="system-desc">{{ system.description }}</p>
          <a
              href="#"
              class="system-link"
              @click.stop="handleSystemLinkClick(system.id)"
          >
            进入系统 <el-icon><Right /></el-icon>
          </a>
        </div>
      </section>
    </div>
    <!-- 底部 -->
    <footer>
      <div class="footer-decoration"></div>
      <div class="footer-container">
        <div class="copyright-section">
          <div class="copyright">
            © 2025 多体系建设信息化系统 | 中国科学院苏州纳米技术与纳米仿生研究所 版权所有
          </div>
          <div class="version">版本号 V1.0.0</div>
        </div>
      </div>
    </footer>
    <user-dialog ref="reviewRef"></user-dialog>
    <edit-dialog ref="dialogRef" @getList=getPlatformList></edit-dialog>
    <sealDialog ref="noticeRef"></sealDialog>
  </div>
</template>
<script setup>
import {ref, onMounted, computed, reactive, toRefs, watch} from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { getToken, removeToken } from "@/utils/auth";
import Cookies from "js-cookie";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import useUserStore from '@/store/modules/user'
import { ref, onMounted, nextTick } from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import {getToken, removeToken} from "@/utils/auth";
import userDialog from '@/views/build/conpanyFunctionConsult/staffManage/staffRegister/components/staffDialog.vue'
import editDialog from '@/views/build/conpanyFunctionConsult/infoPlatform/components/editDialog.vue'
import sealDialog from "@/views/work/sealManagement/apply/components/editDialog"
import menu1 from '@/assets/icons/menu1.png'
import menu2 from '@/assets/icons/menu2.png'
import menu3 from '@/assets/icons/menu3.png'
import menu4 from '@/assets/icons/menu4.png'
import menu5 from '@/assets/icons/menu5.png'
import menu6 from '@/assets/icons/menu6.png'
import shield from '@/assets/icons/shield-alt.png'
import lock from '@/assets/icons/lock.png'
import hat from '@/assets/icons/hard-hat.png'
import diagram from '@/assets/icons/project-diagram.png'
import clipboard from '@/assets/icons/clipboard-check.png'
import chartLine from '@/assets/icons/chart-line.png'
// 引入农历库
import * as lunarCalendar from 'lunar-calendar'
import {getIndexTitle, getMemoList, listNotice, updateMemo} from "@/api/system/notice";
import {renderAsync} from "docx-preview";
import {getInfoPlatforms} from "@/api/staffManage/staff";
import {getCompany} from "@/api/onlineEducation/company";
import {getSealApply} from "@/api/sealManage/apply";
import Cookies from "js-cookie";
import useUserStore from "@/store/modules/user";
import {useRouter} from "vue-router";
// 响应式数据
const systems = ref([
  {
    id: 1,
    name: '国军标9001C质量管理体系',
    description: '基于GJB9001C-2017标准,专为军工产品研制、生产、维修和服务单位设计。',
    icon: shield,
    color: '#1a56db'
  },
  {
    id: 2,
    name: 'ISO27001信息安全体系',
    description: '遵循ISO/IEC 27001:2022标准,帮助企业建立、实施、维护和持续改进信息安全管理体系。',
    icon: lock,
    color: '#0d9488'
  },
  {
    id: 3,
    name: 'ISO45001安全体系',
    description: '基于ISO45001:2018标准,系统化管理职业健康安全风险,预防工伤和健康损害。',
    icon: hat,
    color: '#10b981'
  },
  {
    id: 4,
    name: '项目管理控制',
    description: '集成PMBOK和PRINCE2最佳实践的项目管理平台,支持项目全生命周期管理。',
    icon: diagram,
    color: '#7c3aed'
  },
  {
    id: 5,
    name: '承制评价系统',
    description: '针对承制单位资格管理的综合系统,确保承制单位持续满足军用产品承制要求。',
    icon: clipboard,
    color: '#f97316'
  },
  {
    id: 6,
    name: '新体系评价系统',
    description: '面向新兴管理体系标准的评估与导入平台,支持新标准的适应性评估和实施规划。',
    icon: chartLine,
    color: '#ef4444'
  }
])
// Refs
const adminInfoRef = ref(null)
const cardRefs = ref([])
const iconRefs = ref([])
const router = useRouter()
const route = useRoute();
const reviewRef = ref();
const userInfo = ref();
const userName = ref('')
const userTypeName = ref('')
const cardStates = ref({})
const currentDate = ref(new Date())
const newMemo = ref('')
const calendarRef = ref()
const dialogRef = ref()
const noticeRef = ref();
const userStore = useUserStore()
const state = reactive({
  noticeParams: {
    pageNum: 1,
    pageSize: 6,
    companyId: null
  },
  platformParams: {
    pageNum: 1,
    pageSize: 99,
    companyId: null
  },
  noticeList: [],
  platformList: [],
  picUrl: import.meta.env.VITE_APP_BASE_API + '/',
  isAdmin: false,
  companyList: [],
  flowList: [],
  memo: {}
})
const { noticeParams,platformParams, noticeList,platformList,picUrl,isAdmin,companyList,flowList,memo } = toRefs(state)
// 组件挂载时获取用户信息和系统列表
onMounted(async () => {
  if(getToken()){
    userInfo.value = JSON.parse(Cookies.get('userInfo'))
    userName.value = userInfo.value.username
    userTypeName.value = userInfo.value.userType == 0 ? '系统管理员' : (userInfo.value.userType == 1 ||  userInfo.value.userType == 2 || userInfo.value.userType == 3) ? '企业用户' :userInfo.value.userType == 6 ? '企业管理员' :userInfo.value.userType == 4 ? '其他' : '学员'
  }
  if(userStore.roles.includes('admin')){
    state.noticeParams.companyId = null
    state.platformParams.companyId = null
    state.isAdmin = true
  }else{
    state.noticeParams.companyId = userStore.companyId
    state.platformParams.companyId = userStore.companyId
    state.isAdmin = false
  }
  await getNoticeList()
  await getPlatformList()
  await getFlowList()
  await getMemo()
  state.platformList.forEach(system => {
    cardStates.value[system.id] = {
      mouseX: 0,
      mouseY: 0,
      width: 0,
      height: 0,
      hover: false
    }
  })
})
const getSealDetail = async (type,sealId) => {
  let param = {}
  if(type == 5){
    param = {
      pageNum: 1,
      pageSize: 999,
      companyId: state.noticeParams.companyId,
      applyUserId: userStore.id
    }
  }else{
    param = {
      pageNum: 1,
      pageSize: 999,
      companyId: state.noticeParams.companyId,
      nextCheck: userStore.id
    }
  }
  const res = await getSealApply(param);
  if(res.code === 200){
    return res.data.list.find(i=>i.id == sealId)
  }else{
    ElMessage.warning(res.message)
  }
}
const toNoticeMng = ()=>{
  router.push({ path: "/work/noticeMng" });
}
const openDetail = async (value) => {
  if(value.type == '5' || value.type == '6'){
    const data = await getSealDetail(Number(value.type),Number(value.dataId))
    noticeRef.value.openDialog('review', data,state.companyList)
  }
}
function getNoticeList() {
  listNotice(state.noticeParams).then(res => {
    state.noticeList = res.data.list
  })
}
const getCompanyList = async ()=>{
  const queryParams = {
    pageNum: 1,
    pageSize: 999
  }
  const res = await getCompany(queryParams)
  if (res.code == 200) {
    state.companyList = res.data.list?res.data.list:[]
  } else {
    ElMessage.warning(res.message)
  }
}
const getPlatformList = async () => {
  const res = await getInfoPlatforms(state.platformParams)
  if(res.code == 200){
    const originPlatform = {
      id: 0,
      platformName: '国军标9001C质量管理体系',
      platformPic: menu1
    }
    state.platformList = [originPlatform, ...(Array.isArray(res.data) ? res.data : [])]
  }else{
    ElMessage.warning(res.message)
  }
}
const openAdd = async (type, value) => {
  await getCompanyList()
  dialogRef.value.openDialog(type, value, state.platformParams.companyId, state.isAdmin, state.companyList );
}
const getFlowList = async () => {
  const res = await getIndexTitle({pageNum: 1,pageSize: 99})
  if(res.code == 200){
    state.flowList = Array.isArray(res.data.list) ? res.data.list : []
  }else{
    ElMessage.warning(res.message)
  }
}
const getMemo = async () => {
  const res = await getMemoList()
  if(res.code == 200){
    state.memo = res.data ? res.data : {}
  }else{
    ElMessage.warning(res.message)
  }
}
// 分页相关
const currentPage = ref(0)
const pageSize = 9 // 九宫格,每页9个
// 计算总页数
const totalPages = computed(() => {
  return Math.ceil(state.platformList.length / pageSize)
})
// 获取当前页显示的系统列表
const displayedSystems = computed(() => {
  const start = currentPage.value * pageSize
  const end = start + pageSize
  return state.platformList.slice(start, end)
})
// 是否显示敬请期待的卡片(只在最后一页且系统总数不是9的倍数时显示)
const showEmptyCard = computed(() => {
  // 如果是最后一页,并且系统总数不是9的倍数,且当前页显示的系统数量小于9
  const isLastPage = currentPage.value === totalPages.value - 1
  const totalCount = state.platformList.length
  const currentCount = displayedSystems.value.length
  return isLastPage && (totalCount % pageSize !== 0) && currentCount < 9
})
// 获取实际在原始数组中的索引
const getActualIndex = (displayIndex) => {
  return currentPage.value * pageSize + displayIndex
}
// 分页方法
const prevPage = () => {
  if (currentPage.value > 0) {
    currentPage.value--
  }
}
const nextPage = () => {
  if (currentPage.value < totalPages.value - 1) {
    currentPage.value++
  }
}
// 重置分页(当系统列表变化时)
watch(state.platformList, () => {
  currentPage.value = 0
})
const openNoticeFile = async(path)=>{
  const ext = path.split('.').pop().toLowerCase();
  if (ext === 'doc' || ext === 'xls' || ext === 'xlsx') {
    ElMessageBox.confirm('暂不支持线上预览文件,是否下载查看?', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => {
      window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
    }).catch(() => {
      console.log('取消预览')
    });
    return
  }
  if(ext === 'pdf'){
    window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank')
    return
  }
  try {
    // 1. 获取文件
    const response = await fetch(import.meta.env.VITE_APP_BASE_API + '/' + path);
    const arrayBuffer = await response.arrayBuffer();
    // 2. 创建新窗口
    const win = window.open('', '_blank')
    win.document.write(`
      <!DOCTYPE html>
      <html>
        <head>
          <title>预览</title>
          <style>
            body { margin: 20px; font-family: Arial; }
            .docx-container { width: 100%; height: 100%; }
          </style>
        </head>
        <body>
          <div id="container" class="docx-container"></div>
        </body>
      </html>
    `);
    // 3. 渲染 DOCX
    await renderAsync(arrayBuffer, win.document.getElementById('container'));
  } catch (error) {
    console.error('预览失败:', error);
    alert(`预览失败: ${error.message}`);
  }
}
// 十二生肖数组
const zodiacAnimals = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']
// 获取生肖年份
const getZodiacYear = (lunarYear) => {
  // 农历年份计算生肖:年份减去4后除以12取余数
  // 因为鼠年对应4,牛年对应5,以此类推
  const index = (lunarYear - 4) % 12
  return index >= 0 ? zodiacAnimals[index] : zodiacAnimals[index + 12]
}
// 计算当前日期信息
const currentWeekDay = computed(() => {
  const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
  return days[currentDate.value.getDay()]
})
const currentSolarDate = computed(() => {
  const date = currentDate.value
  return `${date.getMonth() + 1}月${date.getDate()}日`
})
const currentLunarDate = computed(() => {
  try {
    const date = currentDate.value
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    const lunar = lunarCalendar.solarToLunar(year, month, day)
    if (lunar && lunar.lunarMonthName && lunar.lunarDayName) {
      return `${lunar.lunarMonthName}${lunar.lunarDayName}`
    }
    return ''
  } catch (error) {
    console.error('获取农历日期错误:', error)
    return ''
  }
})
const currentLunarYear = computed(() => {
  try {
    const date = currentDate.value
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    const lunar = lunarCalendar.solarToLunar(year, month, day)
    if (lunar && lunar.GanZhiYear) {
      const zodiac = getZodiacYear(year)
      return `${lunar.GanZhiYear}年【${zodiac}年】`
    }
    return ''
  } catch (error) {
    console.error('获取农历年份错误:', error)
    return ''
  }
})
// 月份导航方法
const prevMonth = () => {
  const date = new Date(currentDate.value)
  date.setMonth(date.getMonth() - 1)
  currentDate.value = date
}
const nextMonth = () => {
  const date = new Date(currentDate.value)
  date.setMonth(date.getMonth() + 1)
  currentDate.value = date
}
const goToday = () => {
  currentDate.value = new Date()
}
// 添加备忘录
const addMemo = async () => {
  if (state.memo.content) {
    const data = {
      id: state.memo.id || null,
      companyId: state.noticeParams.companyId,
      content: state.memo.content,
      createById: userStore.id
    }
    const res = await updateMemo(data)
    if(res.code == 200){
      ElMessage.success('保存成功')
      await getMemo()
    }else{
      ElMessage.warning(res.message)
    }
    newMemo.value = ''
  }
}
// 获取公历日期(去掉前导零)
const getSolarDate = (dateString) => {
  const date = new Date(dateString)
  return date.getDate()
}
// 获取农历日期
const getLunarDate = (dateString) => {
  try {
    const date = new Date(dateString)
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    // 使用农历库获取农历信息
    const lunar = lunarCalendar.solarToLunar(year, month, day)
    if (lunar && lunar.lunarDayName) {
      // 如果是初一,显示月份,否则显示日期
      if (lunar.lunarDay === 1) {
        return lunar.lunarMonthName + '月'
      } else {
        // 简化显示,只显示数字日期
        const lunarDay = lunar.lunarDayName.replace('初', '').replace('十', '')
        return lunarDay
// 方法
const handleAdminClick = () => {
  if (adminInfoRef.value) {
    adminInfoRef.value.style.transform = 'scale(0.94)'
    setTimeout(() => {
      if (adminInfoRef.value) {
        adminInfoRef.value.style.transform = ''
      }
    }
    return ''
  } catch (error) {
    console.error('获取农历日期错误:', error)
    return ''
  }
}
// 检查日期是否有事件
const hasEvent = (date) => {
  const eventDates = []
  return eventDates.includes(date)
}
// 检查是否是今天
const isToday = (dateString) => {
  const today = new Date().toISOString().split('T')[0]
  return dateString === today
}
// 检查是否是当前月份
const isCurrentMonth = (dateString) => {
  const date = new Date(dateString)
  const current = new Date(currentDate.value)
  return date.getMonth() === current.getMonth() && date.getFullYear() === current.getFullYear()
}
const handleCardEnter = (event, id) => {
  const card = event.currentTarget
  cardStates.value[id] = {
    ...cardStates.value[id],
    width: card.offsetWidth,
    height: card.offsetHeight,
    hover: true
  }
}
const handleCardMove = (event, id) => {
  if (!cardStates.value[id]?.hover) return
  const card = event.currentTarget
  const rect = card.getBoundingClientRect()
  cardStates.value[id].mouseX = event.clientX - rect.left - cardStates.value[id].width / 2
  cardStates.value[id].mouseY = event.clientY - rect.top - cardStates.value[id].height / 2
}
const handleCardLeave = (id) => {
  cardStates.value[id].hover = false;
  cardStates.value[id].mouseX = 0;
  cardStates.value[id].mouseY = 0;
}
const getCardStyle = (id) => {
  const state = cardStates.value[id] || {}
  const mousePX = state.mouseX / (state.width || 1)
  const mousePY = state.mouseY / (state.height || 1)
  const rX = mousePX * 20
  const rY = mousePY * -20
  const tX = mousePX * -20
  const tY = mousePY * -20
  return {
    transform: `rotateY(${rX}deg) rotateX(${rY}deg)`,
    '--bg-transform': `translateX(${tX}px) translateY(${tY}px)`
      alert('管理员菜单已打开')
    }, 150)
  }
}
@@ -672,23 +199,21 @@
  }
}
const enterSystem = (address,index) => {
  if(index == 0){
    router.push({ path: "/learn/standardSysTemp/sysStandardModule"})
const handleSystemLinkClick = (systemId) => {
  if(systemId == 1){
    router.push({ path: "/menuIndex"});
  }else{
    window.open(address)
    // ElMessage.warning('系统正在开发中...')
    ElMessage.warning('系统正在开发中...')
  }
}
function getInfo() {
  reviewRef.value.openDialog('view',userInfo.value)
}
function editPsd() {
  reviewRef.value.openDialog('pwd',userInfo.value)
}
// 退出登录
function logout() {
  ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
    confirmButtonText: '确定',
@@ -697,692 +222,519 @@
  }).then(() => {
    removeToken()
    location.href = '/homePage';
  }).catch(() => { });
}
const handleCardHover = (system, isEnter) => {
  const cardIndex = systems.value.findIndex(s => s.id === system.id)
  if (cardIndex !== -1 && iconRefs.value[cardIndex]) {
    iconRefs.value[cardIndex].style.transform = isEnter ? 'scale(1.04)' : 'scale(1)'
    iconRefs.value[cardIndex].style.transition = 'transform 0.3s ease'
  }
}
// 页面加载后计算高度并调整
const adjustLayout = () => {
  const bodyHeight = document.body.scrollHeight
  const windowHeight = window.innerHeight
  // 获取DOM元素
  const welcomeSection = document.querySelector('.welcome-section')
  const systemsGrid = document.querySelector('.systems-grid')
  const footer = document.querySelector('footer')
  // 如果内容超过屏幕高度,进行微调
  if (bodyHeight > windowHeight) {
    if (welcomeSection) welcomeSection.style.marginBottom = '1.5rem'
    if (systemsGrid) {
      systemsGrid.style.gap = '1.2rem'
      systemsGrid.style.marginBottom = '2rem'
    }
    if (footer) footer.style.padding = '1.2rem 1.8rem'
    if (welcomeSection) welcomeSection.style.padding = '1.8rem 1.5rem'
  }
}
// 生命周期钩子
onMounted(() => {
  if(getToken()){
    userInfo.value = JSON.parse(Cookies.get('userInfo'))
    userName.value = userInfo.value.username
    userTypeName.value = userInfo.value.userType == 0 ? '系统管理员' : (userInfo.value.userType == 1 ||  userInfo.value.userType == 2 || userInfo.value.userType == 3) ? '企业用户' :userInfo.value.userType == 6 ? '企业管理员' :userInfo.value.userType == 4 ? '其他' : '学员'
  }
  const userStore = useUserStore()
  userStore.roles = []
  // 等待DOM更新完成后执行
  nextTick(() => {
    adjustLayout()
    // 渐显效果
    document.body.style.opacity = '0'
    document.body.style.transition = 'opacity 0.5s ease'
    setTimeout(() => {
      document.body.style.opacity = '1'
    }, 100)
  })
  // 监听窗口大小变化
  window.addEventListener('resize', adjustLayout)
})
</script>
<style scoped lang="scss">
.system-select-container {
<style lang="scss" scoped>
body {
  background-color: #f8fafc;
  color: #1f2937;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.multi-system-dashboard{
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
  align-items: center;
  .menu-container {
    flex: 1;
    overflow-y: auto;
    max-width: 1600px;
    width: 100%;
    margin: 1rem auto;
    padding: 0 1.8rem;
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* IE and Edge */
  }
}
.user-info-bar {
/* 头部样式 - 更加紧凑 */
header {
  width: 100%;
  background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
  color: white;
  padding: 0.8rem 1.8rem;
  box-shadow: 0 3px 10px rgba(30, 58, 138, 0.12);
}
.header-container {
  max-width: 1600px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.system-title {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.2px;
}
.admin-info {
  display: flex;
  align-items: center;
  gap: 10px;
  background: rgba(255, 255, 255, 0.15);
  padding: 8px 16px;
  border-radius: 10px;
  backdrop-filter: blur(4px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  transition: all 0.3s ease;
  cursor: pointer;
}
.admin-info:hover {
  background: rgba(255, 255, 255, 0.25);
}
.admin-icon {
  background: linear-gradient(135deg, #f59e0b, #f97316);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  img{
    width: 100%;
    height: 100%;
  }
}
.admin-details {
  display: flex;
  flex-direction: column;
  color: #fff;
}
.admin-name {
  font-weight: 600;
  font-size: 0.95rem;
  margin-bottom: 0.2rem;
}
.admin-role {
  font-size: 0.75rem;
  opacity: 0.9;
}
.welcome-section {
  position: relative;
  text-align: center;
  margin-bottom: 1rem;
  padding: 2rem;
  background: white;
  border-radius: 16px;
  box-shadow: 0 5px 15px -4px rgba(0, 0, 0, 0.07);
  overflow: hidden;
  border: 1px solid rgba(226, 232, 240, 0.8);
}
.welcome-decoration {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: linear-gradient(90deg,
  #1a56db,
  #0d9488,
  #7c3aed,
  #f97316
  );
}
.welcome-title {
  font-size: 1.5rem;
  margin: 0 0 0.8rem;
  font-weight: 800;
  color: #1a56db;
}
.welcome-subtitle {
  font-size: 0.95rem;
  color: #4b5563;
  max-width: 900px;
  margin: 0 auto;
  line-height: 1.5;
  font-weight: 400;
}
/* 系统入口网格 - 更加紧凑 */
.systems-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin-bottom: 2.5rem;
  width: 100%;
}
/* 为每个系统卡片分配不同的颜色主题 */
.system-card.card-1 { --card-color: #1a56db; }
.system-card.card-2 { --card-color: #0d9488; }
.system-card.card-3 { --card-color: #10b981; }
.system-card.card-4 { --card-color: #7c3aed; }
.system-card.card-5 { --card-color: #f97316; }
.system-card.card-6 { --card-color: #ef4444; }
.system-card {
  background: white;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 5px 15px -4px rgba(0, 0, 0, 0.07);
  transition: all 0.3s ease;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  height: 100%;
  position: relative;
  width: 100%;
}
.system-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.card-decoration {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: linear-gradient(90deg,
  var(--card-color),
  color-mix(in srgb, var(--card-color) 70%, white)
  );
}
.system-header {
  padding: 0.8rem 1.5rem;
  position: relative;
}
.system-icon-container {
  display: flex;
  align-items: center;
  gap: 14px;
}
.system-icon {
  background: linear-gradient(135deg, var(--card-color), color-mix(in srgb, var(--card-color) 80%, white));
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  img{
    width: 24px;
    height: 24px;
  }
}
.system-name {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--card-color);
  flex-grow: 1;
  line-height: 1.25;
}
.system-desc {
  padding: 0 1.5rem 1.2rem;
  flex-grow: 1;
  color: #4b5563;
  line-height: 1.5;
  font-size: 0.9rem;
  margin: 0;
}
.system-link {
  display: block;
  padding: 0.8rem;
  text-align: center;
  background: linear-gradient(90deg,
  var(--card-color),
  color-mix(in srgb, var(--card-color) 80%, white)
  );
  color: white;
  font-weight: 600;
  text-decoration: none;
  transition: all 0.3s ease;
  font-size: 0.95rem;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 7px;
}
.system-link:hover {
  background: linear-gradient(90deg,
  color-mix(in srgb, var(--card-color) 90%, black),
  var(--card-color)
  );
}
/* 底部样式 - 更加紧凑 */
footer {
  width: 100%;
  height: 100px;
  align-items: center;
  justify-content: space-between;
  padding: 10px 20px;
  background-color: #ffffff;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  .user-left{
    width: 20%;
  }
  .user-details{
    width: 60%;
    margin: 0;
    color: #333;
    text-align: center;
    font-size: 28px;
    letter-spacing: 2px;
  }
  .avatar-container {
    width: 20%;
    display: flex;
    justify-content: center;
    .avatar-wrapper {
      position: relative;
      .user-avatar {
        cursor: pointer;
        width: 40px;
        height: 40px;
        border-radius: 10px;
        margin-right: 15px;
      }
      i {
        cursor: pointer;
        position: absolute;
        right: -20px;
        font-size: 12px;
      }
    }
  }
  background: linear-gradient(90deg, #111827 0%, #1f2937 100%);
  color: white;
  padding: 1.5rem 1.8rem;
  margin-top: auto;
  position: relative;
}
.systems-container {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
.footer-decoration {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg,
  #1a56db,
  #0d9488,
  #7c3aed
  );
}
.layout-container {
  display: flex;
  gap: 20px;
  width: 100%;
  height: 100%;
  max-width: none; /* 移除最大宽度限制 */
  margin: 0; /* 移除居中margin */
}
// 左侧列 - 宽度占比2
.left-column {
  flex: 2;
.footer-container {
  max-width: 1600px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-width: 0; /* 防止内容溢出 */
}
// 右侧列 - 宽度占比1
.right-column {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-width: 0; /* 防止内容溢出 */
  min-width: 400px; /* 设置最小宽度避免过窄 */
}
// 通用模块卡片样式
.module-card {
  background: #ffffff;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.3s ease;
  height: 100%;
  display: flex;
  flex-direction: column;
  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }
}
.module-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid #f0f0f0;
  flex-shrink: 0; /* 防止header被压缩 */
  gap: 0.8rem;
}
  h3 {
    margin: 0;
    color: #333;
    font-size: 18px;
    font-weight: 600;
  }
.copyright-section {
  text-align: center;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
  .more-link {
    color: #409eff;
    font-size: 14px;
    cursor: pointer;
.copyright {
  font-size: 0.9rem;
  color: #d1d5db;
  line-height: 1.3;
}
    &:hover {
      color: #337ecc;
    }
.version {
  display: inline-block;
  background: rgba(59, 130, 246, 0.2);
  color: #60a5fa;
  padding: 4px 12px;
  border-radius: 16px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.2px;
  border: 1px solid rgba(96, 165, 250, 0.3);
}
/* 响应式调整 */
@media (max-width: 1300px) {
  .systems-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
// 通知公告模块
.notice-module {
  flex: 1;
  .notice-list {
    flex: 1;
    overflow: hidden;
    overflow-y: auto;
    .notice-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px 0;
      border-bottom: 1px solid #f5f5f5;
      &:last-child {
        border-bottom: none;
      }
      .notice-title {
        color: #333;
        font-size: 16px;
        cursor: pointer;
        flex: 1;
        margin-right: 12px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        &:hover {
          color: #409eff;
        }
      }
      .notice-date {
        color: #999;
        font-size: 14px;
        flex-shrink: 0;
      }
    }
  }
}
// 流程中心模块
.process-module {
  flex: 1;
  overflow-y: auto;
  .process-list {
    flex: 1;
    overflow-y: auto;
    .process-item {
      margin-bottom: 8px;
      .process-info {
        display: flex;
        align-items: center;
        padding-bottom: 8px;
        margin-bottom: 8px;
        box-sizing: border-box;
        border-bottom: 1px dashed #f0f0f0;
        cursor: pointer;
        .process-name {
          color: #333;
          font-size: 16px;
          flex: 1;
          &:hover {
            color: #409eff;
          }
        }
        .process-status {
          font-size: 12px;
          padding: 2px 8px;
          border-radius: 4px;
          flex-shrink: 0;
          margin-right: 10px;
          &.processing {
            background: #e6f7ff;
            color: #1890ff;
          }
          &.pending {
            background: #fff7e6;
            color: #fa8c16;
          }
          &.success {
            background: #edffdb;
            color: #52c41a;
          }
          &.normal {
            background: #ffebca;
            color: #ff6518;
          }
          &.seal {
            background: #ffe6e6;
            color: #ff1818;
          }
        }
      }
    }
  }
}
// 备忘录模块
.memo-module {
  flex: 1;
  .memo-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    .memo-input {
      flex: 1;
      .memo-time{
        color: #999;
        font-size: 12px;
        text-align: right;
        margin-top: 10px;
      }
    }
  }
}
// 快捷入口模块
.quick-access-module {
  .module-header {
    .pagination-controls {
      display: flex;
      align-items: center;
      gap: 8px;
      .page-info {
        font-size: 12px;
        color: #666;
        min-width: 40px;
        text-align: center;
      }
      .el-button {
        width: 28px;
        height: 28px;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
@media (max-width: 900px) {
  header {
    padding: 0.7rem 1.5rem;
  }
  .systems-grid-container {
    flex: 1;
    overflow: hidden;
  .system-title {
    font-size: 1.4rem;
  }
  .menu-container {
    padding: 0 1.5rem;
    margin: 0.8rem auto;
  }
  .welcome-section {
    padding: 1.5rem;
    margin-bottom: 0.8rem;
  }
  .welcome-title {
    font-size: 1.3rem;
  }
  .welcome-subtitle {
    font-size: 0.9rem;
  }
  .systems-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    gap: 16px;
    height: 100%;
    min-height: 400px; // 确保有足够的高度显示九宫格
    perspective: 1000px;
    gap: 1rem;
    margin-bottom: 2rem;
  }
  .system-card {
    position: relative;
    background-color: #ffffff;
    border-radius: 4px;
    transition: transform 1s cubic-bezier(0.23, 1, 0.32, 1),
    box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1);
    transform-style: preserve-3d;
    cursor: pointer;
    overflow: hidden;
    min-height: 100px; // 确保卡片有最小高度
    // 空白卡片样式
    &.empty-card {
      opacity: 0.6;
      .system-icon {
        color: #ccc;
      }
      h3 {
        color: #999;
      }
      &:hover {
        transform: none;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        &::after {
          border-color: transparent;
        }
        &::before {
          background: #fff;
        }
      }
    }
    &:hover{
      border-radius: 8px;
    }
    &::after {
      content: '';
      position: absolute;
      top: 4px;
      left: 4px;
      right: 4px;
      bottom: 4px;
      border-radius: 4px;
      border: 1px solid transparent;
      transition: border-color 0.3s ease;
      pointer-events: none;
      z-index: 3;
    }
    &::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      border-radius: 4px;
      background: #fff;
      transform: var(--bg-transform, translateX(0) translateY(0));
      transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1);
      z-index: 1;
    }
    &:hover::after {
      border-color: rgba(37,99,235,1);
      border-radius: 6px;
      box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);
    }
    &:hover::before {
      border-radius: 8px;
      background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(20,20,20,0.05) 100%);
    }
  .system-header {
    padding: 0.6rem 1.3rem;
  }
  .system-card:hover {
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15),
    0 0 0 1px rgba(255, 255, 255, 0.5) inset;
  .system-desc {
    padding: 0 1.3rem 1rem;
    font-size: 0.85rem;
  }
  .card-content {
    position: relative;
    height: 100%;
    display: flex;
  .system-link {
    padding: 0.7rem;
  }
}
@media (max-width: 700px) {
  .systems-grid {
    grid-template-columns: 1fr;
  }
  .header-container {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 12px;
    z-index: 2;
    transform-style: preserve-3d;
    gap: 0.8rem;
    text-align: center;
  }
  .admin-info {
    padding: 7px 14px;
  }
  .welcome-title {
    font-size: 1.2rem;
  }
  .system-name {
    font-size: 1.2rem;
  }
  footer {
    padding: 1.2rem 1.5rem;
  }
}
@media (max-width: 480px) {
  .menu-container {
    padding: 0 1.2rem;
  }
  .welcome-section {
    padding: 1rem 1.2rem;
  }
  .welcome-title {
    font-size: 1rem;
  }
  .system-header {
    padding: 0.5rem 1.2rem;
  }
  .system-icon {
    margin-bottom: 8px;
    .el-image {
      width: 40px;
      height: 40px;
      transition: transform 0.5s;
    }
    .el-icon {
      font-size: 40px;
      color: #ccc;
    }
    width: 42px;
    height: 42px;
  }
  .system-card:hover .system-icon img {
    transform: scale(1.2);
  .system-name {
    font-size: 1.15rem;
  }
  .system-card h3 {
    margin: 0;
    color: #333;
    font-size: 14px;
    text-align: center;
    transition: transform 0.3s;
    line-height: 1.2;
    font-weight: 500;
  .copyright {
    font-size: 0.85rem;
  }
  .system-card:hover h3 {
    transform: translateZ(10px);
  }
}
// 日历模块
.calendar-module {
  .calendar-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 16px;
    .lunar-info {
      width: 33.33%;
      display: flex;
      flex-direction: column;
      font-size: 16px;
      .lunar-date-full {
        color: #e6a23c;
        font-weight: 500;
      }
      .lunar-year {
        color: #999;
      }
    }
    .current-date-info {
      width: 33.33%;
      font-size: 16px;
      display: flex;
      flex-direction: column;
      align-items: center;
      .solar-date-large {
        color: #333;
        font-weight: 600;
      }
      .week-day {
        color: #666;
        margin-bottom: 4px;
        font-weight: 500;
      }
    }
    .calendar-actions {
      display: flex;
      justify-content: right;
      width: 33.33%;
      .el-button-group {
        display: flex;
        gap: 1px;
        .el-button {
          padding: 6px 12px;
          border-radius: 4px;
          &:first-child {
            border-top-right-radius: 0;
            border-bottom-right-radius: 0;
          }
          &:last-child {
            border-top-left-radius: 0;
            border-bottom-left-radius: 0;
          }
          &:not(:first-child):not(:last-child) {
            border-radius: 0;
          }
        }
      }
    }
  }
  .calendar-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    :deep(.el-calendar) {
      border: none;
      flex: 1;
      display: flex;
      flex-direction: column;
      .el-calendar__header {
        padding: 0;
        flex-shrink: 0;
      }
      .el-calendar__body {
        flex: 1;
      }
      .el-calendar-table {
        height: 100%;
        .el-calendar-day {
          height: 60px;
          padding: 2px;
          text-align: center;
        }
        td.is-selected {
          background-color: transparent;
        }
        .el-calendar-day:hover {
          background-color: #f5f7fa;
        }
      }
    }
    .calendar-date {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;
      height: 100%;
      position: relative;
      padding-top: 4px;
      .solar-date {
        font-size: 14px;
        font-weight: 500;
        color: #333;
        margin-bottom: 2px;
      }
      .lunar-date {
        font-size: 10px;
        color: #999;
        margin-bottom: 4px;
      }
      .calendar-event-dot {
        width: 4px;
        height: 4px;
        background: #409eff;
        border-radius: 50%;
        margin-bottom: 2px;
      }
      .today-indicator {
        position: absolute;
        top: 2px;
        right: 2px;
        width: 16px;
        height: 16px;
        background: #409eff;
        color: white;
        border-radius: 50%;
        font-size: 10px;
        display: flex;
        align-items: center;
        justify-content: center;
        line-height: 1;
      }
    }
    // 今天日期的样式
    .calendar-date.is-today {
      background-color: #ecf5ff;
      .solar-date {
        color: #409eff;
        font-weight: 600;
      }
      &::before {
        content: '';
        position: absolute;
        top: 2px;
        left: 50%;
        transform: translateX(-50%);
        width: 24px;
        height: 24px;
        background: #409eff;
        border-radius: 50%;
        z-index: -1;
        opacity: 0.1;
      }
    }
    .calendar-legend {
      display: flex;
      justify-content: center;
      gap: 16px;
      margin-top: 12px;
      padding-top: 12px;
      border-top: 1px solid #f0f0f0;
      flex-shrink: 0;
      .legend-item {
        display: flex;
        align-items: center;
        gap: 6px;
        .legend-dot {
          width: 8px;
          height: 8px;
          border-radius: 50%;
        }
        .event-dot {
          background: #409eff;
        }
        .today-dot {
          background: #409eff;
        }
        span {
          font-size: 12px;
          color: #666;
        }
      }
    }
  .version {
    font-size: 0.8rem;
  }
}
// 响应式设计
@media (max-width: 1200px) {
  .layout-container {
    flex-direction: column;
/* 确保在一个屏幕内显示 */
@media (min-height: 900px) {
  .menu-container {
    margin: 1rem auto;
  }
  .left-column,
  .right-column {
    flex: 1;
    min-width: auto;
  }
}
// 超大屏幕优化
@media (min-width: 1920px) {
  .systems-container {
    padding: 30px 40px;
  .welcome-section {
    margin-bottom: 1rem;
    padding: 2rem;
  }
  .layout-container {
    gap: 30px;
  }
  .module-card {
    padding: 25px;
  }
  // 在超大屏幕上可以显示3列的系统卡片
  .quick-access-module .systems-grid {
    grid-template-columns: repeat(3, 1fr);
  .systems-grid {
    gap: 1rem;
    margin-bottom: 3rem;
  }
}
</style>