<script lang="ts" setup>
|
import type { PendingTask } from '../../../types';
|
|
import { Descriptions, Progress, Tag } from 'ant-design-vue';
|
|
defineOptions({ name: 'WorkbenchTaskDetailTab' });
|
|
defineProps<{
|
task?: PendingTask | null;
|
}>();
|
|
function getProgressStatus(rate?: number): 'exception' | 'normal' | 'success' {
|
if (rate === undefined || rate === null) return 'normal';
|
if (rate >= 100) return 'success';
|
if (rate < 0) return 'exception';
|
return 'normal';
|
}
|
</script>
|
|
<template>
|
<div class="task-detail-tab">
|
<div v-if="!task" class="task-detail-tab__empty">
|
请从左侧工单列表选择一条任务
|
</div>
|
<template v-else>
|
<!-- 进度概览 -->
|
<div class="detail-progress">
|
<div class="detail-progress__head">
|
<span class="detail-progress__title">报工进度</span>
|
<span class="detail-progress__rate">{{ task.feedbackRate ?? 0 }}%</span>
|
<span class="detail-progress__qty">
|
{{ task.producedQuantity ?? 0 }} / {{ task.quantity ?? 0 }}
|
{{ task.unitMeasureName }}
|
</span>
|
</div>
|
<Progress
|
:percent="task.feedbackRate ?? 0"
|
:status="getProgressStatus(task.feedbackRate)"
|
:stroke-color="{ from: '#108ee9', to: '#87d068' }"
|
:show-info="false"
|
:stroke-width="14"
|
/>
|
<div class="detail-progress__stats">
|
<div class="stat-item">
|
<span class="stat-item__label">排产数量</span>
|
<span class="stat-item__value">{{ task.quantity ?? 0 }}</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-item__label">已生产</span>
|
<span class="stat-item__value">{{ task.producedQuantity ?? 0 }}</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-item__label">在途报工</span>
|
<span class="stat-item__value">{{ task.inTransitQuantity ?? 0 }}</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-item__label">可报工</span>
|
<span class="stat-item__value stat-item__value--primary">
|
{{ task.reportableQuantity ?? 0 }}
|
</span>
|
</div>
|
</div>
|
</div>
|
|
<!-- 详细信息 -->
|
<Descriptions
|
bordered
|
:column="2"
|
size="middle"
|
class="detail-desc"
|
>
|
<Descriptions.Item label="任务编码">{{ task.code ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="任务名称">{{ task.name ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="工单编码">{{ task.workOrderCode ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="工单名称">{{ task.workOrderName ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="工作站">{{ task.workstationName ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="工序">{{ task.processName ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="产品编码">{{ task.itemCode ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="产品名称">{{ task.itemName ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="规格型号">{{ task.itemSpecification ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="计量单位">{{ task.unitMeasureName ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="合格品数量">{{ task.qualifyQuantity ?? 0 }}</Descriptions.Item>
|
<Descriptions.Item label="不良品数量">{{ task.unqualifyQuantity ?? 0 }}</Descriptions.Item>
|
<Descriptions.Item label="客户名称">{{ task.clientName ?? '—' }}</Descriptions.Item>
|
<Descriptions.Item label="是否质检工序">
|
<Tag v-if="task.checkFlag" color="orange">是</Tag>
|
<Tag v-else>否</Tag>
|
</Descriptions.Item>
|
<Descriptions.Item label="需求日期" :span="2">
|
{{ task.requestDate ?? '—' }}
|
</Descriptions.Item>
|
<Descriptions.Item label="备注" :span="2">{{ task.remark ?? '—' }}</Descriptions.Item>
|
</Descriptions>
|
</template>
|
</div>
|
</template>
|
|
<style lang="scss" scoped>
|
.task-detail-tab {
|
padding: 20px 24px;
|
min-height: 100%;
|
height: 100%;
|
overflow: auto;
|
}
|
|
.task-detail-tab__empty {
|
padding: 64px 0;
|
text-align: center;
|
color: #8c8c8c;
|
font-size: 16px;
|
}
|
|
.detail-progress {
|
margin-bottom: 20px;
|
padding: 16px 20px;
|
border-radius: 8px;
|
background: #f6f8fa;
|
border: 1px solid #e8e8e8;
|
}
|
|
.detail-progress__head {
|
display: flex;
|
align-items: baseline;
|
flex-wrap: wrap;
|
gap: 8px 16px;
|
margin-bottom: 12px;
|
}
|
|
.detail-progress__title {
|
font-size: 16px;
|
font-weight: 600;
|
color: #1a1a1a;
|
}
|
|
.detail-progress__rate {
|
font-size: 22px;
|
font-weight: 700;
|
color: var(--ant-primary-color, #1890ff);
|
font-variant-numeric: tabular-nums;
|
}
|
|
.detail-progress__qty {
|
margin-left: auto;
|
font-size: 14px;
|
font-weight: 600;
|
color: #595959;
|
}
|
|
.detail-progress__stats {
|
display: flex;
|
gap: 24px;
|
margin-top: 14px;
|
flex-wrap: wrap;
|
}
|
|
.stat-item {
|
display: flex;
|
flex-direction: column;
|
gap: 4px;
|
|
&__label {
|
font-size: 12px;
|
color: #8c8c8c;
|
font-weight: 500;
|
}
|
|
&__value {
|
font-size: 18px;
|
font-weight: 700;
|
color: #1a1a1a;
|
font-variant-numeric: tabular-nums;
|
|
&--primary {
|
color: var(--ant-primary-color, #1890ff);
|
}
|
}
|
}
|
|
.detail-desc {
|
:deep(.ant-descriptions-item-label) {
|
width: 140px;
|
font-weight: 600;
|
background: #fafafa;
|
}
|
|
:deep(.ant-descriptions-item-content) {
|
font-size: 14px;
|
}
|
}
|
</style>
|