|
@@ -184,15 +184,15 @@ function renderRawCases(rawCasesObj) {
|
|
|
const cId = c.case_id || (c._raw && c._raw.case_id);
|
|
const cId = c.case_id || (c._raw && c._raw.case_id);
|
|
|
const cUrl = c.source_url || c.url;
|
|
const cUrl = c.source_url || c.url;
|
|
|
if (c.workflow) calcWorkflow++;
|
|
if (c.workflow) calcWorkflow++;
|
|
|
- if (c.capabilities && c.capabilities.length > 0) calcCapabilities++;
|
|
|
|
|
|
|
+ if (c.capability && c.capability.length > 0) calcCapabilities++;
|
|
|
|
|
|
|
|
if (cId) {
|
|
if (cId) {
|
|
|
if (c.workflow) detailMap[cId] = { ...detailMap[cId], workflow: c.workflow };
|
|
if (c.workflow) detailMap[cId] = { ...detailMap[cId], workflow: c.workflow };
|
|
|
- if (c.capabilities) detailMap[cId] = { ...detailMap[cId], capabilities: c.capabilities };
|
|
|
|
|
|
|
+ if (c.capability) detailMap[cId] = { ...detailMap[cId], capability: c.capability };
|
|
|
}
|
|
}
|
|
|
if (cUrl) {
|
|
if (cUrl) {
|
|
|
if (c.workflow) detailMapByUrl[cUrl] = { ...detailMapByUrl[cUrl], workflow: c.workflow };
|
|
if (c.workflow) detailMapByUrl[cUrl] = { ...detailMapByUrl[cUrl], workflow: c.workflow };
|
|
|
- if (c.capabilities) detailMapByUrl[cUrl] = { ...detailMapByUrl[cUrl], capabilities: c.capabilities };
|
|
|
|
|
|
|
+ if (c.capability) detailMapByUrl[cUrl] = { ...detailMapByUrl[cUrl], capability: c.capability };
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
@@ -956,7 +956,7 @@ function renderAggregatedPerCaseData(cases, type) {
|
|
|
if (type === 'workflow') {
|
|
if (type === 'workflow') {
|
|
|
items = c.workflow ? [c.workflow] : null;
|
|
items = c.workflow ? [c.workflow] : null;
|
|
|
} else if (type === 'capabilities') {
|
|
} else if (type === 'capabilities') {
|
|
|
- items = c.capabilities && Array.isArray(c.capabilities) ? c.capabilities : null;
|
|
|
|
|
|
|
+ items = c.capability && Array.isArray(c.capability) ? c.capability : null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const targetId = `case-${type}-${idx}`;
|
|
const targetId = `case-${type}-${idx}`;
|
|
@@ -983,7 +983,7 @@ function renderAggregatedPerCaseData(cases, type) {
|
|
|
|
|
|
|
|
contentHtml += `<div id="${targetId}" class="case-section" style="margin-bottom: 3.5rem; padding-top: 1rem;">`;
|
|
contentHtml += `<div id="${targetId}" class="case-section" style="margin-bottom: 3.5rem; padding-top: 1rem;">`;
|
|
|
|
|
|
|
|
- const stepName = type === 'workflow' ? 'workflow-extract' : 'capability-extract';
|
|
|
|
|
|
|
+ const stepName = 'workflow-extract';
|
|
|
const caseIndexToPass = c.index || (idx + 1);
|
|
const caseIndexToPass = c.index || (idx + 1);
|
|
|
const btnHtml = `<button class="btn btn-secondary" style="font-size: 0.85em; padding: 0.4rem 0.8rem; border-radius: 4px;" onclick="event.stopPropagation(); triggerSingleCaseRerun('${stepName}', ${caseIndexToPass})">🔄 重跑${typeLabel}</button>`;
|
|
const btnHtml = `<button class="btn btn-secondary" style="font-size: 0.85em; padding: 0.4rem 0.8rem; border-radius: 4px;" onclick="event.stopPropagation(); triggerSingleCaseRerun('${stepName}', ${caseIndexToPass})">🔄 重跑${typeLabel}</button>`;
|
|
|
|
|
|
|
@@ -1971,7 +1971,7 @@ window.openCaseDetail = function(p, initialIdx) {
|
|
|
let metaHtml = '';
|
|
let metaHtml = '';
|
|
|
const wf = ctx.detailMap[cId] || (cUrl ? ctx.detailMapByUrl[cUrl] : null) || c;
|
|
const wf = ctx.detailMap[cId] || (cUrl ? ctx.detailMapByUrl[cUrl] : null) || c;
|
|
|
if (wf && wf.workflow && wf.workflow.steps) metaHtml += `<span>工序 ${wf.workflow.steps.length}</span>`;
|
|
if (wf && wf.workflow && wf.workflow.steps) metaHtml += `<span>工序 ${wf.workflow.steps.length}</span>`;
|
|
|
- if (wf && wf.capabilities) metaHtml += `<span>能力 ${wf.capabilities.length}</span>`;
|
|
|
|
|
|
|
+ if (wf && wf.capability) metaHtml += `<span>能力 ${wf.capability.length}</span>`;
|
|
|
if (!metaHtml) metaHtml = '<span>无提取</span>';
|
|
if (!metaHtml) metaHtml = '<span>无提取</span>';
|
|
|
|
|
|
|
|
sidebarHtml += `<div class="modal-sidebar-item ${idx === globalInitialIdx ? 'active' : ''}" id="sidebar-item-${idx}" onclick="window.renderSingleCaseDetail(${idx})">
|
|
sidebarHtml += `<div class="modal-sidebar-item ${idx === globalInitialIdx ? 'active' : ''}" id="sidebar-item-${idx}" onclick="window.renderSingleCaseDetail(${idx})">
|
|
@@ -2156,7 +2156,7 @@ window.renderSingleCaseDetail = function(idx) {
|
|
|
);
|
|
);
|
|
|
const caseIndexToPass = realCaseIndex >= 0 ? (caseJsonCases[realCaseIndex].index || (realCaseIndex + 1)) : -1;
|
|
const caseIndexToPass = realCaseIndex >= 0 ? (caseJsonCases[realCaseIndex].index || (realCaseIndex + 1)) : -1;
|
|
|
const btnWorkflowHtml = caseIndexToPass !== -1 ? `<button class="btn btn-secondary" style="font-size: 0.8em; padding: 0.3rem 0.6rem; border-radius: 4px;" onclick="event.stopPropagation(); triggerSingleCaseRerun('workflow-extract', ${caseIndexToPass})">🔄 重跑工序</button>` : '';
|
|
const btnWorkflowHtml = caseIndexToPass !== -1 ? `<button class="btn btn-secondary" style="font-size: 0.8em; padding: 0.3rem 0.6rem; border-radius: 4px;" onclick="event.stopPropagation(); triggerSingleCaseRerun('workflow-extract', ${caseIndexToPass})">🔄 重跑工序</button>` : '';
|
|
|
- const btnCapabilityHtml = caseIndexToPass !== -1 ? `<button class="btn btn-secondary" style="font-size: 0.8em; padding: 0.3rem 0.6rem; border-radius: 4px;" onclick="event.stopPropagation(); triggerSingleCaseRerun('capability-extract', ${caseIndexToPass})">🔄 重跑能力</button>` : '';
|
|
|
|
|
|
|
+ const btnCapabilityHtml = caseIndexToPass !== -1 ? `<button class="btn btn-secondary" style="font-size: 0.8em; padding: 0.3rem 0.6rem; border-radius: 4px;" onclick="event.stopPropagation(); triggerSingleCaseRerun('workflow-extract', ${caseIndexToPass})">🔄 重跑能力</button>` : '';
|
|
|
|
|
|
|
|
mainScrollableHtml += `
|
|
mainScrollableHtml += `
|
|
|
<div class="case-section" style="margin-top: 2rem;">
|
|
<div class="case-section" style="margin-top: 2rem;">
|
|
@@ -2181,7 +2181,7 @@ window.renderSingleCaseDetail = function(idx) {
|
|
|
${btnCapabilityHtml}
|
|
${btnCapabilityHtml}
|
|
|
</div>
|
|
</div>
|
|
|
<div class="hidden" style="padding-top: 1.2rem;">
|
|
<div class="hidden" style="padding-top: 1.2rem;">
|
|
|
- ${window.renderStructuredData(wf && wf.capabilities ? wf.capabilities : null, 'capabilities', wf)}
|
|
|
|
|
|
|
+ ${window.renderStructuredData(wf && wf.capability ? wf.capability : null, 'capabilities', wf)}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
`;
|
|
`;
|
|
@@ -2230,16 +2230,16 @@ window.renderStructuredData = function(items, type, parentItem = null) {
|
|
|
const hasValidIO = (arr) => Array.isArray(arr) && arr.length > 0 && (arr[0].role || arr[0].description);
|
|
const hasValidIO = (arr) => Array.isArray(arr) && arr.length > 0 && (arr[0].role || arr[0].description);
|
|
|
if (hasValidIO(item.inputs) || hasValidIO(item.outputs) || (item.steps && item.steps.length > 0)) {
|
|
if (hasValidIO(item.inputs) || hasValidIO(item.outputs) || (item.steps && item.steps.length > 0)) {
|
|
|
let actionStr = '';
|
|
let actionStr = '';
|
|
|
- if (item.action && item.action.main_action) {
|
|
|
|
|
- actionStr = item.action.main_action;
|
|
|
|
|
|
|
+ if (item.action && item.action.description) {
|
|
|
|
|
+ actionStr = item.action.description;
|
|
|
} else if (item.method && !item.method.includes('[')) {
|
|
} else if (item.method && !item.method.includes('[')) {
|
|
|
actionStr = item.method;
|
|
actionStr = item.method;
|
|
|
} else if (item.steps && Array.isArray(item.steps)) {
|
|
} else if (item.steps && Array.isArray(item.steps)) {
|
|
|
const hasAnyValidIO = item.steps.some(s => hasValidIO(s.inputs) || hasValidIO(s.outputs));
|
|
const hasAnyValidIO = item.steps.some(s => hasValidIO(s.inputs) || hasValidIO(s.outputs));
|
|
|
if (hasAnyValidIO) {
|
|
if (hasAnyValidIO) {
|
|
|
actionStr = item.steps.map(s => {
|
|
actionStr = item.steps.map(s => {
|
|
|
- if (s.action && s.action.main_action) {
|
|
|
|
|
- return s.action.mechanism ? `[${s.action.main_action}] ${s.action.mechanism}` : s.action.main_action;
|
|
|
|
|
|
|
+ if (s.action && s.action.description) {
|
|
|
|
|
+ return s.action.description;
|
|
|
}
|
|
}
|
|
|
if (s.method) return s.method;
|
|
if (s.method) return s.method;
|
|
|
if (s.phase) return s.phase;
|
|
if (s.phase) return s.phase;
|
|
@@ -2258,9 +2258,8 @@ window.renderStructuredData = function(items, type, parentItem = null) {
|
|
|
} else {
|
|
} else {
|
|
|
const escapeHtml = (s) => String(s).replace(/</g, '<').replace(/>/g, '>');
|
|
const escapeHtml = (s) => String(s).replace(/</g, '<').replace(/>/g, '>');
|
|
|
title = escapeHtml(item.method || item.name || '');
|
|
title = escapeHtml(item.method || item.name || '');
|
|
|
- if (!title && item.action && item.action.main_action) {
|
|
|
|
|
- const actText = item.action.mechanism ? `[${item.action.main_action}] ${item.action.mechanism}` : item.action.main_action;
|
|
|
|
|
- title = escapeHtml(actText);
|
|
|
|
|
|
|
+ if (!title && item.action && item.action.description) {
|
|
|
|
|
+ title = escapeHtml(item.action.description);
|
|
|
}
|
|
}
|
|
|
if (!title) {
|
|
if (!title) {
|
|
|
title = escapeHtml(type === 'workflow' ? '工作流' : `节点 ${idx + 1}`);
|
|
title = escapeHtml(type === 'workflow' ? '工作流' : `节点 ${idx + 1}`);
|
|
@@ -2393,6 +2392,18 @@ window.renderStructuredData = function(items, type, parentItem = null) {
|
|
|
<div class="structured-value">${renderApplyToVal(applyToData.val, applyToData.suggest)}</div>
|
|
<div class="structured-value">${renderApplyToVal(applyToData.val, applyToData.suggest)}</div>
|
|
|
</div>`;
|
|
</div>`;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (item.action && typeof item.action === 'object' && (item.action.description || item.action.reasoning)) {
|
|
|
|
|
+ const actionDescription = item.action.description ? String(item.action.description).replace(/</g, '<').replace(/>/g, '>') : '';
|
|
|
|
|
+ const actionReasoning = item.action.reasoning ? String(item.action.reasoning).replace(/</g, '<').replace(/>/g, '>') : '';
|
|
|
|
|
+ html += `<div class="structured-row">
|
|
|
|
|
+ <div class="structured-label">action</div>
|
|
|
|
|
+ <div class="structured-value">
|
|
|
|
|
+ ${actionDescription ? `<span class="data-type-badge" style="background:#e0e7ff;color:#3730a3;font-weight:normal;margin-right:6px;">${actionDescription}</span>` : ''}
|
|
|
|
|
+ ${actionReasoning ? `<span style="color:var(--text-secondary);">${actionReasoning}</span>` : ''}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>`;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Stage rendering removed per request
|
|
// Stage rendering removed per request
|
|
|
// Render effects
|
|
// Render effects
|
|
@@ -2570,15 +2581,15 @@ window.renderStructuredData = function(items, type, parentItem = null) {
|
|
|
|
|
|
|
|
// Render steps array specially
|
|
// Render steps array specially
|
|
|
if (item.steps && Array.isArray(item.steps)) {
|
|
if (item.steps && Array.isArray(item.steps)) {
|
|
|
- const allFragments = (parentItem && parentItem.fragments) || [];
|
|
|
|
|
|
|
+ const allCapabilities = (parentItem && parentItem.capability) || [];
|
|
|
const escapeHtml = (s) => String(s).replace(/</g, '<').replace(/>/g, '>');
|
|
const escapeHtml = (s) => String(s).replace(/</g, '<').replace(/>/g, '>');
|
|
|
const minWidth = 1250;
|
|
const minWidth = 1250;
|
|
|
const renderAction = (src) => {
|
|
const renderAction = (src) => {
|
|
|
if (!src) return '-';
|
|
if (!src) return '-';
|
|
|
- if (src.action && src.action.main_action) {
|
|
|
|
|
- const mainAction = escapeHtml(src.action.main_action);
|
|
|
|
|
- const mechanism = src.action.mechanism ? escapeHtml(src.action.mechanism) : '';
|
|
|
|
|
- return `<span class="data-type-badge" style="background:#e0e7ff;color:#3730a3;font-weight:normal;margin-right:6px;margin-bottom:2px;display:inline-block;">${mainAction}</span>${mechanism}`;
|
|
|
|
|
|
|
+ if (src.action && src.action.description) {
|
|
|
|
|
+ const description = escapeHtml(src.action.description);
|
|
|
|
|
+ const reasoning = src.action.reasoning ? escapeHtml(src.action.reasoning) : '';
|
|
|
|
|
+ return `<span class="data-type-badge" style="background:#e0e7ff;color:#3730a3;font-weight:normal;margin-right:6px;margin-bottom:2px;display:inline-block;">${description}</span>${reasoning ? `<div style="font-size:0.85em;color:#64748b;margin-top:4px;">${reasoning}</div>` : ''}`;
|
|
|
}
|
|
}
|
|
|
if (src.method) return escapeHtml(src.method);
|
|
if (src.method) return escapeHtml(src.method);
|
|
|
if (src.description) return escapeHtml(src.description);
|
|
if (src.description) return escapeHtml(src.description);
|
|
@@ -2612,34 +2623,34 @@ window.renderStructuredData = function(items, type, parentItem = null) {
|
|
|
</div>`;
|
|
</div>`;
|
|
|
}).join('')}</div>`;
|
|
}).join('')}</div>`;
|
|
|
};
|
|
};
|
|
|
- const getStepFragments = (step) => {
|
|
|
|
|
|
|
+ const getStepCapabilities = (step) => {
|
|
|
if (!step || !step.step_id) return [];
|
|
if (!step || !step.step_id) return [];
|
|
|
- return allFragments.filter(f => {
|
|
|
|
|
- const refStepId = f.workflow_step_ref && f.workflow_step_ref.step_id;
|
|
|
|
|
|
|
+ return allCapabilities.filter(capability => {
|
|
|
|
|
+ const refStepId = capability.workflow_step_ref && capability.workflow_step_ref.step_id;
|
|
|
return refStepId === step.step_id || (
|
|
return refStepId === step.step_id || (
|
|
|
- f.fragment_id && (
|
|
|
|
|
- f.fragment_id === `f_${step.step_id}` ||
|
|
|
|
|
- f.fragment_id.startsWith(`f_${step.step_id}_`)
|
|
|
|
|
|
|
+ capability.capability_id && (
|
|
|
|
|
+ capability.capability_id === `c_${step.step_id}` ||
|
|
|
|
|
+ capability.capability_id.startsWith(`c_${step.step_id}_`)
|
|
|
)
|
|
)
|
|
|
);
|
|
);
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
- const matchedFragments = new Set();
|
|
|
|
|
- const renderFragmentColumns = (fragment) => {
|
|
|
|
|
- const applyTo = fragment && (fragment.apply_to_draft || fragment.apply_to_grounding || fragment.apply_to);
|
|
|
|
|
- const suggestApplyTo = fragment && fragment.apply_to_draft ? null : fragment && fragment.suggest_apply_to;
|
|
|
|
|
|
|
+ const matchedCapabilities = new Set();
|
|
|
|
|
+ const renderCapabilityColumns = (capability) => {
|
|
|
|
|
+ const applyTo = capability && (capability.apply_to_draft || capability.apply_to_grounding || capability.apply_to);
|
|
|
|
|
+ const suggestApplyTo = capability && capability.apply_to_draft ? null : capability && capability.suggest_apply_to;
|
|
|
return `
|
|
return `
|
|
|
- <td class="fragment-cell" style="font-family: monospace;">
|
|
|
|
|
|
|
+ <td class="capability-cell" style="font-family: monospace;">
|
|
|
<span class="row-expand-icon">▶</span>
|
|
<span class="row-expand-icon">▶</span>
|
|
|
- ${fragment && fragment.fragment_id ? `<span style="display:inline-block; color:#94a3b8; font-size:0.85em; font-weight:400;">${escapeHtml(fragment.fragment_id)}</span>` : '-'}
|
|
|
|
|
|
|
+ ${capability && capability.capability_id ? `<span style="display:inline-block; color:#94a3b8; font-size:0.85em; font-weight:400;">${escapeHtml(capability.capability_id)}</span>` : '-'}
|
|
|
</td>
|
|
</td>
|
|
|
- <td class="fragment-cell">${renderAction(fragment)}</td>
|
|
|
|
|
- <td class="fragment-cell">${fragment && fragment.inputs && fragment.inputs.length > 0 ? renderDataObjList(fragment.inputs) : '-'}</td>
|
|
|
|
|
- <td class="fragment-cell">${fragment && fragment.outputs && fragment.outputs.length > 0 ? renderDataObjList(fragment.outputs) : '-'}</td>
|
|
|
|
|
- <td class="fragment-cell"><div class="fragment-clamp">${fragment ? renderEffects(fragment.effects) : '-'}</div></td>
|
|
|
|
|
- <td class="fragment-cell" style="font-size:0.9em;"><div class="fragment-clamp">${applyTo ? renderApplyToVal(applyTo, suggestApplyTo) : '-'}</div></td>
|
|
|
|
|
- <td class="fragment-cell"><div class="fragment-clamp">${fragment ? renderTools(fragment.tools) : '-'}</div></td>
|
|
|
|
|
- <td class="fragment-cell"><div class="fragment-clamp fragment-text">${fragment && fragment.body ? escapeHtml(fragment.body) : '-'}</div></td>
|
|
|
|
|
|
|
+ <td class="capability-cell">${renderAction(capability)}</td>
|
|
|
|
|
+ <td class="capability-cell">${capability && capability.inputs && capability.inputs.length > 0 ? renderDataObjList(capability.inputs) : '-'}</td>
|
|
|
|
|
+ <td class="capability-cell">${capability && capability.outputs && capability.outputs.length > 0 ? renderDataObjList(capability.outputs) : '-'}</td>
|
|
|
|
|
+ <td class="capability-cell"><div class="capability-clamp">${capability ? renderEffects(capability.effects) : '-'}</div></td>
|
|
|
|
|
+ <td class="capability-cell" style="font-size:0.9em;"><div class="capability-clamp">${applyTo ? renderApplyToVal(applyTo, suggestApplyTo) : '-'}</div></td>
|
|
|
|
|
+ <td class="capability-cell"><div class="capability-clamp">${capability ? renderTools(capability.tools) : '-'}</div></td>
|
|
|
|
|
+ <td class="capability-cell"><div class="capability-clamp capability-text">${capability && capability.body ? escapeHtml(capability.body) : '-'}</div></td>
|
|
|
`;
|
|
`;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -2651,14 +2662,14 @@ window.renderStructuredData = function(items, type, parentItem = null) {
|
|
|
.steps-table tbody tr:hover { background: rgba(0,0,0,0.02) !important; }
|
|
.steps-table tbody tr:hover { background: rgba(0,0,0,0.02) !important; }
|
|
|
.steps-table td { border-bottom: 1px solid rgba(0,0,0,0.05); }
|
|
.steps-table td { border-bottom: 1px solid rgba(0,0,0,0.05); }
|
|
|
.steps-table .step-merged-cell { background: #fbfdff; border-right: 1px dashed rgba(0,0,0,0.08); }
|
|
.steps-table .step-merged-cell { background: #fbfdff; border-right: 1px dashed rgba(0,0,0,0.08); }
|
|
|
- .steps-table .fragment-cell { padding: 12px 10px; vertical-align: top; line-height: 1.5; color: var(--text-main); }
|
|
|
|
|
- .steps-table .fragment-clamp { max-height: 72px; overflow: hidden; position: relative; }
|
|
|
|
|
- .steps-table .fragment-clamp::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 24px; background: linear-gradient(to bottom, rgba(255,255,255,0), white); pointer-events: none; }
|
|
|
|
|
- .steps-table tr.fragment-expanded .fragment-clamp { max-height: none; overflow: visible; }
|
|
|
|
|
- .steps-table tr.fragment-expanded .fragment-clamp::after { display: none; }
|
|
|
|
|
|
|
+ .steps-table .capability-cell { padding: 12px 10px; vertical-align: top; line-height: 1.5; color: var(--text-main); }
|
|
|
|
|
+ .steps-table .capability-clamp { max-height: 72px; overflow: hidden; position: relative; }
|
|
|
|
|
+ .steps-table .capability-clamp::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 24px; background: linear-gradient(to bottom, rgba(255,255,255,0), white); pointer-events: none; }
|
|
|
|
|
+ .steps-table tr.capability-expanded .capability-clamp { max-height: none; overflow: visible; }
|
|
|
|
|
+ .steps-table tr.capability-expanded .capability-clamp::after { display: none; }
|
|
|
.steps-table .row-expand-icon { display: inline-block; margin-right: 6px; color: var(--text-muted); font-size: 0.8em; transition: transform 0.2s; }
|
|
.steps-table .row-expand-icon { display: inline-block; margin-right: 6px; color: var(--text-muted); font-size: 0.8em; transition: transform 0.2s; }
|
|
|
- .steps-table tr.fragment-expanded .row-expand-icon { transform: rotate(90deg); }
|
|
|
|
|
- .steps-table .fragment-text { white-space: pre-wrap; word-break: break-word; }
|
|
|
|
|
|
|
+ .steps-table tr.capability-expanded .row-expand-icon { transform: rotate(90deg); }
|
|
|
|
|
+ .steps-table .capability-text { white-space: pre-wrap; word-break: break-word; }
|
|
|
.steps-table .effect-item { padding-bottom:8px; margin-bottom:8px; border-bottom:1px dashed rgba(0,0,0,0.08); color:var(--text-main); line-height:1.5; }
|
|
.steps-table .effect-item { padding-bottom:8px; margin-bottom:8px; border-bottom:1px dashed rgba(0,0,0,0.08); color:var(--text-main); line-height:1.5; }
|
|
|
.steps-table .effect-item:last-child { margin-bottom:0; padding-bottom:0; border-bottom:0; }
|
|
.steps-table .effect-item:last-child { margin-bottom:0; padding-bottom:0; border-bottom:0; }
|
|
|
.steps-table .effect-content { min-width:0; flex:1; }
|
|
.steps-table .effect-content { min-width:0; flex:1; }
|
|
@@ -2686,34 +2697,34 @@ window.renderStructuredData = function(items, type, parentItem = null) {
|
|
|
<tbody>`;
|
|
<tbody>`;
|
|
|
|
|
|
|
|
item.steps.forEach((step, stepIdx) => {
|
|
item.steps.forEach((step, stepIdx) => {
|
|
|
- const stepFragments = getStepFragments(step);
|
|
|
|
|
- stepFragments.forEach(fragment => matchedFragments.add(fragment));
|
|
|
|
|
- const fragsToRender = stepFragments.length > 0 ? stepFragments : [null];
|
|
|
|
|
- const rowspan = fragsToRender.length;
|
|
|
|
|
|
|
+ const stepCapabilities = getStepCapabilities(step);
|
|
|
|
|
+ stepCapabilities.forEach(capability => matchedCapabilities.add(capability));
|
|
|
|
|
+ const capabilitiesToRender = stepCapabilities.length > 0 ? stepCapabilities : [null];
|
|
|
|
|
+ const rowspan = capabilitiesToRender.length;
|
|
|
|
|
|
|
|
- fragsToRender.forEach((fragment, fragmentIdx) => {
|
|
|
|
|
|
|
+ capabilitiesToRender.forEach((capability, capabilityIdx) => {
|
|
|
html += `
|
|
html += `
|
|
|
- <tr style="vertical-align: top;" onclick="this.classList.toggle('fragment-expanded')">
|
|
|
|
|
- ${fragmentIdx === 0 ? `
|
|
|
|
|
|
|
+ <tr style="vertical-align: top;" onclick="this.classList.toggle('capability-expanded')">
|
|
|
|
|
+ ${capabilityIdx === 0 ? `
|
|
|
<td class="step-merged-cell" rowspan="${rowspan}" style="padding: 14px 10px; font-weight: 600; color: var(--text-muted); text-align: center;">
|
|
<td class="step-merged-cell" rowspan="${rowspan}" style="padding: 14px 10px; font-weight: 600; color: var(--text-muted); text-align: center;">
|
|
|
${step.order || stepIdx + 1}
|
|
${step.order || stepIdx + 1}
|
|
|
</td>
|
|
</td>
|
|
|
<td class="step-merged-cell" rowspan="${rowspan}" style="padding: 14px 10px;">
|
|
<td class="step-merged-cell" rowspan="${rowspan}" style="padding: 14px 10px;">
|
|
|
${step.phase ? `<span class="structured-badge" style="background:#f1f5f9; color:#475569; font-weight: 500;">${escapeHtml(step.phase)}</span>` : '-'}
|
|
${step.phase ? `<span class="structured-badge" style="background:#f1f5f9; color:#475569; font-weight: 500;">${escapeHtml(step.phase)}</span>` : '-'}
|
|
|
</td>` : ''}
|
|
</td>` : ''}
|
|
|
- ${renderFragmentColumns(fragment)}
|
|
|
|
|
|
|
+ ${renderCapabilityColumns(capability)}
|
|
|
</tr>
|
|
</tr>
|
|
|
`;
|
|
`;
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
- allFragments.filter(fragment => !matchedFragments.has(fragment)).forEach(fragment => {
|
|
|
|
|
|
|
+ allCapabilities.filter(capability => !matchedCapabilities.has(capability)).forEach(capability => {
|
|
|
html += `
|
|
html += `
|
|
|
- <tr style="vertical-align: top;" onclick="this.classList.toggle('fragment-expanded')">
|
|
|
|
|
|
|
+ <tr style="vertical-align: top;" onclick="this.classList.toggle('capability-expanded')">
|
|
|
<td class="step-merged-cell" style="padding: 14px 10px; font-weight: 600; color: var(--text-muted); text-align: center;">-</td>
|
|
<td class="step-merged-cell" style="padding: 14px 10px; font-weight: 600; color: var(--text-muted); text-align: center;">-</td>
|
|
|
<td class="step-merged-cell" style="padding: 14px 10px;">
|
|
<td class="step-merged-cell" style="padding: 14px 10px;">
|
|
|
- <span class="structured-badge" style="background:#f8fafc; color:#64748b; font-weight: 500;">独立片段</span>
|
|
|
|
|
|
|
+ <span class="structured-badge" style="background:#f8fafc; color:#64748b; font-weight: 500;">独立能力</span>
|
|
|
</td>
|
|
</td>
|
|
|
- ${renderFragmentColumns(fragment)}
|
|
|
|
|
|
|
+ ${renderCapabilityColumns(capability)}
|
|
|
</tr>
|
|
</tr>
|
|
|
`;
|
|
`;
|
|
|
});
|
|
});
|