@gct-paas/word 0.1.73-patch.2 → 0.1.73-patch.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,8 @@ export declare function computeImageDisplaySize(natural: ImageSize, opts?: Image
20
20
  * 在目标框内等比缩放(contain),不压缩、不拉伸
21
21
  */
22
22
  export declare function computeContainDisplaySize(natural: ImageSize, box: ImageSize): ImageSize;
23
+ /** 同步取无图签名缓存(布局重建时可避免先闪占位再异步补图) */
24
+ export declare function getCachedSignatureImage(name: string, width?: number, height?: number, time?: number | string): HTMLImageElement | null;
23
25
  /**
24
26
  * 创建无图签名兜底图(用户名 + 电子签名 + 验证日期)
25
27
  * 按字段宽高绘制,显示框设多大,字就按多大排
@@ -25,7 +25,13 @@ export declare class WtblCalculation {
25
25
  */
26
26
  private static processBounded;
27
27
  /**
28
- * 处理 boundedItem 数据
28
+ * 按 itemRegion.id 查找嵌套的数据分组 / 动态关联区域
29
+ * (itemRegion 不在 table.regions 顶层,不能用 findRegionById)
30
+ */
31
+ private static findItemRegionById;
32
+ private static applyBoundsToItemRegion;
33
+ /**
34
+ * 处理 boundedItem 数据(更新父级 bounded 的 itemRegion 边界)
29
35
  */
30
36
  private static processBoundedItem;
31
37
  /**
@@ -33,7 +39,7 @@ export declare class WtblCalculation {
33
39
  */
34
40
  private static processCheckTable;
35
41
  /**
36
- * 处理 dataGroup2D 数据
42
+ * 处理 dataGroup2D 数据(更新检验表 / 二维表上的 itemRegion 边界)
37
43
  */
38
44
  private static processDataGroup2D;
39
45
  }
