Просмотр исходного кода

feat(s8): t3f wire first order flow frontend domain api

YY968XX 2 месяцев назад
Родитель
Сommit
34f990f9e6
1 измененных файлов с 68 добавлено и 22 удалено
  1. 68 22
      Web/src/views/aidop/s8/monitoring/SoOrderExecutionPreviewPage.vue

+ 68 - 22
Web/src/views/aidop/s8/monitoring/SoOrderExecutionPreviewPage.vue

@@ -1,42 +1,88 @@
 <script setup lang="ts" name="aidopS8SoOrderExecutionPreview">
-// ORDER-FLOW-FIXTURE-STORE-1:fixture/store 落地预览页。
-// 仅用于本切片自检 105 订单 / 5 客户 / KPI 三均值;本轮不注册菜单 / 不接正式路由 / 不做完整 UI。
-import { computed, onMounted } from 'vue';
-import { useOrderExecutionStore } from '/@/stores/orderExecution';
+// ORDER-FLOW-S8-INTEGRATED-DOMAIN-RESET-1 t3f:前端首个正式 API 接入点。
+// 旧 store / fixture 保留不动;本页旁路 store,直接调用 s8OrderFlowDomainApi 验证:
+//   1. /api/aidop/s8/order-flow/orders 真实出现在 Network;
+//   2. 返回 baseline 订单数且关键字段可在 UI 显示;
+//   3. 客户数 / 订单数 / KPI 三均值由 list 自派生,不查 aggregate(按规约最小接口)。
+// 字段映射(旧 fixture/demo → 新正式):
+//   soNo                 → orderCode
+//   customerName         → customerName
+//   productName          → productName
+//   currentNode          → currentOrderFlowName
+//   exceptionCount       → exceptionCount
+//   kpi.avgResponse      → mean(responseMinutes)
+//   kpi.avgProcessing    → mean(processingMinutes)
+//   kpi.avgLoss          → mean(totalLossMinutes)
+import { computed, onMounted, ref } from 'vue';
+import {
+	getOrderFlowOrders,
+	type OrderFlowOrderListItem,
+} from '/@/views/aidop/s8/api/s8OrderFlowDomainApi';
 
-const store = useOrderExecutionStore();
+const orders = ref<OrderFlowOrderListItem[]>([]);
+const loading = ref(false);
+const errorMsg = ref('');
 
-onMounted(() => {
-	store.loadFixture();
+onMounted(async () => {
+	loading.value = true;
+	try {
+		const list = await getOrderFlowOrders({});
+		orders.value = Array.isArray(list) ? list : [];
+	} catch (err) {
+		errorMsg.value = err instanceof Error ? err.message : String(err);
+	} finally {
+		loading.value = false;
+	}
 });
 
-const customerCount = computed(() => store.customerGroups.length);
-const orderCount = computed(() => store.allOrders.length);
-const kpi = computed(() => store.kpiAverages);
-const observedAt = computed(() => store.currentObservationTime);
-const previewOrders = computed(() => store.filteredOrders.slice(0, 5));
+function avg(values: Array<number | null | undefined>): number {
+	const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v));
+	if (nums.length === 0) return 0;
+	const sum = nums.reduce((a, b) => a + b, 0);
+	return sum / nums.length;
+}
+
+const orderCount = computed(() => orders.value.length);
+const customerCount = computed(() => {
+	const set = new Set<string>();
+	for (const o of orders.value) {
+		if (o.customerCode) set.add(o.customerCode);
+	}
+	return set.size;
+});
+const kpi = computed(() => ({
+	avgResponse: avg(orders.value.map((o) => o.responseMinutes)),
+	avgProcessing: avg(orders.value.map((o) => o.processingMinutes)),
+	avgLoss: avg(orders.value.map((o) => o.totalLossMinutes)),
+}));
+const previewOrders = computed(() => orders.value.slice(0, 5));
 const fmt = (v: number) => v.toFixed(1);
 </script>
 
 <template>
 	<div class="so-preview">
-		<h2>SO 订单执行档案数据预览</h2>
-		<p class="hint">本页仅用于 ORDER-FLOW-FIXTURE-STORE-1 自检;不在正式菜单中。</p>
+		<h2>SO 订单执行档案数据预览(正式 API)</h2>
+		<p class="hint">
+			t3f 切片:直接调用 /api/aidop/s8/order-flow/orders;
+			客户数 / 订单数 / KPI 三均值由列表自派生。
+		</p>
+
+		<el-alert v-if="errorMsg" :title="errorMsg" type="error" show-icon :closable="false" class="meta" />
 
-		<el-descriptions :column="2" border size="small" class="meta">
+		<el-descriptions :column="2" border size="small" class="meta" v-loading="loading">
 			<el-descriptions-item label="客户数">{{ customerCount }}</el-descriptions-item>
 			<el-descriptions-item label="订单数">{{ orderCount }}</el-descriptions-item>
-			<el-descriptions-item label="平均响应时间">{{ fmt(kpi.avgResponse) }}</el-descriptions-item>
-			<el-descriptions-item label="平均处理时间">{{ fmt(kpi.avgProcessing) }}</el-descriptions-item>
-			<el-descriptions-item label="平均损失时间">{{ fmt(kpi.avgLoss) }}</el-descriptions-item>
-			<el-descriptions-item label="当前观测时间">{{ observedAt }}</el-descriptions-item>
+			<el-descriptions-item label="平均响应时间(分钟)">{{ fmt(kpi.avgResponse) }}</el-descriptions-item>
+			<el-descriptions-item label="平均处理时间(分钟)">{{ fmt(kpi.avgProcessing) }}</el-descriptions-item>
+			<el-descriptions-item label="平均损失时间(分钟)">{{ fmt(kpi.avgLoss) }}</el-descriptions-item>
+			<el-descriptions-item label="数据源">正式 API</el-descriptions-item>
 		</el-descriptions>
 
-		<el-table :data="previewOrders" border size="small" class="orders">
-			<el-table-column prop="soNo" label="SO 号" width="160" />
+		<el-table :data="previewOrders" border size="small" class="orders" v-loading="loading">
+			<el-table-column prop="orderCode" label="订单号" width="160" />
 			<el-table-column prop="customerName" label="客户" width="160" />
 			<el-table-column prop="productName" label="产品名称" width="180" show-overflow-tooltip />
-			<el-table-column prop="currentNode" label="当前节点" width="140" />
+			<el-table-column prop="currentOrderFlowName" label="当前节点" width="140" />
 			<el-table-column prop="exceptionCount" label="异常数" width="80" />
 		</el-table>
 	</div>