feat(轮播看板): 重构轮播看板组件并添加统一标题样式

重构轮播看板管理页面布局,添加kbHeader组件统一标题样式
新增header.png和header.svg作为看板标题背景
优化WorkorderOnlineCard和QualityStatisticsCard组件布局和样式
实现表格自动滚动功能,添加统计图表展示数据
调整轮播容器高度和间距,提升视觉效果
This commit is contained in:
2025-10-28 23:05:47 +08:00
parent bbd43f53ef
commit cb8a9d001f
7 changed files with 1209 additions and 735 deletions

View File

@@ -1,108 +1,167 @@
<template>
<div class="workorder-online-card">
<dv-title text="生产计划工单" :color="['#00ffff', '#0066ff']" style="margin-bottom: 15px;" />
<kb-header>生产计划工单</kb-header>
<!-- 今日统计数据区域 -->
<div class="statistics-container">
<div class="stat-item">
<span class="stat-label">今日总计划数:</span>
<span class="stat-value">{{ todayStatistics.totalPlan }}</span>
<!-- 第一行布局 -->
<div class="first-row">
<!-- 第一行第一个区域今日生产未完成数及已完成数占比饼图 -->
<div class="chart-section">
<div class="section-title">今日生产状态</div>
<div id="workorderStatusChart" style="width: 100%; height: 100%;"></div>
</div>
<div class="stat-item">
<span class="stat-label">已完成计划数:</span>
<span class="stat-value completed">{{ todayStatistics.completedPlan }}</span>
</div>
<div class="stat-item">
<span class="stat-label">未完成计划数:</span>
<span class="stat-value uncompleted">{{ todayStatistics.uncompletedPlan }}</span>
</div>
<div class="stat-item">
<span class="stat-label">今日总投入数:</span>
<span class="stat-value">{{ todayStatistics.totalInput }}</span>
</div>
<div class="stat-item">
<span class="stat-label">今日总合格数:</span>
<span class="stat-value qualified">{{ todayStatistics.totalQualified }}</span>
<!-- 第一行第二三区域合并今日统计数据翻牌器 -->
<div class="statistics-section">
<div class="section-title">今日统计</div>
<div class="flip-card-container">
<div class="flip-card">
<div class="flip-card-label">今日总计划数</div>
<div class="flip-card-value">{{ todayStatistics.totalPlan }}</div>
</div>
<div class="flip-card">
<div class="flip-card-label">已完成计划数</div>
<div class="flip-card-value completed">{{ todayStatistics.completedPlan }}</div>
</div>
<div class="flip-card">
<div class="flip-card-label">未完成计划数</div>
<div class="flip-card-value uncompleted">{{ todayStatistics.uncompletedPlan }}</div>
</div>
<div class="flip-card">
<div class="flip-card-label">今日总投入数</div>
<div class="flip-card-value">{{ todayStatistics.totalInput }}</div>
</div>
</div>
</div>
</div>
<!-- 工单完成状态分布环形进度图 -->
<div class="chart-container">
<div id="workorderStatusChart" style="width: 100%; height: 200px;"></div>
<!-- 第二行布局 -->
<div class="second-row">
<!-- 第一二区域工单表格 -->
<div class="table-section">
<div class="section-title">工单列表</div>
<div class="custom-table-wrapper" :style="{ height: tableHeight }">
<table class="custom-table" v-if="!loading">
<thead>
<tr>
<th width="60">序号</th>
<th width="130">工单号</th>
<th width="120">毛坯号</th>
<th width="150">成品零件号</th>
<th>产品描述</th>
<th width="100">颜色</th>
<th width="100">规格</th>
<th width="80">车数</th>
<th width="80">上件数</th>
<th width="100">状态</th>
</tr>
</thead>
<tbody ref="tableBody">
<tr v-for="(row, index) in workorderOnlineTable" :key="index" class="table-row">
<td>{{ index + 1 }}</td>
<td>{{ row.clientWorkorder || '-' }}</td>
<td>{{ row.blankNumber || '-' }}</td>
<td>{{ row.finishedPartNumber || '-' }}</td>
<td class="ellipsis">{{ row.productDescription || '-' }}</td>
<td>{{ row.colour || '-' }}</td>
<td>{{ row.specifications || '-' }}</td>
<td>{{ row.vehicleNumber || '-' }}</td>
<td>{{ row.previousNumber || '-' }}</td>
<td>
<span
class="status-tag"
:class="getStatusClass(row.status)"
>
{{ getStatusText(row.status) }}
</span>
</td>
</tr>
</tbody>
</table>
<div class="loading-overlay" v-if="loading">
<div class="loading-spinner"></div>
<div class="loading-text">加载中...</div>
</div>
</div>
</div>
<!-- 第三区域生产统计横向柱状图 -->
<div class="bar-chart-section">
<div class="section-title">生产零件Top5统计</div>
<div id="productionTypeChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<el-table
:data="workorderOnlineTable"
v-loading="loading"
border
style="width: 100%"
:height="tableHeight"
ref="workorderTable"
stripe
highlight-current-row
class="dark-table"
>
<el-table-column type="index" width="60"></el-table-column>
<el-table-column prop="clientWorkorder" label="工单号" width="130"></el-table-column>
<el-table-column prop="blankNumber" label="毛坯号" width="120"></el-table-column>
<el-table-column prop="finishedPartNumber" label="成品零件号" width="150"></el-table-column>
<el-table-column prop="productDescription" label="产品描述"></el-table-column>
<el-table-column prop="colour" label="颜色" width="100"></el-table-column>
<el-table-column prop="specifications" label="规格" width="100"></el-table-column>
<el-table-column prop="vehicleNumber" label="车数" width="80"></el-table-column>
<el-table-column prop="previousNumber" label="上件数" width="80"></el-table-column>
<el-table-column prop="remark3" label="状态" width="100">
<template slot-scope="scope">
<el-tag size="small" v-if="scope.row.status === 2" type="success">已完成</el-tag>
<el-tag size="small" v-else-if="scope.row.status === 1" type="warning">进行中</el-tag>
<el-tag size="small" v-else type="info">未开始</el-tag>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { getWorkOrderCarouselBoardData } from '@/api/kanbanManagement/carouselBoard.js'
import * as echarts from 'echarts';
import { DvTitle } from '@jiaminghi/data-view';
import kbHeader from './kbHeader.vue';
export default {
name: 'WorkorderOnlineCard',
components: {
DvTitle
kbHeader
},
data() {
return {
loading: false,
workorderOnlineTable: [],
tableHeight: '500px', // 调整表格高度,为图表留出空间
realTotal: 0,
tableHeight: '500px',
workorderChart: null,
productionChart: null,
tableScrollTimer: null,
refreshTimer: null,
scrollCheckTimer: null,
// 今日统计数据
todayStatistics: {
totalPlan: 0, // 今日总计划数
completedPlan: 0, // 已完成计划数
uncompletedPlan: 0, // 未完成计划数
totalInput: 0, // 今日总投入数
totalQualified: 0 // 今日总合格数
totalInput: 0 // 今日总投入数
}
}
},
mounted() {
console.log('工单组件mounted生命周期调用')
this.getWorkorderData()
window.addEventListener('resize', this.handleResize)
// 组件挂载后延迟启动滚动,确保数据已加载
setTimeout(() => {
this.$nextTick(() => {
console.log('延迟启动滚动')
this.startTableAutoScroll()
})
}, 1000)
// 添加一个定时器每10秒重新启动一次滚动确保滚动持续工作
this.scrollCheckTimer = setInterval(() => {
console.log('工单组件定时检查滚动')
this.$nextTick(() => {
this.startTableAutoScroll()
})
}, 5000) // 缩短为5秒检查一次
// 设置5分钟定时刷新
this.refreshTimer = setInterval(() => {
this.getWorkorderData()
}, 5 * 60 * 1000) // 5分钟 = 5 * 60 * 1000毫秒
},
updated() {
// 数据更新后初始化图表
if (this.workorderOnlineTable.length > 0 && !this.workorderChart) {
this.$nextTick(() => {
// 数据更新后初始化图表和启动表格滚动
this.$nextTick(() => {
console.log('工单组件updated生命周期调用')
if (this.workorderOnlineTable.length > 0) {
this.initWorkorderChart()
this.startTableAutoScroll()
})
}
this.initProductionTypeChart()
}
// 无论数据是否为空,都尝试启动滚动,确保表格有内容时能正常滚动
this.startTableAutoScroll()
})
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
@@ -111,11 +170,25 @@ export default {
this.workorderChart.dispose()
this.workorderChart = null
}
// 清理表格滚动定时器
if (this.productionChart) {
this.productionChart.dispose()
this.productionChart = null
}
// 清理表格滚动定时器setInterval
if (this.tableScrollTimer) {
clearInterval(this.tableScrollTimer)
this.tableScrollTimer = null
}
// 清理滚动检查定时器
if (this.scrollCheckTimer) {
clearInterval(this.scrollCheckTimer)
this.scrollCheckTimer = null
}
// 清理数据刷新定时器
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
this.refreshTimer = null
}
},
methods: {
getWorkorderData() {
@@ -130,10 +203,16 @@ export default {
.then((res) => {
if (res.code == 200) {
this.workorderOnlineTable = res.data || []
this.realTotal = this.workorderOnlineTable.length
console.log('工单数据加载完成,共', this.workorderOnlineTable.length, '条记录')
// 计算今日统计数据
this.calculateTodayStatistics()
// 数据加载完成后立即启动滚动
this.$nextTick(() => {
console.log('数据加载后启动滚动')
this.startTableAutoScroll()
})
}
})
.finally(() => {
@@ -148,13 +227,12 @@ export default {
totalPlan: 0,
completedPlan: 0,
uncompletedPlan: 0,
totalInput: 0,
totalQualified: 0
totalInput: 0
}
// 统计工单数据
this.workorderOnlineTable.forEach(item => {
// 假设vehicleNumber是计划数
// 确保使用实际的计划数字段
const planCount = Number(item.vehicleNumber) || 0
this.todayStatistics.totalPlan += planCount
@@ -165,129 +243,274 @@ export default {
this.todayStatistics.uncompletedPlan += planCount
}
// 假设previousNumber是投入数
// 确保使用实际的投入数字段
this.todayStatistics.totalInput += Number(item.previousNumber) || 0
// 假设合格数为投入数的90%实际应从API获取
const qualifiedCount = Math.round((Number(item.previousNumber) || 0) * 0.9)
this.todayStatistics.totalQualified += qualifiedCount
})
},
// 初始化工单状态分布环形进度图
// 获取状态文本
getStatusText(status) {
switch (status) {
case 2: return '已完成'
case 1: return '进行中'
default: return '未开始'
}
},
// 获取状态样式类
getStatusClass(status) {
switch (status) {
case 2: return 'status-completed'
case 1: return 'status-progress'
default: return 'status-not-started'
}
},
// 初始化工单状态分布饼图
initWorkorderChart() {
const chartDom = document.getElementById('workorderStatusChart')
if (!chartDom) return
this.workorderChart = echarts.init(chartDom)
// 准备环形图数据
const statusCounts = {
'已完成': 0,
'进行中': 0,
'未开始': 0,
'已暂停': 0
if (this.workorderChart) {
this.workorderChart.dispose()
}
// 根据工单状态统计数量
this.workorderOnlineTable.forEach(item => {
switch (item.status) {
case 2: // 已完成
statusCounts['已完成']++
break
case 1: // 进行中
statusCounts['进行中']++
break
default: // 未开始
statusCounts['未开始']++
}
})
this.workorderChart = echarts.init(chartDom)
// 统计已完成和未完成数量
const completedCount = this.workorderOnlineTable.filter(item => item.status === 2).length
const uncompletedCount = this.workorderOnlineTable.filter(item => item.status !== 2).length
const option = {
title: {
text: '工单状态分布',
left: 'center',
top: 0
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'horizontal',
bottom: 0
orient: 'vertical',
left: 10,
top: 'center',
textStyle: {
color: '#00ffff'
}
},
series: [
{
name: '工单状态',
name: '今日生产',
type: 'pie',
radius: ['40%', '70%'], // 环形图
radius: ['40%', '70%'],
center: ['60%', '50%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderColor: 'rgba(0, 20, 40, 0.6)',
borderWidth: 2
},
label: {
show: true,
formatter: '{b}\n{d}%'
formatter: '{b}\n{d}%',
color: '#ffffff'
},
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'bold'
fontWeight: 'bold',
color: '#00ffff'
}
},
data: [
{ value: statusCounts['已完成'], name: '已完成', itemStyle: { color: '#67c23a' } },
{ value: statusCounts['进行中'], name: '进行中', itemStyle: { color: '#409EFF' } },
{ value: statusCounts['未开始'], name: '未开始', itemStyle: { color: '#909399' } }
].filter(item => item.value > 0) // 过滤掉数量为0的状态
{ value: completedCount, name: '已完成', itemStyle: { color: '#67c23a' } },
{ value: uncompletedCount, name: '未完成', itemStyle: { color: '#e6a23c' } }
].filter(item => item.value > 0)
}
]
}
this.workorderChart.setOption(option)
},
// 初始化生产统计横向柱状图
initProductionTypeChart() {
const chartDom = document.getElementById('productionTypeChart')
if (!chartDom) return
// 监听窗口大小变化,调整图表大小
window.addEventListener('resize', () => {
if (this.workorderChart) {
this.workorderChart.resize()
if (this.productionChart) {
this.productionChart.dispose()
}
this.productionChart = echarts.init(chartDom)
// 按零件汇总并统计上件数
const partStats = {}
this.workorderOnlineTable.forEach(item => {
// 使用成品零件号作为唯一标识
const partKey = item.finishedPartNumber || item.productDescription || '未知'
const previousNumber = Number(item.previousNumber) || 0
if (!partStats[partKey]) {
partStats[partKey] = {
name: partKey,
value: 0,
description: item.productDescription || partKey
}
}
partStats[partKey].value += previousNumber
})
// 转换为数组并按上件数降序排序确保数量最大的显示在顶部只取前5个
const sortedData = Object.values(partStats)
.sort((a, b) => b.value - a.value)
.slice(0, 5)
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '10%', // 减小左侧边距,让图表整体向左移动
right: '10%',
top: '10%',
bottom: '10%',
containLabel: true
},
xAxis: {
type: 'value',
axisLabel: {
color: '#ffffff'
},
splitLine: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.1)'
}
}
},
yAxis: {
type: 'category',
data: sortedData.map(item => {
// 使用描述或零件号,进行自动换行处理
const displayText = item.description || item.name
const maxLength = 8
let result = displayText
if (result.length > maxLength) {
result = ''
for (let i = 0; i < displayText.length; i += maxLength) {
result += displayText.substring(i, i + maxLength) + '\n'
}
result = result.trim()
}
return result
}),
axisLabel: {
color: '#00ffff',
fontSize: 10,
interval: 0
}
},
series: [
{
name: '数量',
type: 'bar',
data: sortedData.map(item => item.value),
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: '#0066ff' },
{ offset: 1, color: '#00ffff' }
])
},
label: {
show: true,
position: 'right',
color: '#ffffff'
}
}
]
}
this.productionChart.setOption(option)
},
// 表格自动滚动功能 - 修复滚动逻辑
startTableAutoScroll() {
// 先清理可能存在的定时器
if (this.tableScrollTimer) {
cancelAnimationFrame(this.tableScrollTimer)
this.tableScrollTimer = null
}
// 确保表格元素已渲染
this.$nextTick(() => {
// 直接获取DOM元素避免选择器问题
const tableSection = this.$el.querySelector('.table-section')
const wrapper = tableSection ? tableSection.querySelector('.custom-table-wrapper') : null
console.log('工单组件滚动容器:', wrapper)
if (!wrapper) {
console.log('滚动容器未找到')
return
}
// 重要:确保容器内容高度大于容器高度才需要滚动
const scrollableHeight = wrapper.scrollHeight - wrapper.clientHeight
console.log('容器可滚动高度差:', scrollableHeight)
// 优化滚动容器样式设置
// 不设置height因为模板中已经通过:style绑定
wrapper.style.overflow = 'auto'
wrapper.style.overflowX = 'hidden'
wrapper.style.scrollBehavior = 'smooth'
console.log('设置滚动容器样式完成')
// 重置滚动位置
wrapper.scrollTop = 0
// 增加滚动速度,使其更容易观察
const scrollSpeed = 2 // 提高到2确保明显可见
// 使用setInterval替代requestAnimationFrame更稳定
this.tableScrollTimer = setInterval(() => {
if (wrapper && wrapper.scrollHeight > wrapper.clientHeight) {
// 检查是否滚动到底部
if (wrapper.scrollTop + 10 >= wrapper.scrollHeight - wrapper.clientHeight) {
console.log('工单组件已滚动到底部,准备复位')
// 重置到顶部
wrapper.scrollTop = 0
} else {
// 持续滚动
wrapper.scrollTop += scrollSpeed
}
}
}, 50) // 每50毫秒滚动一次更平滑
console.log('工单组件启动滚动定时器')
})
},
// 表格自动滚动功能
startTableAutoScroll() {
if (this.tableScrollTimer) {
clearInterval(this.tableScrollTimer)
handleResize() {
// 考虑kbHeader的高度重新计算内容高度
const windowHeight = window.innerHeight
// 减去标题高度和padding等确保内容适配
const availableHeight = windowHeight - 60 // 标题高度
// 调整第一行高度,进一步减小以给第二行留出更多空间
const firstRow = document.querySelector('.first-row')
if (firstRow) {
firstRow.style.height = '200px' // 进一步减小第一行高度
}
this.tableScrollTimer = setInterval(() => {
if (this.$refs.workorderTable) {
const elTableBody = this.$refs.workorderTable.$el.querySelector('.el-table__body-wrapper')
if (elTableBody) {
// 每次滚动一行的高度
const scrollStep = 31 // 行高 + 边框
elTableBody.scrollTop += scrollStep
// 如果滚动到底部,回到顶部继续滚动
if (elTableBody.scrollTop + elTableBody.clientHeight >= elTableBody.scrollHeight) {
elTableBody.scrollTop = 0
}
}
}
}, 2000) // 每2秒滚动一次
},
handleResize() {
const windowHeight = window.innerHeight
this.tableHeight = Math.max(windowHeight * 0.5, 400) + 'px' // 为图表留出空间
// 计算表格高度,确保表格固定高度且不会超出屏幕
// 将表格高度固定为一个合理的值,确保在各种屏幕尺寸下都能正常显示
this.tableHeight = Math.min(Math.max(availableHeight - 350, 300), 400) + 'px' // 限制最大高度为400px
// 调整图表大小
if (this.workorderChart) {
this.workorderChart.resize()
}
if (this.productionChart) {
this.productionChart.resize()
}
}
}
}
@@ -295,166 +518,244 @@ export default {
<style scoped>
.workorder-online-card {
padding: 15px;
background: white;
padding: 10px;
background: transparent;
width: 100%;
min-height: 100vh; /* 确保至少填满整个视口高度 */
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 15px; /* 减小间距 */
}
/* kbHeader组件已包含标题样式 */
/* 第一行布局 */
.first-row {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 15px;
height: 200px;
}
/* 第二行布局 */
.second-row {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 15px;
flex: 1;
min-height: 0;
}
/* 通用区域样式 */
.chart-section,
.statistics-section,
.table-section,
.bar-chart-section {
background: rgba(0, 20, 40, 0.6);
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
height: 100%;
border: 1px solid rgba(0, 255, 255, 0.3);
padding: 15px;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
/* 今日统计数据样式 */
.statistics-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
margin-bottom: 15px;
padding: 10px;
background-color: #f0f2f5;
border-radius: 6px;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 8px;
background-color: white;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}
.stat-label {
font-size: 12px;
color: #606266;
margin-bottom: 4px;
}
.stat-value {
.section-title {
color: #00ffff;
font-size: 16px;
font-weight: bold;
color: #303133;
margin-bottom: 15px;
text-align: center;
padding-bottom: 8px;
border-bottom: 1px solid rgba(0, 255, 255, 0.3);
}
.stat-value.completed {
/* 统计翻牌器样式 */
.flip-card-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
flex: 1;
align-items: center;
}
.flip-card {
background: rgba(0, 60, 120, 0.8);
border-radius: 6px;
padding: 15px 10px;
text-align: center;
border: 1px solid rgba(0, 255, 255, 0.2);
transition: all 0.3s ease;
}
.flip-card:hover {
box-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
transform: translateY(-2px);
}
.flip-card-label {
color: #ffffff;
font-size: 12px;
margin-bottom: 8px;
}
.flip-card-value {
color: #00ffff;
font-size: 24px;
font-weight: bold;
font-family: 'Courier New', monospace;
letter-spacing: 2px;
}
.flip-card-value.completed {
color: #67c23a;
}
.stat-value.uncompleted {
.flip-card-value.uncompleted {
color: #e6a23c;
}
.stat-value.qualified {
color: #409EFF;
}
.chart-container {
margin-bottom: 15px;
flex-shrink: 0;
background-color: #fafafa;
/* 自定义表格样式 */
.custom-table-wrapper {
/* 确保表格固定高度不依赖flex:1避免内容超出屏幕 */
overflow-y: auto;
border-radius: 6px;
padding: 10px;
background: rgba(0, 60, 120, 0.8);
/* 确保高度已通过JS设置这里不再设置 */
}
.el-table {
flex: 1;
min-height: 0;
border-radius: 6px;
overflow: hidden;
.custom-table {
width: 100%;
border-collapse: collapse;
color: #ffffff;
}
/* 优化表格样式 */
.el-table__header-wrapper th {
background-color: #e6f7ff !important;
color: #303133;
font-weight: 600;
.custom-table thead {
position: sticky;
top: 0;
z-index: 10;
}
.custom-table th {
background: rgba(0, 60, 120, 1);
color: #00ffff;
font-weight: bold;
text-align: center;
padding: 12px 5px;
border-bottom: 1px solid rgba(0, 255, 255, 0.3);
font-size: 13px;
padding: 10px 5px;
}
.el-table__body-wrapper td {
.custom-table td {
text-align: center;
font-size: 13px;
padding: 10px 5px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
font-size: 13px;
}
.table-row:hover td {
background-color: rgba(0, 255, 255, 0.1);
}
/* 状态标签样式 */
.status-tag {
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
border: 1px solid transparent;
}
.status-completed {
background-color: rgba(103, 194, 58, 0.3);
border-color: #67c23a;
color: #67c23a;
}
.status-progress {
background-color: rgba(230, 162, 60, 0.3);
border-color: #e6a23c;
color: #e6a23c;
}
.status-not-started {
background-color: rgba(90, 143, 242, 0.3);
border-color: #5a8ff2;
color: #5a8ff2;
}
/* 加载样式 */
.loading-overlay {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: #00ffff;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(0, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #00ffff;
animation: spin 1s ease-in-out infinite;
margin-bottom: 10px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.loading-text {
font-size: 14px;
}
/* 超出省略 */
.ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 150px;
}
/* 优化斑马纹效果 */
.el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: #fafafa;
/* 滚动条样式 */
.custom-table-wrapper::-webkit-scrollbar {
width: 8px;
}
/* 高亮当前行 */
.el-table__body tr:hover>td {
background-color: #f5f7fa;
}
</style>
<style scoped>
.workorder-online-card {
padding: 20px;
background: transparent;
width: 100%;
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
.custom-table-wrapper::-webkit-scrollbar-track {
background: rgba(0, 60, 120, 0.5);
border-radius: 4px;
}
/* 表格样式优化 */
.dark-table {
background: rgba(0, 20, 40, 0.6) !important;
.custom-table-wrapper::-webkit-scrollbar-thumb {
background: rgba(0, 255, 255, 0.5);
border-radius: 4px;
}
::v-deep .el-table__header th {
background: rgba(0, 60, 120, 0.8) !important;
color: #00ffff !important;
border-bottom: 1px solid rgba(0, 255, 255, 0.3) !important;
font-weight: bold;
.custom-table-wrapper::-webkit-scrollbar-thumb:hover {
background: rgba(0, 255, 255, 0.8);
}
::v-deep .el-table__body td {
color: #ffffff !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
}
::v-deep .el-table__row:hover td {
background-color: rgba(0, 255, 255, 0.1) !important;
}
/* 标签样式优化 */
::v-deep .el-tag {
background-color: rgba(0, 102, 255, 0.3) !important;
color: #ffffff !important;
border-color: #0066ff !important;
}
::v-deep .el-tag--success {
background-color: rgba(103, 194, 58, 0.3) !important;
border-color: #67c23a !important;
}
::v-deep .el-tag--warning {
background-color: rgba(230, 162, 60, 0.3) !important;
border-color: #e6a23c !important;
}
::v-deep .el-tag--info {
background-color: rgba(90, 143, 242, 0.3) !important;
border-color: #5a8ff2 !important;
}
/* 加载动画样式 */
::v-deep .el-loading-spinner .path {
stroke: #00ffff !important;
}
::v-deep .el-loading-spinner .el-loading-text {
color: #00ffff !important;
/* 响应式调整 */
@media (max-width: 1200px) {
.first-row {
grid-template-columns: 1fr;
height: auto;
gap: 15px;
}
.second-row {
grid-template-columns: 1fr;
gap: 15px;
}
.flip-card-container {
grid-template-columns: repeat(2, 1fr);
}
}
</style>

View File

@@ -0,0 +1,29 @@
<template>
<div class="header">
<span class="title"><slot></slot></span>
</div>
</template>
<script></script>
<style scoped>
.header {
background-image: url('../images/header.png');
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.title {
font-size: 36px;
font-weight: 600;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
-webkit-background-clip: text; /* 仅将背景应用于文本 */
-webkit-text-fill-color: transparent; /* 设置文本颜色为透明 */
color: transparent; /* 兼容非WebKit浏览器 */
background-image: linear-gradient(92deg, #0072ff 0%, #00eaff 50%, #01aaff 100%);
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 1200 100">
<defs>
<linearGradient id="headerGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#002854;stop-opacity:0.8" />
<stop offset="50%" style="stop-color:#004d8c;stop-opacity:0.8" />
<stop offset="100%" style="stop-color:#002854;stop-opacity:0.8" />
</linearGradient>
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="5" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<rect width="100%" height="100%" fill="url(#headerGradient)" />
<rect x="10" y="10" width="1180" height="80" rx="5" ry="5" fill="none" stroke="#00ffff" stroke-width="1" stroke-opacity="0.3" filter="url(#glow)" />
<line x1="10" y1="90" x2="1190" y2="90" stroke="#00ffff" stroke-width="1" stroke-opacity="0.5" />
</svg>

After

Width:  |  Height:  |  Size: 953 B

View File

@@ -1,10 +1,8 @@
<template>
<dv-full-screen-container>
<!-- <dv-decoration-1 :color="['#00ffff', '#0066ff']" />
<dv-decoration-2 :color="['#00ffff', '#0066ff']" /> -->
<div class="carousel-board-container">
<dv-border-box-1 class="dashboard-border">
<el-carousel ref="carousel" :interval="60000" height="99vh" arrow="never" indicator-position="bottom" autoplay
<el-carousel ref="carousel" :interval="60000" height="100vh" arrow="never" indicator-position="bottom" autoplay
class="dashboard-carousel">
<el-carousel-item>
<QualityStatisticsCard />
@@ -53,9 +51,9 @@ export default {
.carousel-board-container {
width: 100%;
height: 100%;
padding: 20px;
padding: 0px;
background: linear-gradient(135deg, #001529 0%, #002140 100%);
overflow: hidden;
overflow: auto;
box-sizing: border-box;
}
@@ -71,8 +69,9 @@ export default {
/* 优化轮播项样式 */
.el-carousel__item {
padding: 10px;
padding: 0;
box-sizing: border-box;
min-height: 100vh;
}
/* 确保指示器清晰可见 */

View File

@@ -1,5 +1,6 @@
<template>
<div class="carousel-board-management">
<div class="carousel-board-root">
<div class="carousel-board-management">
<!-- 页面标题 -->
<div class="page-header">
<h3>轮播看板管理</h3>
@@ -82,9 +83,9 @@
<el-table-column prop="result" label="操作结果"></el-table-column>
</el-table>
</el-card>
</div>
</div>
<!-- 时间选择弹窗 -->
<!-- 时间选择弹窗 -->
<el-dialog :title="`${currentAction}${currentModuleName}数据 - 选择日期`" :visible.sync="timeDialogVisible" width="400px" :close-on-click-modal="false">
<div style="padding: 20px 0">
<el-form label-position="top">
@@ -97,7 +98,8 @@
<el-button @click="timeDialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirmTimeSelection">{{ currentAction }}</el-button>
</span>
</el-dialog>
</el-dialog>
</div>
</template>
<script>