| | |
| | | <template> |
| | | <div class="report-management"> |
| | | <!-- 图表区域 --> |
| | | <div class="charts-container"> |
| | | <el-row :gutter="20"> |
| | | <!-- 各类型完成数量 --> |
| | | <el-col :span="9"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>各类型完成数量</span> |
| | | </div> |
| | | </template> |
| | | <div class="top-container"> |
| | | <div class="typeNum"> |
| | | <div class="typeNum-left"> |
| | | <img src="~@/assets/images/chartCard.svg" |
| | | alt="图表" |
| | | style="width: 40px; height: 40px; object-fit: contain;"> |
| | | <div class="typeNum-left-text">原材料</div> |
| | | </div> |
| | | <div class="typeNum-center"> |
| | | <div class="typeNum-leftLine">-</div> |
| | | <div class="typeNum-rightLine"></div> |
| | | </div> |
| | | <div class="typeNum-right"> |
| | | <div class="typeNum-right-top"> |
| | | <div class="typeNum-right-top-name">总数量</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(0, 'totalCount') }} <span class="unit">个</span></div> |
| | | <div class="scale-container"> |
| | | <div class="report-management-container" |
| | | :style="{ transform: `scale(${scaleRatio})` }"> |
| | | <div class="report-management"> |
| | | <!-- 图表区域 --> |
| | | <div class="charts-container"> |
| | | <el-row :gutter="20"> |
| | | <!-- 各类型完成数量 --> |
| | | <el-col :span="9"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>各类型完成数量</span> |
| | | </div> |
| | | <div class="typeNum-right-bottom"> |
| | | <div class="typeNum-right-top-name">已完成数</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(0, 'completedCount') }} <span class="unit">个</span> |
| | | </template> |
| | | <div class="top-container"> |
| | | <div class="typeNum"> |
| | | <div class="typeNum-left"> |
| | | <img src="~@/assets/images/chartCard.svg" |
| | | alt="图表" |
| | | style="width: 40px; height: 40px; object-fit: contain;"> |
| | | <div class="typeNum-left-text">原材料</div> |
| | | </div> |
| | | <div class="typeNum-center"> |
| | | <div class="typeNum-leftLine">-</div> |
| | | <div class="typeNum-rightLine"></div> |
| | | </div> |
| | | <div class="typeNum-right"> |
| | | <div class="typeNum-right-top"> |
| | | <div class="typeNum-right-top-name">总数量</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(0, 'totalCount') }} <span class="unit">个</span></div> |
| | | </div> |
| | | <div class="typeNum-right-bottom"> |
| | | <div class="typeNum-right-top-name">已完成数</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(0, 'completedCount') }} <span class="unit">个</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="typeNum"> |
| | | <div class="typeNum-left"> |
| | | <img src="~@/assets/images/chartCard2.svg" |
| | | alt="图表" |
| | | style="width: 40px; height: 40px; object-fit: contain;"> |
| | | <div class="typeNum-left-text" |
| | | style="color: #5EB334;">半成品</div> |
| | | </div> |
| | | <div class="typeNum-center"> |
| | | <div class="typeNum-leftLine2">-</div> |
| | | <div class="typeNum-rightLine2"></div> |
| | | </div> |
| | | <div class="typeNum-right"> |
| | | <div class="typeNum-right-top"> |
| | | <div class="typeNum-right-top-name">总数量</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(1, 'totalCount') }} <span class="unit">个</span></div> |
| | | </div> |
| | | <div class="typeNum-right-bottom"> |
| | | <div class="typeNum-right-top-name">已完成数</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(1, 'completedCount') }} <span class="unit">个</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="typeNum"> |
| | | <div class="typeNum-left"> |
| | | <img src="~@/assets/images/chartCard3.svg" |
| | | alt="图表" |
| | | style="width: 40px; height: 40px; object-fit: contain;"> |
| | | <div class="typeNum-left-text" |
| | | style="color: #8000FF;">成品</div> |
| | | </div> |
| | | <div class="typeNum-center"> |
| | | <div class="typeNum-leftLine3">-</div> |
| | | <div class="typeNum-rightLine3"></div> |
| | | </div> |
| | | <div class="typeNum-right"> |
| | | <div class="typeNum-right-top"> |
| | | <div class="typeNum-right-top-name">总数量</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(2, 'totalCount') }} <span class="unit">个</span></div> |
| | | </div> |
| | | <div class="typeNum-right-bottom"> |
| | | <div class="typeNum-right-top-name">已完成数</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(2, 'completedCount') }} <span class="unit">个</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="typeNum"> |
| | | <div class="typeNum-left"> |
| | | <img src="~@/assets/images/chartCard2.svg" |
| | | alt="图表" |
| | | style="width: 40px; height: 40px; object-fit: contain;"> |
| | | <div class="typeNum-left-text" |
| | | style="color: #5EB334;">半成品</div> |
| | | </div> |
| | | <div class="typeNum-center"> |
| | | <div class="typeNum-leftLine2">-</div> |
| | | <div class="typeNum-rightLine2"></div> |
| | | </div> |
| | | <div class="typeNum-right"> |
| | | <div class="typeNum-right-top"> |
| | | <div class="typeNum-right-top-name">总数量</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(1, 'totalCount') }} <span class="unit">个</span></div> |
| | | </el-card> |
| | | </el-col> |
| | | <!-- 质检合格率 --> |
| | | <el-col :span="15"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>质检合格率</span> |
| | | </div> |
| | | <div class="typeNum-right-bottom"> |
| | | <div class="typeNum-right-top-name">已完成数</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(1, 'completedCount') }} <span class="unit">个</span> |
| | | </template> |
| | | <div class="top-container flex-center"> |
| | | <div class="quality-card blue-card"> |
| | | <div class="quality-card-title"> |
| | | <img src="~@/assets/images/chartCard.svg" |
| | | alt="原材料" |
| | | style="width: 24px; height: 24px; margin-right: 8px;"> |
| | | 原材料合格率 |
| | | </div> |
| | | <div class="quality-card-content"> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label blue-label">完成率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(0, 'completionRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="materialCompletionChart"></div> |
| | | </div> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label green-label">合格率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(0, 'passRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="materialQualityChart"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-card green-card"> |
| | | <div class="quality-card-title"> |
| | | <img src="~@/assets/images/chartCard2.svg" |
| | | alt="半成品" |
| | | style="width: 24px; height: 24px; margin-right: 8px;"> |
| | | 半成品合格率 |
| | | </div> |
| | | <div class="quality-card-content"> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label blue-label">完成率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(1, 'completionRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="semiCompletionChart"></div> |
| | | </div> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label green-label">合格率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(1, 'passRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="semiQualityChart"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-card purple-card"> |
| | | <div class="quality-card-title"> |
| | | <img src="~@/assets/images/chartCard3.svg" |
| | | alt="成品" |
| | | style="width: 24px; height: 24px; margin-right: 8px;"> |
| | | 成品合格率 |
| | | </div> |
| | | <div class="quality-card-content"> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label blue-label">完成率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(2, 'completionRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="finalCompletionChart"></div> |
| | | </div> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label green-label">合格率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(2, 'passRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="finalQualityChart"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="typeNum"> |
| | | <div class="typeNum-left"> |
| | | <img src="~@/assets/images/chartCard3.svg" |
| | | alt="图表" |
| | | style="width: 40px; height: 40px; object-fit: contain;"> |
| | | <div class="typeNum-left-text" |
| | | style="color: #8000FF;">成品</div> |
| | | </div> |
| | | <div class="typeNum-center"> |
| | | <div class="typeNum-leftLine3">-</div> |
| | | <div class="typeNum-rightLine3"></div> |
| | | </div> |
| | | <div class="typeNum-right"> |
| | | <div class="typeNum-right-top"> |
| | | <div class="typeNum-right-top-name">总数量</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(2, 'totalCount') }} <span class="unit">个</span></div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="charts-container"> |
| | | <el-row :gutter="20"> |
| | | <!-- 质检合格率 --> |
| | | <el-col :span="24"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>质检合格率</span> |
| | | </div> |
| | | <div class="typeNum-right-bottom"> |
| | | <div class="typeNum-right-top-name">已完成数</div> |
| | | <div class="typeNum-right-top-text">{{ getInspectStatValue(2, 'completedCount') }} <span class="unit">个</span> |
| | | </template> |
| | | <div class="chart-container-line"> |
| | | <div class="container-line-left"> |
| | | <div style="height: 100%; width: 100%;" |
| | | ref="usageChartRef"> |
| | | </div> |
| | | </div> |
| | | <div class="container-line-right"> |
| | | <div style="height: 80%; width: 100%;" |
| | | ref="inspectionChartRef"> |
| | | </div> |
| | | <div class="container-line-right-bottom"> |
| | | <div class="inspection-chart-box"> |
| | | <div class="chart-box-title">原材料总数</div> |
| | | <div class="chart-box-num">{{ getYearlyStatValue(0, 'totalCount') }}</div> |
| | | </div> |
| | | <div class="inspection-chart-box"> |
| | | <div class="chart-box-title">半成品总数</div> |
| | | <div class="chart-box-num">{{ getYearlyStatValue(1, 'totalCount') }}</div> |
| | | </div> |
| | | <div class="inspection-chart-box"> |
| | | <div class="chart-box-title">成品总数</div> |
| | | <div class="chart-box-num">{{ getYearlyStatValue(2, 'totalCount') }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | <!-- 质检合格率 --> |
| | | <el-col :span="15"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>质检合格率</span> |
| | | </div> |
| | | </template> |
| | | <div class="top-container flex-center"> |
| | | <div class="quality-card blue-card"> |
| | | <div class="quality-card-title"> |
| | | <img src="~@/assets/images/chartCard.svg" |
| | | alt="原材料" |
| | | style="width: 24px; height: 24px; margin-right: 8px;"> |
| | | 原材料合格率 |
| | | </div> |
| | | <div class="quality-card-content"> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label blue-label">完成率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(0, 'completionRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="materialCompletionChart"></div> |
| | | </div> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label green-label">合格率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(0, 'passRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="materialQualityChart"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-card green-card"> |
| | | <div class="quality-card-title"> |
| | | <img src="~@/assets/images/chartCard2.svg" |
| | | alt="半成品" |
| | | style="width: 24px; height: 24px; margin-right: 8px;"> |
| | | 半成品合格率 |
| | | </div> |
| | | <div class="quality-card-content"> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label blue-label">完成率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(1, 'completionRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="semiCompletionChart"></div> |
| | | </div> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label green-label">合格率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(1, 'passRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="semiQualityChart"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-card purple-card"> |
| | | <div class="quality-card-title"> |
| | | <img src="~@/assets/images/chartCard3.svg" |
| | | alt="成品" |
| | | style="width: 24px; height: 24px; margin-right: 8px;"> |
| | | 成品合格率 |
| | | </div> |
| | | <div class="quality-card-content"> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label blue-label">完成率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(2, 'completionRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="finalCompletionChart"></div> |
| | | </div> |
| | | <div class="quality-item"> |
| | | <div> |
| | | <div class="quality-item-label green-label">合格率</div> |
| | | <div class="quality-item-tip">占比</div> |
| | | <div class="quality-item-value">{{ getPassRateStatValue(2, 'passRate') }}</div> |
| | | </div> |
| | | <div class="quality-item-chart" |
| | | ref="finalQualityChart"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="charts-container"> |
| | | <el-row :gutter="20"> |
| | | <!-- 质检合格率 --> |
| | | <el-col :span="24"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>质检合格率</span> |
| | | </div> |
| | | </template> |
| | | <div class="chart-container-line"> |
| | | <div class="container-line-left"> |
| | | <div style="height: 100%; width: 100%;" |
| | | ref="usageChartRef"> |
| | | </div> |
| | | </div> |
| | | <div class="container-line-right"> |
| | | <div style="height: 80%; width: 100%;" |
| | | ref="inspectionChartRef"> |
| | | </div> |
| | | <div class="container-line-right-bottom"> |
| | | <div class="inspection-chart-box"> |
| | | <div class="chart-box-title">原材料总数</div> |
| | | <div class="chart-box-num">{{ getYearlyStatValue(0, 'totalCount') }}</div> |
| | | </div> |
| | | <div class="inspection-chart-box"> |
| | | <div class="chart-box-title">半成品总数</div> |
| | | <div class="chart-box-num">{{ getYearlyStatValue(1, 'totalCount') }}</div> |
| | | </div> |
| | | <div class="inspection-chart-box"> |
| | | <div class="chart-box-title">成品总数</div> |
| | | <div class="chart-box-num">{{ getYearlyStatValue(2, 'totalCount') }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- </div> --> |
| | | <!-- <div ref="sampleChartRef" |
| | | <!-- </div> --> |
| | | <!-- <div ref="sampleChartRef" |
| | | class="chart-container"></div> --> |
| | | <div class="yearchange"> |
| | | <div style="margin-right: 8px;font-size: 14px;">年份:</div> |
| | | <el-date-picker v-model="value3" |
| | | size="mini" |
| | | :clearable="false" |
| | | style="width: 60px;" |
| | | type="year" |
| | | :disabled-date="disabledDate" |
| | | placeholder=""> |
| | | </el-date-picker> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="charts-container"> |
| | | <el-row :gutter="20"> |
| | | <!-- 样品进度图表 --> |
| | | <el-col :span="12"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>质量完成明细</span> |
| | | </div> |
| | | </template> |
| | | <div ref="equipmentChartRef" |
| | | class="chart-container"></div> |
| | | </el-card> |
| | | </el-col> |
| | | <!-- 设备使用图表 --> |
| | | <el-col :span="12"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>检测项目分类</span> |
| | | </div> |
| | | </template> |
| | | <div class="chart-container-line"> |
| | | <div class="container-line2-left"> |
| | | <div class="info-box"> |
| | | <div class="info-box-header">项目分布</div> |
| | | <div class="info-line" |
| | | v-for="(item, index) in topParametersData.list" |
| | | :key="index"> |
| | | <div class="info-icon" |
| | | :style="{ backgroundColor: getParameterColor(index) }"></div> |
| | | <div class="info-line-title">{{ item.name }}</div> |
| | | <div class="info-line-value1">{{ item.percentage }}%</div> |
| | | <div class="info-line-value2">{{ item.count }}</div> |
| | | </div> |
| | | <div class="yearchange"> |
| | | <div style="margin-right: 8px;font-size: 14px;">年份:</div> |
| | | <el-date-picker v-model="value3" |
| | | size="mini" |
| | | :clearable="false" |
| | | style="width: 60px;" |
| | | type="year" |
| | | :disabled-date="disabledDate" |
| | | placeholder=""> |
| | | </el-date-picker> |
| | | </div> |
| | | </div> |
| | | <div ref="sampleChartRef" |
| | | style="height: 100%; width: 50%;" |
| | | class="chart-container"></div> |
| | | </div> |
| | | <!-- Tab 选择器 --> |
| | | <div class="tab-selector"> |
| | | <div class="tab-item" |
| | | :class="{ active: activeTab === 'raw' }" |
| | | @click="activeTab = 'raw'">原材料</div> |
| | | <div class="tab-item" |
| | | :class="{ active: activeTab === 'semi' }" |
| | | @click="activeTab = 'semi'">半成品</div> |
| | | <div class="tab-item" |
| | | :class="{ active: activeTab === 'final' }" |
| | | @click="activeTab = 'final'">成品</div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div class="charts-container"> |
| | | <el-row :gutter="20"> |
| | | <!-- 样品进度图表 --> |
| | | <el-col :span="12"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>质量完成明细</span> |
| | | </div> |
| | | </template> |
| | | <div ref="equipmentChartRef" |
| | | class="chart-container"></div> |
| | | </el-card> |
| | | </el-col> |
| | | <!-- 设备使用图表 --> |
| | | <el-col :span="12"> |
| | | <el-card class="chart-card" |
| | | shadow="hover"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <div class="chart-title-line"></div> |
| | | <span>检测项目分类</span> |
| | | </div> |
| | | </template> |
| | | <div class="chart-container-line"> |
| | | <div class="container-line2-left"> |
| | | <div class="info-box"> |
| | | <div class="info-box-header">项目分布</div> |
| | | <div class="info-line" |
| | | v-for="(item, index) in topParametersData.list" |
| | | :key="index"> |
| | | <div class="info-icon" |
| | | :style="{ backgroundColor: getParameterColor(index) }"></div> |
| | | <div class="info-line-title">{{ item.name }}</div> |
| | | <div class="info-line-value1">{{ item.percentage }}%</div> |
| | | <div class="info-line-value2">{{ item.count }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div ref="sampleChartRef" |
| | | style="height: 100%; width: 50%;" |
| | | class="chart-container"></div> |
| | | </div> |
| | | <!-- Tab 选择器 --> |
| | | <div class="tab-selector"> |
| | | <div class="tab-item" |
| | | :class="{ active: activeTab === 'raw' }" |
| | | @click="activeTab = 'raw'">原材料</div> |
| | | <div class="tab-item" |
| | | :class="{ active: activeTab === 'semi' }" |
| | | @click="activeTab = 'semi'">半成品</div> |
| | | <div class="tab-item" |
| | | :class="{ active: activeTab === 'final' }" |
| | | @click="activeTab = 'final'">成品</div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, nextTick } from "vue"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | onMounted, |
| | | nextTick, |
| | | onBeforeUnmount, |
| | | watch, |
| | | } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import * as echarts from "echarts"; |
| | | import { |
| | |
| | | getMonthlyCompletionDetails, |
| | | getTopParameters, |
| | | } from "@/api/reportAnalysis/qualityReport"; |
| | | |
| | | // 缩放比例 |
| | | const scaleRatio = ref(1); |
| | | // 设计尺寸(基准尺寸) |
| | | const designWidth = 1920; |
| | | const designHeight = 1080; |
| | | |
| | | // 计算缩放比例 |
| | | const calculateScale = () => { |
| | | const container = document.querySelector(".scale-container"); |
| | | if (!container) return; |
| | | |
| | | // 获取容器的实际尺寸 |
| | | const containerWidth = container.clientWidth; |
| | | const containerHeight = container.clientHeight; |
| | | |
| | | if (containerWidth === 0) { |
| | | // 如果还没渲染出来,延迟一下再计算 |
| | | setTimeout(calculateScale, 100); |
| | | return; |
| | | } |
| | | |
| | | // 计算宽度缩放比例,使其始终占满宽度 |
| | | const scaleX = containerWidth / designWidth; |
| | | scaleRatio.value = scaleX; |
| | | }; |
| | | |
| | | // 窗口大小变化处理 |
| | | const handleResize = () => { |
| | | calculateScale(); |
| | | // 同时调整图表 |
| | | sampleChart?.resize(); |
| | | equipmentChart?.resize(); |
| | | inspectionChart?.resize(); |
| | | usageChart?.resize(); |
| | | materialCompletionChartInstance?.resize(); |
| | | materialQualityChartInstance?.resize(); |
| | | semiCompletionChartInstance?.resize(); |
| | | semiQualityChartInstance?.resize(); |
| | | finalCompletionChartInstance?.resize(); |
| | | finalQualityChartInstance?.resize(); |
| | | }; |
| | | |
| | | // 响应式数据 |
| | | const filterForm = reactive({ |
| | |
| | | }; |
| | | |
| | | const getYearlyStatValue = (type, field) => { |
| | | const stat = yearlyPassRateData.value.find(item => item.inspectType === type); |
| | | const stat = yearlyPassRateData.value.find(item => item.modelType === type); |
| | | return stat ? stat[field] : 0; |
| | | }; |
| | | |
| | | const getInspectStatValue = (type, field) => { |
| | | const stat = inspectStatisticsData.value.find( |
| | | item => item.inspectType === type |
| | | item => item.modelType === type |
| | | ); |
| | | return stat ? stat[field] : 0; |
| | | }; |
| | | |
| | | const getPassRateStatValue = (type, field) => { |
| | | const stat = passRateStatisticsData.value.find( |
| | | item => item.inspectType === type |
| | | item => item.modelType === type |
| | | ); |
| | | if (stat) { |
| | | if (field === "completionRate" || field === "passRate") { |
| | | return stat[field] ? Number(stat[field]).toFixed(0) + "%" : "0%"; |
| | | return stat[field] ? parseFloat(stat[field]) + "%" : "0%"; |
| | | } |
| | | return stat[field]; |
| | | } |
| | |
| | | |
| | | const fetchTopParametersData = async () => { |
| | | try { |
| | | const typeMap = { raw: 0, semi: 1, final: 2 }; |
| | | const typeMap = { raw: 1, semi: 2, final: 3 }; |
| | | const res = await getTopParameters(typeMap[activeTab.value]); |
| | | if (res.code === 200) { |
| | | topParametersData.value = res.data; |
| | | sumnum.value = topParametersData.value.list.reduce( |
| | | (acc, cur) => acc + cur.count, |
| | | 0 |
| | | ); |
| | | console.log(sumnum.value); |
| | | initSampleChart(); |
| | | } |
| | | } catch (error) { |
| | |
| | | const currentYear = new Date().getFullYear(); |
| | | return time.getFullYear() > currentYear; |
| | | }; |
| | | const sumnum = ref(0); |
| | | |
| | | // 监听年份变化 |
| | | import { watch } from "vue"; |
| | | watch(value3, () => { |
| | | fetchMonthlyPassRateData(); |
| | | fetchYearlyPassRateData(); |
| | |
| | | title: { |
| | | show: false, |
| | | }, |
| | | // tooltip: { |
| | | // trigger: "item", |
| | | // formatter: "{a} <br/>{b}: {c} ({d}%)", |
| | | tooltip: { |
| | | trigger: "item", |
| | | formatter: "{a} <br/>{b}: {c} ({d}%)", |
| | | }, |
| | | // legend: { |
| | | // orient: "vertical", |
| | | // left: "left", |
| | | // }, |
| | | series: [ |
| | | { |
| | | name: "", |
| | | name: "检测项目", |
| | | type: "pie", |
| | | radius: ["40%", "80%"], |
| | | avoidLabelOverlap: false, |
| | | label: { |
| | | show: true, |
| | | show: false, |
| | | position: "center", |
| | | formatter: function () { |
| | | return `{a|检测数量}\n{b|${sumnum.value}}`; |
| | | }, |
| | | disabled: true, |
| | | rich: { |
| | | a: { |
| | | fontSize: 14, |
| | | color: "#606266", |
| | | fontWeight: "normal", |
| | | lineHeight: 20, |
| | | }, |
| | | b: { |
| | | fontSize: 20, |
| | | color: "#303133", |
| | | fontWeight: "bold", |
| | | lineHeight: 24, |
| | | padding: [5, 0, 0, 0], |
| | | }, |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: "18", |
| | | fontWeight: "bold", |
| | | }, |
| | | }, |
| | | labelLine: { |
| | |
| | | }; |
| | | |
| | | // 生命周期 |
| | | let resizeObserver = null; |
| | | onMounted(() => { |
| | | // 计算初始缩放比例 |
| | | nextTick(() => { |
| | | calculateScale(); |
| | | }); |
| | | |
| | | fetchInspectStatisticsData(); |
| | | fetchPassRateStatisticsData(); |
| | | fetchMonthlyPassRateData(); |
| | |
| | | initAllQualityCharts(); |
| | | }); |
| | | // 监听窗口大小变化,重新调整图表大小 |
| | | window.addEventListener("resize", () => { |
| | | sampleChart?.resize(); |
| | | equipmentChart?.resize(); |
| | | inspectionChart?.resize(); |
| | | usageChart?.resize(); |
| | | window.addEventListener("resize", handleResize); |
| | | |
| | | // 调整质检合格率图表大小 |
| | | materialCompletionChartInstance?.resize(); |
| | | materialQualityChartInstance?.resize(); |
| | | semiCompletionChartInstance?.resize(); |
| | | semiQualityChartInstance?.resize(); |
| | | finalCompletionChartInstance?.resize(); |
| | | finalQualityChartInstance?.resize(); |
| | | }); |
| | | // 使用 ResizeObserver 监听容器尺寸变化(解决侧边栏切换问题) |
| | | const container = document.querySelector(".scale-container"); |
| | | if (container && window.ResizeObserver) { |
| | | resizeObserver = new ResizeObserver(() => { |
| | | handleResize(); |
| | | }); |
| | | resizeObserver.observe(container); |
| | | } |
| | | }); |
| | | |
| | | onBeforeUnmount(() => { |
| | | window.removeEventListener("resize", handleResize); |
| | | if (resizeObserver) { |
| | | resizeObserver.disconnect(); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .scale-container { |
| | | position: relative; |
| | | width: 100%; |
| | | height: calc(100vh - 84px); |
| | | background-color: #f0f2f5; |
| | | overflow-x: hidden; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .report-management-container { |
| | | position: relative; |
| | | width: 1920px; |
| | | height: 1080px; |
| | | transform-origin: left top; |
| | | background-color: #f0f2f5; |
| | | transition: transform 0.3s; |
| | | } |
| | | |
| | | .report-management { |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | min-height: 100vh; |
| | | /* height: 87vh; |
| | | overflow: hidden; */ |
| | | height: 100%; |
| | | } |
| | | |
| | | .page-header { |
| | |
| | | color: #1d2129; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | line-height: 37px; |
| | | } |
| | | |
| | | .info-line { |
| | |
| | | display: flex; |
| | | padding-left: 20px; |
| | | align-items: center; |
| | | flex: 1; |
| | | } |
| | | |
| | | .info-icon { |
| | |
| | | } |
| | | |
| | | /* .flex-center { |
| | | justify-content: space-evenly; |
| | | } */ |
| | | justify-content: space-evenly; |
| | | } */ |
| | | |
| | | .blue-chart { |
| | | /* background-color: rgba(24, 144, 255, 0.1); */ |