feat: add selectable demo flow tasks

This commit is contained in:
2026-09-02 15:23:15 +08:00
parent f879328562
commit e3dc7ebe21
19 changed files with 871 additions and 110 deletions

84
server/demoFlow.test.ts Normal file
View File

@@ -0,0 +1,84 @@
import { describe, expect, it } from 'vitest';
import { buildDemoTaskCatalog, resolveSelectedDemoJobs } from './demoFlow';
import { listPlugins } from './plugins/registry';
import type { PluginManifest } from './plugins/types';
function manifest(id: string, tasks: PluginManifest['demoTasks']): PluginManifest {
return {
id,
name: id,
description: id,
version: '1',
schemaVersion: 1,
demoTasks: tasks,
demoSelection: { kind: 'task-nos', param: 'demoTaskNos' },
runtime: { kind: 'mock', fixture: 'unused.json' },
};
}
const manifests = [
manifest('distance', [
{ taskNo: 2, name: '车体长度', category: '尺寸', inspectionObjects: ['head', 'middle'] },
]),
manifest('contour', [
{ taskNo: 11, name: '车钩面板的平整度', category: '轮廓', inspectionObjects: ['head', 'middle'] },
]),
manifest('coupler', [
{ taskNo: 9, name: '参考面右偏转', category: '车钩', inspectionObjects: ['middle'] },
{ taskNo: 10, name: '纵向中心右偏转', category: '车钩', inspectionObjects: ['head'] },
]),
];
describe('demo task catalog', () => {
it('按数值排序并标记不适用于当前检测对象的任务', () => {
const catalog = buildDemoTaskCatalog(manifests, 'head', '头车');
expect(catalog.items.map((item) => item.taskNo)).toEqual([2, 9, 10, 11]);
expect(catalog.total).toBe(3);
expect(catalog.items.find((item) => item.taskNo === 9)).toMatchObject({ enabled: false });
});
it('跨算法选择转换为最小作业集合并去重', () => {
const catalog = buildDemoTaskCatalog(manifests, 'head', '头车');
const plan = resolveSelectedDemoJobs(manifests, catalog, [11, 2, 10, 2]);
expect(plan.taskNos).toEqual([2, 10, 11]);
expect(plan.jobs.map((job) => job.pluginId)).toEqual(['distance', 'coupler', 'contour']);
expect(plan.jobs).toHaveLength(3);
});
it('拒绝当前检测对象不可运行的任务', () => {
const catalog = buildDemoTaskCatalog(manifests, 'head', '头车');
expect(() => resolveSelectedDemoJobs(manifests, catalog, [9])).toThrow('不适用于当前头车');
});
});
describe('actual plugin demo task catalog', () => {
const actualManifests = listPlugins();
it('返回真实非连续任务号、名称与检测对象动态数量', () => {
const head = buildDemoTaskCatalog(actualManifests, 'head', '头车');
const middle = buildDemoTaskCatalog(actualManifests, 'middle', '中车');
expect(head.total).toBe(39);
expect(middle.total).toBe(26);
expect(head.items.find((item) => item.taskNo === 11)?.name).toBe('车钩面板的平整度');
expect(head.items.some((item) => item.taskNo === 3)).toBe(false);
expect(head.items.map((item) => item.taskNo)).toEqual(
[...head.items.map((item) => item.taskNo)].sort((a, b) => a - b),
);
});
it('任务 2、11、10 生成三个插件作业,单个车钩任务只生成一次共享作业', () => {
const head = buildDemoTaskCatalog(actualManifests, 'head', '头车');
const mixed = resolveSelectedDemoJobs(actualManifests, head, [2, 11, 10]);
expect(mixed.jobs.map((job) => job.pluginId)).toEqual([
'train-measurement',
'coupler-panel',
'flatness-suite',
]);
const couplerOnly = resolveSelectedDemoJobs(actualManifests, head, [8]);
expect(couplerOnly.jobs).toEqual([{
pluginId: 'coupler-panel',
taskNos: [8],
params: { demoTaskNos: [8] },
}]);
});
});