Pārlūkot izejas kodu

fix(s8): 修复产品设计责任人分布(阶段4重演通过)

原 (sort_no-1)%6 致 6 设计师仅覆盖 4 人(sort_no 是订单内序号,max=4),
缺刘振宇、周启明。改为全局序号 seq 轮转 designers[(seq-1)%6],6 桶严格全覆盖。

- SeedData 类:modulo key 由 sortNo 改为 seq(全表 1..63)
- 新增 1.0.124.sql:UPDATE 既有 63 行 ((id-IdBase-1) MOD 6) CASE 6 设计师,
  product_design_drawing 仍 63 行,无 DELETE/TRUNCATE/DROP
- Web.Entry.csproj:版本号 1.0.122→1.0.124,注册 1.0.124.sql
- Web/package.json:2.4.161→2.4.162(同提交含前端批次 B 累积改动)

随本提交一并提交批次 B 在 a87e53c49 之后累积的主体收尾:
SnapshotSeedData PPT 基线 2.6/96→2.5/98、API/Service/DTO/Page 单订单态路径、
baseline.ts 默认态 PPT 静态、1.0.123.sql 非标 KPI/status/red + 责任人单位名→姓名。

阶段 4 重演验证(通过):
- AutoVersionUpdate 执行 1.0.124,全程无 DELETE/TRUNCATE/DROP
- DISTINCT responsible_person 恰 6 人(11/11/11/10/10/10 共 63 行)
- NON_STANDARD 11 行 kpi=3/achieved=0/red 不变
- SO-2026-001 4 图(3 STD + 1 X01 8.34 red)不变
- snapshot PPT actualAvgDays=2.5/onTimeRate=98 不变
- API /product-design/drawings 单订单 overall {4,22,kpi=3,avg=2.9325,rate=0.9545} 不变
- 页面 A/B/C 三态切换 0 console error,Database.json 最终 diff 空
YY968XX 1 mēnesi atpakaļ
vecāks
revīzija
e24d9aed69

+ 1 - 1
Web/package.json

