拆分SPC直方图和正态曲线页面
This commit is contained in:
@@ -16,11 +16,13 @@ npm run dev
|
||||
|
||||
- `/overview`:SPC 总览和关键指标
|
||||
- `/run-chart`:基本趋势图,显示原始序列、均值线、中位线、规格限和移动平均线
|
||||
- `/histogram`:频数直方图,只显示分箱频数和规格限,不叠加正态曲线
|
||||
- `/normal-curve`:正态曲线,单独显示拟合分布和规格限
|
||||
- `/xbar-r`:Xbar 控制图,控制限来自 XR 结果
|
||||
- `/r-chart`:R 极差控制图
|
||||
- `/xbar-s`:Xbar 控制图,控制限来自 XS 结果
|
||||
- `/s-chart`:S 标准差控制图
|
||||
- `/cpk`:过程能力与直方图
|
||||
- `/cpk`:过程能力指标
|
||||
|
||||
## 接口校验重点
|
||||
|
||||
|
||||
@@ -6,11 +6,15 @@ import XBarSView from "./views/XBarSView.vue";
|
||||
import SChartView from "./views/SChartView.vue";
|
||||
import CpkView from "./views/CpkView.vue";
|
||||
import RunChartView from "./views/RunChartView.vue";
|
||||
import HistogramView from "./views/HistogramView.vue";
|
||||
import NormalCurveView from "./views/NormalCurveView.vue";
|
||||
|
||||
export const routes = [
|
||||
{ path: "/", redirect: "/overview" },
|
||||
{ path: "/overview", component: OverviewView, meta: { title: "总览" } },
|
||||
{ path: "/run-chart", component: RunChartView, meta: { title: "趋势图" } },
|
||||
{ path: "/histogram", component: HistogramView, meta: { title: "直方图" } },
|
||||
{ path: "/normal-curve", component: NormalCurveView, meta: { title: "正态曲线" } },
|
||||
{ path: "/xbar-r", component: XBarRView, meta: { title: "Xbar-R" } },
|
||||
{ path: "/r-chart", component: RChartView, meta: { title: "R 图" } },
|
||||
{ path: "/xbar-s", component: XBarSView, meta: { title: "Xbar-S" } },
|
||||
|
||||
@@ -287,12 +287,12 @@ export function createCapabilityBarOption(cpk: CpkResult): EChartsOption {
|
||||
};
|
||||
}
|
||||
|
||||
// 创建直方图和正态曲线配置,用来核对分布和规格限位置。
|
||||
export function createHistogramOption(cpk: CpkResult): EChartsOption {
|
||||
// 创建单独直方图配置,只展示频数分布和规格限,不叠加正态曲线。
|
||||
export function createFrequencyHistogramOption(cpk: CpkResult): EChartsOption {
|
||||
const xRange = calculateHistogramXAxisRange(cpk);
|
||||
|
||||
return {
|
||||
color: ["#0f766e", "#b45309"],
|
||||
color: ["#0f766e"],
|
||||
tooltip: { trigger: "axis" },
|
||||
legend: { top: 0, right: 0 },
|
||||
grid: { left: 52, right: 48, top: 46, bottom: 42 },
|
||||
@@ -303,44 +303,73 @@ export function createHistogramOption(cpk: CpkResult): EChartsOption {
|
||||
max: xRange.max,
|
||||
axisLabel: { color: "#667085" }
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
yAxis: {
|
||||
type: "value",
|
||||
name: "频数",
|
||||
minInterval: 1,
|
||||
axisLabel: { color: "#667085" },
|
||||
splitLine: { lineStyle: { color: "#e5e7eb" } }
|
||||
},
|
||||
{
|
||||
type: "value",
|
||||
name: "正态曲线",
|
||||
axisLabel: { color: "#667085" },
|
||||
splitLine: { show: false }
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "频数",
|
||||
type: "bar",
|
||||
data: cpk.Xk.map((value, index) => [value, cpk.YkCount[index]]),
|
||||
barMaxWidth: 28,
|
||||
barMaxWidth: 34,
|
||||
markLine: {
|
||||
symbol: "none",
|
||||
data: [
|
||||
{ xAxis: cpk.LSL, name: "LSL" },
|
||||
{ xAxis: cpk.USL, name: "USL" },
|
||||
{ xAxis: cpk.SL, name: "SL" }
|
||||
{ xAxis: cpk.SL, name: "目标值" }
|
||||
],
|
||||
label: { color: "#667085" },
|
||||
lineStyle: { color: "#991b1b", type: "dashed" }
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
// 创建正态曲线配置,单独查看拟合曲线与规格限关系。
|
||||
export function createNormalCurveOption(cpk: CpkResult): EChartsOption {
|
||||
const xRange = calculateHistogramXAxisRange(cpk);
|
||||
|
||||
return {
|
||||
color: ["#b45309"],
|
||||
tooltip: { trigger: "axis" },
|
||||
legend: { top: 0, right: 0 },
|
||||
grid: { left: 52, right: 48, top: 46, bottom: 42 },
|
||||
xAxis: {
|
||||
type: "value",
|
||||
name: "测量值",
|
||||
min: xRange.min,
|
||||
max: xRange.max,
|
||||
axisLabel: { color: "#667085" }
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
name: "概率密度",
|
||||
axisLabel: { color: "#667085" },
|
||||
splitLine: { lineStyle: { color: "#e5e7eb" } }
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "正态曲线",
|
||||
type: "line",
|
||||
smooth: true,
|
||||
symbolSize: 4,
|
||||
data: cpk.NormalDistributionX.map((value, index) => [value, cpk.NormalDistributionY[index]]),
|
||||
markLine: {
|
||||
symbol: "none",
|
||||
data: [
|
||||
{ xAxis: cpk.LSL, name: "LSL" },
|
||||
{ xAxis: cpk.USL, name: "USL" },
|
||||
{ xAxis: cpk.SL, name: "目标值" }
|
||||
],
|
||||
label: { color: "#667085" },
|
||||
lineStyle: { color: "#991b1b", type: "dashed" }
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "正态曲线",
|
||||
type: "line",
|
||||
yAxisIndex: 1,
|
||||
smooth: true,
|
||||
symbolSize: 4,
|
||||
data: cpk.NormalDistributionX.map((value, index) => [value, cpk.NormalDistributionY[index]])
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { computed } from "vue";
|
||||
import EChartPanel from "../components/EChartPanel.vue";
|
||||
import MetricStrip from "../components/MetricStrip.vue";
|
||||
import { useSpc } from "../composables/useSpc";
|
||||
import { createCapabilityBarOption, createHistogramOption } from "../utils/chartOptions";
|
||||
import { createCapabilityBarOption } from "../utils/chartOptions";
|
||||
|
||||
const { result } = useSpc();
|
||||
|
||||
@@ -21,25 +21,16 @@ const metrics = computed(() => {
|
||||
});
|
||||
|
||||
const capabilityOption = computed(() => (result.value?.Cpk ? createCapabilityBarOption(result.value.Cpk) : null));
|
||||
const histogramOption = computed(() => (result.value?.Cpk ? createHistogramOption(result.value.Cpk) : null));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="page-stack">
|
||||
<MetricStrip v-if="metrics.length" :metrics="metrics" />
|
||||
<div class="two-column">
|
||||
<EChartPanel
|
||||
title="过程能力指标"
|
||||
eyebrow="Capability"
|
||||
description="能力柱状图用于快速比较 Cp、Cpk、Pp、Ppk。页面保留 1.00 与 1.33 参考线,方便验证常见能力门槛。"
|
||||
description="能力柱状图用于快速比较 Cp、Cpk、Pp、Ppk。页面保留 1.00 与 1.33 参考线,方便验证常见能力门槛;分布形态请在直方图和正态曲线页面单独查看。"
|
||||
:option="capabilityOption"
|
||||
/>
|
||||
<EChartPanel
|
||||
title="直方图与正态曲线"
|
||||
eyebrow="Distribution"
|
||||
description="直方图展示测量值分布,并叠加正态曲线和规格限,便于判断能力指标是否被偏态或边界数据影响。"
|
||||
:option="histogramOption"
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
38
spc-vue/src/views/HistogramView.vue
Normal file
38
spc-vue/src/views/HistogramView.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import EChartPanel from "../components/EChartPanel.vue";
|
||||
import MetricStrip from "../components/MetricStrip.vue";
|
||||
import { useSpc } from "../composables/useSpc";
|
||||
import { createFrequencyHistogramOption } from "../utils/chartOptions";
|
||||
|
||||
const { result } = useSpc();
|
||||
|
||||
const option = computed(() => (result.value?.Cpk ? createFrequencyHistogramOption(result.value.Cpk) : null));
|
||||
|
||||
const metrics = computed(() => {
|
||||
const cpk = result.value?.Cpk;
|
||||
if (!cpk) return [];
|
||||
const maxCount = Math.max(...cpk.YkCount);
|
||||
|
||||
return [
|
||||
{ label: "分箱数", value: cpk.GroupCount },
|
||||
{ label: "组距", value: cpk.GroupWidth },
|
||||
{ label: "最大频数", value: maxCount },
|
||||
{ label: "最小值", value: cpk.ValueMin },
|
||||
{ label: "最大值", value: cpk.ValueMax },
|
||||
{ label: "规格限", value: `${cpk.LSL} ~ ${cpk.USL}` }
|
||||
];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="page-stack">
|
||||
<MetricStrip v-if="metrics.length" :metrics="metrics" />
|
||||
<EChartPanel
|
||||
title="频数直方图"
|
||||
eyebrow="Histogram"
|
||||
description="直方图只展示各测量区间的频数分布,并标出规格限和目标值。它适合先观察真实分布形态、偏态、双峰、离群区间以及数据是否靠近规格边界。"
|
||||
:option="option"
|
||||
/>
|
||||
</article>
|
||||
</template>
|
||||
37
spc-vue/src/views/NormalCurveView.vue
Normal file
37
spc-vue/src/views/NormalCurveView.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import EChartPanel from "../components/EChartPanel.vue";
|
||||
import MetricStrip from "../components/MetricStrip.vue";
|
||||
import { useSpc } from "../composables/useSpc";
|
||||
import { createNormalCurveOption } from "../utils/chartOptions";
|
||||
|
||||
const { result } = useSpc();
|
||||
|
||||
const option = computed(() => (result.value?.Cpk ? createNormalCurveOption(result.value.Cpk) : null));
|
||||
|
||||
const metrics = computed(() => {
|
||||
const cpk = result.value?.Cpk;
|
||||
if (!cpk) return [];
|
||||
|
||||
return [
|
||||
{ label: "Sigma", value: cpk.Singma },
|
||||
{ label: "SigmaS", value: cpk.SingmaS },
|
||||
{ label: "Ca", value: cpk.Ca },
|
||||
{ label: "SL", value: cpk.SL },
|
||||
{ label: "USL", value: cpk.USL },
|
||||
{ label: "LSL", value: cpk.LSL }
|
||||
];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="page-stack">
|
||||
<MetricStrip v-if="metrics.length" :metrics="metrics" />
|
||||
<EChartPanel
|
||||
title="正态曲线"
|
||||
eyebrow="Normal Curve"
|
||||
description="正态曲线单独展示当前 SPC 结果中的拟合分布,并标出规格限和目标值。它用于辅助判断能力指标解释是否依赖正态分布假设。"
|
||||
:option="option"
|
||||
/>
|
||||
</article>
|
||||
</template>
|
||||
Reference in New Issue
Block a user