feat: update production kanban details
This commit is contained in:
205
生产任务看板/src/views/plan-kanban/components/CenterDetailPanel.vue
Normal file
205
生产任务看板/src/views/plan-kanban/components/CenterDetailPanel.vue
Normal file
@@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<section class="center-detail-panel panel">
|
||||
<header class="detail-panel-head">
|
||||
<h2>{{ title }}</h2>
|
||||
<span v-if="status === 'ready'" class="detail-count">{{ rows.length }} 条</span>
|
||||
</header>
|
||||
|
||||
<div class="detail-table-head detail-grid-row" :style="gridStyle">
|
||||
<span v-for="column in columns" :key="column.key">{{ column.label }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-table-body">
|
||||
<div
|
||||
v-if="status === 'ready'"
|
||||
class="detail-table-track"
|
||||
:class="{ scrolling: shouldScroll }"
|
||||
:style="scrollStyle"
|
||||
>
|
||||
<div
|
||||
v-for="(row, index) in displayRows"
|
||||
:key="`${row.id}-${index}`"
|
||||
class="detail-grid-row detail-data-row"
|
||||
:class="{ urgent: row.urgent }"
|
||||
:style="gridStyle"
|
||||
:title="row.title"
|
||||
>
|
||||
<span
|
||||
v-for="column in columns"
|
||||
:key="column.key"
|
||||
:class="[`cell-${column.key}`, { 'category-cell': column.key === 'category' }]"
|
||||
>
|
||||
{{ row[column.key] || '--' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="detail-panel-state">
|
||||
<span v-if="status === 'loading'" class="detail-loading-icon"></span>
|
||||
{{ status === 'loading' ? '加载中' : message }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
title: { type: String, required: true },
|
||||
columns: { type: Array, required: true },
|
||||
rows: { type: Array, default: () => [] },
|
||||
status: { type: String, default: 'loading' },
|
||||
message: { type: String, default: '' },
|
||||
visibleRows: { type: Number, default: 9 }
|
||||
})
|
||||
|
||||
const rowHeight = 34
|
||||
const shouldScroll = computed(() => props.rows.length > props.visibleRows)
|
||||
const displayRows = computed(() => shouldScroll.value ? [...props.rows, ...props.rows] : props.rows)
|
||||
const gridStyle = computed(() => ({
|
||||
gridTemplateColumns: props.columns.map(column => column.width || '1fr').join(' ')
|
||||
}))
|
||||
const scrollStyle = computed(() => ({
|
||||
'--scroll-distance': `${props.rows.length * rowHeight}px`,
|
||||
'--scroll-duration': `${Math.max(props.rows.length * 1.8, 20)}s`
|
||||
}))
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.center-detail-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
color: #dcecff;
|
||||
background: rgba(7, 31, 72, 0.72);
|
||||
}
|
||||
|
||||
.detail-panel-head {
|
||||
display: flex;
|
||||
flex: 0 0 36px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-width: 0;
|
||||
padding: 0 10px;
|
||||
border-bottom: 1px solid rgba(43, 216, 255, 0.28);
|
||||
}
|
||||
|
||||
.detail-panel-head h2 {
|
||||
margin: 0;
|
||||
color: #8cd3ff;
|
||||
font-size: 14px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.detail-count {
|
||||
color: #1ce6ff;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.detail-grid-row {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.detail-table-head {
|
||||
flex: 0 0 30px;
|
||||
color: #bfe8ff;
|
||||
font-size: 9px;
|
||||
font-weight: 800;
|
||||
background: rgba(10, 75, 145, 0.76);
|
||||
}
|
||||
|
||||
.detail-table-head span,
|
||||
.detail-data-row > span {
|
||||
min-width: 0;
|
||||
padding: 0 2px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.detail-table-body {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.detail-table-track.scrolling {
|
||||
animation: detail-table-scroll var(--scroll-duration) linear infinite;
|
||||
}
|
||||
|
||||
.detail-table-track.scrolling:hover {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
.detail-data-row {
|
||||
height: 34px;
|
||||
color: #dcecff;
|
||||
font-size: 9px;
|
||||
border-bottom: 1px solid rgba(43, 216, 255, 0.1);
|
||||
}
|
||||
|
||||
.detail-data-row:nth-child(odd) {
|
||||
background: rgba(4, 25, 59, 0.38);
|
||||
}
|
||||
|
||||
.detail-data-row:nth-child(even) {
|
||||
background: rgba(4, 18, 47, 0.24);
|
||||
}
|
||||
|
||||
.detail-data-row.urgent,
|
||||
.detail-data-row.urgent .category-cell {
|
||||
color: #ff637a;
|
||||
background: rgba(116, 19, 37, 0.22);
|
||||
}
|
||||
|
||||
.category-cell {
|
||||
color: #1ce6ff;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.cell-materialName {
|
||||
display: -webkit-box;
|
||||
overflow-wrap: anywhere;
|
||||
line-height: 12px;
|
||||
white-space: normal;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.detail-panel-state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #78a9ce;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.detail-loading-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: 2px solid rgba(43, 216, 255, 0.25);
|
||||
border-top-color: #2bd8ff;
|
||||
border-radius: 50%;
|
||||
animation: detail-loading 0.8s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes detail-table-scroll {
|
||||
from { transform: translateY(0); }
|
||||
to { transform: translateY(calc(-1 * var(--scroll-distance))); }
|
||||
}
|
||||
|
||||
@keyframes detail-loading {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user