| | |
| | | <template> |
| | | <div> |
| | | <div class="center-top-container"> |
| | | <!-- 顶部统计卡片 --> |
| | | <div class="stats-cards"> |
| | | <div class="stat-card"> |
| | | <!-- <div class="stat-card"> |
| | | <img src="@/assets/BI/icon@2x.png" alt="图标" class="card-icon" /> |
| | | <div class="card-content"> |
| | | <span class="card-label">员工总数</span> |
| | |
| | | <span class="compare-icon">{{ staffYoY >= 0 ? '↑' : '↓' }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> --> |
| | | <div class="stat-card"> |
| | | <img src="@/assets/BI/icon@2x.png" alt="图标" class="card-icon" /> |
| | | <img src="@/assets/BI/icon@2x.png" |
| | | alt="图标" |
| | | class="card-icon" /> |
| | | <div class="card-content"> |
| | | <span class="card-label">客户总数</span> |
| | | <span class="card-value">{{ totalCustomers }}</span> |
| | | <div class="card-compare" :class="compareClass(customersYoY)"> |
| | | <div class="card-compare" |
| | | :class="compareClass(customersYoY)"> |
| | | <span>同比</span> |
| | | <span class="compare-value">{{ formatPercent(customersYoY) }}</span> |
| | | <span class="compare-icon">{{ customersYoY >= 0 ? '↑' : '↓' }}</span> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="stat-card"> |
| | | <img src="@/assets/BI/icon@2x.png" alt="图标" class="card-icon" /> |
| | | <img src="@/assets/BI/icon@2x.png" |
| | | alt="图标" |
| | | class="card-icon" /> |
| | | <div class="card-content"> |
| | | <span class="card-label">供应商总数</span> |
| | | <span class="card-value">{{ totalSuppliers }}</span> |
| | | <div class="card-compare" :class="compareClass(suppliersYoY)"> |
| | | <div class="card-compare" |
| | | :class="compareClass(suppliersYoY)"> |
| | | <span>同比</span> |
| | | <span class="compare-value">{{ formatPercent(suppliersYoY) }}</span> |
| | | <span class="compare-icon">{{ suppliersYoY >= 0 ? '↑' : '↓' }}</span> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 设备统计 --> |
| | | <div class="equipment-stats"> |
| | | <div class="equipment-header"> |
| | | <img |
| | | src="@/assets/BI/shujutongjiicon@2x.png" |
| | | alt="图标" |
| | | class="equipment-icon" |
| | | /> |
| | | <img src="@/assets/BI/shujutongjiicon@2x.png" |
| | | alt="图标" |
| | | class="equipment-icon" /> |
| | | <span class="equipment-title">设备统计</span> |
| | | </div> |
| | | <div class="equipment-items"> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 事件名称 --> |
| | | <div class="event-info"> |
| | | <div class="event-header"> |
| | | <img |
| | | src="@/assets/BI/shijianmingxiicon@2x.png" |
| | | alt="图标" |
| | | class="event-icon" |
| | | /> |
| | | <img src="@/assets/BI/shijianmingxiicon@2x.png" |
| | | alt="图标" |
| | | class="event-icon" /> |
| | | <span class="event-title">事件名称</span> |
| | | </div> |
| | | <div class="event-content"> |
| | | <ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList"> |
| | | <li v-for="item in todoList" :key="item.id"> |
| | | <div |
| | | style=" |
| | | <ul class="todo-list" |
| | | v-if="todoList.length > 0" |
| | | ref="refTodoList"> |
| | | <li v-for="item in todoList" |
| | | :key="item.id"> |
| | | <div style=" |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | width: 100%; |
| | | gap: 20px; |
| | | " |
| | | > |
| | | <div class="todo-division">待办事由:{{ item.approveReason }}</div> |
| | | <div style="display: flex;justify-content: space-between;align-items: center;" |
| | | > |
| | | "> |
| | | <div class="todo-division">待办事由:{{ item.approveReason }}</div> |
| | | <div style="display: flex;justify-content: space-between;align-items: center;"> |
| | | <div class="todo-title">申请类型:{{ item.approveTypeName }}</div> |
| | | <div class="todo-division">申请部门:{{ item.approveDeptName }}</div> |
| | | <div class="todo-time">{{ item.approveTime }}</div> |
| | | </div> |
| | | |
| | | </div> |
| | | </li> |
| | | </ul> |
| | | <div v-else style="text-align: center">暂无数据</div> |
| | | <div v-else |
| | | style="text-align: center;color:#fff">暂无数据</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue' |
| | | import { homeTodos, summaryStatistics } from '@/api/viewIndex.js' |
| | | import { getLedgerPage } from '@/api/equipmentManagement/ledger.js' |
| | | import { getRepairPage } from '@/api/equipmentManagement/repair.js' |
| | | import { getUpkeepPage } from '@/api/equipmentManagement/upkeep.js' |
| | | import { measuringInstrumentListPage } from '@/api/equipmentManagement/measurementEquipment.js' |
| | | import { ref, onMounted, onBeforeUnmount, nextTick } from "vue"; |
| | | import { homeTodos, summaryStatistics } from "@/api/viewIndex.js"; |
| | | import { getLedgerPage } from "@/api/equipmentManagement/ledger.js"; |
| | | import { getRepairPage } from "@/api/equipmentManagement/repair.js"; |
| | | import { getUpkeepPage } from "@/api/equipmentManagement/upkeep.js"; |
| | | import { measuringInstrumentListPage } from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | |
| | | // 统计数据 |
| | | const totalStaff = ref(0) |
| | | const totalCustomers = ref(0) |
| | | const totalSuppliers = ref(0) |
| | | // 同比 |
| | | const staffYoY = ref(0) |
| | | const customersYoY = ref(0) |
| | | const suppliersYoY = ref(0) |
| | | const equipmentNum = ref(0) |
| | | const equipmentRepair = ref(0) |
| | | const equipmentMaintain = ref(0) |
| | | const totalMeasuring = ref(0) |
| | | // 统计数据 |
| | | const totalStaff = ref(0); |
| | | const totalCustomers = ref(0); |
| | | const totalSuppliers = ref(0); |
| | | // 同比 |
| | | const staffYoY = ref(0); |
| | | const customersYoY = ref(0); |
| | | const suppliersYoY = ref(0); |
| | | const equipmentNum = ref(0); |
| | | const equipmentRepair = ref(0); |
| | | const equipmentMaintain = ref(0); |
| | | const totalMeasuring = ref(0); |
| | | |
| | | // 待办事项 |
| | | const todoList = ref([]) |
| | | const refTodoList = ref(null) |
| | | // 待办事项 |
| | | const todoList = ref([]); |
| | | const refTodoList = ref(null); |
| | | |
| | | const formatPercent = (val) => { |
| | | const num = Number(val) || 0 |
| | | return `${Math.abs(num).toFixed(2)}%` |
| | | } |
| | | const formatPercent = val => { |
| | | const num = Number(val) || 0; |
| | | return `${Math.abs(num).toFixed(2)}%`; |
| | | }; |
| | | |
| | | const compareClass = (val) => (val >= 0 ? 'compare-up' : 'compare-down') |
| | | const compareClass = val => (val >= 0 ? "compare-up" : "compare-down"); |
| | | |
| | | // 获取员工、客户、供应商数量 |
| | | const getNum = () => { |
| | | summaryStatistics().then((res) => { |
| | | totalStaff.value = res.data.totalStaff |
| | | staffYoY.value = res.data.staffGrowthRate |
| | | totalCustomers.value = res.data.totalCustomer |
| | | customersYoY.value = res.data.customerGrowthRate |
| | | totalSuppliers.value = res.data.totalSupplier |
| | | suppliersYoY.value = res.data.supplierGrowthRate |
| | | }).catch(err => { |
| | | console.error('获取基础统计数据失败:', err) |
| | | }) |
| | | } |
| | | // 获取员工、客户、供应商数量 |
| | | const getNum = () => { |
| | | summaryStatistics() |
| | | .then(res => { |
| | | totalStaff.value = res.data.totalStaff; |
| | | staffYoY.value = res.data.staffGrowthRate; |
| | | totalCustomers.value = res.data.totalCustomer; |
| | | customersYoY.value = res.data.customerGrowthRate; |
| | | totalSuppliers.value = res.data.totalSupplier; |
| | | suppliersYoY.value = res.data.supplierGrowthRate; |
| | | }) |
| | | .catch(err => { |
| | | console.error("获取基础统计数据失败:", err); |
| | | }); |
| | | }; |
| | | |
| | | // 获取设备相关数量 |
| | | const getLedgerNum = () => { |
| | | const params = { |
| | | pageNum: -1, |
| | | pageSize: -1, |
| | | } |
| | | getLedgerPage(params).then((res) => { |
| | | equipmentNum.value = res.data.total |
| | | }) |
| | | getRepairPage({ ...params, status: 0 }).then((res) => { |
| | | equipmentRepair.value = res.data.total |
| | | }) |
| | | getUpkeepPage({ ...params, status: 0 }).then((res) => { |
| | | equipmentMaintain.value = res.data.total |
| | | }) |
| | | measuringInstrumentListPage(params).then((res) => { |
| | | totalMeasuring.value = res.data.total |
| | | }) |
| | | } |
| | | // 获取设备相关数量 |
| | | const getLedgerNum = () => { |
| | | const params = { |
| | | pageNum: -1, |
| | | pageSize: -1, |
| | | }; |
| | | getLedgerPage(params).then(res => { |
| | | equipmentNum.value = res.data.total; |
| | | }); |
| | | getRepairPage({ ...params, status: 0 }).then(res => { |
| | | equipmentRepair.value = res.data.total; |
| | | }); |
| | | getUpkeepPage({ ...params, status: 0 }).then(res => { |
| | | equipmentMaintain.value = res.data.total; |
| | | }); |
| | | measuringInstrumentListPage(params).then(res => { |
| | | totalMeasuring.value = res.data.total; |
| | | }); |
| | | }; |
| | | |
| | | // 初始化待办事项列表滚动功能 |
| | | const initTodoListScroll = () => { |
| | | const todoListEl = refTodoList.value |
| | | // 强制启用滚动,不检查任何条件 |
| | | if (todoListEl) { |
| | | // 创建一个克隆项,用于实现无缝滚动 |
| | | const scrollItems = Array.from(todoListEl.querySelectorAll('li')) |
| | | if (scrollItems.length > 0) { |
| | | // 确保有足够的项目用于滚动 |
| | | // 如果项目太少,多复制几次以确保滚动效果 |
| | | if (scrollItems.length < 4) { |
| | | const originalItems = [...scrollItems] |
| | | for (let i = 0; i < 4; i++) { |
| | | originalItems.forEach((item) => { |
| | | const clone = item.cloneNode(true) |
| | | todoListEl.appendChild(clone) |
| | | }) |
| | | } |
| | | // 重新获取所有项目 |
| | | scrollItems.push( |
| | | ...Array.from(todoListEl.querySelectorAll('li')).slice( |
| | | scrollItems.length |
| | | ) |
| | | ) |
| | | } |
| | | const itemHeight = scrollItems[0]?.offsetHeight || 0 |
| | | const containerHeight = todoListEl.clientHeight |
| | | const cloneCount = Math.ceil(containerHeight / itemHeight) + 2 |
| | | |
| | | // 克隆前几个项目并添加到列表末尾,实现无缝滚动 |
| | | for (let i = 0; i < cloneCount; i++) { |
| | | const clone = scrollItems[i % scrollItems.length].cloneNode(true) |
| | | todoListEl.appendChild(clone) |
| | | } |
| | | |
| | | let scrollPosition = 0 |
| | | const scrollSpeed = 1.5 // 增加滚动速度,使滚动更加明显 |
| | | const pauseTime = 3000 // 滚动暂停时间 |
| | | let isPaused = false |
| | | let lastTimestamp = 0 |
| | | |
| | | // 连续滚动动画函数 |
| | | function scrollAnimation(timestamp) { |
| | | if (!lastTimestamp) lastTimestamp = timestamp |
| | | const deltaTime = timestamp - lastTimestamp |
| | | lastTimestamp = timestamp |
| | | |
| | | if (!isPaused) { |
| | | scrollPosition += scrollSpeed * (deltaTime / 16) // 标准化为60fps的速度 |
| | | |
| | | // 当滚动超过原始内容长度时,重置位置实现无缝滚动 |
| | | const maxScroll = Math.max( |
| | | todoListEl.scrollHeight - |
| | | containerHeight - |
| | | cloneCount * itemHeight, |
| | | itemHeight * scrollItems.length |
| | | ) |
| | | if (scrollPosition >= maxScroll) { |
| | | scrollPosition = 0 |
| | | todoListEl.scrollTop = 0 |
| | | } else { |
| | | todoListEl.scrollTop = scrollPosition |
| | | // 初始化待办事项列表滚动功能 |
| | | const initTodoListScroll = () => { |
| | | const todoListEl = refTodoList.value; |
| | | // 强制启用滚动,不检查任何条件 |
| | | if (todoListEl) { |
| | | // 创建一个克隆项,用于实现无缝滚动 |
| | | const scrollItems = Array.from(todoListEl.querySelectorAll("li")); |
| | | if (scrollItems.length > 0) { |
| | | // 确保有足够的项目用于滚动 |
| | | // 如果项目太少,多复制几次以确保滚动效果 |
| | | if (scrollItems.length < 4) { |
| | | const originalItems = [...scrollItems]; |
| | | for (let i = 0; i < 4; i++) { |
| | | originalItems.forEach(item => { |
| | | const clone = item.cloneNode(true); |
| | | todoListEl.appendChild(clone); |
| | | }); |
| | | } |
| | | // 重新获取所有项目 |
| | | scrollItems.push( |
| | | ...Array.from(todoListEl.querySelectorAll("li")).slice( |
| | | scrollItems.length |
| | | ) |
| | | ); |
| | | } |
| | | const itemHeight = scrollItems[0]?.offsetHeight || 0; |
| | | const containerHeight = todoListEl.clientHeight; |
| | | const cloneCount = Math.ceil(containerHeight / itemHeight) + 2; |
| | | |
| | | // 克隆前几个项目并添加到列表末尾,实现无缝滚动 |
| | | for (let i = 0; i < cloneCount; i++) { |
| | | const clone = scrollItems[i % scrollItems.length].cloneNode(true); |
| | | todoListEl.appendChild(clone); |
| | | } |
| | | |
| | | todoListEl._animationFrame = requestAnimationFrame(scrollAnimation) |
| | | let scrollPosition = 0; |
| | | const scrollSpeed = 1.5; // 增加滚动速度,使滚动更加明显 |
| | | const pauseTime = 3000; // 滚动暂停时间 |
| | | let isPaused = false; |
| | | let lastTimestamp = 0; |
| | | |
| | | // 连续滚动动画函数 |
| | | function scrollAnimation(timestamp) { |
| | | if (!lastTimestamp) lastTimestamp = timestamp; |
| | | const deltaTime = timestamp - lastTimestamp; |
| | | lastTimestamp = timestamp; |
| | | |
| | | if (!isPaused) { |
| | | scrollPosition += scrollSpeed * (deltaTime / 16); // 标准化为60fps的速度 |
| | | |
| | | // 当滚动超过原始内容长度时,重置位置实现无缝滚动 |
| | | const maxScroll = Math.max( |
| | | todoListEl.scrollHeight - containerHeight - cloneCount * itemHeight, |
| | | itemHeight * scrollItems.length |
| | | ); |
| | | if (scrollPosition >= maxScroll) { |
| | | scrollPosition = 0; |
| | | todoListEl.scrollTop = 0; |
| | | } else { |
| | | todoListEl.scrollTop = scrollPosition; |
| | | } |
| | | } |
| | | |
| | | todoListEl._animationFrame = requestAnimationFrame(scrollAnimation); |
| | | } |
| | | |
| | | // 启动滚动动画 |
| | | todoListEl._animationFrame = requestAnimationFrame(scrollAnimation); |
| | | |
| | | // 设置滚动-暂停-滚动的循环效果 |
| | | const pauseTimer = setInterval(() => { |
| | | isPaused = !isPaused; |
| | | }, pauseTime); |
| | | |
| | | // 清理定时器 |
| | | todoListEl._pauseTimer = pauseTimer; |
| | | } |
| | | |
| | | // 启动滚动动画 |
| | | todoListEl._animationFrame = requestAnimationFrame(scrollAnimation) |
| | | |
| | | // 设置滚动-暂停-滚动的循环效果 |
| | | const pauseTimer = setInterval(() => { |
| | | isPaused = !isPaused |
| | | }, pauseTime) |
| | | |
| | | // 清理定时器 |
| | | todoListEl._pauseTimer = pauseTimer |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 待办事项 |
| | | const todoInfoS = () => { |
| | | homeTodos().then((res) => { |
| | | todoList.value = res.data |
| | | // 在获取到待办事项数据后,初始化滚动功能 |
| | | nextTick(() => { |
| | | initTodoListScroll() |
| | | }) |
| | | }) |
| | | } |
| | | // 待办事项 |
| | | const todoInfoS = () => { |
| | | homeTodos().then(res => { |
| | | todoList.value = res.data; |
| | | // 在获取到待办事项数据后,初始化滚动功能 |
| | | nextTick(() => { |
| | | initTodoListScroll(); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getNum() |
| | | getLedgerNum() |
| | | todoInfoS() |
| | | }) |
| | | onMounted(() => { |
| | | getNum(); |
| | | getLedgerNum(); |
| | | todoInfoS(); |
| | | }); |
| | | |
| | | onBeforeUnmount(() => { |
| | | // 清理待办事项列表的动画和定时器 |
| | | const todoListEl = refTodoList.value |
| | | if (todoListEl) { |
| | | if (todoListEl._animationFrame) { |
| | | cancelAnimationFrame(todoListEl._animationFrame) |
| | | todoListEl._animationFrame = null |
| | | onBeforeUnmount(() => { |
| | | // 清理待办事项列表的动画和定时器 |
| | | const todoListEl = refTodoList.value; |
| | | if (todoListEl) { |
| | | if (todoListEl._animationFrame) { |
| | | cancelAnimationFrame(todoListEl._animationFrame); |
| | | todoListEl._animationFrame = null; |
| | | } |
| | | if (todoListEl._pauseTimer) { |
| | | clearInterval(todoListEl._pauseTimer); |
| | | todoListEl._pauseTimer = null; |
| | | } |
| | | } |
| | | if (todoListEl._pauseTimer) { |
| | | clearInterval(todoListEl._pauseTimer) |
| | | todoListEl._pauseTimer = null |
| | | } |
| | | } |
| | | }) |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .stats-cards { |
| | | display: flex; |
| | | gap: 30px; |
| | | } |
| | | .center-top-container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | } |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | background-image: url('@/assets/BI/border@2x.png'); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | height: 142px; |
| | | } |
| | | .stats-cards { |
| | | display: flex; |
| | | gap: 30px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .card-icon { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin: 20px 20px 0 10px; |
| | | } |
| | | .stat-card { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | background-image: url("@/assets/BI/border@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | height: 142px; |
| | | } |
| | | |
| | | .card-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | .card-icon { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin: 20px 20px 0 10px; |
| | | } |
| | | |
| | | .card-value { |
| | | font-weight: 500; |
| | | font-size: 40px; |
| | | background: linear-gradient(360deg, #008bfd 0%, #ffffff 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | } |
| | | .card-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .card-label { |
| | | font-weight: 400; |
| | | font-size: 19px; |
| | | color: rgba(208, 231, 255, 0.7); |
| | | } |
| | | .card-value { |
| | | font-weight: 500; |
| | | font-size: 40px; |
| | | background: linear-gradient(360deg, #008bfd 0%, #ffffff 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | } |
| | | |
| | | .card-compare { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | font-size: 15px; |
| | | color: #d0e7ff; |
| | | } |
| | | .card-label { |
| | | font-weight: 400; |
| | | font-size: 19px; |
| | | color: rgba(208, 231, 255, 0.7); |
| | | } |
| | | |
| | | .card-compare > span:first-child { |
| | | font-size: 13px; |
| | | opacity: 0.8; |
| | | } |
| | | .card-compare { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | font-size: 15px; |
| | | color: #d0e7ff; |
| | | } |
| | | |
| | | .compare-value { |
| | | font-weight: 600; |
| | | } |
| | | .card-compare > span:first-child { |
| | | font-size: 13px; |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .compare-icon { |
| | | font-size: 14px; |
| | | position: relative; |
| | | top: -1px; /* 轻微上移,让箭头与文字垂直居中对齐 */ |
| | | } |
| | | .compare-value { |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .compare-up .compare-value, |
| | | .compare-up .compare-icon { |
| | | color: #00c853; |
| | | } |
| | | .compare-icon { |
| | | font-size: 14px; |
| | | position: relative; |
| | | top: -1px; /* 轻微上移,让箭头与文字垂直居中对齐 */ |
| | | } |
| | | |
| | | .compare-down .compare-value, |
| | | .compare-down .compare-icon { |
| | | color: #ff5252; |
| | | } |
| | | .compare-up .compare-value, |
| | | .compare-up .compare-icon { |
| | | color: #00c853; |
| | | } |
| | | |
| | | .equipment-stats { |
| | | border: 1px solid #1a58b0; |
| | | padding: 18px; |
| | | height: 240px; |
| | | padding-top: 0px; |
| | | } |
| | | .compare-down .compare-value, |
| | | .compare-down .compare-icon { |
| | | color: #ff5252; |
| | | } |
| | | |
| | | .equipment-header { |
| | | font-weight: 500; |
| | | font-size: 21px; |
| | | display: flex; |
| | | border-bottom: 1px solid; |
| | | border-image: linear-gradient( |
| | | 270deg, |
| | | rgba(0, 126, 255, 0) 0%, |
| | | rgba(0, 126, 255, 0.4549) 35%, |
| | | #007eff 78%, |
| | | #007eff 100% |
| | | ) |
| | | 1; |
| | | padding-bottom: 2px; |
| | | } |
| | | .equipment-stats { |
| | | border: 1px solid #1a58b0; |
| | | padding: 18px; |
| | | padding-top: 0px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .equipment-title { |
| | | font-weight: 500; |
| | | font-size: 18px; |
| | | background: linear-gradient(360deg, #056dff 0%, #43e8fc 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | line-height: 50px; |
| | | } |
| | | .equipment-header { |
| | | font-weight: 500; |
| | | font-size: 21px; |
| | | display: flex; |
| | | border-bottom: 1px solid; |
| | | border-image: linear-gradient( |
| | | 270deg, |
| | | rgba(0, 126, 255, 0) 0%, |
| | | rgba(0, 126, 255, 0.4549) 35%, |
| | | #007eff 78%, |
| | | #007eff 100% |
| | | ) |
| | | 1; |
| | | padding-bottom: 2px; |
| | | } |
| | | |
| | | .equipment-icon { |
| | | width: 50px; |
| | | height: 50px; |
| | | } |
| | | .equipment-title { |
| | | font-weight: 500; |
| | | font-size: 18px; |
| | | background: linear-gradient(360deg, #056dff 0%, #43e8fc 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | line-height: 50px; |
| | | } |
| | | |
| | | .equipment-items { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | gap: 30px; |
| | | } |
| | | .equipment-icon { |
| | | width: 50px; |
| | | height: 50px; |
| | | } |
| | | |
| | | .equipment-item { |
| | | text-align: center; |
| | | } |
| | | .equipment-items { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | gap: 30px; |
| | | } |
| | | |
| | | .equipment-value { |
| | | display: block; |
| | | font-weight: 500; |
| | | font-size: 40px; |
| | | color: #ffffff; |
| | | width: 120px; |
| | | height: 110px; |
| | | line-height: 110px; |
| | | background-image: url('@/assets/BI/shujutongji@2x.png'); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | margin-bottom: 8px; |
| | | } |
| | | .equipment-item { |
| | | text-align: center; |
| | | } |
| | | |
| | | .equipment-label { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | } |
| | | .equipment-value { |
| | | display: block; |
| | | font-weight: 500; |
| | | font-size: 40px; |
| | | color: #ffffff; |
| | | width: 120px; |
| | | height: 110px; |
| | | line-height: 110px; |
| | | background-image: url("@/assets/BI/shujutongji@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .event-info { |
| | | background-image: url('@/assets/BI/shijianmingchengbeijing@2x.png'); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | padding: 20px; |
| | | height: 186px; |
| | | } |
| | | .equipment-label { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | } |
| | | |
| | | .event-header { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .event-info { |
| | | background-image: url("@/assets/BI/shijianmingchengbeijing@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | padding: 20px; |
| | | padding-top: 10px; |
| | | flex: 1; |
| | | min-height: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .event-icon { |
| | | width: 40px; |
| | | height: 40px; |
| | | } |
| | | .event-header { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 80px; |
| | | } |
| | | |
| | | .event-title { |
| | | font-weight: 500; |
| | | font-size: 18px; |
| | | color: #fffffe; |
| | | line-height: 30px; |
| | | } |
| | | .event-icon { |
| | | width: 40px; |
| | | height: 40px; |
| | | } |
| | | |
| | | .todo-list { |
| | | list-style: none; |
| | | padding: 0; |
| | | margin: 0; |
| | | height: 120px; /* 按用户要求调整高度 */ |
| | | overflow: hidden; |
| | | font-size: 15px; |
| | | } |
| | | .event-title { |
| | | font-weight: 500; |
| | | font-size: 18px; |
| | | color: #fffffe; |
| | | line-height: 30px; |
| | | } |
| | | .event-content { |
| | | flex: 1; |
| | | } |
| | | |
| | | .todo-list li { |
| | | border-radius: 8px; |
| | | margin-bottom: 12px; |
| | | padding: 12px 40px; |
| | | height: 74px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .todo-list { |
| | | list-style: none; |
| | | padding: 0; |
| | | margin: 0; |
| | | height: 100%; /* 按用户要求调整高度 */ |
| | | overflow: hidden; |
| | | font-size: 15px; |
| | | } |
| | | |
| | | .todo-title { |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | position: relative; |
| | | } |
| | | .todo-list li { |
| | | border-radius: 8px; |
| | | margin-bottom: 12px; |
| | | padding: 12px 40px; |
| | | height: 74px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .todo-title { |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | position: relative; |
| | | } |
| | | |
| | | .todo-division { |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | position: relative; |
| | | } |
| | | |
| | | .todo-division { |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | position: relative; |
| | | } |
| | | .todo-division::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: -20px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 6px; |
| | | height: 6px; |
| | | background: #498ceb; |
| | | border-radius: 50%; |
| | | } |
| | | |
| | | .todo-division::before { |
| | | content: ''; |
| | | position: absolute; |
| | | left: -20px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 6px; |
| | | height: 6px; |
| | | background: #498ceb; |
| | | border-radius: 50%; |
| | | } |
| | | |
| | | .todo-time { |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | background: rgba(24, 93, 190, 0.4); |
| | | border-radius: 5px 5px 5px 5px; |
| | | padding: 5px 10px; |
| | | } |
| | | .todo-time { |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #fffffe; |
| | | background: rgba(24, 93, 190, 0.4); |
| | | border-radius: 5px 5px 5px 5px; |
| | | padding: 5px 10px; |
| | | } |
| | | </style> |