@@ -1,7 +1,7 @@
 {
 	"name": "admin.net",
 	"type": "module",
-	"version": "2.4.158",
+	"version": "2.4.162",
 	"packageManager": "pnpm@10.32.1",
 	"lastBuildTime": "2026.03.15",
 	"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",

+ 7 - 4
Web/src/views/aidop/s8/api/s8OrderFlowDomainApi.ts

@@ -239,10 +239,13 @@ export interface OrderFlowProductDesignCategorySummary {
 	totalQuantity: number;
 	/** product_quantity 占比,小数 0~1;前端格式化为 1 位百分比。 */
 	ratio: number;
-	avgActualDays: number;
-	kpiDays: number;
-	achievementRate: number;
-	/** green / yellow / red / ''(空 = 无数据)。 */
+	/** S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:常规/合计返回 null,前端展示 --;非标返回真实平均设计周期。 */
+	avgActualDays: number | null;
+	/** 常规/合计返回 null,前端展示 --;非标返回 3 天 PRODUCT_DESIGN 阶段 KPI。 */
+	kpiDays: number | null;
+	/** 常规/合计返回 null,前端展示 --;非标返回加权达成率。 */
+	achievementRate: number | null;
+	/** green / yellow / red / ''(空 = 无数据,前端展示 --)。 */
 	status: 'green' | 'yellow' | 'red' | '';
 }
 

+ 20 - 10
Web/src/views/aidop/s8/monitoring/OrderChainOverviewPage.vue

@@ -25,6 +25,8 @@ import {
 	adaptProcurementPivotFromApi,
 	type ProcurementDetailFromApi,
 } from '/@/views/aidop/s8/monitoring/data/order-execution/stage-detail';
+// S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:默认不勾选态产品设计业务基线数据。
+import { PRODUCT_DESIGN_BASELINE_DETAIL } from '/@/views/aidop/s8/monitoring/data/order-execution/product-design-baseline';
 import { getOrderFlowProcurementPivot } from '/@/views/aidop/s8/api/s8OrderFlowDomainApi';
 // ORDER-FLOW-CHAIN-PAGE2-ORIGINAL-LOGIC-RESTORE-1:baseline (isUnfiltered) 态下 L2/L3 使用 PPT 常量。
 import {
@@ -364,19 +366,27 @@ watch(
 	{ immediate: true },
 );
 
-// S8-ORDER-CHAIN-PRODUCT-DESIGN-DRAWING-PERSIST-1:产品设计图号粒度数据加载。
-// 单订单态 → orderCodes=[detailOrder.soNo];多订单态 → orderCodes=filteredChainOrders.map(soNo);
-// 默认基准态(isUnfiltered)→ orderCodes=[],后端走 BASELINE_PPT 聚合全 20 单。
-// 失败由 store.productDesignError 承载并由面板渲染生产级错误文案,不回退到静态数据。
-const productDesignDetail = computed(() => store.productDesignDetail);
-const productDesignLoading = computed(() => store.productDesignLoading);
-const productDesignError = computed(() => store.productDesignError);
+// S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:产品设计阶段二态数据源。
+// 默认不勾选态(isUnfiltered=true)→ 直接使用前端业务基线数据 PRODUCT_DESIGN_BASELINE_DETAIL,
+//   不调用 /api/aidop/s8/order-flow/product-design/drawings 接口。
+// 单订单态 → orderCodes=[detailOrder.soNo],走接口取该订单图号粒度真实数据。
+// 多订单态 → orderCodes=filteredChainOrders.map(soNo),走接口聚合命中订单图号数据。
+// 默认基线 loading/error 不取自 store,避免接口未触发但 store 残留状态导致面板异常。
+const productDesignDetail = computed(() =>
+	isUnfiltered.value ? PRODUCT_DESIGN_BASELINE_DETAIL : store.productDesignDetail,
+);
+const productDesignLoading = computed(() =>
+	isUnfiltered.value ? false : store.productDesignLoading,
+);
+const productDesignError = computed(() =>
+	isUnfiltered.value ? null : store.productDesignError,
+);
 
 async function loadProductDesignDrawings() {
 	if (!showDesignDetail.value) return;
-	const orderCodes = isUnfiltered.value
-		? []
-		: filteredChainOrders.value.map((o) => o.soNo);
+	// 默认基线态走前端业务初始化数据,不触发接口
+	if (isUnfiltered.value) return;
+	const orderCodes = filteredChainOrders.value.map((o) => o.soNo);
 	await store.loadProductDesignDrawings(orderCodes, null);
 }
 

+ 111 - 0
Web/src/views/aidop/s8/monitoring/data/order-execution/product-design-baseline.ts

@@ -0,0 +1,111 @@
+// S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:
+// 产品设计阶段默认基线展示数据(业务初始化,对应 PPT 第 1 页业务口径)。
+// 用途:订单链路全景页默认不勾选态(isUnfiltered=true)时直接渲染本常量,不调用
+// /api/aidop/s8/order-flow/product-design/drawings 接口,避免接口同时承载真实图号聚合
+// 与 PPT 静态业务口径两种语义。单订单态、多订单态仍走接口取真实图号数据。
+//
+// 数据口径:
+//   - 顶部产品设计:KPI=3 天,实际达成=2.5 天,达成率=98%(与 BASELINE_PPT snapshot 一致)
+//   - 设计分类汇总(PPT 业务口径):
+//       常规产品 354 / 93.5% / 52 图号,KPI 与平均设计周期不展示(前端 --)
+//       非标产品 28 / 6.5% / 11 图号,KPI=3 天,平均设计周期 9.28 天,红 / 未达标
+//       合计 382 / 100% / 63 图号,KPI 与平均设计周期不展示
+//   - 图号执行明细:11 张非标影响图号,解释非标 KPI 异常;负责人按 6 位设计师循环。
+//
+// 命名约束:本文件采用业务术语命名,禁止非生产级标签。
+import type { ProductDesignDetailDto } from '/@/views/aidop/s8/monitoring/data/order-execution/types';
+
+const PRODUCT_DESIGN_KPI_DAYS = 3;
+const PRODUCT_DESIGN_BASELINE_PLANNED_START = '2026-04-20T00:00:00';
+const PRODUCT_DESIGN_BASELINE_PLANNED_END = '2026-04-23T00:00:00';
+
+interface BaselineDrawingSpec {
+	drawingNo: string;
+	responsiblePerson: string;
+	actualDays: number;
+	productQuantity: number;
+	actualEndDate: string;
+}
+
+// 11 张非标影响图号:3 张严重超期(actual=13.00 天 / qty=4)+ 8 张次级超期(actual=7.88 天 / qty=2)。
+// quantity 合计 = 3×4 + 8×2 = 28;actual_days 合计 = 3×13.00 + 8×7.88 = 102.04;avg ≈ 9.28 天,与 PPT 业务口径一致。
+const NON_STANDARD_BASELINE_DRAWINGS: readonly BaselineDrawingSpec[] = [
+	{ drawingNo: 'D-SO-2026-008-X01', responsiblePerson: '李海峰', actualDays: 13.0,  productQuantity: 4, actualEndDate: '2026-05-03T00:00:00' },
+	{ drawingNo: 'D-SO-2026-019-X01', responsiblePerson: '陈思远', actualDays: 13.0,  productQuantity: 4, actualEndDate: '2026-05-03T00:00:00' },
+	{ drawingNo: 'D-SO-2026-020-X01', responsiblePerson: '王明华', actualDays: 13.0,  productQuantity: 4, actualEndDate: '2026-05-03T00:00:00' },
+	{ drawingNo: 'D-SO-2026-001-X01', responsiblePerson: '赵建国', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+	{ drawingNo: 'D-SO-2026-002-X01', responsiblePerson: '刘振宇', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+	{ drawingNo: 'D-SO-2026-003-X01', responsiblePerson: '周启明', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+	{ drawingNo: 'D-SO-2026-006-X01', responsiblePerson: '李海峰', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+	{ drawingNo: 'D-SO-2026-007-X01', responsiblePerson: '陈思远', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+	{ drawingNo: 'D-SO-2026-012-X01', responsiblePerson: '王明华', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+	{ drawingNo: 'D-SO-2026-017-X01', responsiblePerson: '赵建国', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+	{ drawingNo: 'D-SO-2026-018-X01', responsiblePerson: '刘振宇', actualDays: 7.88, productQuantity: 2, actualEndDate: '2026-04-27T21:07:00' },
+];
+
+export const PRODUCT_DESIGN_BASELINE_DETAIL: ProductDesignDetailDto = {
+	scope: 'BASELINE_PPT',
+	filter: {
+		orderCodes: [],
+		productType: null,
+	},
+	summary: {
+		overall: {
+			drawingCount: 63,
+			totalQuantity: 382,
+			kpiDays: PRODUCT_DESIGN_KPI_DAYS,
+			avgActualDays: 2.5,
+			achievementRate: 0.98,
+		},
+		categories: [
+			{
+				productType: 'STANDARD',
+				name: '常规产品',
+				drawingCount: 52,
+				totalQuantity: 354,
+				ratio: 0.935,
+				avgActualDays: null,
+				kpiDays: null,
+				achievementRate: null,
+				status: '',
+			},
+			{
+				productType: 'NON_STANDARD',
+				name: '非标产品',
+				drawingCount: 11,
+				totalQuantity: 28,
+				ratio: 0.065,
+				avgActualDays: 9.28,
+				kpiDays: PRODUCT_DESIGN_KPI_DAYS,
+				achievementRate: 0,
+				status: 'red',
+			},
+			{
+				productType: 'TOTAL',
+				name: '合计',
+				drawingCount: 63,
+				totalQuantity: 382,
+				ratio: 1,
+				avgActualDays: null,
+				kpiDays: null,
+				achievementRate: null,
+				status: '',
+			},
+		],
+	},
+	drawings: NON_STANDARD_BASELINE_DRAWINGS.map((spec) => ({
+		orderCode: spec.drawingNo.replace(/^D-(SO-\d{4}-\d{3})-.*$/, '$1'),
+		drawingNo: spec.drawingNo,
+		productType: 'NON_STANDARD',
+		responsiblePerson: spec.responsiblePerson,
+		plannedStartDate: PRODUCT_DESIGN_BASELINE_PLANNED_START,
+		plannedEndDate: PRODUCT_DESIGN_BASELINE_PLANNED_END,
+		actualStartDate: PRODUCT_DESIGN_BASELINE_PLANNED_START,
+		actualEndDate: spec.actualEndDate,
+		kpiDays: PRODUCT_DESIGN_KPI_DAYS,
+		actualDays: spec.actualDays,
+		isAchieved: false,
+		status: 'red',
+		productQuantity: spec.productQuantity,
+	})),
+};

+ 6 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.122</AssemblyVersion>
-    <FileVersion>1.0.122</FileVersion>
-    <Version>1.0.122</Version>
+    <AssemblyVersion>1.0.124</AssemblyVersion>
+    <FileVersion>1.0.124</FileVersion>
+    <Version>1.0.124</Version>
   </PropertyGroup>
 
   <ItemGroup>
@@ -67,6 +67,9 @@
     <None Update="UpdateScripts\1.0.122.sql">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
+    <None Update="UpdateScripts\1.0.124.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
 
   <ItemGroup>

+ 69 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.123.sql

@@ -0,0 +1,69 @@
+-- 1.0.123.sql
+-- S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1
+-- 修正既有产品设计阶段数据,使其与本批次业务口径一致。仅 UPDATE,禁 DELETE / TRUNCATE / DROP。
+--
+-- 修正范围:
+--   1) ado_s8_order_flow_product_design_drawing:
+--      a) 非标 (NON_STANDARD) 图号 KPI 从 12 改为 3,对应 actual_days 全部 > 3 → is_achieved=0 / status='red'
+--      b) responsible_person 由责任单位(研发中心 / 结构设计组 / 电气设计组 / 工艺设计组 / 设计审核组)
+--         改为 6 位设计师姓名(李海峰 / 陈思远 / 王明华 / 赵建国 / 刘振宇 / 周启明),按 sort_no 循环分配
+--   2) ado_s8_order_flow_snapshot:
+--      BASELINE_PPT 中 PRODUCT_DESIGN 行 actualAvgDays 2.6→2.5、onTimeRate 96→98
+--
+-- 安全边界:
+--   * 不动 ado_s8_order_flow_order / stage / substep / substep_unit
+--   * 不动 ORDER_REVIEW_PLAN_CALC / MATERIAL_PURCHASE / BODY_PRODUCTION / FINAL_ASSEMBLY_DELIVERY 任何数据
+--   * 不动 S0 / .vscode / Database.json
+--   * 仅触发 product_type='NON_STANDARD' 的图号行,与无人工修改过的责任人行
+--   * snapshot UPDATE 限定 scope_code='BASELINE_PPT' + snapshot_code='CHAIN_AGGREGATE_BASELINE'
+--
+-- 幂等性:
+--   * 非标行 UPDATE 带 WHERE (kpi_days<>3 OR is_achieved<>0 OR status<>'red'),重复执行命中行数为 0
+--   * 责任人 UPDATE 带 WHERE responsible_person NOT IN (6 设计师姓名),已对齐后不再触发
+--   * snapshot REPLACE 函数对已替换字符串无效,重复执行结果一致
+--
+-- 兼容性:
+--   * 仅使用 UPDATE / REPLACE / CASE / % 运算符,全部 MySQL 5.x / 8.x 通用语法,无需检查 MySQL 版本
+--   * 未使用 JSON_REPLACE / JSON_SET,避免依赖 MySQL 5.7.8+
+--
+-- Rollback:
+--   * 由 SeedData 与本脚本共同维护目标态。如需回滚业务口径,git revert 同 commit 并重新跑一次本脚本以外的 UPDATE 即可
+--   * 本脚本本身无数据破坏性操作
+-- 2026-05-21
+
+
+-- ─── 1) 非标图号 kpi_days / is_achieved / status 联动 ───
+UPDATE ado_s8_order_flow_product_design_drawing
+   SET kpi_days = 3.00,
+       is_achieved = 0,
+       status = 'red'
+ WHERE product_type = 'NON_STANDARD'
+   AND is_deleted = 0
+   AND (kpi_days <> 3.00 OR is_achieved <> 0 OR status <> 'red');
+
+
+-- ─── 2) 责任人按 sort_no 循环 6 位设计师 ───
+UPDATE ado_s8_order_flow_product_design_drawing
+   SET responsible_person = CASE ((sort_no - 1) % 6)
+       WHEN 0 THEN '李海峰'
+       WHEN 1 THEN '陈思远'
+       WHEN 2 THEN '王明华'
+       WHEN 3 THEN '赵建国'
+       WHEN 4 THEN '刘振宇'
+       WHEN 5 THEN '周启明'
+   END
+ WHERE is_deleted = 0
+   AND responsible_person NOT IN ('李海峰','陈思远','王明华','赵建国','刘振宇','周启明');
+
+
+-- ─── 3) snapshot PRODUCT_DESIGN actualAvgDays 2.6→2.5 与 onTimeRate 96→98 ───
+-- 用片段 '"actualAvgDays":2.6,"onTimeRate":96' 作为整体替换键,该字符串在 BASELINE_PPT JSON 中
+-- 仅出现于 PRODUCT_DESIGN 行(其他阶段 actualAvgDays 分别是 6.2 / 15.5 / 6.7 / 2.9),不会误伤。
+UPDATE ado_s8_order_flow_snapshot
+   SET stage_snapshots_json = REPLACE(
+       stage_snapshots_json,
+       '"actualAvgDays":2.6,"onTimeRate":96',
+       '"actualAvgDays":2.5,"onTimeRate":98')
+ WHERE scope_code = 'BASELINE_PPT'
+   AND snapshot_code = 'CHAIN_AGGREGATE_BASELINE'
+   AND is_deleted = 0;

+ 44 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.124.sql

@@ -0,0 +1,44 @@
+-- 1.0.124.sql
+-- S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1
+-- 阶段 4 重演 fix:阶段 4 第 6 项重演时发现 1.0.123.sql 用 (sort_no-1)%6 做责任人分桶,
+-- 但 sort_no 是订单内序号(每订单最多 4 张图),分桶基数天然不足 → DB 实际只覆盖
+-- 4 桶(李海峰/陈思远/王明华/赵建国),刘振宇/周启明从未被分配,业务硬需求 6 人不达标。
+--
+-- 修正范围:
+--   ado_s8_order_flow_product_design_drawing:
+--     按全表全局递增序号 (id - 1329909130000 - 1) MOD 6 重写 responsible_person,6 桶严格全覆盖。
+--     id 基址来自 SeedData 类 IdBase=1329909130000,63 行 id 连续区间 [IdBase+1, IdBase+63]。
+--
+-- 安全边界:
+--   * 仅 UPDATE,禁 DELETE / TRUNCATE / DROP;product_design_drawing 仍 63 行
+--   * 不动 kpi_days / is_achieved / status / actual_days / product_quantity 等字段
+--   * 不动 ado_s8_order_flow_snapshot(PPT 基线 2.5/98 已通过,不重写)
+--   * 不动 ado_s8_order_flow_order / stage / substep / substep_unit
+--   * 不动 S0 / .vscode / Database.json / SysMenu
+--   * 仅触发本表 responsible_person 列
+--
+-- 幂等性:
+--   * AutoVersionUpdate 按版本号是否已执行决定是否跑,1.0.124 执行一次即完成
+--   * SQL 自身:CASE 全分支无条件 UPDATE,二次执行得到同样结果,对响应结果幂等
+--   * 不依赖 WHERE responsible_person NOT IN (...),避免 1.0.123 阶段那种"已被分到 4 人之一就停"的副作用
+--
+-- 兼容性:
+--   * 仅使用 UPDATE / CASE / MOD 运算符,MySQL 5.x / 8.x 通用
+--
+-- 验证(重演后必查):
+--   SELECT DISTINCT responsible_person FROM ado_s8_order_flow_product_design_drawing;
+--   → 恰 6 行:李海峰 / 陈思远 / 王明华 / 赵建国 / 刘振宇 / 周启明
+-- 2026-05-22
+
+
+-- ─── 责任人按全表全局序号 (id - IdBase - 1) MOD 6 重写为 6 设计师轮转 ───
+UPDATE ado_s8_order_flow_product_design_drawing
+   SET responsible_person = CASE ((id - 1329909130000 - 1) MOD 6)
+       WHEN 0 THEN '李海峰'
+       WHEN 1 THEN '陈思远'
+       WHEN 2 THEN '王明华'
+       WHEN 3 THEN '赵建国'
+       WHEN 4 THEN '刘振宇'
+       WHEN 5 THEN '周启明'
+   END
+ WHERE is_deleted = 0;

+ 7 - 4
server/Plugins/Admin.NET.Plugin.AiDOP/Dto/S8/OrderFlow/AdoS8OrderFlowDtos.cs

@@ -319,10 +319,13 @@ public class AdoS8OrderFlowProductDesignCategorySummaryDto
     public int TotalQuantity { get; set; }
     /// <summary>product_quantity 占合计比例,小数 0~1,由前端格式化为 1 位百分比。</summary>
     public decimal Ratio { get; set; }
-    public decimal AvgActualDays { get; set; }
-    public decimal KpiDays { get; set; }
-    public decimal AchievementRate { get; set; }
-    /// <summary>green / yellow / red。由 achievement_rate 分档得出,不再二次判定。</summary>
+    /// <summary>S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:常规/合计返回 null,前端展示 --;非标返回真实平均设计周期。</summary>
+    public decimal? AvgActualDays { get; set; }
+    /// <summary>常规/合计返回 null,前端展示 --;非标返回 3 天 PRODUCT_DESIGN 阶段 KPI。</summary>
+    public decimal? KpiDays { get; set; }
+    /// <summary>常规/合计返回 null,前端展示 --;非标返回加权达成率。</summary>
+    public decimal? AchievementRate { get; set; }
+    /// <summary>green / yellow / red / ''(空 = 无数据,前端展示 --)。由 achievement_rate 分档得出,不再二次判定。</summary>
     public string Status { get; set; } = string.Empty;
 }
 

+ 30 - 26
server/Plugins/Admin.NET.Plugin.AiDOP/SeedData/S8OrderFlowProductDesignDrawingSeedData.cs

@@ -3,17 +3,19 @@ using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
 namespace Admin.NET.Plugin.AiDOP.SeedData;
 
 /// <summary>
-/// S8-ORDER-CHAIN-PRODUCT-DESIGN-DRAWING-PERSIST-1:S8 订单链路产品设计阶段基准业务初始化数据种子。
-/// 20 单 × 63 图号;严格满足七项不变量约束
+/// S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:S8 订单链路产品设计阶段基准业务初始化数据种子。
+/// 20 单 × 63 图号;按业务口径修正
 ///   1) COUNT(DISTINCT drawing_no) = 63;STANDARD=52 / NON_STANDARD=11
 ///   2) SUM(product_quantity ALL) = 382;STANDARD=357 / NON_STANDARD=25
-///   3) AVG(actual_days WHERE product_type='STANDARD')     落在 [1.17, 1.21]
-///   4) AVG(actual_days WHERE product_type='NON_STANDARD') 落在 [9.25, 9.31]
-///   5) AVG(actual_days ALL) ≈ 2.60 天
-///   6) SUM(product_quantity WHERE is_achieved=false) 落在 [14, 16]
-///   7) 加权达成率 = 达标 quantity / 总 quantity ≈ 96%
+///   3) PRODUCT_DESIGN 阶段统一 KPI=3 天:STANDARD 与 NON_STANDARD 的 kpi_days 均为 3
+///   4) NON_STANDARD 图号 actual_days 全部 > 3 → is_achieved=false / status='red'
+///   5) STANDARD 51 张图号 actual_days ≤ 3 → is_achieved=true / status='green';1 张超期 actual=4.50 → red
+///   6) AVG(actual_days WHERE product_type='STANDARD')     落在 [1.17, 1.21]
+///   7) AVG(actual_days WHERE product_type='NON_STANDARD') 落在 [9.25, 9.31]
 /// 图号编码:常规 D-{OrderCode}-G{NN};非标 D-{OrderCode}-X{NN}(绑定 SO-2026-001..020 真实 OrderCode)。
-/// 责任单位/岗位 5 选 1:研发中心 / 结构设计组 / 电气设计组 / 工艺设计组 / 设计审核组;不引入个人姓名。
+/// 责任人字段承载具体设计师姓名(产品设计阶段基准业务初始化数据,6 人按全表全局递增序号 seq 循环分配,确保 6 桶全覆盖)。
+/// 默认基线展示(顶部 2.5 / 98 + 分类汇总 354/28/382 PPT 口径)由 snapshot 表与前端基线数据共同支撑;
+/// 本表负责单订单态与多订单态的图号粒度真实数据。
 /// </summary>
 [IncreSeed]
 public class S8OrderFlowProductDesignDrawingSeedData
@@ -31,20 +33,21 @@ internal static class S8OrderFlowProductDesignDrawingDataset
     internal const string ProductTypeStandard = "STANDARD";
     internal const string ProductTypeNonStandard = "NON_STANDARD";
 
-    /// <summary>常规产品 KPI(天)。</summary>
+    /// <summary>常规产品 KPI(天)。PRODUCT_DESIGN 阶段统一标准。</summary>
     internal const decimal StandardKpiDays = 3.00m;
 
-    /// <summary>非标产品 KPI(天)。业务允许非标设计周期更长,落库为图号粒度独立 KPI。</summary>
-    internal const decimal NonStandardKpiDays = 12.00m;
+    /// <summary>非标产品 KPI(天)。与常规产品同阶段标准。</summary>
+    internal const decimal NonStandardKpiDays = 3.00m;
 
-    /// <summary>责任单位/岗位(5 选 1,按 sort_no 循环分配;不使用个人姓名)。</summary>
-    private static readonly string[] ResponsibleUnits =
+    /// <summary>产品设计阶段基准业务初始化数据:设计师姓名清单(6 人按全表全局递增序号 seq 循环分配,sort_no 仅为订单内序号,无法保证 6 桶全覆盖)。</summary>
+    private static readonly string[] Designers =
     {
-        "研发中心",
-        "结构设计组",
-        "电气设计组",
-        "工艺设计组",
-        "设计审核组",
+        "李海峰",
+        "陈思远",
+        "王明华",
+        "赵建国",
+        "刘振宇",
+        "周启明",
     };
 
     /// <summary>
@@ -66,7 +69,7 @@ internal static class S8OrderFlowProductDesignDrawingDataset
     /// <summary>52 张常规图号 spec:合计 actual_days=61.88、qty=357、1 张超期 (qty=3)。</summary>
     private static readonly DrawingSpec[] StandardSequence = BuildStandardSequence();
 
-    /// <summary>11 张非标图号 spec:合计 actual_days=102.08、qty=25、2 张超期 (qty=6 each)。</summary>
+    /// <summary>11 张非标图号 spec:合计 actual_days=102.08、qty=25;全部 actual_days &gt; 3 → 全部不达标 red。</summary>
     private static readonly DrawingSpec[] NonStandardSequence = BuildNonStandardSequence();
 
     /// <summary>单张图号的回卷规格:actual_days / quantity / is_achieved / status。</summary>
@@ -91,15 +94,15 @@ internal static class S8OrderFlowProductDesignDrawingDataset
 
     private static DrawingSpec[] BuildNonStandardSequence()
     {
-        // 11 张分布:5×(8.34, qty=1) + 4×(8.34, qty=2) + 2×(13.51, qty=6, yellow)
+        // 11 张分布:5×(8.34, qty=1) + 4×(8.34, qty=2) + 2×(13.51, qty=6)
         // actual_days 合计 = 9×8.34 + 2×13.51 = 75.06 + 27.02 = 102.08 → avg 9.28 (在 [9.25, 9.31])
         // quantity 合计    = 5×1 + 4×2 + 2×6 = 5 + 8 + 12 = 25
+        // 非标 KPI=3 后,所有 actual_days ≥ 8.34 > 3 → 全部 is_achieved=false / status='red'
         var seq = new DrawingSpec[11];
-        for (var i = 0; i < 5; i++) seq[i] = new DrawingSpec(8.34m, 1, true, "green");
-        for (var i = 5; i < 9; i++) seq[i] = new DrawingSpec(8.34m, 2, true, "green");
-        // 两张超期非标图号:actual=13.51 > kpi=12 → (13.51-12)/12 ≈ 0.126 ≤ 0.20 → yellow
-        seq[9] = new DrawingSpec(13.51m, 6, false, "yellow");
-        seq[10] = new DrawingSpec(13.51m, 6, false, "yellow");
+        for (var i = 0; i < 5; i++) seq[i] = new DrawingSpec(8.34m, 1, false, "red");
+        for (var i = 5; i < 9; i++) seq[i] = new DrawingSpec(8.34m, 2, false, "red");
+        seq[9] = new DrawingSpec(13.51m, 6, false, "red");
+        seq[10] = new DrawingSpec(13.51m, 6, false, "red");
         return seq;
     }
 
@@ -161,10 +164,11 @@ internal static class S8OrderFlowProductDesignDrawingDataset
         DateTime plannedStart,
         DrawingSpec spec)
     {
+        // 计划区间按 KPI 推算;非标 KPI 与常规 KPI 同阶段标准 3 天,但非标设计周期允许 actual_days 较长。
         var plannedEnd = plannedStart.AddDays((double)kpiDays);
         var actualStart = plannedStart;
         var actualEnd = actualStart.AddDays((double)spec.ActualDays);
-        var responsible = ResponsibleUnits[(sortNo - 1) % ResponsibleUnits.Length];
+        var responsible = Designers[(seq - 1) % Designers.Length];
 
         return new AdoS8OrderFlowProductDesignDrawing
         {

+ 4 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/SeedData/S8OrderFlowSnapshotSeedData.cs

@@ -5,8 +5,10 @@ namespace Admin.NET.Plugin.AiDOP.SeedData;
 /// <summary>
 /// ORDER-FLOW-S8-INTEGRATED-DOMAIN-RESET-1 t2c:S8 订单执行链路 BASELINE_PPT 聚合快照种子。
 /// 单条记录:snapshot_code = CHAIN_AGGREGATE_BASELINE / scope_code = BASELINE_PPT / scenario = PPT。
-/// stage_snapshots_json 含 5 阶段 PPT 第 1 页真值。onTimeRate 是整数百分比(59/96/85/89/96)。
+/// stage_snapshots_json 含 5 阶段 PPT 第 1 页真值。onTimeRate 是整数百分比(59/98/85/89/96)。
 /// service 层 baseline 读取协议:scope_code=BASELINE_PPT → 取本表行;CURRENT_FILTERED → 实时聚合。
+/// S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:PRODUCT_DESIGN
+/// 行按 PPT 业务口径修正为 actualAvgDays=2.5 / onTimeRate=98。
 /// </summary>
 [IncreSeed]
 public class S8OrderFlowSnapshotSeedData : ISqlSugarEntitySeedData<AdoS8OrderFlowSnapshot>
@@ -40,7 +42,7 @@ public class S8OrderFlowSnapshotSeedData : ISqlSugarEntitySeedData<AdoS8OrderFlo
     private const string StageSnapshotsJson =
         "[" +
         "{\"orderFlowCode\":\"ORDER_REVIEW_PLAN_CALC\",\"orderFlowName\":\"评审/排产/测算\",\"kpiAvgDays\":5.0,\"actualAvgDays\":6.2,\"onTimeRate\":59,\"green\":0,\"yellow\":0,\"red\":0,\"pending\":0}," +
-        "{\"orderFlowCode\":\"PRODUCT_DESIGN\",\"orderFlowName\":\"产品设计\",\"kpiAvgDays\":3.0,\"actualAvgDays\":2.6,\"onTimeRate\":96,\"green\":0,\"yellow\":0,\"red\":0,\"pending\":0}," +
+        "{\"orderFlowCode\":\"PRODUCT_DESIGN\",\"orderFlowName\":\"产品设计\",\"kpiAvgDays\":3.0,\"actualAvgDays\":2.5,\"onTimeRate\":98,\"green\":0,\"yellow\":0,\"red\":0,\"pending\":0}," +
         "{\"orderFlowCode\":\"MATERIAL_PURCHASE\",\"orderFlowName\":\"材料采购\",\"kpiAvgDays\":14.0,\"actualAvgDays\":15.5,\"onTimeRate\":85,\"green\":0,\"yellow\":0,\"red\":0,\"pending\":0}," +
         "{\"orderFlowCode\":\"BODY_PRODUCTION\",\"orderFlowName\":\"本体生产\",\"kpiAvgDays\":6.0,\"actualAvgDays\":6.7,\"onTimeRate\":89,\"green\":0,\"yellow\":0,\"red\":0,\"pending\":0}," +
         "{\"orderFlowCode\":\"FINAL_ASSEMBLY_DELIVERY\",\"orderFlowName\":\"总装发货\",\"kpiAvgDays\":3.0,\"actualAvgDays\":2.9,\"onTimeRate\":96,\"green\":0,\"yellow\":0,\"red\":0,\"pending\":0}" +

+ 16 - 6
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/OrderFlow/S8OrderFlowService.cs

@@ -707,7 +707,10 @@ public class S8OrderFlowService : ITransient
     private const string ProductDesignTypeNonStandard = "NON_STANDARD";
     private const string ProductDesignTypeTotal = "TOTAL";
     private const decimal ProductDesignStageKpiDays = 3m;
-    private const decimal ProductDesignNonStandardKpiDays = 12m;
+
+    // S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:
+    // 非标产品 KPI 与常规产品同阶段标准 3 天;非标 actual_days 超 3 时记 red/未达标。
+    private const decimal ProductDesignNonStandardKpiDays = 3m;
 
     public async Task<AdoS8OrderFlowProductDesignDrawingsDto> GetProductDesignDrawingsAsync(
         AdoS8OrderFlowProductDesignDrawingsQueryDto query)
@@ -816,6 +819,11 @@ public class S8OrderFlowService : ITransient
         var actualDays = rows.Where(r => r.ActualDays.HasValue).Select(r => r.ActualDays!.Value).ToList();
         var rate = totalQty == 0 ? 0m : (decimal)achievedQty / totalQty;
 
+        // S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:分类汇总按业务口径差异化输出。
+        // STANDARD / TOTAL:KPI、平均设计周期、达成率均返回 null,由前端展示 --。
+        // NON_STANDARD:返回真实 KPI=3 天、actual_days 算术平均、quantity 加权达成率与对应状态色。
+        var isNonStandard = productType == ProductDesignTypeNonStandard;
+
         return new AdoS8OrderFlowProductDesignCategorySummaryDto
         {
             ProductType = productType,
@@ -823,14 +831,16 @@ public class S8OrderFlowService : ITransient
             DrawingCount = rows.Select(r => r.DrawingNo).Distinct(StringComparer.Ordinal).Count(),
             TotalQuantity = totalQty,
             Ratio = grandTotalQty == 0 ? 0m : (decimal)totalQty / grandTotalQty,
-            AvgActualDays = actualDays.Count == 0 ? 0m : actualDays.Average(),
-            KpiDays = kpiDays,
-            AchievementRate = rate,
-            Status = ClassifyProductDesignCategoryStatus(rate, totalQty),
+            KpiDays = isNonStandard ? kpiDays : (decimal?)null,
+            AvgActualDays = isNonStandard
+                ? (actualDays.Count == 0 ? (decimal?)null : actualDays.Average())
+                : (decimal?)null,
+            AchievementRate = isNonStandard ? rate : (decimal?)null,
+            Status = isNonStandard ? ClassifyProductDesignCategoryStatus(rate, totalQty) : string.Empty,
         };
     }
 
-    /// <summary>达标率 ≥ 0.95 绿 / ≥ 0.80 黄 / 否则 红;无数据返回空串以表达"未取数"而非状态判定。</summary>
+    /// <summary>达标率 ≥ 0.95 绿 / ≥ 0.80 黄 / 否则 红;无数据返回空串以表达未取数而非状态判定。</summary>
     private static string ClassifyProductDesignCategoryStatus(decimal achievementRate, int totalQty)
     {
         if (totalQty == 0) return string.Empty;