From 971ed2f7636afc60802bc06f7fe160b61210aa72 Mon Sep 17 00:00:00 2001
From: 祖安之光 <11848914+light-of-zuan@user.noreply.gitee.com>
Date: 星期一, 17 十一月 2025 10:38:35 +0800
Subject: [PATCH] 修改新增
---
src/views/work/menuIndex/index.vue | 1388 ++++++++++++++++++++++++++++++
src/views/menuPage.vue | 1338 +++-------------------------
src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue | 6
3 files changed, 1,571 insertions(+), 1,161 deletions(-)
diff --git a/src/views/menuPage.vue b/src/views/menuPage.vue
index cdc37ef..d43343f 100644
--- a/src/views/menuPage.vue
+++ b/src/views/menuPage.vue
@@ -1,5 +1,6 @@
<template>
<div class="system-select-container">
+ <!-- 顶部用户信息栏 -->
<div class="user-info-bar">
<div class="user-left"></div>
<h3 class="user-details">欢迎访问多体系建设信息化系统</h3>
@@ -12,6 +13,9 @@
</div>
<template #dropdown>
<el-dropdown-menu>
+<!-- <el-dropdown-item command="info">-->
+<!-- <span>基本信息</span>-->
+<!-- </el-dropdown-item>-->
<el-dropdown-item command="password">
<span>修改密码</span>
</el-dropdown-item>
@@ -24,201 +28,47 @@
</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>
- </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 class="systems-grid">
+ <div
+ v-for="system in systems"
+ :key="system.id"
+ class="system-card"
+ @mouseenter="handleCardEnter($event, system.id)"
+ @mousemove="handleCardMove($event, system.id)"
+ @mouseleave="handleCardLeave(system.id)"
+ @click="enterSystem(system.id)"
+ :style="getCardStyle(system.id)"
+ >
+ <div class="card-content">
+ <div class="system-icon">
+ <img :src="system.icon"/>
</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>
+ <h3>{{ system.name }}</h3>
+ <p>{{ system.description }}</p>
</div>
</div>
</div>
</div>
<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 { ref, onMounted } from 'vue'
+import { useRouter } 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 {ElMessage, ElMessageBox} from "element-plus";
+import useUserStore from '@/store/modules/user'
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 * 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";
const router = useRouter()
const route = useRoute();
@@ -227,53 +77,17 @@
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 () => {
+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 ? '其他' : '学员'
}
- 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 => {
+
+ const userStore = useUserStore()
+ userStore.roles = []
+ systems.value.forEach(system => {
cardStates.value[system.id] = {
mouseX: 0,
mouseY: 0,
@@ -284,335 +98,8 @@
})
})
-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
- }
- }
-
- 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] = {
@@ -623,6 +110,7 @@
}
}
+// 鼠标移动
const handleCardMove = (event, id) => {
if (!cardStates.value[id]?.hover) return
@@ -633,18 +121,21 @@
cardStates.value[id].mouseY = event.clientY - rect.top - cardStates.value[id].height / 2
}
+// 鼠标离开
const handleCardLeave = (id) => {
cardStates.value[id].hover = false;
+ // 立即开始归位动画,不使用setTimeout延迟
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 rX = mousePX * 20 // 减小旋转角度,使效果更柔和
const rY = mousePY * -20
const tX = mousePX * -20
@@ -656,6 +147,46 @@
}
}
+
+// 系统列表
+const systems = ref([
+ {
+ id: 1,
+ name: '国军标9001C质量管理体系',
+ description: '确保产品和服务质量符合国际标准',
+ icon: menu1
+ },
+ {
+ id: 2,
+ name: 'ISO 27001 信息安全体系',
+ description: '保护企业信息资产安全与机密性',
+ icon: menu2
+ },
+ {
+ id: 3,
+ name: 'ISO 45001 安全体系',
+ description: '实现企业安全的持续改进',
+ icon: menu3
+ },
+ {
+ id: 4,
+ name: '项目管理控制',
+ description: '标准化项目管理流程与方法',
+ icon: menu4
+ },
+ {
+ id: 5,
+ name: '承制评价体系',
+ description: '供应商与承包商能力评估标准',
+ icon: menu5
+ },
+ {
+ id: 6,
+ name: '新体系评价',
+ description: '新体系评价',
+ icon: menu6
+ }
+])
function handleCommand(command) {
switch (command) {
case "info":
@@ -671,24 +202,21 @@
break;
}
}
-
-const enterSystem = (address,index) => {
- if(index == 0){
- router.push({ path: "/learn/standardSysTemp/sysStandardModule"})
+// 进入系统
+const enterSystem = (systemId) => {
+ if(systemId == 1){
+ router.push({ path: "/"});
}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,8 +225,11 @@
}).then(() => {
removeToken()
location.href = '/homePage';
+
}).catch(() => { });
}
+
+
</script>
<style scoped lang="scss">
@@ -755,634 +286,125 @@
}
}
}
+
}
+
.systems-container {
flex: 1;
padding: 20px;
overflow-y: auto;
- width: 100%;
+ margin-top: 60px;
}
-.layout-container {
- display: flex;
- gap: 20px;
- width: 100%;
- height: 100%;
- max-width: none; /* 移除最大宽度限制 */
- margin: 0; /* 移除居中margin */
+.systems-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
+ gap: 30px;
+ max-width: 1500px;
+ margin: 0 auto;
+ perspective: 1000px;
}
-// 左侧列 - 宽度占比2
-.left-column {
- flex: 2;
- display: flex;
- flex-direction: column;
- gap: 20px;
- min-width: 0; /* 防止内容溢出 */
-}
+.system-card {
+ position: relative;
+ height: 280px;
+ 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;
-// 右侧列 - 宽度占比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被压缩 */
-
- h3 {
- margin: 0;
- color: #333;
- font-size: 18px;
- font-weight: 600;
+ &:hover{
+ border-radius: 16px;
}
- .more-link {
- color: #409eff;
- font-size: 14px;
- cursor: pointer;
-
- &:hover {
- color: #337ecc;
- }
- }
-}
-
-// 通知公告模块
-.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;
- }
- }
+ &::after {
+ content: '';
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ right: 8px;
+ bottom: 8px;
+ border-radius: 4px; /* 比卡片小1px */
+ border: 1px solid transparent;
+ transition: border-color 0.3s ease;
+ pointer-events: none; /* 确保不影响鼠标事件 */
+ z-index: 3; /* 确保在内容之上 */
}
- .systems-grid-container {
- flex: 1;
- overflow: hidden;
- }
-
- .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;
- }
-
- .system-card {
- position: relative;
- background-color: #ffffff;
+ &::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
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%);
- }
+ 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;
}
-
- .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;
+ &:hover::after {
+ border-color: rgba(37,99,235,1); /* 使用蓝色描边 */
+ border-radius: 12px;
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5); /* 可选:添加内发光效果 */
}
-
- .card-content {
- position: relative;
- height: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 12px;
- z-index: 2;
- transform-style: preserve-3d;
- }
-
- .system-icon {
- margin-bottom: 8px;
-
- .el-image {
- width: 40px;
- height: 40px;
- transition: transform 0.5s;
- }
-
- .el-icon {
- font-size: 40px;
- color: #ccc;
- }
- }
-
- .system-card:hover .system-icon img {
- transform: scale(1.2);
- }
-
- .system-card h3 {
- margin: 0;
- color: #333;
- font-size: 14px;
- text-align: center;
- transition: transform 0.3s;
- line-height: 1.2;
- font-weight: 500;
- }
-
- .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;
- }
- }
- }
+ &:hover::before {
+ border-radius: 16px;
+ background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(20,20,20,0.05) 100%);
}
}
-// 响应式设计
-@media (max-width: 1200px) {
- .layout-container {
- flex-direction: column;
- }
-
- .left-column,
- .right-column {
- flex: 1;
- min-width: auto;
- }
+.system-card:hover {
+ //transform: translateY(-5px);
+ box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15),
+ 0 0 0 1px rgba(255, 255, 255, 0.5) inset;
+}
+.card-content {
+ position: relative;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 25px;
+ z-index: 2;
+ transform-style: preserve-3d;
}
-// 超大屏幕优化
-@media (min-width: 1920px) {
- .systems-container {
- padding: 30px 40px;
- }
+.system-icon img {
+ width: 80px;
+ height: 80px;
+ margin-bottom: 30px;
+ transition: transform 0.5s;
+}
- .layout-container {
- gap: 30px;
- }
+.system-card:hover .system-icon img {
+ transform: scale(1.4);
+}
- .module-card {
- padding: 25px;
- }
+.system-card h3 {
+ margin: 0 0 12px;
+ color: #333;
+ font-size: 24px;
+ text-align: center;
+ transition: transform 0.3s;
+}
- // 在超大屏幕上可以显示3列的系统卡片
- .quick-access-module .systems-grid {
- grid-template-columns: repeat(3, 1fr);
- }
+.system-card p {
+ margin: 0;
+ color: #999;
+ font-size: 15px;
+ text-align: center;
+ transition: transform 0.3s;
+}
+
+.system-card:hover h3,
+.system-card:hover p {
+ transform: translateZ(20px);
}
</style>
diff --git a/src/views/work/menuIndex/index.vue b/src/views/work/menuIndex/index.vue
new file mode 100644
index 0000000..cdc37ef
--- /dev/null
+++ b/src/views/work/menuIndex/index.vue
@@ -0,0 +1,1388 @@
+<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">
+ <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>
+ </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>
+ </div>
+ </div>
+ </div>
+ <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 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 * 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";
+
+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
+ }
+ }
+
+ 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)`
+ }
+}
+
+function handleCommand(command) {
+ switch (command) {
+ case "info":
+ getInfo();
+ break;
+ case "logout":
+ logout();
+ break;
+ case "password":
+ editPsd();
+ break;
+ default:
+ break;
+ }
+}
+
+const enterSystem = (address,index) => {
+ if(index == 0){
+ router.push({ path: "/learn/standardSysTemp/sysStandardModule"})
+ }else{
+ window.open(address)
+ // ElMessage.warning('系统正在开发中...')
+ }
+}
+
+function getInfo() {
+ reviewRef.value.openDialog('view',userInfo.value)
+}
+
+function editPsd() {
+ reviewRef.value.openDialog('pwd',userInfo.value)
+}
+
+function logout() {
+ ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning'
+ }).then(() => {
+ removeToken()
+ location.href = '/homePage';
+ }).catch(() => { });
+}
+</script>
+
+<style scoped lang="scss">
+.system-select-container {
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background-color: #f5f7fa;
+}
+
+.user-info-bar {
+ display: flex;
+ 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;
+ }
+ }
+ }
+}
+
+.systems-container {
+ flex: 1;
+ padding: 20px;
+ overflow-y: auto;
+ width: 100%;
+}
+
+.layout-container {
+ display: flex;
+ gap: 20px;
+ width: 100%;
+ height: 100%;
+ max-width: none; /* 移除最大宽度限制 */
+ margin: 0; /* 移除居中margin */
+}
+
+// 左侧列 - 宽度占比2
+.left-column {
+ flex: 2;
+ 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被压缩 */
+
+ h3 {
+ margin: 0;
+ color: #333;
+ font-size: 18px;
+ font-weight: 600;
+ }
+
+ .more-link {
+ color: #409eff;
+ font-size: 14px;
+ cursor: pointer;
+
+ &:hover {
+ color: #337ecc;
+ }
+ }
+}
+
+// 通知公告模块
+.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;
+ }
+ }
+ }
+
+ .systems-grid-container {
+ flex: 1;
+ overflow: hidden;
+ }
+
+ .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;
+ }
+
+ .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-card:hover {
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15),
+ 0 0 0 1px rgba(255, 255, 255, 0.5) inset;
+ }
+
+ .card-content {
+ position: relative;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 12px;
+ z-index: 2;
+ transform-style: preserve-3d;
+ }
+
+ .system-icon {
+ margin-bottom: 8px;
+
+ .el-image {
+ width: 40px;
+ height: 40px;
+ transition: transform 0.5s;
+ }
+
+ .el-icon {
+ font-size: 40px;
+ color: #ccc;
+ }
+ }
+
+ .system-card:hover .system-icon img {
+ transform: scale(1.2);
+ }
+
+ .system-card h3 {
+ margin: 0;
+ color: #333;
+ font-size: 14px;
+ text-align: center;
+ transition: transform 0.3s;
+ line-height: 1.2;
+ font-weight: 500;
+ }
+
+ .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;
+ }
+ }
+ }
+ }
+}
+
+// 响应式设计
+@media (max-width: 1200px) {
+ .layout-container {
+ flex-direction: column;
+ }
+
+ .left-column,
+ .right-column {
+ flex: 1;
+ min-width: auto;
+ }
+}
+
+// 超大屏幕优化
+@media (min-width: 1920px) {
+ .systems-container {
+ padding: 30px 40px;
+ }
+
+ .layout-container {
+ gap: 30px;
+ }
+
+ .module-card {
+ padding: 25px;
+ }
+
+ // 在超大屏幕上可以显示3列的系统卡片
+ .quick-access-module .systems-grid {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+</style>
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue
index d251cb3..ed8bb2c 100644
--- a/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue
@@ -30,10 +30,10 @@
<!-- 表格数据 -->
<el-table v-loading="loading" :data="dataList" :border="true">
<el-table-column label="序号" type="index" align="center" width="80"/>
- <el-table-column label="供应商" prop="supplierName" align="center"/>
- <el-table-column label="工艺流程图" align="center">
+ <el-table-column label="文件名称" prop="fileName" align="center"/>
+ <el-table-column label="文件" align="center">
<template #default="scope">
- <el-link type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName !== '' ?scope.row.fileName + scope.row.format : '工艺流程图'}}</el-link>
+ <el-link type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName !== '' ?scope.row.fileName + scope.row.format : '文件'}}</el-link>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
--
Gitblit v1.9.2