|
|
@@ -1,5 +1,8 @@
|
|
|
import * as cornerstone from '@cornerstonejs/core';
|
|
|
import * as cornerstoneTools from '@cornerstonejs/tools';
|
|
|
+import { eventTarget } from '@cornerstonejs/core';
|
|
|
+import store from '@/states/store';
|
|
|
+import { clearMeasurementAction } from '@/states/view/measurementPanelSlice';
|
|
|
import TibialPlateauAngleTool from '@/components/measures/TibialPlateauAngleTool';
|
|
|
import DARAMeasurementTool from '@/components/measures/DARAMeasurementTool';
|
|
|
import HipDIMeasurementTool from '@/components/measures/HipDIMeasurementTool';
|
|
|
@@ -37,6 +40,118 @@ const { MouseBindings } = csToolsEnums;
|
|
|
* 统一管理所有测量相关的工具操作
|
|
|
*/
|
|
|
export class MeasurementToolManager {
|
|
|
+ /**
|
|
|
+ * 一次性测量工具列表 - 这些工具在绘制完成后会自动停用
|
|
|
+ */
|
|
|
+ private static readonly ONE_TIME_TOOLS = new Set([
|
|
|
+ 'Length',
|
|
|
+ 'Angle',
|
|
|
+ ]);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 跟踪哪些工具处于一次性模式
|
|
|
+ */
|
|
|
+ private static oneTimeModes = new Map<string, string>();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查工具是否为一次性工具
|
|
|
+ */
|
|
|
+ static isOneTimeTool(toolName: string): boolean {
|
|
|
+ return this.ONE_TIME_TOOLS.has(toolName);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置工具为一次性模式
|
|
|
+ */
|
|
|
+ private static setOneTimeMode(viewportId: string, toolName: string): void {
|
|
|
+ const key = `${viewportId}-${toolName}`;
|
|
|
+ this.oneTimeModes.set(key, toolName);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查工具是否处于一次性模式
|
|
|
+ */
|
|
|
+ private static isInOneTimeMode(viewportId: string, toolName: string): boolean {
|
|
|
+ const key = `${viewportId}-${toolName}`;
|
|
|
+ return this.oneTimeModes.has(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清除工具的一次性模式
|
|
|
+ */
|
|
|
+ private static clearOneTimeMode(viewportId: string, toolName: string): void {
|
|
|
+ const key = `${viewportId}-${toolName}`;
|
|
|
+ this.oneTimeModes.delete(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化一次性模式监听器
|
|
|
+ */
|
|
|
+ static initializeOneTimeMode(): void {
|
|
|
+ // 防止重复初始化
|
|
|
+ if ((this as any).initialized) return;
|
|
|
+
|
|
|
+ // 监听 annotation completed 事件
|
|
|
+ eventTarget.addEventListener(
|
|
|
+ cornerstoneTools.Enums.Events.ANNOTATION_COMPLETED,
|
|
|
+ (evt: any) => {
|
|
|
+ const { annotation } = evt.detail;
|
|
|
+ const toolName = annotation?.metadata?.toolName;
|
|
|
+
|
|
|
+ if (toolName && this.isOneTimeTool(toolName)) {
|
|
|
+ // 查找工具所在的 viewport
|
|
|
+ const viewports = cornerstone.getEnabledElements();
|
|
|
+ for (const enabledElement of viewports) {
|
|
|
+ const viewportId = enabledElement.viewport.id ||
|
|
|
+ enabledElement.viewport.element?.id;
|
|
|
+ if (viewportId && this.isInOneTimeMode(viewportId, toolName)) {
|
|
|
+ // 自动停用工具
|
|
|
+ this.deactivateToolByName(viewportId, toolName);
|
|
|
+ this.clearOneTimeMode(viewportId, toolName);
|
|
|
+
|
|
|
+ // 清除 Redux 测量状态
|
|
|
+ store.dispatch(clearMeasurementAction());
|
|
|
+
|
|
|
+ console.log(`[MeasurementToolManager] Auto-deactivated one-time tool: ${toolName} for viewport: ${viewportId}`);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ (this as any).initialized = true;
|
|
|
+ console.log('[MeasurementToolManager] One-time mode initialized');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据工具名称停用工具
|
|
|
+ */
|
|
|
+ private static deactivateToolByName(viewportId: string, toolName: string): boolean {
|
|
|
+ const toolGroup = this.getToolGroup(viewportId);
|
|
|
+ if (!toolGroup) return false;
|
|
|
+
|
|
|
+ try {
|
|
|
+ toolGroup.setToolPassive(toolName, { removeAllBindings: true });
|
|
|
+ console.log(`[MeasurementToolManager] Tool ${toolName} deactivated for viewport: ${viewportId}`);
|
|
|
+
|
|
|
+ // 恢复viewport的默认光标
|
|
|
+ try {
|
|
|
+ const enabledElement = cornerstone.getEnabledElementByViewportId(viewportId);
|
|
|
+ if (enabledElement?.viewport?.element) {
|
|
|
+ enabledElement.viewport.element.style.cursor = 'default';
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.warn(`[MeasurementToolManager] Failed to reset cursor for viewport: ${viewportId}`, error);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`[MeasurementToolManager] Error deactivating tool ${toolName}:`, error);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 根据 viewportId 获取对应的工具组
|
|
|
*/
|
|
|
@@ -76,6 +191,9 @@ export class MeasurementToolManager {
|
|
|
bindings: [{ mouseButton: MouseBindings.Primary }],
|
|
|
});
|
|
|
|
|
|
+ // 设置一次性模式
|
|
|
+ this.setOneTimeMode(viewportId, LengthTool.toolName);
|
|
|
+
|
|
|
console.log(
|
|
|
`[MeasurementToolManager] Length tool activated for viewport: ${viewportId}`
|
|
|
);
|
|
|
@@ -169,6 +287,9 @@ export class MeasurementToolManager {
|
|
|
bindings: [{ mouseButton: MouseBindings.Primary }],
|
|
|
});
|
|
|
|
|
|
+ // 设置一次性模式
|
|
|
+ this.setOneTimeMode(viewportId, AngleTool.toolName);
|
|
|
+
|
|
|
console.log(
|
|
|
`[MeasurementToolManager] Angle tool activated for viewport: ${viewportId}`
|
|
|
);
|
|
|
@@ -530,6 +651,9 @@ export class MeasurementToolManager {
|
|
|
// 注解创建失败不影响工具激活
|
|
|
}
|
|
|
|
|
|
+ // 设置一次性模式
|
|
|
+ this.setOneTimeMode(viewportId, TibialPlateauAngleTool.toolName);
|
|
|
+
|
|
|
console.log(
|
|
|
`[MeasurementToolManager] TibialPlateauAngle tool activated for viewport: ${viewportId}`
|
|
|
);
|