刘光辉
13 小时以前 0dfe84494048ce27ba8449831782128412d3eb13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { Disposable, ICommandService, Inject, IUniverInstanceService, UniverInstanceType } from '@univerjs/core';
import { IDrawingManagerService } from '@univerjs/drawing';
import { DeviceInputEventType, IRenderManagerService } from '@univerjs/engine-render';
import { SheetsSelectionsService } from '@univerjs/sheets';
import { SheetCanvasFloatDomManagerService } from '@univerjs/sheets-drawing-ui';
import { attachRangeWithCoord, SheetSkeletonManagerService } from '@univerjs/sheets-ui';
 
import { DefaultFloatEchartHeight, DefaultFloatEchartOptions, DefaultFloatEchartWidth, JnpfCommandIds, JnpfUniverFloatEchartKey } from '../utils/define';
import { buildUUID } from '../utils/uuid';
 
const regex = /^JnpfUniverFloat(.*?)Echart$/; // 正则表达式匹配 JnpfUniver 和 Echart
 
export class JnpfSheetsFloatEchartService extends Disposable {
  private _focusDrawingId: null | string = null;
  private _piniaStoreId: null | string = null;
 
  private readonly defaultPosition = {
    endX: DefaultFloatEchartWidth,
    endY: DefaultFloatEchartHeight,
    startX: 100,
    startY: 100,
  };
 
  constructor(
    @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService,
    @ICommandService private readonly _commandService: ICommandService,
    @IRenderManagerService private readonly _renderManagerService: IRenderManagerService,
    @IDrawingManagerService private readonly _drawingManagerService: IDrawingManagerService,
    @Inject(SheetCanvasFloatDomManagerService) private readonly _sheetCanvasFloatDomManagerService: SheetCanvasFloatDomManagerService,
    @Inject(SheetsSelectionsService) private readonly _selectionManagerService: SheetsSelectionsService,
  ) {
    super();
 
    this._subscribeToFocusEvents();
  }
 
  // 清空焦点对象的id
  public clearFocusDrawingId() {
    if (!this._focusDrawingId) {
      return;
    }
 
    this._focusDrawingId = null;
  }
 
  // 创建并插入图表DOM
  public insertFloatEchart(componentKey: string) {
    this._commandService
      .executeCommand('sheet.operation.set-cell-edit-visible', {
        _eventType: DeviceInputEventType.PointerUp,
        visible: false,
      })
      .then();
 
    const initPosition = this._calculateInitPosition();
    const domId = `echart_${buildUUID()}`;
 
    const addResult = this._sheetCanvasFloatDomManagerService?.addFloatDomToPosition({
      allowTransform: true,
      componentKey: JnpfUniverFloatEchartKey,
      initPosition,
      data: {
        id: domId,
        piniaStoreId: this._piniaStoreId,
      },
    });
 
    if (!addResult) {
      return;
    }
 
    const type = componentKey?.replace(regex, '$1');
    const echartType = type ? type.charAt(0)?.toLowerCase() + type.slice(1) : undefined;
 
    const newParams = {
      domId,
      drawingId: addResult.id,
      echartType,
      option: JSON.parse(JSON.stringify(DefaultFloatEchartOptions?.[echartType as keyof typeof DefaultFloatEchartOptions])),
    };
    // 自定义命令出来,告知相关的信息
    this._commandService.executeCommand(JnpfCommandIds?.insertedFloatEchart, newParams).then();
  }
 
  // 存入store的id
  public savePiniaStoreId(data: string) {
    this._piniaStoreId = data;
  }
 
  // 计算初始位置
  private _calculateInitPosition() {
    // 获取当前单元格数据
    const unit = this._univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_SHEET);
    if (!unit) {
      console.warn('警告:未找到单元。使用默认位置 (100, 100)。');
      return this.defaultPosition;
    }
 
    const unitId = unit.getUnitId();
    const currentSelections = this._selectionManagerService.getCurrentSelections();
    const firstSelection = currentSelections?.[0];
    if (!firstSelection?.range) {
      console.warn('警告:未找到选择范围。使用默认位置 (100, 100)。');
      return this.defaultPosition;
    }
 
    // 获取当前表格骨架信息
    const sheetSkeletonService = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService);
    const currentSkeleton = sheetSkeletonService?.getCurrent()?.skeleton;
    if (!currentSkeleton) {
      console.warn('警告:未找到骨架。使用默认位置 (100, 100)。');
      return this.defaultPosition;
    }
 
    // 解构表格尺寸信息
    const { columnHeaderHeight = 0, columnTotalWidth = 0, rowHeaderWidth = 0, rowTotalHeight = 0 } = currentSkeleton;
    const columnScreenTotalWidth = columnTotalWidth + rowHeaderWidth;
    const columnScreenTotalHeight = rowTotalHeight + columnHeaderHeight;
 
    // 获取范围信息并计算坐标
    const rangeInfo = attachRangeWithCoord(currentSkeleton, firstSelection.range) || {
      startX: 0,
      startY: 0,
    };
    const { startX: rangeStartX, startY: rangeStartY } = rangeInfo;
 
    // 计算图表的边界坐标
    const startX = Math.min(rangeStartX + DefaultFloatEchartWidth, columnScreenTotalWidth) - DefaultFloatEchartWidth;
    const endX = Math.min(rangeStartX + DefaultFloatEchartWidth, columnScreenTotalWidth);
    const startY = Math.min(rangeStartY + DefaultFloatEchartHeight, columnScreenTotalHeight) - DefaultFloatEchartHeight;
    const endY = Math.min(rangeStartY + DefaultFloatEchartHeight, columnScreenTotalHeight);
 
    return { endX, endY, startX, startY };
  }
 
  // 订阅图表的焦点事件
  private _subscribeToFocusEvents() {
    this.disposeWithMe(
      this._drawingManagerService.focus$.subscribe(params => {
        if (params && params?.length) {
          const firstParam = (params?.[0] ?? {}) as any;
          const { componentKey, drawingId } = firstParam;
 
          if (drawingId !== this._focusDrawingId && componentKey === JnpfUniverFloatEchartKey) {
            this._focusDrawingId = drawingId;
 
            this._commandService?.executeCommand(JnpfCommandIds.focusFloatEchart, firstParam);
          }
        }
      }),
    );
  }
}