| | |
| | | <template> |
| | | <div> |
| | | <div class="panel-root"> |
| | | <PanelHeader title="质量指标合格分析" /> |
| | | <div class="main-panel panel-item-customers"> |
| | | <div v-for="section in sections" :key="section.key" class="inspect-block"> |
| | |
| | | import PanelHeader from './PanelHeader.vue' |
| | | import DateTypeSwitch from './DateTypeSwitch.vue' |
| | | import { rawMaterialDetection, processDetection, factoryDetection } from '@/api/viewIndex.js' |
| | | import { BI, baseChartOptions } from '../theme.js' |
| | | |
| | | const QUALIFIED_COLOR = '#4EE4FF' |
| | | const UNQUALIFIED_COLOR = '#3378FF' |
| | | const TRACK_COLOR = 'rgba(78, 228, 255, 0.12)' |
| | | const QUALIFIED_COLOR = BI.accentBright |
| | | const UNQUALIFIED_COLOR = BI.series[2] |
| | | const TRACK_COLOR = 'rgba(74, 108, 240, 0.12)' |
| | | |
| | | const apiMap = { |
| | | raw: rawMaterialDetection, |
| | |
| | | { |
| | | key: 'raw', |
| | | title: '原材料检测', |
| | | dateType: 1, |
| | | dateType: 3, |
| | | qualifiedCount: 0, |
| | | unqualifiedCount: 0, |
| | | qualifiedRate: 0, |
| | |
| | | { |
| | | key: 'process', |
| | | title: '过程检测', |
| | | dateType: 1, |
| | | dateType: 3, |
| | | qualifiedCount: 0, |
| | | unqualifiedCount: 0, |
| | | qualifiedRate: 0, |
| | |
| | | { |
| | | key: 'final', |
| | | title: '成品出厂检测', |
| | | dateType: 1, |
| | | dateType: 3, |
| | | qualifiedCount: 0, |
| | | unqualifiedCount: 0, |
| | | qualifiedRate: 0, |
| | |
| | | height: '110px', |
| | | } |
| | | |
| | | const ringOptions = { |
| | | backgroundColor: 'transparent', |
| | | textStyle: { color: '#B8C8E0' }, |
| | | } |
| | | const ringOptions = baseChartOptions |
| | | |
| | | const ringTooltip = { |
| | | show: false, |
| | |
| | | const unqualified = Number(section.unqualifiedCount || 0) |
| | | const total = qualified + unqualified |
| | | |
| | | return [ |
| | | const series = [ |
| | | { |
| | | type: 'pie', |
| | | radius: ['68%', '82%'], |
| | |
| | | itemStyle: { color: TRACK_COLOR }, |
| | | data: [1], |
| | | }, |
| | | { |
| | | ] |
| | | |
| | | // 数据为空时不渲染主环,避免 ECharts 空饼图渲染出灰色圆环 |
| | | if (total > 0) series.push({ |
| | | name: section.title, |
| | | type: 'pie', |
| | | radius: ['68%', '82%'], |
| | |
| | | clockwise: true, |
| | | minAngle: total > 0 ? 8 : 0, |
| | | itemStyle: { |
| | | borderColor: 'rgba(10, 28, 58, 0.95)', |
| | | borderColor: BI.sliceBorder, |
| | | borderWidth: 2, |
| | | borderRadius: 4, |
| | | }, |
| | | data: [ |
| | | { |
| | | value: qualified, |
| | | name: '合格数', |
| | | itemStyle: { |
| | | color: QUALIFIED_COLOR, |
| | | shadowBlur: 16, |
| | | shadowColor: 'rgba(78, 228, 255, 0.45)', |
| | | }, |
| | | itemStyle: { color: QUALIFIED_COLOR }, |
| | | }, |
| | | { |
| | | value: unqualified, |
| | | name: '不合格数', |
| | | itemStyle: { |
| | | color: UNQUALIFIED_COLOR, |
| | | shadowBlur: 10, |
| | | shadowColor: 'rgba(51, 120, 255, 0.35)', |
| | | }, |
| | | itemStyle: { color: UNQUALIFIED_COLOR }, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | }) |
| | | |
| | | series.push({ |
| | | type: 'pie', |
| | | radius: ['52%', '56%'], |
| | | center: ['50%', '50%'], |
| | | silent: true, |
| | | label: { show: false }, |
| | | labelLine: { show: false }, |
| | | itemStyle: { color: 'rgba(0, 127, 255, 0.22)' }, |
| | | itemStyle: { color: 'rgba(74, 108, 240, 0.22)' }, |
| | | data: [1], |
| | | }, |
| | | ] |
| | | }) |
| | | |
| | | return series |
| | | } |
| | | |
| | | const handleDateTypeChange = (key, dateType) => { |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .panel-root { |
| | | flex: 1; |
| | | height: 100%; |
| | | min-height: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .main-panel { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | flex: 1; |
| | | min-height: 0; |
| | | gap: 0; |
| | | } |
| | | |
| | |
| | | |
| | | .filters-row-left { |
| | | width: 50%; |
| | | color: white; |
| | | /* 用flex替代float,让子元素对齐更稳定 */ |
| | | color: var(--bi-text-strong); |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | |
| | | /* 品牌蓝细竖条,与 PanelHeader 呼应 */ |
| | | span { |
| | | /* 核心:父级相对定位,作为伪元素基准 */ |
| | | position: relative; |
| | | display: inline-block; |
| | | /* 给伪元素和文字留空间 */ |
| | | padding-left: 22px; |
| | | /* 文字垂直居中 */ |
| | | line-height: 23px; |
| | | margin-right: 8px; |
| | | |
| | | &::after { |
| | | content: ''; |
| | | display: inline-block; |
| | | width: 16px; |
| | | height: 16px; |
| | | clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); |
| | | background: #217AFF; |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 0; |
| | | transform: translateY(-50%); |
| | | /* 确保菱形在渐变块上方 */ |
| | | z-index: 1; |
| | | } |
| | | |
| | | &::before { |
| | | content: ''; |
| | | display: inline-block; |
| | | width: 18px; |
| | | height: 7px; |
| | | border-radius: 8px; |
| | | background: linear-gradient(360deg, rgba(33, 133, 255, 0.4) 0%, rgba(33, 221, 255, 0) 100%); |
| | | position: absolute; |
| | | top: 50%; |
| | | left: -1px; |
| | | /* 精准贴在菱形正下方 */ |
| | | transform: translateY(calc(0% + 8px)); |
| | | z-index: 0; |
| | | } |
| | | flex-shrink: 0; |
| | | width: 3px; |
| | | height: 14px; |
| | | border-radius: 2px; |
| | | background: linear-gradient(180deg, var(--bi-accent-bright) 0%, var(--bi-accent) 100%); |
| | | } |
| | | |
| | | p { |
| | | width: 100px; |
| | | height: 23px; |
| | | /* 渐变起始色和菱形统一,更协调 */ |
| | | background: linear-gradient(90deg, #217AFF 0%, rgba(33, 221, 255, 0) 100%); |
| | | /* 精准垂直居中 */ |
| | | line-height: 26px; |
| | | text-align: center; |
| | | color: white; |
| | | /* 用高度的一半做圆角,确保左边是完美半圆 */ |
| | | border-radius: 12px 0 0 12px; |
| | | /* 可选:加一点左内边距,让文字不贴边 */ |
| | | padding-left: 4px; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | letter-spacing: 1px; |
| | | color: var(--bi-text-strong); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .panel-item-customers { |
| | | border: 1px solid #1a58b0; |
| | | border: 1px solid var(--bi-panel-border); |
| | | background: var(--bi-panel-bg); |
| | | border-radius: 8px; |
| | | padding: 14px 18px; |
| | | width: 100%; |
| | | height: 958px; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | |
| | | right: 0; |
| | | bottom: 0; |
| | | height: 1px; |
| | | background: linear-gradient(90deg, rgba(33, 122, 255, 0) 0%, rgba(33, 122, 255, 0.55) 50%, rgba(33, 122, 255, 0) 100%); |
| | | background: linear-gradient(90deg, rgba(74, 108, 240, 0) 0%, rgba(74, 108, 240, 0.55) 50%, rgba(74, 108, 240, 0) 100%); |
| | | pointer-events: none; |
| | | } |
| | | |
| | |
| | | justify-content: center; |
| | | } |
| | | |
| | | /* 外圈刻度(点状环) */ |
| | | .ring::before { |
| | | content: ''; |
| | | position: absolute; |
| | | inset: -8px; |
| | | border-radius: 50%; |
| | | background: repeating-conic-gradient(from 0deg, |
| | | rgba(78, 228, 255, 0.75) 0 1deg, |
| | | rgba(78, 228, 255, 0) 1deg 9deg); |
| | | -webkit-mask: radial-gradient(circle, transparent 62%, #000 63%); |
| | | mask: radial-gradient(circle, transparent 62%, #000 63%); |
| | | opacity: 0.35; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | /* 柔和发光背景 */ |
| | | .ring::after { |
| | | content: ''; |
| | | position: absolute; |
| | | inset: -20px; |
| | | border-radius: 50%; |
| | | background: radial-gradient(circle, rgba(78, 228, 255, 0.18) 0%, rgba(78, 228, 255, 0.06) 40%, rgba(0, 0, 0, 0) 70%); |
| | | filter: blur(0.2px); |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .stats { |
| | | width: 240px; |
| | | flex: 0 0 240px; |
| | |
| | | align-items: center; |
| | | height: 100%; |
| | | padding: 10px 14px; |
| | | border-radius: 4px; |
| | | border: 1px solid rgba(78, 228, 255, 0.22); |
| | | background: linear-gradient(90deg, rgba(33, 122, 255, 0.28) 0%, rgba(10, 28, 58, 0.35) 55%, rgba(10, 28, 58, 0.2) 100%); |
| | | box-shadow: inset 0 0 18px rgba(16, 45, 95, 0.25); |
| | | border-radius: 6px; |
| | | border: 1px solid var(--bi-panel-border); |
| | | background: rgba(13, 24, 52, 0.6); |
| | | } |
| | | |
| | | .stat-left { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | color: #b8c8e0; |
| | | color: var(--bi-text); |
| | | font-size: 12px; |
| | | } |
| | | |
| | |
| | | height: 10px; |
| | | border-radius: 2px; |
| | | display: inline-block; |
| | | box-shadow: 0 0 10px rgba(78, 228, 255, 0.25); |
| | | } |
| | | |
| | | .dot-qualified { |
| | | background: rgba(184, 200, 224, 0.85); |
| | | background: var(--bi-accent-bright); |
| | | } |
| | | |
| | | .dot-unqualified { |
| | | background: #4ee4ff; |
| | | background: #8E7CE6; |
| | | } |
| | | |
| | | .stat-right { |
| | |
| | | } |
| | | |
| | | .stat-value { |
| | | color: #ffffff; |
| | | color: var(--bi-text-strong); |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | min-width: 40px; |
| | | text-align: right; |
| | | text-shadow: 0 0 10px rgba(78, 228, 255, 0.15); |
| | | font-variant-numeric: tabular-nums; |
| | | } |
| | | |
| | | .stat-percent { |
| | | color: rgba(184, 200, 224, 0.95); |
| | | color: var(--bi-text); |
| | | font-size: 12px; |
| | | min-width: 40px; |
| | | text-align: right; |
| | | font-variant-numeric: tabular-nums; |
| | | } |
| | | |
| | | /* 让切换按钮更贴近截图(更紧凑) */ |