@@ -9,11 +9,23 @@ export declare class WtblRowColumnOps {
9
9
  /** 仅外表需要做「删除行/列/表时联动删除嵌套表」 */
10
10
  private static detachNestedTablesFromOuterTable;
11
11
  /**
12
- * 新单元格同步引用信息
13
- * refCell: 参考单元格 (above | left)
14
- * nextRefCell: 后参考单元格 (below | right ),如果传入,需要跟 refCell 比对一致后同步
12
+ * 新单元格同步引用信息(mergeId / subTable / subTableItem / header)
13
+ *
14
+ * 必须两侧参考单元格都存在,且对应字段一致,才写入新格。
15
+ * 单侧缺失(表边界、子表外侧空行)不同步,避免检验表等 region
16
+ * 在「上一行/下一行插入」时被错误扩大,进而触发重叠校验误报。
15
17
  */
16
18
  private static syncRefInfo;
19
+ /**
20
+ * 在 insertIndex 处插入一行后,将落在该行及以下的 region / itemRegion 行号整体 +1。
21
+ * 否则仅靠单元格标记回写时,动态关联 itemRegion 若未能匹配 id,边界会留在原行,
22
+ * 设计端字段与背景框就不会随检验表下移。
23
+ */
24
+ private static shiftRegionsForRowInsert;
25
+ /**
26
+ * 在 insertIndex 处插入一列后,将落在该列及右侧的 region / itemRegion 列号整体 +1。
27
+ */
28
+ private static shiftRegionsForColInsert;
17
29
  /**
18
30
  * 在指定行位置插入新行
19
31
  */
@@ -1,6 +1,7 @@
1
1
  import { CheckTableItemInfosPayload, CheckTableRegionRef } from '../types';
2
2
  /**
3
3
  * 按已扫描的检验表 region 并行拉取检验项详情。
4
+ * @param instanceId 真实填报实例 id;设计态 / 模拟填报应传空字符串(默认数据源将跳过请求)
4
5
  * @returns infosMap / countMap(count 至少为 1,用于占位行)
5
6
  */
6
7
  export declare function fetchCheckItemsForRegions(instanceId: string, regions: CheckTableRegionRef[]): Promise<{
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @gct-paas/word v0.1.73-patch.2 */
1
+ /*! @gct-paas/word v0.1.73-patch.3 */
2
2
  import { Fragment, Suspense, Teleport, Transition, TransitionGroup, cloneVNode, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createStaticVNode, createTextVNode, createVNode, defineAsyncComponent, defineComponent, getCurrentInstance, getCurrentScope, guardReactiveProps, h, inject, isRef, isVNode, markRaw, mergeModels, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeMount, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, provide, reactive, readonly, ref, render, renderList, renderSlot, resolveComponent, resolveDynamicComponent, shallowRef, toDisplayString, toRaw, toRef, toValue, unref, useCssVars, useModel, useSlots, vModelText, vShow, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers } from "vue";
3
3
  import FloatingVue, { PopperWrapper } from "floating-vue";
4
4
  import VueKonva from "vue-konva";
@@ -92458,16 +92458,16 @@ async function fetchCustomCheckDsData(customCheckDsItems) {
92458
92458
  return toPayload(await callBizService(CUSTOM_API, { ids: customCheckDsItems.join(",") }));
92459
92459
  }
92460
92460
  async function fetchOneRegionInfo(instanceId, region) {
92461
- if (!instanceId) return EMPTY_INFO;
92462
92461
  const props = region.props ?? {};
92463
92462
  const checkDsType = props.checkDsType;
92464
92463
  const customCheckDsItems = Array.isArray(props.customCheckDsItems) ? props.customCheckDsItems : [];
92465
- const info = checkDsType === CheckDsTypeEnum.CUSTOM ? await fetchCustomCheckDsData(customCheckDsItems) : await fetchCheckDsDataForTable(instanceId);
92464
+ const info = checkDsType === CheckDsTypeEnum.CUSTOM ? await fetchCustomCheckDsData(customCheckDsItems) : instanceId ? await fetchCheckDsDataForTable(instanceId) : EMPTY_INFO;
92466
92465
  for (const item of info.data) delete item.id_;
92467
92466
  return info;
92468
92467
  }
92469
92468
  /**
92470
92469
  * 按已扫描的检验表 region 并行拉取检验项详情。
92470
+ * @param instanceId 真实填报实例 id;设计态 / 模拟填报应传空字符串(默认数据源将跳过请求)
92471
92471
  * @returns infosMap / countMap(count 至少为 1,用于占位行)
92472
92472
  */
92473
92473
  async function fetchCheckItemsForRegions(instanceId, regions) {
@@ -100569,11 +100569,12 @@ var init_BoundedRegion = __esmMin((() => {
100569
100569
  widgetMeta: json.widgetMeta
100570
100570
  });
100571
100571
  if (json.itemRegion) {
100572
- var _json$itemRegion, _json$itemRegion2;
100572
+ var _json$itemRegion, _json$itemRegion2, _json$itemRegion3;
100573
100573
  region.itemRegion = new BoundedItemRegion({
100574
100574
  table,
100575
- start: (_json$itemRegion = json.itemRegion) === null || _json$itemRegion === void 0 ? void 0 : _json$itemRegion.start,
100576
- end: (_json$itemRegion2 = json.itemRegion) === null || _json$itemRegion2 === void 0 ? void 0 : _json$itemRegion2.end,
100575
+ id: (_json$itemRegion = json.itemRegion) === null || _json$itemRegion === void 0 ? void 0 : _json$itemRegion.id,
100576
+ start: (_json$itemRegion2 = json.itemRegion) === null || _json$itemRegion2 === void 0 ? void 0 : _json$itemRegion2.start,
100577
+ end: (_json$itemRegion3 = json.itemRegion) === null || _json$itemRegion3 === void 0 ? void 0 : _json$itemRegion3.end,
100577
100578
  parent: region
100578
100579
  });
100579
100580
  }
@@ -100677,11 +100678,12 @@ var init_LinkSubTableRegion = __esmMin((() => {
100677
100678
  }
100678
100679
  static restoreItemRegion(region, json, table) {
100679
100680
  if (json.itemRegion) {
100680
- var _json$itemRegion, _json$itemRegion2;
100681
+ var _json$itemRegion, _json$itemRegion2, _json$itemRegion3;
100681
100682
  region.itemRegion = new DataGroup2DRegion({
100682
100683
  table,
100683
- start: (_json$itemRegion = json.itemRegion) === null || _json$itemRegion === void 0 ? void 0 : _json$itemRegion.start,
100684
- end: (_json$itemRegion2 = json.itemRegion) === null || _json$itemRegion2 === void 0 ? void 0 : _json$itemRegion2.end,
100684
+ id: (_json$itemRegion = json.itemRegion) === null || _json$itemRegion === void 0 ? void 0 : _json$itemRegion.id,
100685
+ start: (_json$itemRegion2 = json.itemRegion) === null || _json$itemRegion2 === void 0 ? void 0 : _json$itemRegion2.start,
100686
+ end: (_json$itemRegion3 = json.itemRegion) === null || _json$itemRegion3 === void 0 ? void 0 : _json$itemRegion3.end,
100685
100687
  parent: region
100686
100688
  });
100687
100689
  }
@@ -100918,19 +100920,50 @@ var init_RowColumnOps = __esmMin((() => {
100918
100920
  table.collectNestedTables().forEach((nested) => nested.remove());
100919
100921
  }
100920
100922
  /**
100921
- * 新单元格同步引用信息
100922
- * refCell: 参考单元格 (above | left)
100923
- * nextRefCell: 后参考单元格 (below | right ),如果传入,需要跟 refCell 比对一致后同步
100923
+ * 新单元格同步引用信息(mergeId / subTable / subTableItem / header)
100924
+ *
100925
+ * 必须两侧参考单元格都存在,且对应字段一致,才写入新格。
100926
+ * 单侧缺失(表边界、子表外侧空行)不同步,避免检验表等 region
100927
+ * 在「上一行/下一行插入」时被错误扩大,进而触发重叠校验误报。
100924
100928
  */
100925
- static syncRefInfo(newCell, refCell, nextRefCell) {
100929
+ static syncRefInfo(newCell, sideA, sideB) {
100930
+ if (!sideA || !sideB) return;
100926
100931
  WTC_REF_KEYS.forEach((key) => {
100927
- const refValue = refCell[key];
100932
+ const refValue = sideA[key];
100928
100933
  if (!refValue) return;
100929
- if (nextRefCell && JSON.stringify(nextRefCell[key]) !== JSON.stringify(refValue)) return;
100934
+ if (JSON.stringify(sideB[key]) !== JSON.stringify(refValue)) return;
100930
100935
  newCell[key] = refValue;
100931
100936
  });
100932
100937
  }
100933
100938
  /**
100939
+ * 在 insertIndex 处插入一行后,将落在该行及以下的 region / itemRegion 行号整体 +1。
100940
+ * 否则仅靠单元格标记回写时,动态关联 itemRegion 若未能匹配 id,边界会留在原行,
100941
+ * 设计端字段与背景框就不会随检验表下移。
100942
+ */
100943
+ static shiftRegionsForRowInsert(table, insertIndex) {
100944
+ for (const region of table.regions) {
100945
+ if (region.start.row >= insertIndex) region.start.row += 1;
100946
+ if (region.end.row >= insertIndex) region.end.row += 1;
100947
+ const itemRegion = region.itemRegion;
100948
+ if (!itemRegion) continue;
100949
+ if (itemRegion.start.row >= insertIndex) itemRegion.start.row += 1;
100950
+ if (itemRegion.end.row >= insertIndex) itemRegion.end.row += 1;
100951
+ }
100952
+ }
100953
+ /**
100954
+ * 在 insertIndex 处插入一列后,将落在该列及右侧的 region / itemRegion 列号整体 +1。
100955
+ */
100956
+ static shiftRegionsForColInsert(table, insertIndex) {
100957
+ for (const region of table.regions) {
100958
+ if (region.start.col >= insertIndex) region.start.col += 1;
100959
+ if (region.end.col >= insertIndex) region.end.col += 1;
100960
+ const itemRegion = region.itemRegion;
100961
+ if (!itemRegion) continue;
100962
+ if (itemRegion.start.col >= insertIndex) itemRegion.start.col += 1;
100963
+ if (itemRegion.end.col >= insertIndex) itemRegion.end.col += 1;
100964
+ }
100965
+ }
100966
+ /**
100934
100967
  * 在指定行位置插入新行
100935
100968
  */
100936
100969
  static insertRowAt(table, index) {
@@ -100944,6 +100977,7 @@ var init_RowColumnOps = __esmMin((() => {
100944
100977
  this.syncRefInfo(cell, above, below);
100945
100978
  });
100946
100979
  table.insertChildAt(index, newRow);
100980
+ this.shiftRegionsForRowInsert(table, index);
100947
100981
  } });
100948
100982
  }
100949
100983
  /**
@@ -100953,11 +100987,13 @@ var init_RowColumnOps = __esmMin((() => {
100953
100987
  const refRow = table.getChildAt(index);
100954
100988
  if (!refRow) return;
100955
100989
  table.runConsistencyMutation({ mutate: () => {
100990
+ const above = table.rows[index - 1];
100956
100991
  const newRow = Wtr.fromTemplate(table.colWidths || []);
100957
100992
  newRow.children.forEach((cell, cellIndex) => {
100958
- this.syncRefInfo(cell, refRow.cells[cellIndex]);
100993
+ this.syncRefInfo(cell, above === null || above === void 0 ? void 0 : above.cells[cellIndex], refRow.cells[cellIndex]);
100959
100994
  });
100960
100995
  table.insertBefore(refRow, newRow);
100996
+ this.shiftRegionsForRowInsert(table, index);
100961
100997
  } });
100962
100998
  }
100963
100999
  /**
@@ -100967,11 +101003,13 @@ var init_RowColumnOps = __esmMin((() => {
100967
101003
  const refRow = table.getChildAt(index);
100968
101004
  if (!refRow) return;
100969
101005
  table.runConsistencyMutation({ mutate: () => {
101006
+ const below = table.rows[index + 1];
100970
101007
  const newRow = Wtr.fromTemplate(table.colWidths || []);
100971
101008
  newRow.children.forEach((cell, cellIndex) => {
100972
- this.syncRefInfo(cell, refRow.cells[cellIndex]);
101009
+ this.syncRefInfo(cell, refRow.cells[cellIndex], below === null || below === void 0 ? void 0 : below.cells[cellIndex]);
100973
101010
  });
100974
101011
  table.insertAfter(refRow, newRow);
101012
+ this.shiftRegionsForRowInsert(table, index + 1);
100975
101013
  } });
100976
101014
  }
100977
101015
  /**
@@ -100988,6 +101026,7 @@ var init_RowColumnOps = __esmMin((() => {
100988
101026
  this.syncRefInfo(newCell, left, right);
100989
101027
  }
100990
101028
  if (table.colWidths) table.colWidths.splice(index, 0, colWidth);
101029
+ this.shiftRegionsForColInsert(table, index);
100991
101030
  } });
100992
101031
  }
100993
101032
  /**
@@ -100997,13 +101036,15 @@ var init_RowColumnOps = __esmMin((() => {
100997
101036
  table.runConsistencyMutation({ mutate: () => {
100998
101037
  const colWidth = DEFAULT_WIDTH;
100999
101038
  for (const row of table.rows) {
101000
- const refCell = row.cells[index];
101001
- if (!refCell) continue;
101039
+ const right = row.cells[index];
101040
+ if (!right) continue;
101041
+ const left = row.cells[index - 1];
101002
101042
  const newCell = Wtc.fromTemplate(colWidth);
101003
- this.syncRefInfo(newCell, refCell);
101043
+ this.syncRefInfo(newCell, left, right);
101004
101044
  row.insertChildAt(index, newCell);
101005
101045
  }
101006
101046
  if (table.colWidths) table.colWidths.splice(index, 0, colWidth);
101047
+ this.shiftRegionsForColInsert(table, index);
101007
101048
  } });
101008
101049
  }
101009
101050
  /**
@@ -101013,13 +101054,15 @@ var init_RowColumnOps = __esmMin((() => {
101013
101054
  table.runConsistencyMutation({ mutate: () => {
101014
101055
  const colWidth = DEFAULT_WIDTH;
101015
101056
  for (const row of table.rows) {
101016
- const refCell = row.cells[index];
101017
- if (!refCell) continue;
101057
+ const left = row.cells[index];
101058
+ if (!left) continue;
101059
+ const right = row.cells[index + 1];
101018
101060
  const newCell = Wtc.fromTemplate(colWidth);
101019
- this.syncRefInfo(newCell, refCell);
101061
+ this.syncRefInfo(newCell, left, right);
101020
101062
  row.insertChildAt(index + 1, newCell);
101021
101063
  }
101022
101064
  if (table.colWidths) table.colWidths.splice(index + 1, 0, colWidth);
101065
+ this.shiftRegionsForColInsert(table, index + 1);
101023
101066
  } });
101024
101067
  }
101025
101068
  /**
@@ -101590,19 +101633,36 @@ var init_Calculation = __esmMin((() => {
101590
101633
  }
101591
101634
  }
101592
101635
  /**
101593
- * 处理 boundedItem 数据
101636
+ * 按 itemRegion.id 查找嵌套的数据分组 / 动态关联区域
101637
+ * (itemRegion 不在 table.regions 顶层,不能用 findRegionById)
101638
+ */
101639
+ static findItemRegionById(table, itemId) {
101640
+ for (const region of table.regions) {
101641
+ if (region.type === "bounded") {
101642
+ const item = region.itemRegion;
101643
+ if ((item === null || item === void 0 ? void 0 : item.id) === itemId) return item;
101644
+ }
101645
+ if (isLinkSubTableType(region.type)) {
101646
+ const item = region.itemRegion;
101647
+ if ((item === null || item === void 0 ? void 0 : item.id) === itemId) return item;
101648
+ }
101649
+ }
101650
+ }
101651
+ static applyBoundsToItemRegion(itemRegion, bounds) {
101652
+ itemRegion.start.row = bounds.minRow;
101653
+ itemRegion.end.row = bounds.maxRow;
101654
+ itemRegion.start.col = bounds.minCol;
101655
+ itemRegion.end.col = bounds.maxCol;
101656
+ }
101657
+ /**
101658
+ * 处理 boundedItem 数据(更新父级 bounded 的 itemRegion 边界)
101594
101659
  */
101595
101660
  static processBoundedItem(table, boundedItemGroups) {
101596
101661
  for (const [groupId, positions] of boundedItemGroups.entries()) {
101597
101662
  if (positions.length === 0) continue;
101598
- const { minRow, maxRow, minCol, maxCol } = calculateGroupBounds(positions);
101599
- const region = table.findRegionById(groupId);
101600
- if (region && region.type === "bounded") {
101601
- region.start.row = minRow;
101602
- region.end.row = maxRow;
101603
- region.start.col = minCol;
101604
- region.end.col = maxCol;
101605
- }
101663
+ const itemRegion = this.findItemRegionById(table, groupId);
101664
+ if (!itemRegion) continue;
101665
+ this.applyBoundsToItemRegion(itemRegion, calculateGroupBounds(positions));
101606
101666
  }
101607
101667
  }
101608
101668
  /**
@@ -101622,19 +101682,14 @@ var init_Calculation = __esmMin((() => {
101622
101682
  }
101623
101683
  }
101624
101684
  /**
101625
- * 处理 dataGroup2D 数据
101685
+ * 处理 dataGroup2D 数据(更新检验表 / 二维表上的 itemRegion 边界)
101626
101686
  */
101627
101687
  static processDataGroup2D(table, dataGroup2DGroups) {
101628
101688
  for (const [groupId, positions] of dataGroup2DGroups.entries()) {
101629
101689
  if (positions.length === 0) continue;
101630
- const { minRow, maxRow, minCol, maxCol } = calculateGroupBounds(positions);
101631
- const region = table.findRegionById(groupId);
101632
- if (region && isLinkSubTableType(region.type)) {
101633
- region.start.row = minRow;
101634
- region.end.row = maxRow;
101635
- region.start.col = minCol;
101636
- region.end.col = maxCol;
101637
- }
101690
+ const itemRegion = this.findItemRegionById(table, groupId);
101691
+ if (!itemRegion) continue;
101692
+ this.applyBoundsToItemRegion(itemRegion, calculateGroupBounds(positions));
101638
101693
  }
101639
101694
  }
101640
101695
  };
@@ -105483,6 +105538,50 @@ function isTableNested(doc, tableId) {
105483
105538
  return (meta === null || meta === void 0 ? void 0 : meta.component) === BuiltinComponentTypeConst.TableCell;
105484
105539
  });
105485
105540
  }
105541
+ /**
105542
+ * 按合并单元格把选区列范围扩成完整矩形。
105543
+ *
105544
+ * 横向合并只能点到主格(tableCellIndex 为起点列),从上往下拖进合并区时
105545
+ * anchor/focus 往往同为起点列,右侧从格进不了选区。
105546
+ * 需把选中格所属合并区的完整 colspan 扩进 [colFrom, colTo]。
105547
+ */
105548
+ function expandColRangeForMergedCells(doc, tableLines, colFrom, colTo) {
105549
+ let from = colFrom;
105550
+ let to = colTo;
105551
+ for (let guard = 0; guard < 32; guard++) {
105552
+ let expanded = false;
105553
+ for (const line of tableLines) {
105554
+ const colCount = line.nextIds.length;
105555
+ for (let ci = from; ci <= to && ci < colCount; ci++) {
105556
+ const cellId = line.nextIds[ci];
105557
+ if (!cellId) continue;
105558
+ const cell = doc.layoutMapper.getLayoutNodeById(cellId);
105559
+ if (!cell) continue;
105560
+ let spanStart = ci;
105561
+ let spanEnd = ci;
105562
+ if (cell.mergeFromId) {
105563
+ const master = doc.layoutMapper.getLayoutNodeById(cell.mergeFromId);
105564
+ if (!master) continue;
105565
+ spanStart = ci - (cell.mergeRefColOffset ?? 0);
105566
+ spanEnd = spanStart + (master.colspan || 1) - 1;
105567
+ } else if ((cell.colspan || 1) > 1) spanEnd = ci + (cell.colspan || 1) - 1;
105568
+ else continue;
105569
+ const nextFrom = Math.min(from, Math.max(0, spanStart));
105570
+ const nextTo = Math.max(to, Math.min(colCount - 1, spanEnd));
105571
+ if (nextFrom !== from || nextTo !== to) {
105572
+ from = nextFrom;
105573
+ to = nextTo;
105574
+ expanded = true;
105575
+ }
105576
+ }
105577
+ }
105578
+ if (!expanded) break;
105579
+ }
105580
+ return {
105581
+ colFrom: from,
105582
+ colTo: to
105583
+ };
105584
+ }
105486
105585
  function findEnclosingTable(node) {
105487
105586
  let current = node;
105488
105587
  while (current) {
@@ -105685,43 +105784,46 @@ function getSelectLinesInfo(doc, selection, upgrade) {
105685
105784
  }
105686
105785
  }
105687
105786
  const rangeWidgetIds = [];
105688
- scopedSelectedLines.forEach((line) => {
105689
- if (line.type !== "tablerow") return;
105690
- if (tableMode === "cell-range") {
105787
+ if (tableMode === "cell-range") {
105788
+ const tableLines = scopedSelectedLines.filter((line) => line.type === "tablerow");
105789
+ if (tableLines.length > 0) {
105790
+ const firstLine = tableLines[0];
105691
105791
  const startCI = typeof scopedStartCellIndex === "number" ? scopedStartCellIndex : 0;
105692
- const endCI = typeof scopedEndCellIndex === "number" ? scopedEndCellIndex : typeof focusClampToLast === "boolean" ? focusClampToLast ? (line.nextIds.length ?? 1) - 1 : 0 : typeof scopedStartCellIndex === "number" ? scopedStartCellIndex : (line.nextIds.length ?? 1) - 1;
105693
- const colFrom = Math.min(startCI, endCI);
105694
- const colTo = Math.max(startCI, endCI);
105695
- for (let ci = colFrom; ci <= colTo; ci++) {
105792
+ const endCI = typeof scopedEndCellIndex === "number" ? scopedEndCellIndex : typeof focusClampToLast === "boolean" ? focusClampToLast ? (firstLine.nextIds.length ?? 1) - 1 : 0 : typeof scopedStartCellIndex === "number" ? scopedStartCellIndex : (firstLine.nextIds.length ?? 1) - 1;
105793
+ let colFrom = Math.min(startCI, endCI);
105794
+ let colTo = Math.max(startCI, endCI);
105795
+ ({colFrom, colTo} = expandColRangeForMergedCells(doc, tableLines, colFrom, colTo));
105796
+ for (const line of tableLines) for (let ci = colFrom; ci <= colTo; ci++) {
105696
105797
  const cellId = line.nextIds[ci];
105697
105798
  if (cellId) rangeWidgetIds.push(cellId);
105698
105799
  }
105699
- } else if (tableMode === "cell-full") {
105700
- var _start$line4, _end$line3;
105701
- const startCellId = (_start$line4 = start.line) === null || _start$line4 === void 0 ? void 0 : _start$line4.tableCellId;
105702
- const endCellId = (_end$line3 = end.line) === null || _end$line3 === void 0 ? void 0 : _end$line3.tableCellId;
105703
- if (startCellId && startCellId === endCellId) {
105704
- var _start$line5;
105705
- const cell = doc.layoutMapper.getLayoutNodeById(startCellId);
105706
- const table = doc.layoutMapper.getLayoutNodeById((_start$line5 = start.line) === null || _start$line5 === void 0 ? void 0 : _start$line5.tableId);
105707
- if (cell && table) {
105708
- var _start$line6, _start$line7;
105709
- const startRowIdx = (_start$line6 = start.line) === null || _start$line6 === void 0 ? void 0 : _start$line6.tableRowIndex;
105710
- const startColIdx = (_start$line7 = start.line) === null || _start$line7 === void 0 ? void 0 : _start$line7.tableCellIndex;
105711
- const rowspan = cell.rowspan || 1;
105712
- const colspan = cell.colspan || 1;
105713
- table.forEachCell({
105714
- startRowIdx,
105715
- startColIdx,
105716
- endRowIdx: startRowIdx + rowspan - 1,
105717
- endColIdx: startColIdx + colspan - 1,
105718
- callback: (c) => rangeWidgetIds.push(c.id)
105719
- });
105720
- }
105800
+ }
105801
+ } else if (tableMode === "cell-full") {
105802
+ var _start$line4, _end$line3;
105803
+ const startCellId = (_start$line4 = start.line) === null || _start$line4 === void 0 ? void 0 : _start$line4.tableCellId;
105804
+ const endCellId = (_end$line3 = end.line) === null || _end$line3 === void 0 ? void 0 : _end$line3.tableCellId;
105805
+ if (startCellId && startCellId === endCellId) {
105806
+ var _start$line5;
105807
+ const cell = doc.layoutMapper.getLayoutNodeById(startCellId);
105808
+ const table = doc.layoutMapper.getLayoutNodeById((_start$line5 = start.line) === null || _start$line5 === void 0 ? void 0 : _start$line5.tableId);
105809
+ if (cell && table) {
105810
+ var _start$line6, _start$line7;
105811
+ const startRowIdx = (_start$line6 = start.line) === null || _start$line6 === void 0 ? void 0 : _start$line6.tableRowIndex;
105812
+ const startColIdx = (_start$line7 = start.line) === null || _start$line7 === void 0 ? void 0 : _start$line7.tableCellIndex;
105813
+ const rowspan = cell.rowspan || 1;
105814
+ const colspan = cell.colspan || 1;
105815
+ table.forEachCell({
105816
+ startRowIdx,
105817
+ startColIdx,
105818
+ endRowIdx: startRowIdx + rowspan - 1,
105819
+ endColIdx: startColIdx + colspan - 1,
105820
+ callback: (c) => rangeWidgetIds.push(c.id)
105821
+ });
105721
105822
  }
105722
- } else if (tableMode === "mixed") {
105723
- for (const cellId of line.nextIds) if (cellId) rangeWidgetIds.push(cellId);
105724
105823
  }
105824
+ } else if (tableMode === "mixed") scopedSelectedLines.forEach((line) => {
105825
+ if (line.type !== "tablerow") return;
105826
+ for (const cellId of line.nextIds) if (cellId) rangeWidgetIds.push(cellId);
105725
105827
  });
105726
105828
  return {
105727
105829
  normalized,
@@ -109533,6 +109635,34 @@ var init_InsertText = __esmMin((() => {
109533
109635
  //#endregion
109534
109636
  //#region src/core/command/commands/MergeCells.ts
109535
109637
  var MergeCells_exports = /* @__PURE__ */ __exportAll({ MergeCells: () => MergeCells });
109638
+ /**
109639
+ * 选区只包含「可视主格」时,补齐其 merge 区域内的从格。
109640
+ *
109641
+ * 横向合并后从格不渲染、不可点选,跨行再合并时选区往往只有各行主格(同一列)。
109642
+ * 若不展开,会把已有 colspan/rowspan 误判成部分重叠。
109643
+ */
109644
+ function expandSelectionToMergeRegions(table, selectedCells) {
109645
+ var _table$rows$;
109646
+ const selectedIds = new Set(selectedCells.map((cell) => cell.id));
109647
+ const mergeIds = new Set(selectedCells.map((cell) => cell.mergeId).filter((id) => !!id));
109648
+ const expanded = [];
109649
+ const colCount = ((_table$rows$ = table.rows[0]) === null || _table$rows$ === void 0 ? void 0 : _table$rows$.cells.length) ?? 0;
109650
+ if (colCount === 0 || table.rows.length === 0) return expanded;
109651
+ table.forEachCell({
109652
+ startRowIdx: 0,
109653
+ endRowIdx: table.rows.length - 1,
109654
+ startColIdx: 0,
109655
+ endColIdx: colCount - 1,
109656
+ callback: (cell, row, col) => {
109657
+ if (selectedIds.has(cell.id) || cell.mergeId && mergeIds.has(cell.mergeId)) expanded.push({
109658
+ cell,
109659
+ row,
109660
+ col
109661
+ });
109662
+ }
109663
+ });
109664
+ return expanded;
109665
+ }
109536
109666
  var MergeCells;
109537
109667
  var init_MergeCells = __esmMin((() => {
109538
109668
  init_CommandBase();
@@ -109550,66 +109680,41 @@ var init_MergeCells = __esmMin((() => {
109550
109680
  const selectedCells = models.map(({ model }) => model);
109551
109681
  const table = (_selectedCells$ = selectedCells[0]) === null || _selectedCells$ === void 0 ? void 0 : _selectedCells$.table;
109552
109682
  if (!table) return null;
109553
- const positions = selectedCells.map((cell) => {
109683
+ if (selectedCells.map((cell) => {
109554
109684
  var _cell$parent;
109555
109685
  return {
109556
109686
  cell,
109557
109687
  row: ((_cell$parent = cell.parent) === null || _cell$parent === void 0 ? void 0 : _cell$parent.getCurrentIndex()) ?? -1,
109558
109688
  col: cell.getCurrentIndex() ?? -1
109559
109689
  };
109560
- });
109561
- if (positions.some(({ row, col }) => row < 0 || col < 0)) throw new Error("Invalid table selection");
109562
- const minRow = Math.min(...positions.map((p) => p.row));
109563
- const maxRow = Math.max(...positions.map((p) => p.row));
109564
- const minCol = Math.min(...positions.map((p) => p.col));
109565
- const maxCol = Math.max(...positions.map((p) => p.col));
109566
- const rowSpan = maxRow - minRow + 1;
109567
- const colSpan = maxCol - minCol + 1;
109568
- const expectedCount = rowSpan * colSpan;
109569
- const selectedIds = new Set(selectedCells.map((cell) => cell.id));
109690
+ }).some(({ row, col }) => row < 0 || col < 0)) throw new Error("Invalid table selection");
109691
+ let minRow = 0;
109692
+ let maxRow = 0;
109693
+ let minCol = 0;
109694
+ let maxCol = 0;
109570
109695
  let topLeftCell;
109571
109696
  table.runConsistencyMutation({
109572
109697
  validate: () => {
109573
- if (selectedIds.size !== expectedCount) throw new Error("必须是完整矩形");
109574
- const mergeRoots = /* @__PURE__ */ new Map();
109698
+ const expanded = expandSelectionToMergeRegions(table, selectedCells);
109699
+ if (expanded.length === 0) throw new Error("Invalid table selection");
109700
+ minRow = Math.min(...expanded.map((p) => p.row));
109701
+ maxRow = Math.max(...expanded.map((p) => p.row));
109702
+ minCol = Math.min(...expanded.map((p) => p.col));
109703
+ maxCol = Math.max(...expanded.map((p) => p.col));
109704
+ const expectedCount = (maxRow - minRow + 1) * (maxCol - minCol + 1);
109705
+ const expandedIds = new Set(expanded.map((p) => p.cell.id));
109706
+ if (expandedIds.size !== expectedCount) throw new Error("必须是完整矩形");
109575
109707
  for (let row = minRow; row <= maxRow; row++) for (let col = minCol; col <= maxCol; col++) {
109576
109708
  var _table$rows$row;
109577
109709
  const cell = (_table$rows$row = table.rows[row]) === null || _table$rows$row === void 0 ? void 0 : _table$rows$row.cells[col];
109578
- if (!cell || !selectedIds.has(cell.id)) throw new Error("Merge requires a complete rectangle selection");
109579
- if (!cell.mergeId) continue;
109580
- if (mergeRoots.has(cell.mergeId)) continue;
109581
- if (cell.isMergeStart) {
109582
- mergeRoots.set(cell.mergeId, cell);
109583
- continue;
109584
- }
109585
- let root;
109586
- table.forEachCell({
109587
- startRowIdx: 0,
109588
- endRowIdx: table.children.length - 1,
109589
- startColIdx: 0,
109590
- endColIdx: table.rows[0].cells.length - 1,
109591
- filter: (c) => c.id === cell.mergeId,
109592
- callback: (c) => {
109593
- root = c;
109594
- }
109595
- });
109596
- if (root) mergeRoots.set(root.mergeId, root);
109597
- }
109598
- for (const root of mergeRoots.values()) {
109599
- const rRoot = root.parent.getCurrentIndex();
109600
- const cRoot = root.getCurrentIndex();
109601
- const rs = root.rowspan || 1;
109602
- const cs = root.colspan || 1;
109603
- const endRow = rRoot + rs - 1;
109604
- const endCol = cRoot + cs - 1;
109605
- if (rRoot < minRow || endRow > maxRow || cRoot < minCol || endCol > maxCol) throw new Error("Cannot merge: selection partially overlaps an existing merged region");
109710
+ if (!cell || !expandedIds.has(cell.id)) throw new Error("Merge requires a complete rectangle selection");
109606
109711
  }
109607
109712
  },
109608
109713
  mutate: () => {
109609
109714
  var _table$rows$minRow;
109610
109715
  topLeftCell = (_table$rows$minRow = table.rows[minRow]) === null || _table$rows$minRow === void 0 ? void 0 : _table$rows$minRow.cells[minCol];
109611
109716
  if (!topLeftCell) throw new Error("Cannot locate top-left cell for merge");
109612
- topLeftCell.merge(rowSpan, colSpan, { skipConsistency: true });
109717
+ topLeftCell.merge(maxRow - minRow + 1, maxCol - minCol + 1, { skipConsistency: true });
109613
109718
  }
109614
109719
  });
109615
109720
  const mapper = this.doc.layoutMapper;
@@ -125072,7 +125177,7 @@ async function initializeDocumentEngine(props, payload, result) {
125072
125177
  loadSubModels: true
125073
125178
  });
125074
125179
  const cloneRuntimeJson = cloneDeep(JSON.parse(requestInfo.runtimeJson || "{}"));
125075
- const { runtimeJson: runtimeJsonForModel, infosMap, regions: checkTableRegions } = await prepareCheckTableRuntimeJson(fillModeType === DocModeTypeConst.Edit ? "" : id, cloneRuntimeJson);
125180
+ const { runtimeJson: runtimeJsonForModel, infosMap, regions: checkTableRegions } = await prepareCheckTableRuntimeJson(fillModeType !== DocModeTypeConst.Edit && payload.factoryType === "instance" ? id : "", cloneRuntimeJson);
125076
125181
  const docModel = ModelConverter.toModel(runtimeJsonForModel);
125077
125182
  const templateId = result.tid.split(":")[1];
125078
125183
  await syncMaterialConsumeTableBomInfo(templateId, docModel);
@@ -130347,22 +130452,48 @@ function loadDataUrlAsImage(dataUrl) {
130347
130452
  img.onload = () => resolve(img);
130348
130453
  });
130349
130454
  }
130455
+ function buildSignatureCacheKey(name, width, height, time) {
130456
+ return `${name}\0${width}x${height}\0${time ?? ""}`;
130457
+ }
130458
+ /** 同步取无图签名缓存(布局重建时可避免先闪占位再异步补图) */
130459
+ function getCachedSignatureImage(name, width = 180, height = 102, time) {
130460
+ const w = Math.max(1, Math.round(width));
130461
+ const h = Math.max(1, Math.round(height));
130462
+ return signatureImageCache.get(buildSignatureCacheKey(name, w, h, time)) ?? null;
130463
+ }
130350
130464
  /**
130351
130465
  * 创建无图签名兜底图(用户名 + 电子签名 + 验证日期)
130352
130466
  * 按字段宽高绘制,显示框设多大,字就按多大排
130353
130467
  */
130354
130468
  function createSignatureImageDataUrl(name, width = 180, height = 102, time) {
130355
- return createFormSignFallbackImage(name, Math.max(1, Math.round(width)), Math.max(1, Math.round(height)), time);
130469
+ const w = Math.max(1, Math.round(width));
130470
+ const h = Math.max(1, Math.round(height));
130471
+ const key = buildSignatureCacheKey(name, w, h, time);
130472
+ const cached = signatureDataUrlCache.get(key);
130473
+ if (cached) return cached;
130474
+ const dataUrl = createFormSignFallbackImage(name, w, h, time);
130475
+ signatureDataUrlCache.set(key, dataUrl);
130476
+ return dataUrl;
130356
130477
  }
130357
130478
  function createSignatureImage(name, width = 180, height = 102, time) {
130358
- return loadDataUrlAsImage(createSignatureImageDataUrl(name, width, height, time));
130479
+ const w = Math.max(1, Math.round(width));
130480
+ const h = Math.max(1, Math.round(height));
130481
+ const key = buildSignatureCacheKey(name, w, h, time);
130482
+ const cached = signatureImageCache.get(key);
130483
+ if (cached) return Promise.resolve(cached);
130484
+ return loadDataUrlAsImage(createSignatureImageDataUrl(name, w, h, time)).then((img) => {
130485
+ signatureImageCache.set(key, img);
130486
+ return img;
130487
+ });
130359
130488
  }
130360
- var SIGN_CANVAS_BASE_WIDTH, FALLBACK_SIGN_DPR, ELECTRONIC_SIGNATURE_LABEL, DATE_LABEL;
130489
+ var SIGN_CANVAS_BASE_WIDTH, FALLBACK_SIGN_DPR, ELECTRONIC_SIGNATURE_LABEL, DATE_LABEL, signatureImageCache, signatureDataUrlCache;
130361
130490
  var init_image_size_util = __esmMin((() => {
130362
130491
  SIGN_CANVAS_BASE_WIDTH = 240;
130363
130492
  FALLBACK_SIGN_DPR = 2;
130364
130493
  ELECTRONIC_SIGNATURE_LABEL = "电子签名";
130365
130494
  DATE_LABEL = "日期";
130495
+ signatureImageCache = /* @__PURE__ */ new Map();
130496
+ signatureDataUrlCache = /* @__PURE__ */ new Map();
130366
130497
  }));
130367
130498
  //#endregion
130368
130499
  //#region src/runtime/renderer/dialogs/signature/logic.ts
@@ -144518,9 +144649,24 @@ var gct_signature_render_vue_vue_type_script_setup_true_name_gct_signature_rende
144518
144649
  height: imageHeight.value ?? 102,
144519
144650
  fill: "#f3f3f3"
144520
144651
  }));
144652
+ function applyImage(img) {
144653
+ natural.value = {
144654
+ width: img.naturalWidth,
144655
+ height: img.naturalHeight
144656
+ };
144657
+ display.value = computeContainDisplaySize(natural.value, {
144658
+ width: imageWidth.value,
144659
+ height: imageHeight.value
144660
+ });
144661
+ imgRef.value = img;
144662
+ }
144521
144663
  async function loadImage() {
144522
144664
  const { src, signature, signTime } = props.widget;
144523
- if (signature) return await createSignatureImage(signature, imageWidth.value, imageHeight.value, signTime);
144665
+ if (signature) {
144666
+ const cached = getCachedSignatureImage(signature, imageWidth.value, imageHeight.value, signTime);
144667
+ if (cached) return cached;
144668
+ return await createSignatureImage(signature, imageWidth.value, imageHeight.value, signTime);
144669
+ }
144524
144670
  if (src) return await AssetHelper.loadImage(src);
144525
144671
  return null;
144526
144672
  }
@@ -144531,17 +144677,16 @@ var gct_signature_render_vue_vue_type_script_setup_true_name_gct_signature_rende
144531
144677
  imageWidth.value,
144532
144678
  imageHeight.value
144533
144679
  ], async () => {
144680
+ if (props.widget.signature) {
144681
+ const cached = getCachedSignatureImage(props.widget.signature, imageWidth.value, imageHeight.value, props.widget.signTime);
144682
+ if (cached) {
144683
+ applyImage(cached);
144684
+ return;
144685
+ }
144686
+ }
144534
144687
  const img = await loadImage();
144535
144688
  if (!img) return;
144536
- natural.value = {
144537
- width: img.naturalWidth,
144538
- height: img.naturalHeight
144539
- };
144540
- display.value = computeContainDisplaySize(natural.value, {
144541
- width: imageWidth.value,
144542
- height: imageHeight.value
144543
- });
144544
- imgRef.value = img;
144689
+ applyImage(img);
144545
144690
  }, { immediate: true });
144546
144691
  const imageConfig = computed(() => ({
144547
144692
  x: (imageWidth.value - display.value.width) / 2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gct-paas/word",
3
- "version": "0.1.73-patch.2",
3
+ "version": "0.1.73-patch.3",
4
4
  "description": "GCT 在线 word",
5
5
  "keywords": [
6
6
  "vue",