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

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.
Files changed (34) hide show
  1. package/dist/core/command/commands/InsertTable.d.ts +4 -0
  2. package/dist/core/constants/index.d.ts +1 -0
  3. package/dist/core/constants/table.d.ts +11 -0
  4. package/dist/core/cursor/logic/getSelectionRects.d.ts +15 -2
  5. package/dist/core/cursor/logic/index.d.ts +2 -1
  6. package/dist/core/cursor/logic/selectionAnalyzer.d.ts +31 -6
  7. package/dist/core/event/types.d.ts +1 -1
  8. package/dist/core/index.d.ts +1 -1
  9. package/dist/core/interaction/InteractionController.d.ts +11 -0
  10. package/dist/core/interaction/types.d.ts +8 -0
  11. package/dist/core/interaction/useInteraction.d.ts +6 -0
  12. package/dist/core/layout/LayoutManager.d.ts +5 -1
  13. package/dist/core/layout/providers/TableInfoProvider.d.ts +2 -2
  14. package/dist/core/layout/table/split-table.d.ts +10 -0
  15. package/dist/core/layout/types/index.d.ts +2 -0
  16. package/dist/core/model/document/Wbody.d.ts +4 -0
  17. package/dist/core/model/document/Wtbl/RowColumnOps.d.ts +9 -0
  18. package/dist/core/model/document/Wtbl/Serialization.d.ts +26 -1
  19. package/dist/core/model/document/Wtbl.d.ts +31 -3
  20. package/dist/core/model/document/Wtc.d.ts +13 -2
  21. package/dist/core/model/document/Wtr.d.ts +2 -1
  22. package/dist/core/model/document/index.d.ts +1 -0
  23. package/dist/core/model/document/utils/ensure-paragraphs-around-tables.d.ts +18 -0
  24. package/dist/core/model/templates/tableCell.template.d.ts +2 -0
  25. package/dist/core/view/Table.d.ts +13 -0
  26. package/dist/core/view/TableCell.d.ts +2 -1
  27. package/dist/domain/table/design/validate-nested-table-region.d.ts +31 -0
  28. package/dist/domain/table/design/validate-table-selection.d.ts +8 -0
  29. package/dist/domain/table/index.d.ts +1 -0
  30. package/dist/index.es.js +2275 -1299
  31. package/dist/runtime/canvas/table/table-design.vue.d.ts +1 -0
  32. package/dist/runtime/canvas/table/utils/useTableSelection.d.ts +6 -0
  33. package/dist/word.css +66 -66
  34. package/package.json +1 -1
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @gct-paas/word v0.1.73-patch.1 */
1
+ /*! @gct-paas/word v0.1.73-patch.2 */
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";
@@ -5725,7 +5725,7 @@ var init_table_vue_vue_type_style_index_0_scoped_d4d03402_lang = __esmMin((() =>
5725
5725
  //#endregion
5726
5726
  //#region src/base/table/src/table.vue
5727
5727
  var table_default$1;
5728
- var init_table$3 = __esmMin((() => {
5728
+ var init_table$4 = __esmMin((() => {
5729
5729
  init_table_vue_vue_type_script_setup_true_lang();
5730
5730
  init_table_vue_vue_type_script_setup_true_lang();
5731
5731
  init_table_vue_vue_type_style_index_0_scoped_d4d03402_lang();
@@ -5734,8 +5734,8 @@ var init_table$3 = __esmMin((() => {
5734
5734
  }));
5735
5735
  //#endregion
5736
5736
  //#region src/base/table/index.ts
5737
- var init_table$2 = __esmMin((() => {
5738
- init_table$3();
5737
+ var init_table$3 = __esmMin((() => {
5738
+ init_table$4();
5739
5739
  }));
5740
5740
  //#endregion
5741
5741
  //#region src/base/tooltip/src/tooltip.vue?vue&type=script&lang.ts
@@ -8915,7 +8915,7 @@ var init_base$2 = __esmMin((() => {
8915
8915
  init_select();
8916
8916
  init_slider();
8917
8917
  init_switch();
8918
- init_table$2();
8918
+ init_table$3();
8919
8919
  init_tooltip();
8920
8920
  init_tree();
8921
8921
  init_tree_select();
@@ -9159,11 +9159,275 @@ var init_paper = __esmMin((() => {
9159
9159
  DEFAULT_TEXT_COLOR = "black";
9160
9160
  }));
9161
9161
  //#endregion
9162
+ //#region src/core/layout/shared/unit-converter.ts
9163
+ var UnitConverter;
9164
+ var init_unit_converter = __esmMin((() => {
9165
+ init_defineProperty();
9166
+ UnitConverter = class UnitConverter {
9167
+ /**
9168
+ * 将 twips 转换为像素
9169
+ * @param twips Twips 值
9170
+ * @param dpi 屏幕 DPI(默认 96)
9171
+ * @returns 像素值
9172
+ */
9173
+ static twipToPixel(twips, dpi = UnitConverter.DEFAULT_DPI) {
9174
+ return Math.round(twips * dpi / UnitConverter.DXA_PER_INCH);
9175
+ }
9176
+ /**
9177
+ * 将 twips 转换为cm
9178
+ * @param twips Twips 值
9179
+ * @returns cm
9180
+ */
9181
+ static twipToCm(twip) {
9182
+ const cm = twip / UnitConverter.DXA_PER_INCH * UnitConverter.INCH_TO_CM;
9183
+ return Math.ceil(cm * 100) / 100;
9184
+ }
9185
+ static twipToMm(twip) {
9186
+ return this.twipToCm(twip) * 10;
9187
+ }
9188
+ /**
9189
+ * 将 cm 转换为twips
9190
+ * @param cm cm 值
9191
+ * @returns Twips 值
9192
+ */
9193
+ static cmToTwip(cm) {
9194
+ return cm / UnitConverter.INCH_TO_CM * UnitConverter.DXA_PER_INCH;
9195
+ }
9196
+ static mmToTwip(mm) {
9197
+ return this.cmToTwip(mm / 10);
9198
+ }
9199
+ /**
9200
+ * 将像素转换为 twips
9201
+ * @param pixel 像素值
9202
+ * @param dpi 屏幕 DPI(默认 96)
9203
+ * @returns Twips 值
9204
+ * @example
9205
+ * UnitConverter.pixelToTwip(96) // 1440
9206
+ */
9207
+ static pixelToTwip(pixel, dpi = UnitConverter.DEFAULT_DPI) {
9208
+ return Math.round(pixel * UnitConverter.DXA_PER_INCH / dpi);
9209
+ }
9210
+ /**
9211
+ * 将 DXA (twips) 转换为像素
9212
+ * @param dxa DXA 值
9213
+ * @param dpi 屏幕 DPI(默认 96)
9214
+ * @returns 像素值
9215
+ * @example
9216
+ * UnitConverter.dxaToPixel(1440) // 96
9217
+ */
9218
+ static dxaToPixel(dxa, dpi = UnitConverter.DEFAULT_DPI) {
9219
+ return Math.round(dxa * dpi / UnitConverter.DXA_PER_INCH);
9220
+ }
9221
+ /**
9222
+ * 将像素转换为 DXA (twips)
9223
+ * @param pixel 像素值
9224
+ * @param dpi 屏幕 DPI(默认 96)
9225
+ * @returns DXA 值
9226
+ * @example
9227
+ * UnitConverter.pixelToDxa(96) // 1440
9228
+ */
9229
+ static pixelToDxa(pixel, dpi = UnitConverter.DEFAULT_DPI) {
9230
+ return Math.round(pixel * UnitConverter.DXA_PER_INCH / dpi);
9231
+ }
9232
+ /**
9233
+ * 将 EMU (English Metric Units) 转换为像素
9234
+ * @param emu EMU 值
9235
+ * @param dpi 屏幕 DPI(默认 96)
9236
+ * @returns 像素值
9237
+ * @example
9238
+ * UnitConverter.emuToPixel(914400) // 96
9239
+ */
9240
+ static emuToPixel(emu, dpi = UnitConverter.DEFAULT_DPI) {
9241
+ return Math.round(emu * dpi / UnitConverter.EMU_PER_INCH);
9242
+ }
9243
+ /**
9244
+ * 将像素转换为 EMU
9245
+ * @param pixel 像素值
9246
+ * @param dpi 屏幕 DPI(默认 96)
9247
+ * @returns EMU 值
9248
+ * @example
9249
+ * UnitConverter.pixelToEmu(96) // 914400
9250
+ */
9251
+ static pixelToEmu(pixel, dpi = UnitConverter.DEFAULT_DPI) {
9252
+ return Math.round(pixel * UnitConverter.EMU_PER_INCH / dpi);
9253
+ }
9254
+ /**
9255
+ * 将 EMU 转换为 twips
9256
+ * @param emu EMU 值
9257
+ * @returns Twips 值
9258
+ * @example
9259
+ * UnitConverter.emuToTwip(914400) // 1440
9260
+ */
9261
+ static emuToTwip(emu) {
9262
+ return Math.round(emu * UnitConverter.DXA_PER_INCH / UnitConverter.EMU_PER_INCH);
9263
+ }
9264
+ /**
9265
+ * 将 twips 转换为 EMU
9266
+ * @param twips Twips 值
9267
+ * @returns EMU 值
9268
+ * @example
9269
+ * UnitConverter.twipToEmu(1440) // 914400
9270
+ */
9271
+ static twipToEmu(twips) {
9272
+ return Math.round(twips * UnitConverter.EMU_PER_INCH / UnitConverter.DXA_PER_INCH);
9273
+ }
9274
+ /**
9275
+ * 将 points 转换为像素
9276
+ * @param points Points 值
9277
+ * @param dpi 屏幕 DPI(默认 96)
9278
+ * @returns 像素值
9279
+ * @example
9280
+ * UnitConverter.pointToPixel(72) // 96
9281
+ */
9282
+ static pointToPixel(points, dpi = UnitConverter.DEFAULT_DPI) {
9283
+ return Math.round(points * dpi / UnitConverter.INCH_TO_POINTS);
9284
+ }
9285
+ /**
9286
+ * 将像素转换为 points
9287
+ * @param pixel 像素值
9288
+ * @param dpi 屏幕 DPI(默认 96)
9289
+ * @returns Points 值
9290
+ * @example
9291
+ * UnitConverter.pixelToPoint(96) // 72
9292
+ */
9293
+ static pixelToPoint(pixel, dpi = UnitConverter.DEFAULT_DPI) {
9294
+ return Math.round(pixel * UnitConverter.INCH_TO_POINTS / dpi);
9295
+ }
9296
+ /**
9297
+ * 将 inches 转换为像素
9298
+ * @param inches Inches 值
9299
+ * @param dpi 屏幕 DPI(默认 96)
9300
+ * @returns 像素值
9301
+ * @example
9302
+ * UnitConverter.inchToPixel(1) // 96
9303
+ */
9304
+ static inchToPixel(inches, dpi = UnitConverter.DEFAULT_DPI) {
9305
+ return Math.round(inches * dpi);
9306
+ }
9307
+ /**
9308
+ * 将像素转换为 inches
9309
+ * @param pixel 像素值
9310
+ * @param dpi 屏幕 DPI(默认 96)
9311
+ * @returns Inches 值
9312
+ * @example
9313
+ * UnitConverter.pixelToInch(96) // 1
9314
+ */
9315
+ static pixelToInch(pixel, dpi = UnitConverter.DEFAULT_DPI) {
9316
+ return pixel / dpi;
9317
+ }
9318
+ /**
9319
+ * 将厘米转换为 inches
9320
+ * @param cm 厘米值
9321
+ * @returns Inches 值
9322
+ * @example
9323
+ * UnitConverter.cmToInch(2.54) // 1
9324
+ */
9325
+ static cmToInch(cm) {
9326
+ return cm / UnitConverter.INCH_TO_CM;
9327
+ }
9328
+ /**
9329
+ * 将 inches 转换为厘米
9330
+ * @param inches Inches 值
9331
+ * @returns 厘米值
9332
+ * @example
9333
+ * UnitConverter.inchToCm(1) // 2.54
9334
+ */
9335
+ static inchToCm(inches) {
9336
+ return inches * UnitConverter.INCH_TO_CM;
9337
+ }
9338
+ /**
9339
+ * 将厘米转换为像素
9340
+ * @param cm 厘米值
9341
+ * @param dpi 屏幕 DPI(默认 96)
9342
+ * @returns 像素值
9343
+ * @example
9344
+ * UnitConverter.cmToPixel(2.54) // 96
9345
+ */
9346
+ static cmToPixel(cm, dpi = UnitConverter.DEFAULT_DPI) {
9347
+ const inches = UnitConverter.cmToInch(cm);
9348
+ return UnitConverter.inchToPixel(inches, dpi);
9349
+ }
9350
+ /**
9351
+ * 将像素转换为厘米
9352
+ * @param pixel 像素值
9353
+ * @param dpi 屏幕 DPI(默认 96)
9354
+ * @returns 厘米值
9355
+ * @example
9356
+ * UnitConverter.pixelToCm(96) // 2.54
9357
+ */
9358
+ static pixelToCm(pixel, dpi = UnitConverter.DEFAULT_DPI) {
9359
+ const inches = UnitConverter.pixelToInch(pixel, dpi);
9360
+ return UnitConverter.inchToCm(inches);
9361
+ }
9362
+ /**
9363
+ * 将 points 转换为 twips
9364
+ * @param points Points 值
9365
+ * @returns Twips 值
9366
+ * @example
9367
+ * UnitConverter.pointToTwip(72) // 1440
9368
+ */
9369
+ static pointToTwip(points) {
9370
+ return Math.round(points / UnitConverter.TWIP_TO_POINT);
9371
+ }
9372
+ /**
9373
+ * 将 twips 转换为 points
9374
+ * @param twips Twips 值
9375
+ * @returns Points 值
9376
+ * @example
9377
+ * UnitConverter.twipToPoint(1440) // 72
9378
+ */
9379
+ static twipToPoint(twips) {
9380
+ return twips * UnitConverter.TWIP_TO_POINT;
9381
+ }
9382
+ /**
9383
+ * 将像素数组转换为 twips 数组
9384
+ * @param pixels 像素数组
9385
+ * @param dpi 屏幕 DPI(默认 96)
9386
+ * @returns Twips 数组
9387
+ * @example
9388
+ * UnitConverter.pixelsToTwips([96, 192, 288]) // [1440, 2880, 4320]
9389
+ */
9390
+ static pixelsToTwips(pixels, dpi = UnitConverter.DEFAULT_DPI) {
9391
+ return pixels.map((px) => UnitConverter.pixelToTwip(px, dpi));
9392
+ }
9393
+ /**
9394
+ * 将 twips 数组转换为像素数组
9395
+ * @param twips Twips 数组
9396
+ * @param dpi 屏幕 DPI(默认 96)
9397
+ * @returns 像素数组
9398
+ * @example
9399
+ * UnitConverter.twipsToPixels([1440, 2880, 4320]) // [96, 192, 288]
9400
+ */
9401
+ static twipsToPixels(twips, dpi = UnitConverter.DEFAULT_DPI) {
9402
+ return twips.map((t) => UnitConverter.twipToPixel(t, dpi));
9403
+ }
9404
+ };
9405
+ _defineProperty(UnitConverter, "INCH_TO_CM", 2.54);
9406
+ _defineProperty(UnitConverter, "INCH_TO_POINTS", 72);
9407
+ _defineProperty(UnitConverter, "TWIP_TO_POINT", 1 / 20);
9408
+ _defineProperty(UnitConverter, "POINT_TO_INCH", 1 / 72);
9409
+ _defineProperty(UnitConverter, "DEFAULT_DPI", 96);
9410
+ _defineProperty(UnitConverter, "EMU_PER_INCH", 914400);
9411
+ _defineProperty(UnitConverter, "DXA_PER_INCH", 1440);
9412
+ })), MIN_TABLE_COL_WIDTH_DXA, BUSINESS_DATA_REGION_TYPES;
9413
+ var init_table$2 = __esmMin((() => {
9414
+ init_unit_converter();
9415
+ MIN_TABLE_COL_WIDTH_DXA = UnitConverter.pixelToDxa(30);
9416
+ BUSINESS_DATA_REGION_TYPES = /* @__PURE__ */ new Set([
9417
+ "repeating",
9418
+ "bounded",
9419
+ "2d-table",
9420
+ "check-table",
9421
+ "material-consume-table"
9422
+ ]);
9423
+ }));
9424
+ //#endregion
9162
9425
  //#region src/core/constants/index.ts
9163
9426
  var init_constants$1 = __esmMin((() => {
9164
9427
  init_component();
9165
9428
  init_doc_mode();
9166
9429
  init_paper();
9430
+ init_table$2();
9167
9431
  }));
9168
9432
  //#endregion
9169
9433
  //#region src/core/model/capability/index.ts
@@ -10981,13 +11245,57 @@ var init_tableCell_template = __esmMin((() => {
10981
11245
  };
10982
11246
  }));
10983
11247
  //#endregion
11248
+ //#region src/core/model/document/utils/ensure-paragraphs-around-tables.ts
11249
+ /**
11250
+ * 在数组中为每个表格补齐前后段落(就地修改,倒序遍历)。
11251
+ * 适用于 fromXmlJson 等尚未挂到 ModelGroup 的构建阶段。
11252
+ */
11253
+ function ensureParagraphsAroundTablesInList(children, isTable, isParagraph, createParagraph) {
11254
+ for (let i = children.length - 1; i >= 0; i--) {
11255
+ if (!isTable(children[i])) continue;
11256
+ if (!isParagraph(children[i + 1])) children.splice(i + 1, 0, createParagraph());
11257
+ if (!isParagraph(children[i - 1])) children.splice(i, 0, createParagraph());
11258
+ }
11259
+ }
11260
+ /** Wp / Wtbl 列表的便捷封装 */
11261
+ function ensureWpAroundWtblInList(children) {
11262
+ ensureParagraphsAroundTablesInList(children, (item) => item instanceof Wtbl, (item) => item instanceof Wp, () => Wp.fromTemplate());
11263
+ }
11264
+ /**
11265
+ * 确保单个表格在 ModelGroup 中前后都紧跟段落。
11266
+ * 插入表格后调用即可(body / 单元格共用)。
11267
+ */
11268
+ function ensureParagraphsAroundTable(group, table) {
11269
+ const idx = group.children.indexOf(table);
11270
+ if (idx < 0) return;
11271
+ const next = group.children[idx + 1];
11272
+ if (!next || !(next instanceof Wp)) group.insertAfter(table, Wp.fromTemplate());
11273
+ const prev = group.children[group.children.indexOf(table) - 1];
11274
+ if (!prev || !(prev instanceof Wp)) group.insertBefore(table, Wp.fromTemplate());
11275
+ }
11276
+ /** 确保 group 内每个表格前后都有段落 */
11277
+ function ensureParagraphsAroundAllTables(group) {
11278
+ for (let i = group.children.length - 1; i >= 0; i--) {
11279
+ const child = group.children[i];
11280
+ if (child instanceof Wtbl) ensureParagraphsAroundTable(group, child);
11281
+ }
11282
+ }
11283
+ var init_ensure_paragraphs_around_tables = __esmMin((() => {
11284
+ init_Wp();
11285
+ init_Wtbl();
11286
+ }));
11287
+ //#endregion
10984
11288
  //#region src/core/model/document/Wtc.ts
10985
11289
  var WTC_REF_KEYS, Wtc;
10986
11290
  var init_Wtc = __esmMin((() => {
10987
11291
  init_helpers$1();
10988
11292
  init_Wp();
11293
+ init_Wtbl();
10989
11294
  init_base$1();
10990
11295
  init_tableCell_template();
11296
+ init_constants$1();
11297
+ init_unit_converter();
11298
+ init_ensure_paragraphs_around_tables();
10991
11299
  init_defineProperty();
10992
11300
  WTC_REF_KEYS = [
10993
11301
  "mergeId",
@@ -11051,8 +11359,50 @@ var init_Wtc = __esmMin((() => {
11051
11359
  return !!this.mergeId && !this.mergeFromId;
11052
11360
  }
11053
11361
  get contents() {
11362
+ return this.getParagraphs();
11363
+ }
11364
+ getParagraphs() {
11054
11365
  return this.children.filter((child) => child instanceof Wp);
11055
11366
  }
11367
+ getNestedTables() {
11368
+ return this.children.filter((child) => child instanceof Wtbl);
11369
+ }
11370
+ getTableScope() {
11371
+ return this.table.getTableScope();
11372
+ }
11373
+ /** 单元格内容区宽度(DXA),用于嵌套表初始列宽(已扣除左右 padding) */
11374
+ getContentWidthDxa() {
11375
+ var _table$colWidths;
11376
+ const table = this.table;
11377
+ const colIndex = this.getCurrentIndex() ?? 0;
11378
+ const span = this.colspan || 1;
11379
+ let width = 0;
11380
+ if ((_table$colWidths = table.colWidths) === null || _table$colWidths === void 0 ? void 0 : _table$colWidths.length) for (let i = colIndex; i < colIndex + span && i < table.colWidths.length; i++) width += table.colWidths[i] ?? 0;
11381
+ if (width <= 0 && this.tcPrRaw) {
11382
+ var _tcW$Attrs;
11383
+ const tcW = pickElement(this.tcPrRaw, "w:tcW");
11384
+ const val = tcW === null || tcW === void 0 || (_tcW$Attrs = tcW["@attrs"]) === null || _tcW$Attrs === void 0 ? void 0 : _tcW$Attrs["w:w"];
11385
+ if (val) width = parseInt(val, 10) || 0;
11386
+ }
11387
+ if (width <= 0) return 0;
11388
+ const horizontalPaddingDxa = UnitConverter.pixelToDxa(DEFAULT_CELL_PADDING[1] + DEFAULT_CELL_PADDING[3]);
11389
+ return Math.max(0, width - horizontalPaddingDxa);
11390
+ }
11391
+ /** 是否允许在本单元格插入物理嵌套表 */
11392
+ canInsertNestedTable() {
11393
+ if (this.isMergeSlave) return false;
11394
+ if (this.table.isNestedTable) return false;
11395
+ if (this.subTable || this.subTableItem) return false;
11396
+ const region = this.getRegion();
11397
+ if (region && BUSINESS_DATA_REGION_TYPES.has(region.type)) return false;
11398
+ return true;
11399
+ }
11400
+ /** 在 block 子节点序列中插入嵌套表(纵向堆叠) */
11401
+ insertNestedTableAt(index, wtbl) {
11402
+ wtbl.attachAsNested(this);
11403
+ this.insertChildAt(index, wtbl);
11404
+ ensureParagraphsAroundTable(this, wtbl);
11405
+ }
11056
11406
  /** 单元格垂直对齐(w:tcPr/w:vAlign) */
11057
11407
  get vAlign() {
11058
11408
  var _elem$Attrs;
@@ -11198,7 +11548,7 @@ var init_Wtc = __esmMin((() => {
11198
11548
  /**
11199
11549
  * 从 XML JSON 创建单元格(返回数组,因为 colspan 会产生多个单元格)
11200
11550
  */
11201
- static fromXmlJson(tcRaw) {
11551
+ static fromXmlJson(tcRaw, cellParseOptions) {
11202
11552
  var _tcRaw$elements;
11203
11553
  let children = [];
11204
11554
  let tcPrRaw = null;
@@ -11208,8 +11558,13 @@ var init_Wtc = __esmMin((() => {
11208
11558
  else if (el.name === "w:p") {
11209
11559
  const p = Wp.fromXmlJson(el);
11210
11560
  children.push(p);
11561
+ } else if (el.name === "w:tbl") {
11562
+ const nested = Wtc.parseNestedTableFromXml(el, cellParseOptions);
11563
+ if (nested) children.push(nested);
11211
11564
  } else children.push(el);
11212
11565
  });
11566
+ ensureWpAroundWtblInList(children);
11567
+ if (!(children[children.length - 1] instanceof Wp)) children.push(Wp.fromTemplate());
11213
11568
  let colspan;
11214
11569
  let vMergeType;
11215
11570
  let backgroundColor;
@@ -11242,8 +11597,11 @@ var init_Wtc = __esmMin((() => {
11242
11597
  children,
11243
11598
  ...pick(tcRaw, ...WTC_REF_KEYS)
11244
11599
  });
11245
- cell.children.forEach((p) => {
11246
- if (p instanceof ModelNode) p.parent = cell;
11600
+ cell.children.forEach((child) => {
11601
+ if (child instanceof ModelNode) {
11602
+ child.parent = cell;
11603
+ if (child instanceof Wtbl) child.nestedInCellId = cell.id;
11604
+ }
11247
11605
  });
11248
11606
  const result = [cell];
11249
11607
  if (isColspanMultiple) {
@@ -11278,7 +11636,7 @@ var init_Wtc = __esmMin((() => {
11278
11636
  const tcPr = this.buildTcPr();
11279
11637
  if (tcPr) elements.push(tcPr);
11280
11638
  this.children.forEach((child) => {
11281
- if (child instanceof Wp) elements.push(child.toXmlJson());
11639
+ if (child instanceof Wp || child instanceof Wtbl) elements.push(child.toXmlJson());
11282
11640
  else if (child instanceof ModelNode && "toXmlJson" in child) elements.push(child.toXmlJson());
11283
11641
  else if (typeof child === "object" && "name" in child) elements.push(child);
11284
11642
  });
@@ -11318,6 +11676,15 @@ var init_Wtc = __esmMin((() => {
11318
11676
  tcPr.elements = filtered;
11319
11677
  return tcPr;
11320
11678
  }
11679
+ static parseNestedTableFromXml(tblRaw, cellParseOptions) {
11680
+ if (((cellParseOptions === null || cellParseOptions === void 0 ? void 0 : cellParseOptions.hostTableDepth) ?? 0) >= 1) {
11681
+ var _cellParseOptions$onG;
11682
+ cellParseOptions === null || cellParseOptions === void 0 || (_cellParseOptions$onG = cellParseOptions.onGrandchildIgnored) === null || _cellParseOptions$onG === void 0 || _cellParseOptions$onG.call(cellParseOptions);
11683
+ return null;
11684
+ }
11685
+ if (!(cellParseOptions === null || cellParseOptions === void 0 ? void 0 : cellParseOptions.parseNestedTable)) return null;
11686
+ return cellParseOptions.parseNestedTable(tblRaw);
11687
+ }
11321
11688
  static normalizeWordColor(color) {
11322
11689
  if (!color) return void 0;
11323
11690
  const value = color.trim();
@@ -11685,7 +12052,7 @@ var init_Wtr = __esmMin((() => {
11685
12052
  /**
11686
12053
  * 从 XML JSON 创建表格行
11687
12054
  */
11688
- static fromXmlJson(trRaw) {
12055
+ static fromXmlJson(trRaw, cellParseOptions) {
11689
12056
  var _trRaw$elements;
11690
12057
  let tds = [];
11691
12058
  let trPr;
@@ -11693,7 +12060,7 @@ var init_Wtr = __esmMin((() => {
11693
12060
  let el = _;
11694
12061
  if (el.name === "w:trPr") trPr = WtrPr.fromXmlJson(el);
11695
12062
  else if (el.name === "w:tc") {
11696
- const tc = Wtc.fromXmlJson(el);
12063
+ const tc = Wtc.fromXmlJson(el, cellParseOptions);
11697
12064
  tds.push(...tc);
11698
12065
  }
11699
12066
  });
@@ -100529,266 +100896,27 @@ var init_table_template = __esmMin((() => {
100529
100896
  };
100530
100897
  }));
100531
100898
  //#endregion
100532
- //#region src/core/layout/shared/unit-converter.ts
100533
- var UnitConverter;
100534
- var init_unit_converter = __esmMin((() => {
100535
- init_defineProperty();
100536
- UnitConverter = class UnitConverter {
100537
- /**
100538
- * 将 twips 转换为像素
100539
- * @param twips Twips 值
100540
- * @param dpi 屏幕 DPI(默认 96)
100541
- * @returns 像素值
100542
- */
100543
- static twipToPixel(twips, dpi = UnitConverter.DEFAULT_DPI) {
100544
- return Math.round(twips * dpi / UnitConverter.DXA_PER_INCH);
100545
- }
100546
- /**
100547
- * 将 twips 转换为cm
100548
- * @param twips Twips 值
100549
- * @returns cm
100550
- */
100551
- static twipToCm(twip) {
100552
- const cm = twip / UnitConverter.DXA_PER_INCH * UnitConverter.INCH_TO_CM;
100553
- return Math.ceil(cm * 100) / 100;
100554
- }
100555
- static twipToMm(twip) {
100556
- return this.twipToCm(twip) * 10;
100557
- }
100558
- /**
100559
- * 将 cm 转换为twips
100560
- * @param cm cm 值
100561
- * @returns Twips 值
100562
- */
100563
- static cmToTwip(cm) {
100564
- return cm / UnitConverter.INCH_TO_CM * UnitConverter.DXA_PER_INCH;
100565
- }
100566
- static mmToTwip(mm) {
100567
- return this.cmToTwip(mm / 10);
100568
- }
100569
- /**
100570
- * 将像素转换为 twips
100571
- * @param pixel 像素值
100572
- * @param dpi 屏幕 DPI(默认 96)
100573
- * @returns Twips 值
100574
- * @example
100575
- * UnitConverter.pixelToTwip(96) // 1440
100576
- */
100577
- static pixelToTwip(pixel, dpi = UnitConverter.DEFAULT_DPI) {
100578
- return Math.round(pixel * UnitConverter.DXA_PER_INCH / dpi);
100579
- }
100580
- /**
100581
- * 将 DXA (twips) 转换为像素
100582
- * @param dxa DXA 值
100583
- * @param dpi 屏幕 DPI(默认 96)
100584
- * @returns 像素值
100585
- * @example
100586
- * UnitConverter.dxaToPixel(1440) // 96
100587
- */
100588
- static dxaToPixel(dxa, dpi = UnitConverter.DEFAULT_DPI) {
100589
- return Math.round(dxa * dpi / UnitConverter.DXA_PER_INCH);
100590
- }
100591
- /**
100592
- * 将像素转换为 DXA (twips)
100593
- * @param pixel 像素值
100594
- * @param dpi 屏幕 DPI(默认 96)
100595
- * @returns DXA 值
100596
- * @example
100597
- * UnitConverter.pixelToDxa(96) // 1440
100598
- */
100599
- static pixelToDxa(pixel, dpi = UnitConverter.DEFAULT_DPI) {
100600
- return Math.round(pixel * UnitConverter.DXA_PER_INCH / dpi);
100601
- }
100602
- /**
100603
- * 将 EMU (English Metric Units) 转换为像素
100604
- * @param emu EMU 值
100605
- * @param dpi 屏幕 DPI(默认 96)
100606
- * @returns 像素值
100607
- * @example
100608
- * UnitConverter.emuToPixel(914400) // 96
100609
- */
100610
- static emuToPixel(emu, dpi = UnitConverter.DEFAULT_DPI) {
100611
- return Math.round(emu * dpi / UnitConverter.EMU_PER_INCH);
100612
- }
100613
- /**
100614
- * 将像素转换为 EMU
100615
- * @param pixel 像素值
100616
- * @param dpi 屏幕 DPI(默认 96)
100617
- * @returns EMU 值
100618
- * @example
100619
- * UnitConverter.pixelToEmu(96) // 914400
100620
- */
100621
- static pixelToEmu(pixel, dpi = UnitConverter.DEFAULT_DPI) {
100622
- return Math.round(pixel * UnitConverter.EMU_PER_INCH / dpi);
100623
- }
100624
- /**
100625
- * 将 EMU 转换为 twips
100626
- * @param emu EMU 值
100627
- * @returns Twips 值
100628
- * @example
100629
- * UnitConverter.emuToTwip(914400) // 1440
100630
- */
100631
- static emuToTwip(emu) {
100632
- return Math.round(emu * UnitConverter.DXA_PER_INCH / UnitConverter.EMU_PER_INCH);
100633
- }
100634
- /**
100635
- * 将 twips 转换为 EMU
100636
- * @param twips Twips 值
100637
- * @returns EMU 值
100638
- * @example
100639
- * UnitConverter.twipToEmu(1440) // 914400
100640
- */
100641
- static twipToEmu(twips) {
100642
- return Math.round(twips * UnitConverter.EMU_PER_INCH / UnitConverter.DXA_PER_INCH);
100643
- }
100644
- /**
100645
- * 将 points 转换为像素
100646
- * @param points Points 值
100647
- * @param dpi 屏幕 DPI(默认 96)
100648
- * @returns 像素值
100649
- * @example
100650
- * UnitConverter.pointToPixel(72) // 96
100651
- */
100652
- static pointToPixel(points, dpi = UnitConverter.DEFAULT_DPI) {
100653
- return Math.round(points * dpi / UnitConverter.INCH_TO_POINTS);
100654
- }
100655
- /**
100656
- * 将像素转换为 points
100657
- * @param pixel 像素值
100658
- * @param dpi 屏幕 DPI(默认 96)
100659
- * @returns Points 值
100660
- * @example
100661
- * UnitConverter.pixelToPoint(96) // 72
100662
- */
100663
- static pixelToPoint(pixel, dpi = UnitConverter.DEFAULT_DPI) {
100664
- return Math.round(pixel * UnitConverter.INCH_TO_POINTS / dpi);
100665
- }
100666
- /**
100667
- * 将 inches 转换为像素
100668
- * @param inches Inches 值
100669
- * @param dpi 屏幕 DPI(默认 96)
100670
- * @returns 像素值
100671
- * @example
100672
- * UnitConverter.inchToPixel(1) // 96
100673
- */
100674
- static inchToPixel(inches, dpi = UnitConverter.DEFAULT_DPI) {
100675
- return Math.round(inches * dpi);
100676
- }
100677
- /**
100678
- * 将像素转换为 inches
100679
- * @param pixel 像素值
100680
- * @param dpi 屏幕 DPI(默认 96)
100681
- * @returns Inches 值
100682
- * @example
100683
- * UnitConverter.pixelToInch(96) // 1
100684
- */
100685
- static pixelToInch(pixel, dpi = UnitConverter.DEFAULT_DPI) {
100686
- return pixel / dpi;
100687
- }
100688
- /**
100689
- * 将厘米转换为 inches
100690
- * @param cm 厘米值
100691
- * @returns Inches 值
100692
- * @example
100693
- * UnitConverter.cmToInch(2.54) // 1
100694
- */
100695
- static cmToInch(cm) {
100696
- return cm / UnitConverter.INCH_TO_CM;
100697
- }
100698
- /**
100699
- * 将 inches 转换为厘米
100700
- * @param inches Inches 值
100701
- * @returns 厘米值
100702
- * @example
100703
- * UnitConverter.inchToCm(1) // 2.54
100704
- */
100705
- static inchToCm(inches) {
100706
- return inches * UnitConverter.INCH_TO_CM;
100707
- }
100708
- /**
100709
- * 将厘米转换为像素
100710
- * @param cm 厘米值
100711
- * @param dpi 屏幕 DPI(默认 96)
100712
- * @returns 像素值
100713
- * @example
100714
- * UnitConverter.cmToPixel(2.54) // 96
100715
- */
100716
- static cmToPixel(cm, dpi = UnitConverter.DEFAULT_DPI) {
100717
- const inches = UnitConverter.cmToInch(cm);
100718
- return UnitConverter.inchToPixel(inches, dpi);
100719
- }
100720
- /**
100721
- * 将像素转换为厘米
100722
- * @param pixel 像素值
100723
- * @param dpi 屏幕 DPI(默认 96)
100724
- * @returns 厘米值
100725
- * @example
100726
- * UnitConverter.pixelToCm(96) // 2.54
100727
- */
100728
- static pixelToCm(pixel, dpi = UnitConverter.DEFAULT_DPI) {
100729
- const inches = UnitConverter.pixelToInch(pixel, dpi);
100730
- return UnitConverter.inchToCm(inches);
100731
- }
100732
- /**
100733
- * 将 points 转换为 twips
100734
- * @param points Points 值
100735
- * @returns Twips 值
100736
- * @example
100737
- * UnitConverter.pointToTwip(72) // 1440
100738
- */
100739
- static pointToTwip(points) {
100740
- return Math.round(points / UnitConverter.TWIP_TO_POINT);
100741
- }
100742
- /**
100743
- * 将 twips 转换为 points
100744
- * @param twips Twips 值
100745
- * @returns Points 值
100746
- * @example
100747
- * UnitConverter.twipToPoint(1440) // 72
100748
- */
100749
- static twipToPoint(twips) {
100750
- return twips * UnitConverter.TWIP_TO_POINT;
100751
- }
100752
- /**
100753
- * 将像素数组转换为 twips 数组
100754
- * @param pixels 像素数组
100755
- * @param dpi 屏幕 DPI(默认 96)
100756
- * @returns Twips 数组
100757
- * @example
100758
- * UnitConverter.pixelsToTwips([96, 192, 288]) // [1440, 2880, 4320]
100759
- */
100760
- static pixelsToTwips(pixels, dpi = UnitConverter.DEFAULT_DPI) {
100761
- return pixels.map((px) => UnitConverter.pixelToTwip(px, dpi));
100762
- }
100763
- /**
100764
- * 将 twips 数组转换为像素数组
100765
- * @param twips Twips 数组
100766
- * @param dpi 屏幕 DPI(默认 96)
100767
- * @returns 像素数组
100768
- * @example
100769
- * UnitConverter.twipsToPixels([1440, 2880, 4320]) // [96, 192, 288]
100770
- */
100771
- static twipsToPixels(twips, dpi = UnitConverter.DEFAULT_DPI) {
100772
- return twips.map((t) => UnitConverter.twipToPixel(t, dpi));
100773
- }
100774
- };
100775
- _defineProperty(UnitConverter, "INCH_TO_CM", 2.54);
100776
- _defineProperty(UnitConverter, "INCH_TO_POINTS", 72);
100777
- _defineProperty(UnitConverter, "TWIP_TO_POINT", 1 / 20);
100778
- _defineProperty(UnitConverter, "POINT_TO_INCH", 1 / 72);
100779
- _defineProperty(UnitConverter, "DEFAULT_DPI", 96);
100780
- _defineProperty(UnitConverter, "EMU_PER_INCH", 914400);
100781
- _defineProperty(UnitConverter, "DXA_PER_INCH", 1440);
100782
- }));
100783
- //#endregion
100784
100899
  //#region src/core/model/document/Wtbl/RowColumnOps.ts
100785
100900
  var DEFAULT_WIDTH, WtblRowColumnOps;
100786
100901
  var init_RowColumnOps = __esmMin((() => {
100787
100902
  init_Wtr();
100788
100903
  init_Wtc();
100789
100904
  init_unit_converter();
100905
+ init_constants$1();
100790
100906
  DEFAULT_WIDTH = UnitConverter.pixelToDxa(100);
100791
100907
  WtblRowColumnOps = class {
100908
+ /** 外表删除前,显式移除受影响单元格中的嵌套表,避免孤儿节点残留 */
100909
+ static detachNestedTablesFromCells(cells) {
100910
+ cells.forEach((cell) => {
100911
+ if (!cell) return;
100912
+ cell.getNestedTables().forEach((nested) => nested.remove());
100913
+ });
100914
+ }
100915
+ /** 仅外表需要做「删除行/列/表时联动删除嵌套表」 */
100916
+ static detachNestedTablesFromOuterTable(table) {
100917
+ if (table.depth !== 0) return;
100918
+ table.collectNestedTables().forEach((nested) => nested.remove());
100919
+ }
100792
100920
  /**
100793
100921
  * 新单元格同步引用信息
100794
100922
  * refCell: 参考单元格 (above | left)
@@ -100900,10 +101028,13 @@ var init_RowColumnOps = __esmMin((() => {
100900
101028
  static deleteRowAt(table, index) {
100901
101029
  if (index < 0 || index >= table.rows.length) throw new Error(`Invalid row index: ${index}, table has ${table.rows.length} rows`);
100902
101030
  if (table.rows.length === 1) {
101031
+ this.detachNestedTablesFromOuterTable(table);
100903
101032
  table.remove();
100904
101033
  return;
100905
101034
  }
100906
101035
  table.runConsistencyMutation({ mutate: () => {
101036
+ var _table$rows$index;
101037
+ this.detachNestedTablesFromCells(((_table$rows$index = table.rows[index]) === null || _table$rows$index === void 0 ? void 0 : _table$rows$index.cells) ?? []);
100907
101038
  table.removeChildAt(index);
100908
101039
  } });
100909
101040
  }
@@ -100913,9 +101044,16 @@ var init_RowColumnOps = __esmMin((() => {
100913
101044
  static deleteRowRange(table, startIndex, endIndex) {
100914
101045
  if (startIndex < 0 || endIndex >= table.rows.length || startIndex > endIndex) throw new Error(`Invalid row range: [${startIndex}, ${endIndex}], table has ${table.rows.length} rows`);
100915
101046
  table.runConsistencyMutation({ mutate: () => {
101047
+ for (let i = startIndex; i <= endIndex; i++) {
101048
+ var _table$rows$i;
101049
+ this.detachNestedTablesFromCells(((_table$rows$i = table.rows[i]) === null || _table$rows$i === void 0 ? void 0 : _table$rows$i.cells) ?? []);
101050
+ }
100916
101051
  for (let i = endIndex; i >= startIndex; i--) table.removeChildAt(i);
100917
101052
  if (table.rows.length === 0) {
100918
- if (table.parent) table.remove();
101053
+ if (table.parent) {
101054
+ this.detachNestedTablesFromOuterTable(table);
101055
+ table.remove();
101056
+ }
100919
101057
  }
100920
101058
  } });
100921
101059
  }
@@ -100927,12 +101065,16 @@ var init_RowColumnOps = __esmMin((() => {
100927
101065
  if (index < 0) throw new Error(`Invalid column index: ${index}`);
100928
101066
  const colCount = ((_table$colWidths = table.colWidths) === null || _table$colWidths === void 0 ? void 0 : _table$colWidths.length) ?? ((_table$rows$ = table.rows[0]) === null || _table$rows$ === void 0 ? void 0 : _table$rows$.cells.length) ?? 0;
100929
101067
  if (colCount <= 1) {
101068
+ this.detachNestedTablesFromOuterTable(table);
100930
101069
  table.remove();
100931
101070
  return;
100932
101071
  }
100933
101072
  if (index >= colCount) throw new Error(`Invalid column index: ${index}, table has ${colCount} columns`);
100934
101073
  table.runConsistencyMutation({ mutate: () => {
100935
- for (const row of table.rows) if (index < row.cells.length) row.removeChildAt(index);
101074
+ for (const row of table.rows) if (index < row.cells.length) {
101075
+ this.detachNestedTablesFromCells([row.cells[index]]);
101076
+ row.removeChildAt(index);
101077
+ }
100936
101078
  if (table.colWidths && index < table.colWidths.length) table.colWidths.splice(index, 1);
100937
101079
  } });
100938
101080
  }
@@ -100944,11 +101086,15 @@ var init_RowColumnOps = __esmMin((() => {
100944
101086
  if (startIndex < 0 || startIndex > endIndex) throw new Error(`Invalid column range: [${startIndex}, ${endIndex}]`);
100945
101087
  const colCount = ((_table$colWidths2 = table.colWidths) === null || _table$colWidths2 === void 0 ? void 0 : _table$colWidths2.length) ?? ((_table$rows$2 = table.rows[0]) === null || _table$rows$2 === void 0 ? void 0 : _table$rows$2.cells.length) ?? 0;
100946
101088
  if (startIndex === 0 && endIndex >= colCount - 1) {
101089
+ this.detachNestedTablesFromOuterTable(table);
100947
101090
  table.remove();
100948
101091
  return;
100949
101092
  }
100950
101093
  table.runConsistencyMutation({ mutate: () => {
100951
- for (const row of table.rows) for (let i = endIndex; i >= startIndex; i--) if (i < row.cells.length) row.removeChildAt(i);
101094
+ for (const row of table.rows) for (let i = endIndex; i >= startIndex; i--) if (i < row.cells.length) {
101095
+ this.detachNestedTablesFromCells([row.cells[i]]);
101096
+ row.removeChildAt(i);
101097
+ }
100952
101098
  if (table.colWidths) table.colWidths.splice(startIndex, endIndex - startIndex + 1);
100953
101099
  } });
100954
101100
  }
@@ -100961,13 +101107,49 @@ var init_RowColumnOps = __esmMin((() => {
100961
101107
  var _table$colWidths3;
100962
101108
  throw new Error(`Column index ${colIndex} out of bounds for table with ${((_table$colWidths3 = table.colWidths) === null || _table$colWidths3 === void 0 ? void 0 : _table$colWidths3.length) || 0} columns`);
100963
101109
  }
100964
- const widthDifference = width - table.colWidths[colIndex];
101110
+ const oldWidth = table.colWidths[colIndex];
101111
+ const minWidth = MIN_TABLE_COL_WIDTH_DXA;
101112
+ let targetWidth = Math.max(minWidth, width);
101113
+ if (colIndex + 1 < table.colWidths.length) {
101114
+ const neighbor = table.colWidths[colIndex + 1];
101115
+ targetWidth = Math.min(targetWidth, oldWidth + Math.max(0, neighbor - minWidth));
101116
+ }
101117
+ const widthDifference = targetWidth - oldWidth;
100965
101118
  table.runConsistencyMutation({ mutate: () => {
100966
- table.colWidths[colIndex] = width;
101119
+ table.colWidths[colIndex] = targetWidth;
100967
101120
  if (colIndex + 1 < table.colWidths.length) table.colWidths[colIndex + 1] -= widthDifference;
100968
101121
  } });
100969
101122
  }
100970
101123
  /**
101124
+ * 从其他列借宽度给指定列跨度,保持表格总宽不变。
101125
+ * 优先借右侧列,再借左侧;被借列不低于 minWidth。
101126
+ */
101127
+ static stealWidthToColumn(table, startCol, colSpan, extra, minWidth = MIN_TABLE_COL_WIDTH_DXA) {
101128
+ if (!table.colWidths || extra <= 0) return 0;
101129
+ const colWidths = table.colWidths;
101130
+ const start = Math.max(0, startCol);
101131
+ const end = Math.min(colWidths.length, start + Math.max(1, colSpan));
101132
+ if (start >= end) return 0;
101133
+ let remaining = extra;
101134
+ let stolen = 0;
101135
+ const trySteal = (index) => {
101136
+ if (index < 0 || index >= colWidths.length) return;
101137
+ if (index >= start && index < end) return;
101138
+ const available = (colWidths[index] ?? 0) - minWidth;
101139
+ if (available <= 0) return;
101140
+ const take = Math.min(available, remaining);
101141
+ colWidths[index] = (colWidths[index] ?? 0) - take;
101142
+ remaining -= take;
101143
+ stolen += take;
101144
+ };
101145
+ table.runConsistencyMutation({ mutate: () => {
101146
+ for (let i = end; i < colWidths.length && remaining > 0; i++) trySteal(i);
101147
+ for (let i = start - 1; i >= 0 && remaining > 0; i--) trySteal(i);
101148
+ if (stolen > 0) colWidths[end - 1] = (colWidths[end - 1] ?? 0) + stolen;
101149
+ } });
101150
+ return stolen;
101151
+ }
101152
+ /**
100971
101153
  * 调整行高
100972
101154
  */
100973
101155
  static resizeRow(table, rowIndex, height) {
@@ -101574,19 +101756,32 @@ var init_WtblPr = __esmMin((() => {
101574
101756
  }));
101575
101757
  //#endregion
101576
101758
  //#region src/core/model/document/Wtbl/Serialization.ts
101577
- var WtblSerialization;
101759
+ var docImportGrandchildIgnored, WtblSerialization;
101578
101760
  var init_Serialization = __esmMin((() => {
101579
101761
  init_Wtr();
101580
101762
  init_WtblPr();
101581
101763
  init_logic$2();
101582
101764
  init_Wtbl();
101765
+ init_Wtc();
101766
+ docImportGrandchildIgnored = { value: 0 };
101583
101767
  WtblSerialization = class WtblSerialization {
101768
+ static resetImportGrandchildWarning() {
101769
+ docImportGrandchildIgnored.value = 0;
101770
+ }
101771
+ static consumeImportGrandchildWarning() {
101772
+ const ignored = docImportGrandchildIgnored.value;
101773
+ docImportGrandchildIgnored.value = 0;
101774
+ return ignored;
101775
+ }
101776
+ static markGrandchildTableIgnored(warnedRef) {
101777
+ (warnedRef ?? docImportGrandchildIgnored).value += 1;
101778
+ }
101584
101779
  /**
101585
101780
  * 从 XML JSON 创建表格实例
101586
101781
  */
101587
- static fromXmlJson(json) {
101782
+ static fromXmlJson(json, context) {
101588
101783
  var _json$elements, _wtbl$colWidths;
101589
- const trs = [];
101784
+ const trElements = [];
101590
101785
  let colWidths = [];
101591
101786
  let tblPr;
101592
101787
  (_json$elements = json.elements) === null || _json$elements === void 0 || _json$elements.forEach((_) => {
@@ -101597,13 +101792,31 @@ var init_Serialization = __esmMin((() => {
101597
101792
  const width = (_gc$Attrs = gc["@attrs"]) === null || _gc$Attrs === void 0 ? void 0 : _gc$Attrs["w:w"];
101598
101793
  return width ? parseInt(width) : 0;
101599
101794
  });
101600
- else if (el.name === "w:tr") trs.push(Wtr.fromXmlJson(el));
101795
+ else if (el.name === "w:tr") trElements.push(el);
101601
101796
  });
101602
101797
  const wtbl = new Wtbl({
101603
101798
  tblPr,
101604
101799
  colWidths,
101605
101800
  attrs: json["@attrs"],
101606
- children: trs
101801
+ children: []
101802
+ });
101803
+ wtbl.depth = (context === null || context === void 0 ? void 0 : context.depth) ?? 0;
101804
+ wtbl.rootTableId = (context === null || context === void 0 ? void 0 : context.rootTableId) ?? wtbl.id;
101805
+ wtbl.nestedInCellId = context === null || context === void 0 ? void 0 : context.hostCellId;
101806
+ const grandchildWarned = (context === null || context === void 0 ? void 0 : context.grandchildWarned) ?? docImportGrandchildIgnored;
101807
+ const cellParseOptions = {
101808
+ hostTableDepth: wtbl.depth,
101809
+ rootTableId: wtbl.rootTableId,
101810
+ grandchildWarned,
101811
+ onGrandchildIgnored: () => WtblSerialization.markGrandchildTableIgnored(grandchildWarned),
101812
+ parseNestedTable: (tblJson) => WtblSerialization.fromXmlJson(tblJson, {
101813
+ depth: 1,
101814
+ rootTableId: wtbl.rootTableId,
101815
+ grandchildWarned
101816
+ })
101817
+ };
101818
+ trElements.forEach((trRaw) => {
101819
+ wtbl.appendChild(Wtr.fromXmlJson(trRaw, cellParseOptions));
101607
101820
  });
101608
101821
  wtbl.rows.forEach((row) => {
101609
101822
  row.parent = wtbl;
@@ -101751,8 +101964,8 @@ var init_Serialization = __esmMin((() => {
101751
101964
  //#region src/core/model/document/Wtbl.ts
101752
101965
  var Wtbl;
101753
101966
  var init_Wtbl = __esmMin((() => {
101754
- init_Wtr();
101755
101967
  init_Wtc();
101968
+ init_Wtr();
101756
101969
  init_base$1();
101757
101970
  init_logic$2();
101758
101971
  init_table_template();
@@ -101771,6 +101984,24 @@ var init_Wtbl = __esmMin((() => {
101771
101984
  _defineProperty(this, "tblPr", void 0);
101772
101985
  _defineProperty(this, "colWidths", void 0);
101773
101986
  _defineProperty(this, "regions", []);
101987
+ _defineProperty(
101988
+ this,
101989
+ /** 嵌套表宿主单元格 id */
101990
+ "nestedInCellId",
101991
+ void 0
101992
+ );
101993
+ _defineProperty(
101994
+ this,
101995
+ /** 最外层 Wtbl.id */
101996
+ "rootTableId",
101997
+ void 0
101998
+ );
101999
+ _defineProperty(
102000
+ this,
102001
+ /** 嵌套深度:0(外表)或 1(嵌套表) */
102002
+ "depth",
102003
+ 0
102004
+ );
101774
102005
  _defineProperty(this, "pendingRecalculate", false);
101775
102006
  _defineProperty(this, "mutationDepth", 0);
101776
102007
  _defineProperty(this, "mutationNeedsRecalculate", false);
@@ -101825,6 +102056,55 @@ var init_Wtbl = __esmMin((() => {
101825
102056
  get hasCheckTable() {
101826
102057
  return this.checkTable.length > 0;
101827
102058
  }
102059
+ /** 是否已标为业务表 / 数据表 */
102060
+ get isBusinessOrDataTable() {
102061
+ return this.hasBounded || this.hasCheckTable || this.hasRepeating || this.has2DTable || this.hasMaterialConsumeTable;
102062
+ }
102063
+ /** 沿 parent 链找到最外层 Wtbl */
102064
+ getRootTable() {
102065
+ let current = this;
102066
+ while (current.parent instanceof Wtc) current = current.parent.table;
102067
+ return current;
102068
+ }
102069
+ getTableScope() {
102070
+ const depth = this.depth ?? (this.parent instanceof Wtc ? 1 : 0);
102071
+ return {
102072
+ wtbl: this,
102073
+ depth,
102074
+ hostCell: this.parent instanceof Wtc ? this.parent : void 0,
102075
+ rootWtbl: this.getRootTable()
102076
+ };
102077
+ }
102078
+ /** 收集本表单元格内的物理嵌套表 */
102079
+ collectNestedTables() {
102080
+ var _this$colWidths;
102081
+ const nested = [];
102082
+ if (this.rows.length === 0) return nested;
102083
+ const endColIdx = Math.max((((_this$colWidths = this.colWidths) === null || _this$colWidths === void 0 ? void 0 : _this$colWidths.length) ?? 1) - 1, ...this.rows.map((row) => row.cells.length - 1));
102084
+ this.forEachCell({
102085
+ startRowIdx: 0,
102086
+ endRowIdx: this.rows.length - 1,
102087
+ startColIdx: 0,
102088
+ endColIdx,
102089
+ filter: (cell) => !cell.isMergeSlave,
102090
+ callback: (cell) => {
102091
+ nested.push(...cell.getNestedTables());
102092
+ }
102093
+ });
102094
+ return nested;
102095
+ }
102096
+ /** 本表内是否存在已标业务/数据区的嵌套表 */
102097
+ hasNestedBusinessOrDataTable() {
102098
+ return this.collectNestedTables().some((table) => table.isBusinessOrDataTable);
102099
+ }
102100
+ /** 作为物理嵌套表挂到宿主单元格 */
102101
+ attachAsNested(hostCell) {
102102
+ const rootTable = hostCell.table;
102103
+ this.parent = hostCell;
102104
+ this.depth = 1;
102105
+ this.nestedInCellId = hostCell.id;
102106
+ this.rootTableId = rootTable.depth === 0 ? rootTable.id : rootTable.rootTableId ?? rootTable.id;
102107
+ }
101828
102108
  get tableHeader() {
101829
102109
  return this.regions.filter((r) => r.type === "table-header" || r.type === "sub-table-header");
101830
102110
  }
@@ -101861,8 +102141,12 @@ var init_Wtbl = __esmMin((() => {
101861
102141
  }
101862
102142
  }
101863
102143
  }
101864
- static fromXmlJson(json) {
101865
- return WtblSerialization.fromXmlJson(json);
102144
+ static fromXmlJson(json, context) {
102145
+ return WtblSerialization.fromXmlJson(json, context);
102146
+ }
102147
+ /** 是否为嵌套在单元格内的物理子表 */
102148
+ get isNestedTable() {
102149
+ return this.depth === 1 || this.parent instanceof Wtc;
101866
102150
  }
101867
102151
  toXmlJson() {
101868
102152
  return WtblSerialization.toXmlJson(this);
@@ -101943,6 +102227,8 @@ var init_Wtbl = __esmMin((() => {
101943
102227
  wtbl.rows.forEach((row) => {
101944
102228
  row.parent = wtbl;
101945
102229
  });
102230
+ wtbl.depth = 0;
102231
+ wtbl.rootTableId = wtbl.id;
101946
102232
  return wtbl;
101947
102233
  }
101948
102234
  insertRowAt(index) {
@@ -101978,6 +102264,9 @@ var init_Wtbl = __esmMin((() => {
101978
102264
  resizeCol(colIndex, width) {
101979
102265
  WtblRowColumnOps.resizeCol(this, colIndex, width);
101980
102266
  }
102267
+ stealWidthToColumn(startCol, colSpan, extra, minWidth) {
102268
+ return WtblRowColumnOps.stealWidthToColumn(this, startCol, colSpan, extra, minWidth);
102269
+ }
101981
102270
  resizeRow(rowIndex, height) {
101982
102271
  WtblRowColumnOps.resizeRow(this, rowIndex, height);
101983
102272
  }
@@ -102366,6 +102655,7 @@ var init_Wbody = __esmMin((() => {
102366
102655
  init_WsecPr();
102367
102656
  init_Wdocument();
102368
102657
  init_base$1();
102658
+ init_ensure_paragraphs_around_tables();
102369
102659
  init_defineProperty();
102370
102660
  Wbody = class Wbody extends ModelGroup {
102371
102661
  constructor(options) {
@@ -102411,9 +102701,16 @@ var init_Wbody = __esmMin((() => {
102411
102701
  children.forEach((child) => {
102412
102702
  child.parent = body;
102413
102703
  });
102704
+ body.ensureParagraphsAroundTables();
102414
102705
  return body;
102415
102706
  }
102416
102707
  /**
102708
+ * 规范化:确保 body 中每个 Wtbl 前后都紧跟一个 Wp。
102709
+ */
102710
+ ensureParagraphsAroundTables() {
102711
+ ensureParagraphsAroundAllTables(this);
102712
+ }
102713
+ /**
102417
102714
  * 实例转换为原始 XML JSON
102418
102715
  *
102419
102716
  * @returns RawElement 格式的 XML JSON
@@ -103880,6 +104177,9 @@ function isLayoutTextRun(node) {
103880
104177
  function isLayoutTextWidget(node) {
103881
104178
  return node instanceof TextWidget;
103882
104179
  }
104180
+ function isLayoutTable(node) {
104181
+ return node != null && node.component === BuiltinComponentTypeConst.Table;
104182
+ }
103883
104183
  var init_layout_node_by_component = __esmMin((() => {
103884
104184
  init_constants$1();
103885
104185
  init_TextWidget();
@@ -103935,13 +104235,14 @@ function buildPosBox(node) {
103935
104235
  }
103936
104236
  };
103937
104237
  }
103938
- function walkPageDFS(pages, cb) {
104238
+ function walkPageDFS(pages, cb, onLeave) {
103939
104239
  pages.forEach((page, pi) => {
103940
104240
  const visit = (node, idx, path) => {
103941
104241
  var _node$getChildren;
103942
104242
  cb(node, idx, path);
103943
104243
  const children = (node === null || node === void 0 || (_node$getChildren = node.getChildren) === null || _node$getChildren === void 0 ? void 0 : _node$getChildren.call(node)) ?? node.children;
103944
104244
  if (Array.isArray(children)) children.forEach((c, i) => visit(c, idx.concat(i), path.concat(c.id)));
104245
+ onLeave === null || onLeave === void 0 || onLeave(node);
103945
104246
  };
103946
104247
  visit(page, [pi], [page.id]);
103947
104248
  if (page.headerBand) visit(page.headerBand, [pi, -1], [page.id, page.headerBand.id]);
@@ -103954,6 +104255,7 @@ function buildLayoutMeta(pages) {
103954
104255
  const lineCenter = /* @__PURE__ */ new Map();
103955
104256
  const widgetMetaMap = /* @__PURE__ */ new Map();
103956
104257
  const widgetIds = [];
104258
+ const tableCtxStack = [];
103957
104259
  const ctx = {
103958
104260
  currentPageId: "",
103959
104261
  lineIndex: -1,
@@ -103978,7 +104280,8 @@ function buildLayoutMeta(pages) {
103978
104280
  pageArea: ctx.area,
103979
104281
  sort: areaOrder * 1e5 + ctx.lineIndex,
103980
104282
  nextIds: children.map((c) => c.id),
103981
- size: absBoxes
104283
+ size: absBoxes,
104284
+ tableId: type === "tablerow" ? ctx.tableId : void 0
103982
104285
  });
103983
104286
  }
103984
104287
  walkPageDFS(pages, (node, pathIndex, path) => {
@@ -104001,6 +104304,17 @@ function buildLayoutMeta(pages) {
104001
104304
  lineUtils.enterOverlay(ctx);
104002
104305
  break;
104003
104306
  case BuiltinComponentTypeConst.Table:
104307
+ tableCtxStack.push({
104308
+ tableId: ctx.tableId,
104309
+ tableRowId: ctx.tableRowId,
104310
+ tableRowIndex: ctx.tableRowIndex,
104311
+ __rowCounter: ctx.__rowCounter,
104312
+ tableCellId: ctx.tableCellId,
104313
+ tableCellIndex: ctx.tableCellIndex,
104314
+ __cellCounter: ctx.__cellCounter,
104315
+ lineId: ctx.lineId,
104316
+ lineType: ctx.lineType
104317
+ });
104004
104318
  lineUtils.enterTable(ctx, node.id);
104005
104319
  break;
104006
104320
  case BuiltinComponentTypeConst.TableRow:
@@ -104057,6 +104371,21 @@ function buildLayoutMeta(pages) {
104057
104371
  dataCenter.set(node.id, fr);
104058
104372
  widgetIds.push(node.id);
104059
104373
  cursor += textMeta.charLength;
104374
+ }, (node) => {
104375
+ if ((node === null || node === void 0 ? void 0 : node.component) === BuiltinComponentTypeConst.Table) {
104376
+ const saved = tableCtxStack.pop();
104377
+ if (saved) {
104378
+ ctx.tableId = saved.tableId;
104379
+ ctx.tableRowId = saved.tableRowId;
104380
+ ctx.tableRowIndex = saved.tableRowIndex;
104381
+ ctx.__rowCounter = saved.__rowCounter;
104382
+ ctx.tableCellId = saved.tableCellId;
104383
+ ctx.tableCellIndex = saved.tableCellIndex;
104384
+ ctx.__cellCounter = saved.__cellCounter;
104385
+ ctx.lineId = saved.lineId;
104386
+ ctx.lineType = saved.lineType;
104387
+ }
104388
+ }
104060
104389
  });
104061
104390
  return {
104062
104391
  dataCenter,
@@ -104843,6 +105172,14 @@ var init_TableCellHitHandler = __esmMin((() => {
104843
105172
  }
104844
105173
  return null;
104845
105174
  }
105175
+ if (this.registry) {
105176
+ const sideInfo = getIntervalSide(toVerticalIntervalsAbs(doc, childMeta, node.pageId), actualY);
105177
+ if (sideInfo) {
105178
+ const nearestMeta = childMeta[sideInfo.index];
105179
+ const delegated = this.registry.handleHitDetection(doc, nearestMeta, actualX, actualY);
105180
+ if (delegated) return delegated;
105181
+ }
105182
+ }
104846
105183
  return null;
104847
105184
  }
104848
105185
  };
@@ -105135,6 +105472,84 @@ var init_getCursorCoords = __esmMin((() => {
105135
105472
  }));
105136
105473
  //#endregion
105137
105474
  //#region src/core/cursor/logic/selectionAnalyzer.ts
105475
+ /**
105476
+ * 判断 tableId 对应的表格是否是嵌套表(path 中存在 TableCell 祖先)。
105477
+ * 嵌套表的选区不允许扩散到外部段落。
105478
+ */
105479
+ function isTableNested(doc, tableId) {
105480
+ const tableMeta = doc.layoutMapper.getBaseMetaNodeById(tableId);
105481
+ return ((tableMeta === null || tableMeta === void 0 ? void 0 : tableMeta.path) ?? []).some((pid) => {
105482
+ const meta = doc.layoutMapper.getBaseMetaNodeById(pid);
105483
+ return (meta === null || meta === void 0 ? void 0 : meta.component) === BuiltinComponentTypeConst.TableCell;
105484
+ });
105485
+ }
105486
+ function findEnclosingTable(node) {
105487
+ let current = node;
105488
+ while (current) {
105489
+ if (current instanceof Wtbl) return current;
105490
+ current = current.parent;
105491
+ }
105492
+ }
105493
+ /** 从 model 节点向上解析当前表格作用域 */
105494
+ function resolveTableScopeFromModelNode(node) {
105495
+ const wtbl = findEnclosingTable(node);
105496
+ return wtbl === null || wtbl === void 0 ? void 0 : wtbl.getTableScope();
105497
+ }
105498
+ /** 从光标定位当前 Wtbl 作用域(含嵌套表内光标) */
105499
+ function resolveTableScopeFromCursor(doc) {
105500
+ const cursor = doc.cursorManager.getCursor();
105501
+ if (!(cursor === null || cursor === void 0 ? void 0 : cursor.nodeId)) return void 0;
105502
+ const mapper = doc.layoutMapper;
105503
+ let layoutNode = mapper.getLayoutNodeById(cursor.nodeId);
105504
+ while (layoutNode) {
105505
+ var _layoutNode$modelRef;
105506
+ let modelNode;
105507
+ if ((_layoutNode$modelRef = layoutNode.modelRef) === null || _layoutNode$modelRef === void 0 ? void 0 : _layoutNode$modelRef.id) modelNode = mapper.getModelNodeById(layoutNode.modelRef.id);
105508
+ else try {
105509
+ modelNode = mapper.getModelNodeByLayoutId(layoutNode.id);
105510
+ } catch {
105511
+ modelNode = void 0;
105512
+ }
105513
+ if (modelNode) {
105514
+ const scope = resolveTableScopeFromModelNode(modelNode);
105515
+ if (scope) return scope;
105516
+ }
105517
+ layoutNode = layoutNode.parent;
105518
+ }
105519
+ }
105520
+ /** 从当前选区解析表格作用域(仅单表,跨内外表时返回 undefined) */
105521
+ function resolveSelectionTableScope(doc) {
105522
+ var _anchorMeta$line, _focusMeta$line, _tableMeta$raw;
105523
+ const cursor = doc.cursorManager;
105524
+ if (cursor.isCollapsed()) return void 0;
105525
+ const selection = cursor.getSelection();
105526
+ if (!selection) return void 0;
105527
+ const anchorMeta = doc.layoutMapper.getBaseMetaNodeById(selection.anchor.nodeId);
105528
+ const focusMeta = doc.layoutMapper.getBaseMetaNodeById(selection.focus.nodeId);
105529
+ const anchorTableLayoutId = (anchorMeta === null || anchorMeta === void 0 || (_anchorMeta$line = anchorMeta.line) === null || _anchorMeta$line === void 0 ? void 0 : _anchorMeta$line.lineType) === "tablerow" ? anchorMeta.line.tableId : void 0;
105530
+ const focusTableLayoutId = (focusMeta === null || focusMeta === void 0 || (_focusMeta$line = focusMeta.line) === null || _focusMeta$line === void 0 ? void 0 : _focusMeta$line.lineType) === "tablerow" ? focusMeta.line.tableId : void 0;
105531
+ const targetTableLayoutId = anchorTableLayoutId ?? focusTableLayoutId;
105532
+ if (!targetTableLayoutId) return void 0;
105533
+ const tableMeta = doc.layoutMapper.getBaseMetaNodeById(targetTableLayoutId);
105534
+ const modelId = tableMeta === null || tableMeta === void 0 || (_tableMeta$raw = tableMeta.raw) === null || _tableMeta$raw === void 0 || (_tableMeta$raw = _tableMeta$raw.modelRef) === null || _tableMeta$raw === void 0 ? void 0 : _tableMeta$raw.id;
105535
+ if (!modelId) return void 0;
105536
+ const wtbl = doc.layoutMapper.getModelNodeById(modelId);
105537
+ return wtbl === null || wtbl === void 0 ? void 0 : wtbl.getTableScope();
105538
+ }
105539
+ /**
105540
+ * 当 focus 跑出 selectionTable 时,尝试从 focus 的祖先路径里
105541
+ * 找到 selectionTable 某行的某个 cell,返回该列下标。
105542
+ * 适用场景:拖外表时 focus 落到了内表(内表所在外表 cell 的列下标需要被找到)。
105543
+ */
105544
+ function resolveHostCellIndex(focusMeta, scopedLines) {
105545
+ var _focusMeta$path;
105546
+ if (!(focusMeta === null || focusMeta === void 0 || (_focusMeta$path = focusMeta.path) === null || _focusMeta$path === void 0 ? void 0 : _focusMeta$path.length)) return void 0;
105547
+ const pathSet = new Set(focusMeta.path);
105548
+ for (const line of scopedLines) for (let ci = 0; ci < line.nextIds.length; ci++) {
105549
+ const cellId = line.nextIds[ci];
105550
+ if (cellId && pathSet.has(cellId)) return ci;
105551
+ }
105552
+ }
105138
105553
  function collectSelectedLines(doc, pageIds, startPageIdx, endPageIdx, startLineId, endLineId) {
105139
105554
  const lines = [];
105140
105555
  for (let pi = startPageIdx; pi <= endPageIdx; pi++) {
@@ -105145,6 +105560,7 @@ function collectSelectedLines(doc, pageIds, startPageIdx, endPageIdx, startLineI
105145
105560
  if (pi === startPageIdx) from = lineIds.indexOf(startLineId);
105146
105561
  if (pi === endPageIdx) to = lineIds.indexOf(endLineId);
105147
105562
  if (from < 0 || to < 0) continue;
105563
+ if (from > to) [from, to] = [to, from];
105148
105564
  for (let i = from; i <= to; i++) {
105149
105565
  const line = doc.layoutMapper.getLineInfoById(lineIds[i]);
105150
105566
  if (line) lines.push(line);
@@ -105152,26 +105568,28 @@ function collectSelectedLines(doc, pageIds, startPageIdx, endPageIdx, startLineI
105152
105568
  }
105153
105569
  return lines;
105154
105570
  }
105155
- function analyzeTableSelectionModeByLines(lines, start, end) {
105156
- var _start$line, _end$line, _start$line2, _end$line2;
105157
- if (!lines.length) return "none";
105158
- const hasTable = lines.some((l) => l.type === "tablerow");
105159
- const hasNonTable = lines.some((l) => l.type !== "tablerow");
105160
- if (!hasTable) return "none";
105161
- if (hasNonTable) return "mixed";
105162
- if (lines.filter((l) => l.type === "tablerow").length === 1 && ((_start$line = start.line) === null || _start$line === void 0 ? void 0 : _start$line.tableRowIndex) === ((_end$line = end.line) === null || _end$line === void 0 ? void 0 : _end$line.tableRowIndex) && ((_start$line2 = start.line) === null || _start$line2 === void 0 ? void 0 : _start$line2.tableCellIndex) === ((_end$line2 = end.line) === null || _end$line2 === void 0 ? void 0 : _end$line2.tableCellIndex)) return "cell-inner";
105163
- return "cell-range";
105164
- }
105165
105571
  /**
105572
+ * 计算选区的行级信息(scopedSelectedLines、tableMode、rangeWidgetIds 等)。
105166
105573
  *
105167
- * @param doc
105168
- * @param selection
105169
- * @param upgrade 单元格是否升级成单个单元格选中
105170
- * @returns
105574
+ * 过滤规则:
105575
+ * - anchor 在嵌套表格内 → 严格夹紧在该嵌套表,不纳入外部行/段落
105576
+ * - 其他情况 → 纳入所有顶层表格行 + 所有段落
105577
+ *
105578
+ * tableMode 决定策略:
105579
+ * - mixed → 多张顶层表 OR (表格行 + 段落) → 选整行;段落单独生成 rect
105580
+ * - cell-range → 单张表、多行或跨列
105581
+ * - cell-inner → 单张表、单行、同一列(单格内文字选区)
105582
+ * - cell-full → cell-inner 升级:选中整格(isCellUpgrade)
105583
+ * - none → 纯段落 / 空
105584
+ *
105585
+ * @param upgrade 鼠标在 cellHitPoint 角上,允许 cell-inner → cell-full 升级
105171
105586
  */
105172
105587
  function getSelectLinesInfo(doc, selection, upgrade) {
105588
+ var _anchorMeta$line2, _anchorMeta$line3, _focusMeta$line2;
105173
105589
  const pageIds = doc.layoutMapper.getAllPageIds();
105174
105590
  const normalized = doc.cursorManager.normalizeRange(selection);
105591
+ const anchorMeta = doc.layoutMapper.getBaseMetaNodeById(selection.anchor.nodeId);
105592
+ const focusMeta = doc.layoutMapper.getBaseMetaNodeById(selection.focus.nodeId);
105175
105593
  const start = doc.layoutMapper.getBaseMetaNodeById(normalized.rangeStart.nodeId);
105176
105594
  const end = doc.layoutMapper.getBaseMetaNodeById(normalized.rangeEnd.nodeId);
105177
105595
  if (!start || !end) return;
@@ -105179,7 +105597,57 @@ function getSelectLinesInfo(doc, selection, upgrade) {
105179
105597
  const endPageIdx = pageIds.indexOf(end.pageId);
105180
105598
  if (startPageIdx < 0 || endPageIdx < 0) return;
105181
105599
  const selectedLines = collectSelectedLines(doc, pageIds, startPageIdx, endPageIdx, start.line.lineId, end.line.lineId);
105182
- let tableMode = analyzeTableSelectionModeByLines(selectedLines, start, end);
105600
+ const selectionTableId = (anchorMeta === null || anchorMeta === void 0 || (_anchorMeta$line2 = anchorMeta.line) === null || _anchorMeta$line2 === void 0 ? void 0 : _anchorMeta$line2.lineType) === "tablerow" ? anchorMeta.line.tableId : void 0;
105601
+ const selectionIsNested = selectionTableId ? isTableNested(doc, selectionTableId) : false;
105602
+ const anchorCellIndex = (anchorMeta === null || anchorMeta === void 0 || (_anchorMeta$line3 = anchorMeta.line) === null || _anchorMeta$line3 === void 0 ? void 0 : _anchorMeta$line3.lineType) === "tablerow" && anchorMeta.line.tableId === selectionTableId ? anchorMeta.line.tableCellIndex : void 0;
105603
+ const focusCellIndex = (focusMeta === null || focusMeta === void 0 || (_focusMeta$line2 = focusMeta.line) === null || _focusMeta$line2 === void 0 ? void 0 : _focusMeta$line2.lineType) === "tablerow" && focusMeta.line.tableId === selectionTableId ? focusMeta.line.tableCellIndex : void 0;
105604
+ let scopedSelectedLines = selectionIsNested ? selectedLines.filter((line) => line.type === "tablerow" && line.tableId === selectionTableId) : selectedLines.filter((line) => {
105605
+ if (line.type !== "tablerow") return true;
105606
+ return !isTableNested(doc, line.tableId);
105607
+ });
105608
+ const calcScope = () => ({
105609
+ uniqueTableIds: new Set(scopedSelectedLines.filter((l) => l.type === "tablerow" && l.tableId).map((l) => l.tableId)),
105610
+ hasParagraphs: scopedSelectedLines.some((l) => l.type !== "tablerow")
105611
+ });
105612
+ let { uniqueTableIds, hasParagraphs } = calcScope();
105613
+ let hasTableRows = uniqueTableIds.size > 0;
105614
+ let isMultiTable = uniqueTableIds.size > 1;
105615
+ const scopedStartCellIndex = anchorCellIndex;
105616
+ let scopedEndCellIndex = focusCellIndex;
105617
+ let focusClampToLast;
105618
+ if (!isMultiTable && !hasParagraphs && typeof scopedEndCellIndex !== "number" && selectionTableId) {
105619
+ scopedEndCellIndex = resolveHostCellIndex(focusMeta, scopedSelectedLines);
105620
+ if (typeof scopedEndCellIndex !== "number") {
105621
+ var _start$line3;
105622
+ focusClampToLast = ((_start$line3 = start.line) === null || _start$line3 === void 0 ? void 0 : _start$line3.tableId) === selectionTableId;
105623
+ }
105624
+ }
105625
+ if (selectionIsNested && selectionTableId && typeof focusClampToLast === "boolean") {
105626
+ const allNestedRows = [];
105627
+ for (let pi = startPageIdx; pi <= endPageIdx; pi++) {
105628
+ const pid = pageIds[pi];
105629
+ for (const lineId of doc.layoutMapper.getLineIdsByPageId(pid)) {
105630
+ const li = doc.layoutMapper.getLineInfoById(lineId);
105631
+ if ((li === null || li === void 0 ? void 0 : li.type) === "tablerow" && li.tableId === selectionTableId) allNestedRows.push(li);
105632
+ }
105633
+ }
105634
+ if (allNestedRows.length > 0) {
105635
+ var _anchorMeta$line4;
105636
+ const anchorLineId = anchorMeta === null || anchorMeta === void 0 || (_anchorMeta$line4 = anchorMeta.line) === null || _anchorMeta$line4 === void 0 ? void 0 : _anchorMeta$line4.lineId;
105637
+ const anchorIdx = allNestedRows.findIndex((r) => r.id === anchorLineId);
105638
+ const safeIdx = anchorIdx >= 0 ? anchorIdx : 0;
105639
+ scopedSelectedLines = focusClampToLast ? allNestedRows.slice(safeIdx) : allNestedRows.slice(0, safeIdx + 1);
105640
+ ({uniqueTableIds, hasParagraphs} = calcScope());
105641
+ hasTableRows = uniqueTableIds.size > 0;
105642
+ isMultiTable = uniqueTableIds.size > 1;
105643
+ }
105644
+ }
105645
+ let tableMode;
105646
+ if (!hasTableRows) tableMode = "none";
105647
+ else if (isMultiTable || hasParagraphs && hasTableRows) tableMode = "mixed";
105648
+ else if (scopedSelectedLines.length === 0) tableMode = "none";
105649
+ else if (scopedSelectedLines.length === 1 && typeof scopedStartCellIndex === "number" && typeof scopedEndCellIndex === "number" && scopedStartCellIndex === scopedEndCellIndex) tableMode = "cell-inner";
105650
+ else tableMode = "cell-range";
105183
105651
  const startRunIndex = normalized.rangeStart.side === "after" ? start.runIndex + 1 : start.runIndex;
105184
105652
  const endRunIndex = normalized.rangeEnd.side === "before" ? end.runIndex : end.runIndex + 1;
105185
105653
  const overlapIds = doc.layoutMapper.widgetIds.slice(startRunIndex, endRunIndex);
@@ -105198,37 +105666,41 @@ function getSelectLinesInfo(doc, selection, upgrade) {
105198
105666
  }
105199
105667
  });
105200
105668
  if (tableMode === "cell-inner") {
105201
- const row = start.line;
105669
+ var _anchorMeta$line5;
105670
+ const row = (anchorMeta === null || anchorMeta === void 0 || (_anchorMeta$line5 = anchorMeta.line) === null || _anchorMeta$line5 === void 0 ? void 0 : _anchorMeta$line5.tableId) === selectionTableId ? anchorMeta.line : start.line;
105202
105671
  const cellId = row === null || row === void 0 ? void 0 : row.tableCellId;
105203
- if (row && cellId) {
105672
+ if (row && cellId && (!selectionTableId || row.tableId === selectionTableId)) {
105204
105673
  const cellNode = doc.layoutMapper.getBaseMetaNodeById(cellId);
105205
105674
  if (cellNode) {
105206
- const allRunsInCell = doc.layoutMapper.getChildMetaNodes(cellNode.id).filter((n) => isAtom(n.component));
105207
- const selectedRunsInCell = Array.from(widgetRunMap.values()).flat().filter((n) => {
105675
+ const allRunsInCell = doc.layoutMapper.getChildMetaNodes(cellNode.id).filter((n) => {
105208
105676
  var _n$line;
105209
- return ((_n$line = n.line) === null || _n$line === void 0 ? void 0 : _n$line.tableCellId) === cellId;
105677
+ return isAtom(n.component) && ((_n$line = n.line) === null || _n$line === void 0 ? void 0 : _n$line.tableCellId) === cellId;
105678
+ });
105679
+ const selectedRunsInCell = Array.from(widgetRunMap.values()).flat().filter((n) => {
105680
+ var _n$line2, _n$line3;
105681
+ return ((_n$line2 = n.line) === null || _n$line2 === void 0 ? void 0 : _n$line2.tableCellId) === cellId && ((_n$line3 = n.line) === null || _n$line3 === void 0 ? void 0 : _n$line3.tableId) === selectionTableId;
105210
105682
  });
105211
105683
  if (allRunsInCell.length > 0 && selectedRunsInCell.length === allRunsInCell.length && upgrade) tableMode = "cell-full";
105212
105684
  }
105213
105685
  }
105214
105686
  }
105215
105687
  const rangeWidgetIds = [];
105216
- selectedLines.forEach((line) => {
105217
- if (line.type === "tablerow" && tableMode === "cell-range") {
105218
- var _start$line3, _end$line3;
105219
- const startCellIndex = (_start$line3 = start.line) === null || _start$line3 === void 0 ? void 0 : _start$line3.tableCellIndex;
105220
- const endCellIndex = (_end$line3 = end.line) === null || _end$line3 === void 0 ? void 0 : _end$line3.tableCellIndex;
105221
- const colFrom = Math.min(startCellIndex, endCellIndex);
105222
- const colTo = Math.max(startCellIndex, endCellIndex);
105688
+ scopedSelectedLines.forEach((line) => {
105689
+ if (line.type !== "tablerow") return;
105690
+ if (tableMode === "cell-range") {
105691
+ 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);
105223
105695
  for (let ci = colFrom; ci <= colTo; ci++) {
105224
105696
  const cellId = line.nextIds[ci];
105225
- if (!cellId) continue;
105226
- rangeWidgetIds.push(cellId);
105697
+ if (cellId) rangeWidgetIds.push(cellId);
105227
105698
  }
105228
- } else if (line.type === "tablerow" && tableMode === "cell-full") {
105229
- var _start$line4, _end$line4;
105699
+ } else if (tableMode === "cell-full") {
105700
+ var _start$line4, _end$line3;
105230
105701
  const startCellId = (_start$line4 = start.line) === null || _start$line4 === void 0 ? void 0 : _start$line4.tableCellId;
105231
- if (startCellId === ((_end$line4 = end.line) === null || _end$line4 === void 0 ? void 0 : _end$line4.tableCellId)) {
105702
+ const endCellId = (_end$line3 = end.line) === null || _end$line3 === void 0 ? void 0 : _end$line3.tableCellId;
105703
+ if (startCellId && startCellId === endCellId) {
105232
105704
  var _start$line5;
105233
105705
  const cell = doc.layoutMapper.getLayoutNodeById(startCellId);
105234
105706
  const table = doc.layoutMapper.getLayoutNodeById((_start$line5 = start.line) === null || _start$line5 === void 0 ? void 0 : _start$line5.tableId);
@@ -105243,12 +105715,12 @@ function getSelectLinesInfo(doc, selection, upgrade) {
105243
105715
  startColIdx,
105244
105716
  endRowIdx: startRowIdx + rowspan - 1,
105245
105717
  endColIdx: startColIdx + colspan - 1,
105246
- callback: (c) => {
105247
- rangeWidgetIds.push(c.id);
105248
- }
105718
+ callback: (c) => rangeWidgetIds.push(c.id)
105249
105719
  });
105250
105720
  }
105251
105721
  }
105722
+ } else if (tableMode === "mixed") {
105723
+ for (const cellId of line.nextIds) if (cellId) rangeWidgetIds.push(cellId);
105252
105724
  }
105253
105725
  });
105254
105726
  return {
@@ -105258,15 +105730,23 @@ function getSelectLinesInfo(doc, selection, upgrade) {
105258
105730
  end,
105259
105731
  startPageIdx,
105260
105732
  endPageIdx,
105261
- selectedLines,
105733
+ selectedLines: scopedSelectedLines,
105262
105734
  tableMode,
105263
105735
  overlapIds,
105264
105736
  widgetRunMap,
105265
- rangeWidgetIds
105737
+ rangeWidgetIds,
105738
+ selectionTableId,
105739
+ anchorCellIndex: scopedStartCellIndex,
105740
+ focusCellIndex: scopedEndCellIndex,
105741
+ /** focus 越界夹紧方向:true=夹末列,false=夹首列,undefined=已有精确值 */
105742
+ focusClampToLast
105266
105743
  };
105267
105744
  }
105268
105745
  var init_selectionAnalyzer = __esmMin((() => {
105269
105746
  init_LayoutBuilder();
105747
+ init_Wtbl();
105748
+ init_document();
105749
+ init_constants$1();
105270
105750
  }));
105271
105751
  //#endregion
105272
105752
  //#region src/core/cursor/logic/getCursorTextRawList.ts
@@ -105359,89 +105839,115 @@ var init_LayoutGeometry = __esmMin((() => {
105359
105839
  //#endregion
105360
105840
  //#region src/core/cursor/logic/getSelectionRects.ts
105361
105841
  /**
105362
- * 将 selection(逻辑选区)转换成一组视觉矩形(canvas 绝对坐标)
105842
+ * 将 selection(逻辑选区)转换成一组视觉矩形(canvas 绝对坐标)和单元格 ID 集合。
105843
+ *
105844
+ * 高亮策略(按模式):
105845
+ * - cell-range / cell-full / mixed(表格行部分)
105846
+ * → cellRangeIds:由 table-cell.vue 在内容层渲染选中背景,
105847
+ * 内表格单元格的白色背景会自然覆盖外格蓝色,无需额外处理。
105848
+ * - cell-inner
105849
+ * → rects:cursor 覆盖层渲染文字级别高亮;
105850
+ * 只保留属于 selectionTableId 的原子节点(过滤掉内表格 atoms,解决 Q6 场景)。
105851
+ * - mixed(段落部分) / 纯段落
105852
+ * → rects:cursor 覆盖层渲染。
105363
105853
  */
105364
105854
  function getSelectionRects(doc, selection, upgrade) {
105365
105855
  const rects = [];
105366
- if (!selection || !selection.anchor || !selection.focus) return rects;
105367
- if (doc.cursorManager.isCollapsed()) return rects;
105856
+ const cellRangeIds = [];
105857
+ if (!selection || !selection.anchor || !selection.focus) return {
105858
+ rects,
105859
+ cellRangeIds
105860
+ };
105861
+ if (doc.cursorManager.isCollapsed()) return {
105862
+ rects,
105863
+ cellRangeIds
105864
+ };
105368
105865
  const info = getSelectLinesInfo(doc, selection, upgrade);
105369
- if (!info) return rects;
105370
- const { normalized, start, end, selectedLines, tableMode, widgetRunMap } = info;
105866
+ if (!info) return {
105867
+ rects,
105868
+ cellRangeIds
105869
+ };
105870
+ const { normalized, start, end, selectedLines, tableMode, widgetRunMap, rangeWidgetIds, selectionTableId } = info;
105871
+ const layoutMapper = doc.layoutMapper;
105872
+ const toCanvas = (pageId, x, y) => layoutMapper.getAbsoluteCanvasPosition(pageId, x, y);
105371
105873
  const startLeft = normalized.rangeStart.side === "after" ? start.absbox.left + start.width : start.absbox.left;
105372
105874
  const endRight = normalized.rangeEnd.side === "before" ? end.absbox.left : end.absbox.left + end.width;
105373
- const layoutMapper = doc.layoutMapper;
105374
- const getAbsoluteCanvasPosition = (pageId, x, y) => layoutMapper.getAbsoluteCanvasPosition(pageId, x, y);
105375
- for (let li = 0; li < selectedLines.length; li++) {
105376
- var _start$line, _end$line;
105377
- const line = selectedLines[li];
105378
- if (!line) continue;
105379
- const isStartLine = line.id === ((_start$line = start.line) === null || _start$line === void 0 ? void 0 : _start$line.lineId);
105380
- const isEndLine = line.id === ((_end$line = end.line) === null || _end$line === void 0 ? void 0 : _end$line.lineId);
105381
- const cells = line.size;
105382
- if (!(cells === null || cells === void 0 ? void 0 : cells.length)) continue;
105383
- if (line.type === "paragraph") {
105384
- const b = computeBoundsFromSize(cells, line.pageId, isStartLine ? startLeft : 0, isEndLine ? endRight : Infinity);
105875
+ if (tableMode === "cell-range" || tableMode === "cell-full") {
105876
+ cellRangeIds.push(...rangeWidgetIds ?? []);
105877
+ return {
105878
+ rects,
105879
+ cellRangeIds
105880
+ };
105881
+ }
105882
+ if (tableMode === "mixed") {
105883
+ cellRangeIds.push(...rangeWidgetIds ?? []);
105884
+ for (const line of selectedLines) {
105885
+ var _start$line, _end$line, _line$size;
105886
+ if (line.type !== "paragraph") continue;
105887
+ const isStartLine = line.id === ((_start$line = start.line) === null || _start$line === void 0 ? void 0 : _start$line.lineId);
105888
+ const isEndLine = line.id === ((_end$line = end.line) === null || _end$line === void 0 ? void 0 : _end$line.lineId);
105889
+ if (!((_line$size = line.size) === null || _line$size === void 0 ? void 0 : _line$size.length)) continue;
105890
+ const b = computeBoundsFromSize(line.size, line.pageId, isStartLine ? startLeft : 0, isEndLine ? endRight : Infinity);
105385
105891
  if (b) rects.push(b);
105386
- } else if (line.type === "tablerow") switch (tableMode) {
105387
- case "cell-inner":
105388
- Array.from(widgetRunMap.values()).forEach((group) => {
105389
- try {
105390
- const b = computeBoundsFromRuns(group);
105391
- if (b) rects.push(b);
105392
- } catch (e) {
105393
- console.warn("error", e);
105394
- }
105395
- });
105396
- break;
105397
- case "cell-full": {
105398
- var _start$line2;
105399
- const cell = cells[(_start$line2 = start.line) === null || _start$line2 === void 0 ? void 0 : _start$line2.tableCellIndex];
105400
- if (cell) rects.push({
105401
- pageId: line.pageId,
105402
- x: cell.left,
105403
- y: cell.top,
105404
- width: cell.right - cell.left,
105405
- height: cell.bottom - cell.top
105406
- });
105407
- break;
105408
- }
105409
- case "cell-range": {
105410
- var _start$line3, _end$line2;
105411
- const startCellIndex = (_start$line3 = start.line) === null || _start$line3 === void 0 ? void 0 : _start$line3.tableCellIndex;
105412
- const endCellIndex = (_end$line2 = end.line) === null || _end$line2 === void 0 ? void 0 : _end$line2.tableCellIndex;
105413
- const colFrom = Math.min(startCellIndex, endCellIndex);
105414
- const colTo = Math.max(startCellIndex, endCellIndex);
105415
- for (let ci = colFrom; ci <= colTo; ci++) {
105416
- const cell = cells[ci];
105417
- if (!cell) continue;
105418
- rects.push({
105419
- pageId: line.pageId,
105420
- x: cell.left,
105421
- y: cell.top,
105422
- width: cell.right - cell.left,
105423
- height: cell.bottom - cell.top
105424
- });
105425
- }
105426
- break;
105427
- }
105428
- case "mixed": rects.push(...cells.map((s) => ({
105429
- pageId: line.pageId,
105430
- x: s.left,
105431
- y: s.top,
105432
- width: s.right - s.left,
105433
- height: s.bottom - s.top
105434
- })));
105435
105892
  }
105893
+ return {
105894
+ rects: rects.map((r) => {
105895
+ const abs = toCanvas(r.pageId, r.x, r.y);
105896
+ return {
105897
+ ...r,
105898
+ x: abs.x,
105899
+ y: abs.y
105900
+ };
105901
+ }),
105902
+ cellRangeIds
105903
+ };
105436
105904
  }
105437
- return rects.map((rect) => {
105438
- const abs = getAbsoluteCanvasPosition(rect.pageId, rect.x, rect.y);
105905
+ if (tableMode === "cell-inner" || tableMode === "cell-full") {
105906
+ for (const group of widgetRunMap.values()) {
105907
+ const filtered = selectionTableId ? group.filter((atom) => {
105908
+ var _atom$line;
105909
+ return ((_atom$line = atom.line) === null || _atom$line === void 0 ? void 0 : _atom$line.tableId) === selectionTableId;
105910
+ }) : group;
105911
+ if (!filtered.length) continue;
105912
+ try {
105913
+ const b = computeBoundsFromRuns(filtered);
105914
+ if (b) rects.push(b);
105915
+ } catch (e) {
105916
+ console.warn("getSelectionRects cell-inner error", e);
105917
+ }
105918
+ }
105439
105919
  return {
105440
- ...rect,
105441
- x: abs.x,
105442
- y: abs.y
105920
+ rects: rects.map((r) => {
105921
+ const abs = toCanvas(r.pageId, r.x, r.y);
105922
+ return {
105923
+ ...r,
105924
+ x: abs.x,
105925
+ y: abs.y
105926
+ };
105927
+ }),
105928
+ cellRangeIds
105443
105929
  };
105444
- });
105930
+ }
105931
+ for (const line of selectedLines) {
105932
+ var _start$line2, _end$line2, _line$size2;
105933
+ if (line.type !== "paragraph") continue;
105934
+ const isStartLine = line.id === ((_start$line2 = start.line) === null || _start$line2 === void 0 ? void 0 : _start$line2.lineId);
105935
+ const isEndLine = line.id === ((_end$line2 = end.line) === null || _end$line2 === void 0 ? void 0 : _end$line2.lineId);
105936
+ if (!((_line$size2 = line.size) === null || _line$size2 === void 0 ? void 0 : _line$size2.length)) continue;
105937
+ const b = computeBoundsFromSize(line.size, line.pageId, isStartLine ? startLeft : 0, isEndLine ? endRight : Infinity);
105938
+ if (b) rects.push(b);
105939
+ }
105940
+ return {
105941
+ rects: rects.map((r) => {
105942
+ const abs = toCanvas(r.pageId, r.x, r.y);
105943
+ return {
105944
+ ...r,
105945
+ x: abs.x,
105946
+ y: abs.y
105947
+ };
105948
+ }),
105949
+ cellRangeIds
105950
+ };
105445
105951
  }
105446
105952
  var init_getSelectionRects = __esmMin((() => {
105447
105953
  init_LayoutGeometry();
@@ -105664,7 +106170,6 @@ var init_CommandBase = __esmMin((() => {
105664
106170
  const runIds = mapper.getModelSplitById(wr.id);
105665
106171
  if (pos === -1) {
105666
106172
  const hitRun = runIds.map((id) => mapper.getLayoutNodeById(id)).reverse().find((item) => !item.widgetFieldRightMarker);
105667
- console.log("hitRun", hitRun);
105668
106173
  if (!hitRun) return null;
105669
106174
  return {
105670
106175
  nodeId: hitRun.id,
@@ -105686,14 +106191,17 @@ var init_CommandBase = __esmMin((() => {
105686
106191
  const pIds = mapper.getModelSplitById(wp.id);
105687
106192
  if (pos === 0) {
105688
106193
  const p = pIds && pIds.length > 0 ? mapper.getLayoutNodeById(pIds[0]) : void 0;
106194
+ const hitRun = p === null || p === void 0 ? void 0 : p.getFirstChild();
106195
+ if (!hitRun) return null;
105689
106196
  return {
105690
- nodeId: (p === null || p === void 0 ? void 0 : p.getFirstChild()).id,
106197
+ nodeId: hitRun.id,
105691
106198
  offset: 0,
105692
106199
  side: "before"
105693
106200
  };
105694
106201
  } else if (pos === -1) {
105695
106202
  const p = pIds && pIds.length > 0 ? mapper.getLayoutNodeById(pIds[pIds.length - 1]) : void 0;
105696
106203
  const hitRun = p === null || p === void 0 ? void 0 : p.getLastChild();
106204
+ if (!hitRun) return null;
105697
106205
  return {
105698
106206
  nodeId: hitRun.id,
105699
106207
  offset: hitRun.type === "text" ? hitRun.text.length - 1 : 0,
@@ -106956,6 +107464,7 @@ var init_DeleteTable = __esmMin((() => {
106956
107464
  console.error(`DeleteTable: table not found with id ${tableId}`);
106957
107465
  return null;
106958
107466
  }
107467
+ if (table.depth === 0) table.collectNestedTables().forEach((nested) => nested.remove());
106959
107468
  table.remove();
106960
107469
  return null;
106961
107470
  }
@@ -107937,6 +108446,858 @@ var init_InsertRow = __esmMin((() => {
107937
108446
  };
107938
108447
  }));
107939
108448
  //#endregion
108449
+ //#region src/domain/table/design/ribbon-options.ts
108450
+ /** 生成 Ribbon「数据表」「业务表」下拉选项 */
108451
+ function getRibbonTableOptions() {
108452
+ return {
108453
+ dataTables: [TABLE_HEADER_RIBBON_OPTION, ...getProfilesByCategory("data").map((profile) => ({
108454
+ value: profile.ribbonAction,
108455
+ label: profile.label,
108456
+ disabled: profile.enabled === false
108457
+ }))],
108458
+ businessTables: BUSINESS_RIBBON_GROUPS.map((group) => ({
108459
+ label: group.label,
108460
+ _showDivider: group.showDivider,
108461
+ options: group.tableTypes.map((type) => getProfile(type)).filter((profile) => Boolean(profile)).map((profile) => ({
108462
+ value: profile.ribbonAction,
108463
+ label: profile.label,
108464
+ disabled: profile.enabled === false
108465
+ }))
108466
+ }))
108467
+ };
108468
+ }
108469
+ var TABLE_HEADER_RIBBON_OPTION, BUSINESS_RIBBON_GROUPS;
108470
+ var init_ribbon_options = __esmMin((() => {
108471
+ init_registry$5();
108472
+ TABLE_HEADER_RIBBON_OPTION = {
108473
+ value: "set-table-header",
108474
+ label: "表头"
108475
+ };
108476
+ BUSINESS_RIBBON_GROUPS = [
108477
+ {
108478
+ label: "仓储",
108479
+ tableTypes: [
108480
+ "warehouse-in-out",
108481
+ "warehouse-inventory",
108482
+ "warehouse-allocate"
108483
+ ]
108484
+ },
108485
+ {
108486
+ label: "物料",
108487
+ showDivider: true,
108488
+ tableTypes: ["material-consume", "material-balance"]
108489
+ },
108490
+ {
108491
+ label: "检验",
108492
+ showDivider: true,
108493
+ tableTypes: ["check-table"]
108494
+ },
108495
+ {
108496
+ label: "灭菌",
108497
+ showDivider: true,
108498
+ tableTypes: ["entrust-steril-batch-list"]
108499
+ },
108500
+ {
108501
+ label: "预处理",
108502
+ showDivider: true,
108503
+ tableTypes: ["pretreatment-list"]
108504
+ }
108505
+ ];
108506
+ }));
108507
+ //#endregion
108508
+ //#region src/domain/table/design/theme/region-item-theme.ts
108509
+ var REGION_ITEM_THEME;
108510
+ var init_region_item_theme = __esmMin((() => {
108511
+ REGION_ITEM_THEME = {
108512
+ "table-header": {
108513
+ label: "表头",
108514
+ color: "#B54096",
108515
+ background: "rgba(181,64,150,0.2)",
108516
+ labelBjColor: "rgba(181,64,150,0.8)"
108517
+ },
108518
+ "data-group": {
108519
+ label: "数据分组",
108520
+ color: "#F84E92",
108521
+ background: "rgba(248,78,146,0.2)",
108522
+ labelBjColor: "rgba(248,78,146,0.8)"
108523
+ },
108524
+ "data-group-2d": {
108525
+ label: "动态关联",
108526
+ color: "#F84E92",
108527
+ background: "rgba(248,78,146,0.2)",
108528
+ labelBjColor: "rgba(248,78,146,0.8)"
108529
+ }
108530
+ };
108531
+ }));
108532
+ //#endregion
108533
+ //#region src/domain/table/design/label.ts
108534
+ /** 按 layout 类型获取展示名称(面板标题、设置项等) */
108535
+ function getTableLabelByLayoutType(layoutType) {
108536
+ var _getProfileByLayoutTy, _REGION_ITEM_THEME$la;
108537
+ return ((_getProfileByLayoutTy = getProfileByLayoutType(layoutType)) === null || _getProfileByLayoutTy === void 0 ? void 0 : _getProfileByLayoutTy.label) ?? ((_REGION_ITEM_THEME$la = REGION_ITEM_THEME[layoutType]) === null || _REGION_ITEM_THEME$la === void 0 ? void 0 : _REGION_ITEM_THEME$la.label) ?? layoutType;
108538
+ }
108539
+ var init_label = __esmMin((() => {
108540
+ init_registry$5();
108541
+ init_region_item_theme();
108542
+ }));
108543
+ //#endregion
108544
+ //#region src/domain/table/design/sub-model-matcher.ts
108545
+ /**
108546
+ * 判断 master_slave 字段是否为业务子模型
108547
+ * refModelType 为空 → 数据子表;在业务注册表中 → 业务子表
108548
+ */
108549
+ function isBusinessSubModel(field, businessRefModelTypes = getAllBusinessRefModelTypes()) {
108550
+ if (field.type !== FIELD_TYPE.MASTERSLAVE) return false;
108551
+ const refType = field.refModelType;
108552
+ if (!refType) return false;
108553
+ return businessRefModelTypes.includes(refType);
108554
+ }
108555
+ /**
108556
+ * 判断字段是否可用于指定表类型
108557
+ * @returns true 表示该 master_slave 字段可作为此表的关联子模型
108558
+ */
108559
+ function matchSubModel(field, profile) {
108560
+ if (field.type !== FIELD_TYPE.MASTERSLAVE) return false;
108561
+ if (isDataTableProfile(profile)) return !isBusinessSubModel(field);
108562
+ if (isBusinessSubTableProfile(profile)) return field.refModelType === profile.match.refModelType;
108563
+ return false;
108564
+ }
108565
+ /**
108566
+ * 生成「选择子模型」下拉选项
108567
+ * @param tableTypeOrRibbonAction 表类型或 Ribbon action
108568
+ * @param fields 主模型下所有字段
108569
+ * @param usedKeys 文档中已占用的子模型 field key(不可重复绑定)
108570
+ */
108571
+ function getSubModelOptions(tableTypeOrRibbonAction, fields, usedKeys = []) {
108572
+ const profile = getProfile(tableTypeOrRibbonAction) ?? getProfileByRibbonAction(tableTypeOrRibbonAction);
108573
+ if (!profile) return [];
108574
+ return fields.filter((field) => matchSubModel(field, profile)).map((field) => ({
108575
+ label: field.name,
108576
+ value: field.key,
108577
+ disabled: usedKeys.includes(field.key)
108578
+ }));
108579
+ }
108580
+ /**
108581
+ * 动态关联模型下拉选项
108582
+ * 仅可选普通子模型
108583
+ */
108584
+ function getDynamicLinkSubModelOptions(fields, usedKeys = []) {
108585
+ return fields.filter((field) => matchSubModel(field, profile$8)).map((field) => ({
108586
+ label: field.name,
108587
+ value: field.key,
108588
+ disabled: usedKeys.includes(field.key)
108589
+ }));
108590
+ }
108591
+ /**
108592
+ * 创建子表前兜底校验
108593
+ * @throws 子模型与表类型不匹配时抛出 Error
108594
+ */
108595
+ function validateSubModelBinding(tableTypeOrRibbonAction, fieldKey, fields) {
108596
+ const profile = getProfile(tableTypeOrRibbonAction) ?? getProfileByRibbonAction(tableTypeOrRibbonAction);
108597
+ const field = fields.find((item) => item.key === fieldKey);
108598
+ if (!profile) throw new Error(`未找到表类型配置:${tableTypeOrRibbonAction}`);
108599
+ if (!field || !matchSubModel(field, profile)) throw new Error(`子模型「${(field === null || field === void 0 ? void 0 : field.name) ?? fieldKey}」不能用于「${profile.label}」`);
108600
+ }
108601
+ var init_sub_model_matcher = __esmMin((() => {
108602
+ init_field_type();
108603
+ init_two_d_table();
108604
+ init_registry$5();
108605
+ init_types$5();
108606
+ }));
108607
+ //#endregion
108608
+ //#region src/domain/table/design/theme/table-theme.ts
108609
+ function toStyleResult(label, theme) {
108610
+ if (!theme) return null;
108611
+ return {
108612
+ strokeColor: theme.color,
108613
+ backgroundColor: theme.background,
108614
+ label,
108615
+ labelBjColor: theme.labelBjColor
108616
+ };
108617
+ }
108618
+ function fromRegionItemTheme(theme) {
108619
+ return {
108620
+ strokeColor: theme.color,
108621
+ backgroundColor: theme.background,
108622
+ label: theme.label,
108623
+ labelBjColor: theme.labelBjColor
108624
+ };
108625
+ }
108626
+ /**
108627
+ * 解析子表区域样式
108628
+ */
108629
+ function getTableStyle(options) {
108630
+ const { layoutType, regionItemType } = options;
108631
+ if (layoutType) {
108632
+ const layoutProfile = getProfileByLayoutType(layoutType);
108633
+ const layoutStyle = layoutProfile && toStyleResult(layoutProfile.label, layoutProfile.theme);
108634
+ if (layoutStyle) return layoutStyle;
108635
+ }
108636
+ if (regionItemType) {
108637
+ const regionTheme = REGION_ITEM_THEME[regionItemType];
108638
+ if (regionTheme) return fromRegionItemTheme(regionTheme);
108639
+ }
108640
+ return DEFAULT_TABLE_STYLE;
108641
+ }
108642
+ /**
108643
+ * 获取子表设计态样式
108644
+ */
108645
+ function getStyleByType(type) {
108646
+ if (REGION_ITEM_OUTLINE_TYPES.has(type)) return getTableStyle({ regionItemType: type });
108647
+ return getTableStyle({ layoutType: type });
108648
+ }
108649
+ var REGION_ITEM_OUTLINE_TYPES, DEFAULT_TABLE_STYLE;
108650
+ var init_table_theme = __esmMin((() => {
108651
+ init_registry$5();
108652
+ init_region_item_theme();
108653
+ REGION_ITEM_OUTLINE_TYPES = new Set(Object.keys(REGION_ITEM_THEME));
108654
+ DEFAULT_TABLE_STYLE = {
108655
+ strokeColor: "#000",
108656
+ backgroundColor: "transparent",
108657
+ label: "",
108658
+ labelBjColor: "#666"
108659
+ };
108660
+ }));
108661
+ //#endregion
108662
+ //#region src/domain/table/runtime/engines/init-load-engine.ts
108663
+ var InitLoadEngine;
108664
+ var init_init_load_engine = __esmMin((() => {
108665
+ init_biz_service_api();
108666
+ init_runtime_handlers();
108667
+ init_table_runtime_utils();
108668
+ init_core$1();
108669
+ init_defineProperty();
108670
+ InitLoadEngine = class {
108671
+ constructor(doc) {
108672
+ _defineProperty(this, "doc", void 0);
108673
+ this.doc = doc;
108674
+ }
108675
+ async apply(ctx) {
108676
+ var _ctx$region$widgetMet;
108677
+ const config = ctx.profile.initLoad;
108678
+ if (!config) return;
108679
+ const regionProps = (_ctx$region$widgetMet = ctx.region.widgetMeta) === null || _ctx$region$widgetMet === void 0 ? void 0 : _ctx$region$widgetMet.props;
108680
+ if (!this.isEnabled(config, regionProps)) return;
108681
+ const subFieldKey = ctx.subFieldKey;
108682
+ if (this.shouldSkip(subFieldKey, config)) return;
108683
+ const query = {};
108684
+ for (const item of config.listQuery ?? []) {
108685
+ const value = readContextParam(this.doc, item.fromContext.paramKey);
108686
+ if (value !== void 0) query[item.queryKey] = value;
108687
+ }
108688
+ if (Object.keys(query).length === 0) return;
108689
+ const res = await callBizService(config.api, { ...query });
108690
+ const records = unwrapBizServiceList(res);
108691
+ const dict = unwrapBizServiceDict(res);
108692
+ if (!records.length) return;
108693
+ const groupBy = shouldGroupByWhenFieldAbsent((fieldKey) => ctx.hasFieldWidget(fieldKey), config.groupByWhenFieldAbsent);
108694
+ let rows = mapInitLoadRecords(ctx.profile.type, config.mapRecords, records, {
108695
+ doc: this.doc,
108696
+ runtimeCtx: ctx,
108697
+ groupBy,
108698
+ dict
108699
+ });
108700
+ const fills = (ctx.profile.contextAssignments ?? []).filter((a) => a.when === "onInitLoad");
108701
+ if (fills.length) rows = rows.map((row) => {
108702
+ const next = { ...row };
108703
+ for (const fill of fills) {
108704
+ const contextValue = readContextParam(this.doc, fill.paramKey);
108705
+ if (contextValue === void 0) continue;
108706
+ if (fill.onlyIfEmpty && isPresent(next[fill.fieldKey])) continue;
108707
+ next[fill.fieldKey] = contextValue;
108708
+ }
108709
+ return next;
108710
+ });
108711
+ if (config.rowPatch) rows = rows.map((row) => ({
108712
+ ...row,
108713
+ ...config.rowPatch
108714
+ }));
108715
+ const deletedRows = this.readExistingRows(subFieldKey).filter((row) => row.deleted_);
108716
+ this.doc.dataManager.set(subFieldKey, [...rows, ...deletedRows], "hydrate");
108717
+ }
108718
+ isEnabled(config, regionProps) {
108719
+ if (config.enabled === true) return true;
108720
+ if (config.enabledByWidgetProp) return !!(regionProps === null || regionProps === void 0 ? void 0 : regionProps[config.enabledByWidgetProp]);
108721
+ return false;
108722
+ }
108723
+ /**
108724
+ * 判断当前子字段是否需要跳过赋值逻辑
108725
+ * @param subFieldKey 子字段数据存储的key
108726
+ * @param skipIfRowHasAny 存在任意一个指定字段有值时,就跳过该子字段
108727
+ * @returns true-跳过,false-不跳过
108728
+ */
108729
+ shouldSkip(subFieldKey, config) {
108730
+ const existingRows = this.readExistingRows(subFieldKey).filter((row) => !row.deleted_);
108731
+ if (existingRows.length === 0) return false;
108732
+ if (config.skipWhenNonemptyRows && this.hasNonemptyRow(existingRows)) return true;
108733
+ const skipIfRowHasAny = config.skipIfRowHasAny;
108734
+ if (!(skipIfRowHasAny === null || skipIfRowHasAny === void 0 ? void 0 : skipIfRowHasAny.length)) return false;
108735
+ return existingRows.some((row) => skipIfRowHasAny.some((key) => isPresent(row[key])));
108736
+ }
108737
+ readExistingRows(subFieldKey) {
108738
+ const raw = this.doc.dataManager.getRawData()[subFieldKey];
108739
+ if (Array.isArray(raw)) return raw;
108740
+ if (raw && typeof raw === "object" && Array.isArray(raw.data)) return raw.data;
108741
+ return [];
108742
+ }
108743
+ hasNonemptyRow(rows) {
108744
+ const metaKeys = /* @__PURE__ */ new Set([
108745
+ "_DICT",
108746
+ "_OPCT",
108747
+ "__FOREIGN__",
108748
+ "__CHILDREN__",
108749
+ "deleted_",
108750
+ "group_",
108751
+ "data_version_"
108752
+ ]);
108753
+ return rows.some((row) => Object.entries(row).some(([key, value]) => {
108754
+ if (metaKeys.has(key) || key.startsWith("__gw_")) return false;
108755
+ return value != null && value !== "";
108756
+ }));
108757
+ }
108758
+ };
108759
+ }));
108760
+ //#endregion
108761
+ //#region src/domain/table/runtime/engines/main-field-bind-engine.ts
108762
+ var MainFieldBindEngine;
108763
+ var init_main_field_bind_engine = __esmMin((() => {
108764
+ init_core$1();
108765
+ init_table_runtime_utils();
108766
+ init_defineProperty();
108767
+ MainFieldBindEngine = class {
108768
+ constructor(doc) {
108769
+ _defineProperty(this, "doc", void 0);
108770
+ this.doc = doc;
108771
+ }
108772
+ apply(bindings) {
108773
+ const entries = getWidgetFieldEntries(this.doc);
108774
+ const updates = {};
108775
+ for (const binding of bindings) {
108776
+ if (binding.source.type !== "context") continue;
108777
+ const contextValue = readContextParam(this.doc, binding.source.paramKey);
108778
+ if (contextValue === void 0) continue;
108779
+ for (const { field, valuePath } of entries) {
108780
+ var _binding$excludeField;
108781
+ if (field.subFieldKey) continue;
108782
+ if (field.fieldType !== binding.fieldType) continue;
108783
+ const fieldKey = getLastSegment$1(field.fieldLink);
108784
+ if ((_binding$excludeField = binding.excludeFieldKeys) === null || _binding$excludeField === void 0 ? void 0 : _binding$excludeField.includes(fieldKey)) continue;
108785
+ if (!valuePath) continue;
108786
+ updates[valuePath] = contextValue;
108787
+ }
108788
+ }
108789
+ if (Object.keys(updates).length > 0) this.doc.dataManager.setMultiple(updates, "hydrate");
108790
+ }
108791
+ };
108792
+ }));
108793
+ //#endregion
108794
+ //#region src/domain/table/runtime/table-runtime.ts
108795
+ var TableRuntime;
108796
+ var init_table_runtime = __esmMin((() => {
108797
+ init_data();
108798
+ init_rule_engine();
108799
+ init_linkage_engine();
108800
+ init_row_runtime_engine();
108801
+ init_remote_sync_engine();
108802
+ init_init_load_engine();
108803
+ init_main_field_bind_engine();
108804
+ init_table_runtime_context();
108805
+ init_computed();
108806
+ init_autofill_runtime();
108807
+ init_defineProperty();
108808
+ TableRuntime = class {
108809
+ constructor(doc) {
108810
+ _defineProperty(this, "doc", void 0);
108811
+ _defineProperty(this, "contexts", void 0);
108812
+ _defineProperty(this, "rule", void 0);
108813
+ _defineProperty(this, "linkage", void 0);
108814
+ _defineProperty(this, "row", void 0);
108815
+ _defineProperty(this, "remoteSync", void 0);
108816
+ _defineProperty(this, "initLoad", void 0);
108817
+ _defineProperty(this, "mainFieldBind", void 0);
108818
+ this.doc = doc;
108819
+ this.contexts = TableRuntimeContext.collectAll(doc);
108820
+ this.rule = new RuleEngine(doc);
108821
+ this.linkage = new LinkageEngine(doc);
108822
+ this.row = new RowRuntimeEngine(doc);
108823
+ this.remoteSync = new RemoteSyncEngine(doc);
108824
+ this.initLoad = new InitLoadEngine(doc);
108825
+ this.mainFieldBind = new MainFieldBindEngine(doc);
108826
+ }
108827
+ /** 文档是否包含业务子表 */
108828
+ get hasBusinessTables() {
108829
+ return this.contexts.length > 0;
108830
+ }
108831
+ /** 文档初始化时执行全套运行时逻辑 */
108832
+ async onInit() {
108833
+ var _this$doc$isInEditMod, _this$doc, _this$contexts$find;
108834
+ if ((_this$doc$isInEditMod = (_this$doc = this.doc).isInEditMode) === null || _this$doc$isInEditMod === void 0 ? void 0 : _this$doc$isInEditMod.call(_this$doc)) return;
108835
+ const bindings = (_this$contexts$find = this.contexts.find((ctx) => ctx.profile.mainFieldBindings)) === null || _this$contexts$find === void 0 ? void 0 : _this$contexts$find.profile.mainFieldBindings;
108836
+ if (bindings === null || bindings === void 0 ? void 0 : bindings.length) this.mainFieldBind.apply(bindings);
108837
+ for (const ctx of this.contexts) {
108838
+ await this.initLoad.apply(ctx);
108839
+ this.row.applyRowInitForAllRows(ctx);
108840
+ this.linkage.applyForSubTable(ctx);
108841
+ this.rule.applyOnInit(ctx);
108842
+ this.remoteSync.applyOnInit(ctx);
108843
+ }
108844
+ }
108845
+ /**
108846
+ * 子表新增行初始化:rowInit → 字段态规则 → 级联 → 数据填充。
108847
+ */
108848
+ onRowInit(subFieldKey, rowIndex, rowSource) {
108849
+ var _this$doc$isInEditMod2, _this$doc2;
108850
+ if ((_this$doc$isInEditMod2 = (_this$doc2 = this.doc).isInEditMode) === null || _this$doc$isInEditMod2 === void 0 ? void 0 : _this$doc$isInEditMod2.call(_this$doc2)) return;
108851
+ const ctx = this.findContext(subFieldKey);
108852
+ if (ctx) {
108853
+ this.row.applyRowInit(ctx, rowIndex, rowSource);
108854
+ this.rule.applyOnRowInit(ctx, rowIndex);
108855
+ this.linkage.applyForSubTable(ctx, { rowIndex });
108856
+ }
108857
+ applyAutofillOnSubTableRowInit(this.doc, subFieldKey, rowIndex, fetchAutofillSource);
108858
+ hydrateSubtableRowLabels(this.doc, subFieldKey, [rowIndex]);
108859
+ }
108860
+ /**
108861
+ * 批量字段变更:对每个变更只解析路径、查上下文一次,再分派给各 engine。
108862
+ * 仅处理 source=user 的变更(hydrate/dependency/enrichment 不应触发业务副作用)。
108863
+ */
108864
+ onFieldChanges(changedMap, options) {
108865
+ var _this$doc$isInEditMod3, _this$doc3;
108866
+ if ((_this$doc$isInEditMod3 = (_this$doc3 = this.doc).isInEditMode) === null || _this$doc$isInEditMod3 === void 0 ? void 0 : _this$doc$isInEditMod3.call(_this$doc3)) return;
108867
+ if ((options === null || options === void 0 ? void 0 : options.batchSource) && options.batchSource !== "user") return;
108868
+ const userEntries = Object.entries(changedMap).filter(([, detail]) => detail.source === "user");
108869
+ if (!userEntries.length) return;
108870
+ for (const [changedPath, fieldChange] of userEntries) {
108871
+ if (isDerivedDataPath(changedPath)) continue;
108872
+ const change = parseBusinessFieldChange(changedPath);
108873
+ if (!change) continue;
108874
+ if (fieldChange && isSameFieldValue(fieldChange.oldValue, fieldChange.newValue)) continue;
108875
+ if (change.kind === "subtable") {
108876
+ const ctx = this.findContext(change.subFieldKey);
108877
+ if (!ctx) continue;
108878
+ this.row.applyRowHandlersOnFieldChange(ctx, change, fieldChange);
108879
+ this.rule.applyOnFieldChange(ctx, change, fieldChange);
108880
+ this.linkage.applyForSubTable(ctx, {
108881
+ rowIndex: change.rowIndex,
108882
+ changedFieldKey: change.fieldKey,
108883
+ fieldChange
108884
+ });
108885
+ this.remoteSync.applyOnFieldChange(ctx, change, fieldChange);
108886
+ continue;
108887
+ }
108888
+ }
108889
+ }
108890
+ /**
108891
+ * 解析下拉字段级联联动信息(联动启用状态 + 上游值),供下拉组件使用。
108892
+ */
108893
+ resolveSelectLinkage(options) {
108894
+ const { subFieldKey, fieldKey, runtimeValuePath } = options;
108895
+ if (!subFieldKey || !fieldKey) return null;
108896
+ const ctx = this.findContext(subFieldKey);
108897
+ if (!ctx) return null;
108898
+ return this.linkage.resolveSelectLinkage(ctx, fieldKey, runtimeValuePath);
108899
+ }
108900
+ /**
108901
+ * 解析业务表字段的下拉数据源 / 列覆盖(selectSource)。
108902
+ */
108903
+ resolveSelectSource(options) {
108904
+ var _ctx$findFieldProfile;
108905
+ const { subFieldKey, fieldKey } = options;
108906
+ if (!subFieldKey || !fieldKey) return null;
108907
+ const ctx = this.findContext(subFieldKey);
108908
+ if (!ctx) return null;
108909
+ return ((_ctx$findFieldProfile = ctx.findFieldProfile(fieldKey)) === null || _ctx$findFieldProfile === void 0 ? void 0 : _ctx$findFieldProfile.selectSource) ?? null;
108910
+ }
108911
+ /**
108912
+ * 下拉选中后从选项反向回填同行字段,供 onChange 使用。
108913
+ */
108914
+ buildSelectReverseFill(options) {
108915
+ var _this$doc$isInEditMod4, _this$doc4;
108916
+ if ((_this$doc$isInEditMod4 = (_this$doc4 = this.doc).isInEditMode) === null || _this$doc$isInEditMod4 === void 0 ? void 0 : _this$doc$isInEditMod4.call(_this$doc4)) return {};
108917
+ const ctx = this.findContext(options.subFieldKey);
108918
+ if (!ctx) return {};
108919
+ return this.linkage.buildSelectReverseFill(ctx, options.fieldKey, options.rowIndex, options.selectedOption);
108920
+ }
108921
+ /**
108922
+ * 选中下拉项后,按 profile.fillFromOption 同步填充同行字段(以 enrichment 写入,不触发 remoteSync)。
108923
+ */
108924
+ buildFillFromOption(options) {
108925
+ var _this$doc$isInEditMod5, _this$doc5;
108926
+ if ((_this$doc$isInEditMod5 = (_this$doc5 = this.doc).isInEditMode) === null || _this$doc$isInEditMod5 === void 0 ? void 0 : _this$doc$isInEditMod5.call(_this$doc5)) return {};
108927
+ const ctx = this.findContext(options.subFieldKey);
108928
+ if (!ctx) return {};
108929
+ return this.linkage.buildFillFromOption(ctx, options.fieldKey, options.rowIndex, options.selectedOption);
108930
+ }
108931
+ /**
108932
+ * 批量构建因字段变更需清空的级联下游字段更新集合(写入前预清空)。
108933
+ * 区分子表内字段变更 / 主表隐式联动字段变更两种场景。
108934
+ */
108935
+ buildDownstreamClears(pendingUpdates) {
108936
+ var _this$doc$isInEditMod6, _this$doc6;
108937
+ if ((_this$doc$isInEditMod6 = (_this$doc6 = this.doc).isInEditMode) === null || _this$doc$isInEditMod6 === void 0 ? void 0 : _this$doc$isInEditMod6.call(_this$doc6)) return {};
108938
+ const updates = {};
108939
+ for (const [changedPath, newValue] of Object.entries(pendingUpdates)) {
108940
+ if (isDerivedDataPath(changedPath)) continue;
108941
+ if (isSameFieldValue(this.doc.dataManager.get(changedPath), newValue)) continue;
108942
+ const change = parseBusinessFieldChange(changedPath);
108943
+ if (!change) continue;
108944
+ if (change.kind === "subtable") {
108945
+ const ctx = this.findContext(change.subFieldKey);
108946
+ if (!ctx) continue;
108947
+ const ruleCtx = ctx.buildRuleContext(change.rowIndex, change.fieldKey);
108948
+ Object.assign(updates, this.linkage.collectClearUpdates(ctx, ruleCtx, change.fieldKey));
108949
+ continue;
108950
+ }
108951
+ for (const ctx of this.contexts) {
108952
+ if (!ctx.isImplicitLinkField(change.fieldKey)) continue;
108953
+ ctx.eachRow({ changedFieldKey: change.fieldKey }, (ruleCtx) => {
108954
+ Object.assign(updates, this.linkage.collectClearUpdates(ctx, ruleCtx, change.fieldKey));
108955
+ });
108956
+ }
108957
+ }
108958
+ return updates;
108959
+ }
108960
+ findContext(subFieldKey) {
108961
+ return this.contexts.find((ctx) => ctx.subFieldKey === subFieldKey);
108962
+ }
108963
+ };
108964
+ }));
108965
+ //#endregion
108966
+ //#region src/domain/table/design/hooks/on-subtable-create.ts
108967
+ /**
108968
+ * 从当前文档收集已被子表占用的 master_slave field key
108969
+ */
108970
+ function collectUsedSubModelKeys(docModel) {
108971
+ var _docModel$document;
108972
+ if (!(docModel === null || docModel === void 0 || (_docModel$document = docModel.document) === null || _docModel$document === void 0 || (_docModel$document = _docModel$document.body) === null || _docModel$document === void 0 ? void 0 : _docModel$document.children)) return [];
108973
+ return docModel.document.body.children.flatMap((widget) => {
108974
+ if (!(widget.name === "w:tbl" && (widget.hasBounded || widget.hasCheckTable || widget.hasRepeating || widget.has2DTable || widget.hasMaterialConsumeTable))) return [];
108975
+ return [
108976
+ ...widget.bounded,
108977
+ ...widget.checkTable,
108978
+ ...widget.repeating,
108979
+ ...widget._2DTable,
108980
+ ...widget.materialConsumeTable
108981
+ ].flatMap((region) => [region.subFieldKey, region.linkFieldKey].filter(Boolean));
108982
+ });
108983
+ }
108984
+ /**
108985
+ * 确认创建子表:校验子模型绑定合法性,返回应执行的 Doc 命令
108986
+ * @throws 校验失败时抛出 Error
108987
+ */
108988
+ function confirmSubTableCreate(options) {
108989
+ const { ribbonAction, subFieldKey, fields } = options;
108990
+ const profile = getProfileByRibbonAction(ribbonAction);
108991
+ if (!profile) throw new Error(`未找到表类型配置:${ribbonAction}`);
108992
+ validateSubModelBinding(ribbonAction, subFieldKey, fields);
108993
+ return profile.command;
108994
+ }
108995
+ /** 解析 Ribbon action 对应的表 Profile */
108996
+ function resolveSubTableProfile(ribbonAction) {
108997
+ return getProfileByRibbonAction(ribbonAction) ?? getProfile(ribbonAction);
108998
+ }
108999
+ var init_on_subtable_create = __esmMin((() => {
109000
+ init_sub_model_matcher();
109001
+ init_registry$5();
109002
+ }));
109003
+ //#endregion
109004
+ //#region src/domain/table/design/hooks/on-field-attach.ts
109005
+ function matchBusinessField(field, profile) {
109006
+ const { fieldKey, bizType } = profile.match;
109007
+ if (fieldKey) {
109008
+ if ((Array.isArray(fieldKey) ? fieldKey : [fieldKey]).includes(field.key)) return true;
109009
+ }
109010
+ if (bizType) {
109011
+ if ((field.bizType ?? field.type) === bizType) return true;
109012
+ }
109013
+ return false;
109014
+ }
109015
+ /** 在业务表 fields 配置中匹配当前拖入字段 */
109016
+ function resolveBusinessFieldProfile(field, fieldProfiles = []) {
109017
+ return fieldProfiles.find((profile) => matchBusinessField(field, profile));
109018
+ }
109019
+ function applyLockedProps(props, locked) {
109020
+ if (!(locked === null || locked === void 0 ? void 0 : locked.length)) return;
109021
+ if (locked.includes("disabled")) props.disabled = true;
109022
+ if (locked.includes("required")) props.required = true;
109023
+ if (locked.includes("readonly")) props.viewState = ViewStateTypeConst.Readonly;
109024
+ }
109025
+ /**
109026
+ * 字段拖入画布时应用业务表字段 Profile
109027
+ * - 合并 defaultProps
109028
+ * - 应用 locked 属性
109029
+ * - 展开 autofillTemplates → autofillRules
109030
+ */
109031
+ function applyFieldProfileOnAttach(widget, field, options = {}) {
109032
+ var _businessProfile$fiel, _fieldProfile$autofil;
109033
+ if (!options.parentFieldKey || !options.refModelType) return widget;
109034
+ const businessProfile = getBusinessProfileByRefModelType(options.refModelType);
109035
+ if (!(businessProfile === null || businessProfile === void 0 || (_businessProfile$fiel = businessProfile.fields) === null || _businessProfile$fiel === void 0 ? void 0 : _businessProfile$fiel.length)) return widget;
109036
+ const fieldProfile = resolveBusinessFieldProfile(field, businessProfile.fields);
109037
+ if (!fieldProfile) return widget;
109038
+ const props = {
109039
+ ...widget.props,
109040
+ ...fieldProfile.defaultProps ?? {}
109041
+ };
109042
+ applyLockedProps(props, fieldProfile.locked);
109043
+ if ((_fieldProfile$autofil = fieldProfile.autofillTemplates) === null || _fieldProfile$autofil === void 0 ? void 0 : _fieldProfile$autofil.length) {
109044
+ const inSubTable = Boolean(options.parentFieldKey);
109045
+ props.autofillRules = expandAutofillTemplates(fieldProfile.autofillTemplates, {
109046
+ sourceFieldKey: field.key,
109047
+ toModelKey: inSubTable ? field.modelKey : void 0,
109048
+ toSubModel: inSubTable ? 1 : void 0,
109049
+ toSubFieldKey: inSubTable ? options.parentFieldKey : void 0
109050
+ });
109051
+ props.autofillEnabled = true;
109052
+ }
109053
+ return {
109054
+ ...widget,
109055
+ props
109056
+ };
109057
+ }
109058
+ var init_on_field_attach = __esmMin((() => {
109059
+ init_enum();
109060
+ init_autofill_expander();
109061
+ init_registry$5();
109062
+ }));
109063
+ //#endregion
109064
+ //#region src/domain/table/design/validate-table-selection.ts
109065
+ function normalizeCellBounds(bounds) {
109066
+ return {
109067
+ startRow: Math.min(bounds.start.row, bounds.end.row),
109068
+ endRow: Math.max(bounds.start.row, bounds.end.row),
109069
+ startCol: Math.min(bounds.start.col, bounds.end.col),
109070
+ endCol: Math.max(bounds.start.col, bounds.end.col)
109071
+ };
109072
+ }
109073
+ /**
109074
+ * 同一行并排多个子表(列不重叠)时,布局展开只保留后设 region,需提前拦截。
109075
+ * 若选区与已有 region 重叠,交由 findCrossRegion 处理,此处返回 undefined。
109076
+ */
109077
+ function findSameRowSubTableConflict(table, bounds) {
109078
+ if (table.findCrossRegion(bounds)) return void 0;
109079
+ const { startRow, endRow } = normalizeCellBounds(bounds);
109080
+ for (let row = startRow; row <= endRow; row++) {
109081
+ const existing = table.regions.find((region) => BUSINESS_DATA_REGION_TYPES.has(region.type) && row >= region.start.row && row <= region.end.row);
109082
+ if (existing) return existing;
109083
+ }
109084
+ }
109085
+ function getSameRowSubTableConflictMessage(existing) {
109086
+ return `同一行只能设置一个子表,当前行已有【${existing ? resolveTableRegionLabel(existing) : "子表"}】,请将新子表设置到其它行`;
109087
+ }
109088
+ /** 校验通过返回 true;冲突时弹出提示并返回 false */
109089
+ function assertSameRowSubTableAllowed(table, bounds) {
109090
+ const conflict = findSameRowSubTableConflict(table, bounds);
109091
+ if (!conflict) return true;
109092
+ GctMessage.warning(getSameRowSubTableConflictMessage(conflict));
109093
+ return false;
109094
+ }
109095
+ /** 解析已有逻辑区域的展示名称 */
109096
+ function resolveTableRegionLabel(region) {
109097
+ if (region.type === "repeating") return getTableLabelByLayoutType(region.layoutType);
109098
+ if (region.type === "table-header") return REGION_ITEM_THEME["table-header"].label;
109099
+ if (region.type === "sub-table-header") return "子表表头";
109100
+ const layoutType = REGION_TYPE_LAYOUT[region.type];
109101
+ if (layoutType) return getTableLabelByLayoutType(layoutType);
109102
+ return "子表";
109103
+ }
109104
+ /** 从当前光标选区解析表格单元格范围 */
109105
+ function resolveTableCellSelectionBounds(doc) {
109106
+ var _startCell$parent, _endCell$parent;
109107
+ const cursor = doc.cursorManager;
109108
+ if (cursor.isCollapsed()) return null;
109109
+ const selection = cursor.getSelection();
109110
+ if (!selection) return null;
109111
+ const info = getSelectLinesInfo(doc, selection, true);
109112
+ if (!info) return null;
109113
+ const scope = resolveSelectionTableScope(doc);
109114
+ if (!scope) return null;
109115
+ const { tableMode, rangeWidgetIds } = info;
109116
+ if (tableMode !== "cell-range" && tableMode !== "cell-full") return null;
109117
+ if (!(rangeWidgetIds === null || rangeWidgetIds === void 0 ? void 0 : rangeWidgetIds.length)) return null;
109118
+ const mapper = doc.layoutMapper;
109119
+ const scopedCells = rangeWidgetIds.map((id) => mapper.getModelNodeByLayoutId(id)).filter((cell) => !!cell && cell.table.id === scope.wtbl.id);
109120
+ if (!scopedCells.length) return null;
109121
+ const startCell = scopedCells[0];
109122
+ const endCell = scopedCells[scopedCells.length - 1];
109123
+ if (!startCell || !endCell) return null;
109124
+ if (startCell.table.id !== endCell.table.id) return null;
109125
+ return {
109126
+ table: scope.wtbl,
109127
+ start: {
109128
+ row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
109129
+ col: startCell.getCurrentIndex()
109130
+ },
109131
+ end: {
109132
+ row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
109133
+ col: endCell.getCurrentIndex()
109134
+ }
109135
+ };
109136
+ }
109137
+ /**
109138
+ * 校验是否已选中合法的表格单元格区域
109139
+ */
109140
+ function validateTableSelection(doc, options) {
109141
+ if (!doc) return false;
109142
+ const bounds = resolveTableCellSelectionBounds(doc);
109143
+ if (!bounds) {
109144
+ GctMessage.warning(`请选择${options.targetLabel}区域`);
109145
+ return false;
109146
+ }
109147
+ if (!assertSameRowSubTableAllowed(bounds.table, bounds)) return false;
109148
+ const crossRegion = bounds.table.findCrossRegion(bounds);
109149
+ if (!crossRegion) return true;
109150
+ if (new Set(options.ignoreOverlapTypes ?? []).has(crossRegion.type)) return true;
109151
+ const existingLabel = resolveTableRegionLabel(crossRegion);
109152
+ GctMessage.warning(`当前选区与已有「${existingLabel}」重叠,请重新选择空白区域`);
109153
+ return false;
109154
+ }
109155
+ var REGION_TYPE_LAYOUT;
109156
+ var init_validate_table_selection = __esmMin((() => {
109157
+ init_base$2();
109158
+ init_constants$1();
109159
+ init_logic$1();
109160
+ init_label();
109161
+ init_region_item_theme();
109162
+ REGION_TYPE_LAYOUT = {
109163
+ bounded: "fixed-table",
109164
+ "2d-table": "2d-table",
109165
+ "check-table": "check-table",
109166
+ "material-consume-table": "material-consume-table"
109167
+ };
109168
+ }));
109169
+ //#endregion
109170
+ //#region src/domain/table/design/validate-nested-table-region.ts
109171
+ function getFirstBusinessDataRegion(table) {
109172
+ return table.regions.find((region) => BUSINESS_DATA_REGION_TYPES.has(region.type));
109173
+ }
109174
+ /**
109175
+ * 业务表/数据表互斥校验(内外表)
109176
+ *
109177
+ * 规则 3:内表已标业务/数据区 → 外表该单元格不支持再标(被规则 4 涵盖)
109178
+ * 规则 4:外表选中单元格含有内表 → 不支持标为业务/数据表
109179
+ * 内表视角:外层宿主单元格已被外表标为业务/数据区 → 内表不支持再标
109180
+ *
109181
+ * @param table 当前操作的表格(外表或内表)
109182
+ * @param bounds 当前光标选区对应的单元格范围(来自 resolveTableCellSelectionBounds)
109183
+ */
109184
+ function validateNestedTableRegionMutex(table, bounds) {
109185
+ const scope = table.getTableScope();
109186
+ if (scope.depth === 1) {
109187
+ const hostCell = scope.hostCell;
109188
+ if (hostCell) {
109189
+ const hostRegion = hostCell.getRegion();
109190
+ if (hostRegion && BUSINESS_DATA_REGION_TYPES.has(hostRegion.type)) return {
109191
+ ok: false,
109192
+ existingLabel: resolveTableRegionLabel(hostRegion),
109193
+ reason: "outer-has-region"
109194
+ };
109195
+ }
109196
+ return { ok: true };
109197
+ }
109198
+ if (bounds) {
109199
+ let foundCell;
109200
+ let nestedRegionLabel;
109201
+ try {
109202
+ WtblCellIterator.forEachCell(bounds.table, {
109203
+ startRowIdx: bounds.start.row,
109204
+ startColIdx: bounds.start.col,
109205
+ endRowIdx: bounds.end.row,
109206
+ endColIdx: bounds.end.col,
109207
+ callback: (cell) => {
109208
+ if (foundCell) return;
109209
+ const nestedTables = cell.getNestedTables();
109210
+ if (nestedTables.length > 0) {
109211
+ foundCell = cell;
109212
+ for (const nested of nestedTables) {
109213
+ const region = getFirstBusinessDataRegion(nested);
109214
+ if (region) {
109215
+ nestedRegionLabel = resolveTableRegionLabel(region);
109216
+ break;
109217
+ }
109218
+ }
109219
+ }
109220
+ }
109221
+ });
109222
+ } catch {}
109223
+ if (foundCell) return {
109224
+ ok: false,
109225
+ existingLabel: nestedRegionLabel,
109226
+ reason: "cell-has-nested"
109227
+ };
109228
+ }
109229
+ return { ok: true };
109230
+ }
109231
+ function getNestedTableRegionMutexMessage(reason, existingLabel) {
109232
+ if (reason === "cell-has-nested") {
109233
+ if (existingLabel) return `当前区域已存在【${existingLabel}】,不支持继续标为【业务表】或【数据表】`;
109234
+ return "已存在嵌套表格的外表单元格,不支持继续标为【业务表】或【数据表】";
109235
+ }
109236
+ if (reason === "outer-has-region") return `外层表格的宿主单元格已标为【${existingLabel ?? "业务表或数据表"}】,不支持在嵌套表格内继续标记`;
109237
+ return `当前区域已存在【${existingLabel ?? "业务表或数据表"}】,不支持继续标为【业务表】或【数据表】`;
109238
+ }
109239
+ /**
109240
+ * 校验互斥并弹出警告。返回 true 表示可以继续标记。
109241
+ */
109242
+ function assertNestedTableRegionMutex(table, bounds) {
109243
+ const mutex = validateNestedTableRegionMutex(table, bounds);
109244
+ if (!mutex.ok) {
109245
+ GctMessage.warning(getNestedTableRegionMutexMessage(mutex.reason, mutex.existingLabel));
109246
+ return false;
109247
+ }
109248
+ return true;
109249
+ }
109250
+ /**
109251
+ * 设置子表前的综合校验(嵌套互斥 + 同一行唯一子表)
109252
+ */
109253
+ function assertSubTableRegionPlacement(table, bounds) {
109254
+ if (!assertNestedTableRegionMutex(table, bounds)) return false;
109255
+ if (bounds && !assertSameRowSubTableAllowed(table, bounds)) return false;
109256
+ return true;
109257
+ }
109258
+ /**
109259
+ * 从起止单元格构造互斥校验所需的 bounds。
109260
+ */
109261
+ function buildBoundsFromCellRange(startCell, endCell) {
109262
+ var _startCell$parent, _endCell$parent;
109263
+ if (startCell.table !== endCell.table) return null;
109264
+ return {
109265
+ table: startCell.table,
109266
+ start: {
109267
+ row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
109268
+ col: startCell.getCurrentIndex()
109269
+ },
109270
+ end: {
109271
+ row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
109272
+ col: endCell.getCurrentIndex()
109273
+ }
109274
+ };
109275
+ }
109276
+ var init_validate_nested_table_region = __esmMin((() => {
109277
+ init_base$2();
109278
+ init_constants$1();
109279
+ init_CellIterator();
109280
+ init_validate_table_selection();
109281
+ }));
109282
+ //#endregion
109283
+ //#region src/domain/table/index.ts
109284
+ var init_table$1 = __esmMin((() => {
109285
+ init_types$5();
109286
+ init_registry$5();
109287
+ init_ribbon_options();
109288
+ init_label();
109289
+ init_sub_model_matcher();
109290
+ init_autofill_expander();
109291
+ init_region_item_theme();
109292
+ init_table_theme();
109293
+ init_table_runtime();
109294
+ init_on_subtable_create();
109295
+ init_on_field_attach();
109296
+ init_on_repeating_default_props();
109297
+ init_validate_table_selection();
109298
+ init_validate_nested_table_region();
109299
+ }));
109300
+ //#endregion
107940
109301
  //#region src/core/command/commands/InsertTable.ts
107941
109302
  var InsertTable_exports = /* @__PURE__ */ __exportAll({ InsertTable: () => InsertTable });
107942
109303
  var InsertTable;
@@ -107945,6 +109306,10 @@ var init_InsertTable = __esmMin((() => {
107945
109306
  init_document();
107946
109307
  init_helpers();
107947
109308
  init_unit_converter();
109309
+ init_constants$1();
109310
+ init_base$2();
109311
+ init_table$1();
109312
+ init_ensure_paragraphs_around_tables();
107948
109313
  InsertTable = class extends CommandBase {
107949
109314
  constructor(doc, payload) {
107950
109315
  super(doc, payload);
@@ -107953,54 +109318,107 @@ var init_InsertTable = __esmMin((() => {
107953
109318
  const colWidths = distributeInteger(width, colCount);
107954
109319
  return Wtbl.fromTemplate(rowCount, colWidths);
107955
109320
  }
109321
+ resolveBlockedTableLabel(hostCell) {
109322
+ const table = hostCell.table;
109323
+ const region = hostCell.getRegion() ?? table.regions[0];
109324
+ if (region) return resolveTableRegionLabel(region);
109325
+ if (table.hasRepeating) return getTableLabelByLayoutType("dynamic-table");
109326
+ if (table.hasBounded) return getTableLabelByLayoutType("fixed-table");
109327
+ if (table.has2DTable) return getTableLabelByLayoutType("2d-table");
109328
+ if (table.hasCheckTable) return getTableLabelByLayoutType("check-table");
109329
+ if (table.hasMaterialConsumeTable) return getTableLabelByLayoutType("material-consume-table");
109330
+ return "业务表或数据表";
109331
+ }
107956
109332
  async execute() {
107957
109333
  const { rowCount, colCount } = this.payload ?? {};
107958
109334
  const cursor = this.doc.cursorManager;
107959
109335
  const { nodeId, offset, side } = cursor.getCursor();
107960
- if (cursor.isCollapsed()) {
107961
- const mapper = this.doc.layoutMapper;
107962
- const run = mapper.getLayoutNodeById(nodeId);
107963
- const wp = mapper.getModelNodeById(run.parent.modelRef.id);
107964
- let targetIndex = 0;
107965
- if (!run.isPlaceholderRun) if (run.isWidgetRun || run.isPageWidgetRun) {
107966
- const hitwr = mapper.getModelNodeByLayoutId(run.id);
107967
- let wrIndex = wp.children.findIndex((r) => r.id === hitwr.id);
107968
- targetIndex = ++wrIndex;
107969
- } else targetIndex = CommandBase.splitRunAt(this.doc, {
107970
- id: nodeId,
107971
- offset,
107972
- side
107973
- }).modelIndex;
107974
- const [beforeWp, afterWp] = wp.splitAt(targetIndex);
107975
- if (wp.parent.name === "w:body") {
107976
- const table = this.createTable(UnitConverter.pixelToDxa(run.getPage().contentMaxWidth), rowCount, colCount);
107977
- if (beforeWp) wp.parent.insertAfter(beforeWp, table);
107978
- else if (afterWp) wp.parent.insertBefore(afterWp, table);
107979
- return {
107980
- wp: table.getFirstWp(),
107981
- pos: 0,
107982
- side: "after"
107983
- };
107984
- }
107985
- } else {
107986
- const { mode, models } = CommandBase.getSelectionResult(this.doc, cursor.getSelection());
107987
- if (models.length === 0) return null;
107988
- const result1 = models[0];
107989
- const result2 = models[models.length - 1];
107990
- const model1 = result1.model;
107991
- result2.model;
107992
- if (mode === SelectionMode.PP) {
107993
- var _result1$children$;
107994
- this.clearSelectionContent(models);
107995
- const run = this.doc.layoutMapper.getLayoutNodeById(nodeId);
107996
- const table = this.createTable(UnitConverter.pixelToDxa(run.getPage().contentMaxWidth), rowCount, colCount);
107997
- const prevWr = "children" in result1 ? (_result1$children$ = result1.children[0]) === null || _result1$children$ === void 0 ? void 0 : _result1$children$.getPrev() : void 0;
107998
- const targetWp = prevWr ? prevWr.parent : model1.getPrev();
107999
- targetWp && targetWp.parent.insertAfter(targetWp, table);
108000
- }
109336
+ if (cursor.isCollapsed()) return this.insertAtCursor(nodeId, offset, side, rowCount, colCount);
109337
+ const { mode, models } = CommandBase.getSelectionResult(this.doc, cursor.getSelection());
109338
+ if (models.length === 0) return null;
109339
+ const result1 = models[0];
109340
+ const model1 = result1.model;
109341
+ if (mode === SelectionMode.PP) {
109342
+ var _result1$children$;
109343
+ this.clearSelectionContent(models);
109344
+ const run = this.doc.layoutMapper.getLayoutNodeById(nodeId);
109345
+ const table = this.createTable(UnitConverter.pixelToDxa(run.getPage().contentMaxWidth), rowCount, colCount);
109346
+ const prevWr = "children" in result1 ? (_result1$children$ = result1.children[0]) === null || _result1$children$ === void 0 ? void 0 : _result1$children$.getPrev() : void 0;
109347
+ const targetWp = prevWr ? prevWr.parent : model1.getPrev();
109348
+ targetWp && targetWp.parent.insertAfter(targetWp, table);
109349
+ const firstWp = table.getFirstWp();
109350
+ return firstWp ? {
109351
+ wp: firstWp,
109352
+ pos: 0,
109353
+ side: "after"
109354
+ } : null;
108001
109355
  }
108002
109356
  return null;
108003
109357
  }
109358
+ insertAtCursor(nodeId, offset, side, rowCount, colCount) {
109359
+ const mapper = this.doc.layoutMapper;
109360
+ const run = mapper.getLayoutNodeById(nodeId);
109361
+ const wp = mapper.getModelNodeById(run.parent.modelRef.id);
109362
+ let targetIndex = 0;
109363
+ if (!run.isPlaceholderRun) if (run.isWidgetRun || run.isPageWidgetRun) {
109364
+ const hitwr = mapper.getModelNodeByLayoutId(run.id);
109365
+ let wrIndex = wp.children.findIndex((r) => r.id === hitwr.id);
109366
+ targetIndex = ++wrIndex;
109367
+ } else targetIndex = CommandBase.splitRunAt(this.doc, {
109368
+ id: nodeId,
109369
+ offset,
109370
+ side
109371
+ }).modelIndex;
109372
+ const [beforeWp, afterWp] = wp.splitAt(targetIndex);
109373
+ const anchorWp = beforeWp ?? afterWp;
109374
+ if (wp.parent.name === "w:body") return this.insertIntoBody(beforeWp, afterWp, run, rowCount, colCount);
109375
+ if (wp.parent instanceof Wtc) return this.insertIntoCell(wp.parent, anchorWp, beforeWp, rowCount, colCount);
109376
+ return null;
109377
+ }
109378
+ insertIntoBody(beforeWp, afterWp, run, rowCount, colCount) {
109379
+ const page = run.getPage();
109380
+ const table = this.createTable(UnitConverter.pixelToDxa((page === null || page === void 0 ? void 0 : page.contentMaxWidth) ?? 0), rowCount, colCount);
109381
+ const body = (beforeWp ?? afterWp).parent;
109382
+ if (beforeWp) body.insertAfter(beforeWp, table);
109383
+ else if (afterWp) body.insertBefore(afterWp, table);
109384
+ ensureParagraphsAroundTable(body, table);
109385
+ const firstWp = table.getFirstWp();
109386
+ return firstWp ? {
109387
+ wp: firstWp,
109388
+ pos: 0,
109389
+ side: "after"
109390
+ } : null;
109391
+ }
109392
+ insertIntoCell(hostCell, anchorWp, beforeWp, rowCount, colCount) {
109393
+ if (!hostCell.canInsertNestedTable()) {
109394
+ if (hostCell.table.isNestedTable) GctMessage.warning("当前嵌套表格内不支持继续插入嵌套表格");
109395
+ else {
109396
+ const existingLabel = this.resolveBlockedTableLabel(hostCell);
109397
+ GctMessage.warning(`当前【${existingLabel}】表内不支持继续插入嵌套表格`);
109398
+ }
109399
+ this.isTerminated = true;
109400
+ return null;
109401
+ }
109402
+ const cols = colCount ?? 3;
109403
+ let cellWidthDxa = hostCell.getContentWidthDxa();
109404
+ if (cellWidthDxa <= 0) {
109405
+ var _hostCell$table$colWi;
109406
+ const rawWidth = ((_hostCell$table$colWi = hostCell.table.colWidths) === null || _hostCell$table$colWi === void 0 ? void 0 : _hostCell$table$colWi.reduce((sum, w) => sum + w, 0)) ?? 1e3;
109407
+ const horizontalPaddingDxa = UnitConverter.pixelToDxa(DEFAULT_CELL_PADDING[1] + DEFAULT_CELL_PADDING[3]);
109408
+ cellWidthDxa = Math.max(0, rawWidth - horizontalPaddingDxa);
109409
+ }
109410
+ const table = this.createTable(cellWidthDxa, rowCount, cols);
109411
+ let insertIndex = hostCell.children.indexOf(anchorWp);
109412
+ if (insertIndex < 0) insertIndex = hostCell.children.length;
109413
+ else if (beforeWp) insertIndex += 1;
109414
+ hostCell.insertNestedTableAt(insertIndex, table);
109415
+ const firstWp = table.getFirstWp();
109416
+ return firstWp ? {
109417
+ wp: firstWp,
109418
+ pos: 0,
109419
+ side: "after"
109420
+ } : null;
109421
+ }
108004
109422
  };
108005
109423
  }));
108006
109424
  //#endregion
@@ -108317,12 +109735,12 @@ var Set2DTable_exports = /* @__PURE__ */ __exportAll({ Set2DTable: () => Set2DTa
108317
109735
  var Set2DTable;
108318
109736
  var init_Set2DTable = __esmMin((() => {
108319
109737
  init_CommandBase();
109738
+ init_table$1();
108320
109739
  Set2DTable = class extends CommandBase {
108321
109740
  constructor(doc, payload) {
108322
109741
  super(doc, payload);
108323
109742
  }
108324
109743
  async execute() {
108325
- var _startCell$parent, _endCell$parent;
108326
109744
  const cursor = this.doc.cursorManager;
108327
109745
  if (cursor.isCollapsed()) return null;
108328
109746
  const { mode, models } = CommandBase.getSelectionResult(this.doc, cursor.getSelection());
@@ -108330,17 +109748,12 @@ var init_Set2DTable = __esmMin((() => {
108330
109748
  if (models.length === 0) return null;
108331
109749
  const startCell = models[0].model;
108332
109750
  const endCell = models[models.length - 1].model;
108333
- const start = {
108334
- row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
108335
- col: startCell.getCurrentIndex()
108336
- };
108337
- const end = {
108338
- row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
108339
- col: endCell.getCurrentIndex()
108340
- };
109751
+ const bounds = buildBoundsFromCellRange(startCell, endCell);
109752
+ if (!bounds) return null;
109753
+ if (!assertSubTableRegionPlacement(bounds.table, bounds)) return null;
108341
109754
  this.output = startCell.table.set2DTable({
108342
- start,
108343
- end,
109755
+ start: bounds.start,
109756
+ end: bounds.end,
108344
109757
  name: this.payload.name,
108345
109758
  valuePath: this.payload.valuePath
108346
109759
  });
@@ -108410,6 +109823,7 @@ var init_SetAlign = __esmMin((() => {
108410
109823
  var SetStyleBase;
108411
109824
  var init_SetStyleBase = __esmMin((() => {
108412
109825
  init_CommandBase();
109826
+ init_Wtbl();
108413
109827
  init_defineProperty();
108414
109828
  SetStyleBase = class extends CommandBase {
108415
109829
  constructor(doc, payload) {
@@ -108473,10 +109887,13 @@ var init_SetStyleBase = __esmMin((() => {
108473
109887
  });
108474
109888
  else {
108475
109889
  const extractFromNode = (node) => {
108476
- if (node && typeof node === "object") {
108477
- if (node.name === "w:r" && node.type === "element") wrTexts.push(node);
108478
- else if ("children" in node && Array.isArray(node.children)) node.children.forEach(extractFromNode);
109890
+ if (!node || typeof node !== "object") return;
109891
+ if (node.name === "w:r" && node.type === "element") {
109892
+ wrTexts.push(node);
109893
+ return;
108479
109894
  }
109895
+ if (node instanceof Wtbl && node.isNestedTable) return;
109896
+ if ("children" in node && Array.isArray(node.children)) node.children.forEach(extractFromNode);
108480
109897
  };
108481
109898
  extractFromNode(m.model);
108482
109899
  }
@@ -108530,12 +109947,12 @@ var SetBounded_exports = /* @__PURE__ */ __exportAll({ SetBounded: () => SetBoun
108530
109947
  var SetBounded;
108531
109948
  var init_SetBounded = __esmMin((() => {
108532
109949
  init_CommandBase();
109950
+ init_table$1();
108533
109951
  SetBounded = class extends CommandBase {
108534
109952
  constructor(doc, payload) {
108535
109953
  super(doc, payload);
108536
109954
  }
108537
109955
  async execute() {
108538
- var _startCell$parent, _endCell$parent;
108539
109956
  const cursor = this.doc.cursorManager;
108540
109957
  if (cursor.isCollapsed()) return null;
108541
109958
  const { mode, models } = CommandBase.getSelectionResult(this.doc, cursor.getSelection());
@@ -108543,17 +109960,12 @@ var init_SetBounded = __esmMin((() => {
108543
109960
  if (models.length === 0) return null;
108544
109961
  const startCell = models[0].model;
108545
109962
  const endCell = models[models.length - 1].model;
108546
- const start = {
108547
- row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
108548
- col: startCell.getCurrentIndex()
108549
- };
108550
- const end = {
108551
- row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
108552
- col: endCell.getCurrentIndex()
108553
- };
109963
+ const bounds = buildBoundsFromCellRange(startCell, endCell);
109964
+ if (!bounds) return null;
109965
+ if (!assertSubTableRegionPlacement(bounds.table, bounds)) return null;
108554
109966
  this.output = startCell.table.setBounded({
108555
- start,
108556
- end,
109967
+ start: bounds.start,
109968
+ end: bounds.end,
108557
109969
  name: this.payload.name,
108558
109970
  valuePath: this.payload.valuePath
108559
109971
  });
@@ -108634,12 +110046,12 @@ var SetCheckTable_exports = /* @__PURE__ */ __exportAll({ SetCheckTable: () => S
108634
110046
  var SetCheckTable;
108635
110047
  var init_SetCheckTable = __esmMin((() => {
108636
110048
  init_CommandBase();
110049
+ init_table$1();
108637
110050
  SetCheckTable = class extends CommandBase {
108638
110051
  constructor(doc, payload) {
108639
110052
  super(doc, payload);
108640
110053
  }
108641
110054
  async execute() {
108642
- var _startCell$parent, _endCell$parent;
108643
110055
  const cursor = this.doc.cursorManager;
108644
110056
  if (cursor.isCollapsed()) return null;
108645
110057
  const { mode, models } = CommandBase.getSelectionResult(this.doc, cursor.getSelection());
@@ -108647,17 +110059,12 @@ var init_SetCheckTable = __esmMin((() => {
108647
110059
  if (models.length === 0) return null;
108648
110060
  const startCell = models[0].model;
108649
110061
  const endCell = models[models.length - 1].model;
108650
- const start = {
108651
- row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
108652
- col: startCell.getCurrentIndex()
108653
- };
108654
- const end = {
108655
- row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
108656
- col: endCell.getCurrentIndex()
108657
- };
110062
+ const bounds = buildBoundsFromCellRange(startCell, endCell);
110063
+ if (!bounds) return null;
110064
+ if (!assertSubTableRegionPlacement(bounds.table, bounds)) return null;
108658
110065
  this.output = startCell.table.setCheckTable({
108659
- start,
108660
- end,
110066
+ start: bounds.start,
110067
+ end: bounds.end,
108661
110068
  name: this.payload.name,
108662
110069
  valuePath: this.payload.valuePath
108663
110070
  });
@@ -108836,12 +110243,12 @@ var SetMaterialConsumeTable_exports = /* @__PURE__ */ __exportAll({ SetMaterialC
108836
110243
  var SetMaterialConsumeTable;
108837
110244
  var init_SetMaterialConsumeTable = __esmMin((() => {
108838
110245
  init_CommandBase();
110246
+ init_table$1();
108839
110247
  SetMaterialConsumeTable = class extends CommandBase {
108840
110248
  constructor(doc, payload) {
108841
110249
  super(doc, payload);
108842
110250
  }
108843
110251
  async execute() {
108844
- var _startCell$parent, _endCell$parent;
108845
110252
  const cursor = this.doc.cursorManager;
108846
110253
  if (cursor.isCollapsed()) return null;
108847
110254
  const { mode, models } = CommandBase.getSelectionResult(this.doc, cursor.getSelection());
@@ -108849,19 +110256,14 @@ var init_SetMaterialConsumeTable = __esmMin((() => {
108849
110256
  if (models.length === 0) return null;
108850
110257
  const startCell = models[0].model;
108851
110258
  const endCell = models[models.length - 1].model;
108852
- const start = {
108853
- row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
108854
- col: startCell.getCurrentIndex()
108855
- };
108856
- const end = {
108857
- row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
108858
- col: endCell.getCurrentIndex()
108859
- };
110259
+ const bounds = buildBoundsFromCellRange(startCell, endCell);
110260
+ if (!bounds) return null;
110261
+ if (!assertSubTableRegionPlacement(bounds.table, bounds)) return null;
108860
110262
  const { name, valuePath } = this.payload;
108861
110263
  const props = { table_key_: valuePath };
108862
110264
  this.output = startCell.table.setMaterialConsumeTable({
108863
- start,
108864
- end,
110265
+ start: bounds.start,
110266
+ end: bounds.end,
108865
110267
  name,
108866
110268
  valuePath,
108867
110269
  widgetMeta: { props }
@@ -108933,12 +110335,12 @@ var SetRepeating;
108933
110335
  var init_SetRepeating = __esmMin((() => {
108934
110336
  init_CommandBase();
108935
110337
  init_on_repeating_default_props();
110338
+ init_table$1();
108936
110339
  SetRepeating = class extends CommandBase {
108937
110340
  constructor(doc, payload) {
108938
110341
  super(doc, payload);
108939
110342
  }
108940
110343
  async execute() {
108941
- var _startCell$parent, _endCell$parent;
108942
110344
  const cursor = this.doc.cursorManager;
108943
110345
  if (cursor.isCollapsed()) return null;
108944
110346
  const { mode, models } = CommandBase.getSelectionResult(this.doc, cursor.getSelection());
@@ -108946,17 +110348,12 @@ var init_SetRepeating = __esmMin((() => {
108946
110348
  if (models.length === 0) return null;
108947
110349
  const startCell = models[0].model;
108948
110350
  const endCell = models[models.length - 1].model;
108949
- const start = {
108950
- row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
108951
- col: startCell.getCurrentIndex()
108952
- };
108953
- const end = {
108954
- row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
108955
- col: endCell.getCurrentIndex()
108956
- };
110351
+ const bounds = buildBoundsFromCellRange(startCell, endCell);
110352
+ if (!bounds) return null;
110353
+ if (!assertSubTableRegionPlacement(bounds.table, bounds)) return null;
108957
110354
  this.output = startCell.table.setRepeating({
108958
- start,
108959
- end,
110355
+ start: bounds.start,
110356
+ end: bounds.end,
108960
110357
  name: this.payload.name,
108961
110358
  valuePath: this.payload.valuePath,
108962
110359
  widgetMeta: { props: getDefaultRepeatingWidgetProps(this.payload.layoutType) }
@@ -109534,6 +110931,7 @@ var Table;
109534
110931
  var init_Table = __esmMin((() => {
109535
110932
  init_constants$1();
109536
110933
  init_base();
110934
+ init_unit_converter();
109537
110935
  init_EventUtil();
109538
110936
  init_defineProperty();
109539
110937
  Table = class extends LayoutGroup {
@@ -109543,6 +110941,12 @@ var init_Table = __esmMin((() => {
109543
110941
  _defineProperty(this, "component", BuiltinComponentTypeConst.Table);
109544
110942
  _defineProperty(this, "cellPadding", [...DEFAULT_CELL_PADDING]);
109545
110943
  _defineProperty(this, "colWidths", void 0);
110944
+ _defineProperty(
110945
+ this,
110946
+ /** 表格属性 */
110947
+ "tblPr",
110948
+ void 0
110949
+ );
109546
110950
  _defineProperty(
109547
110951
  this,
109548
110952
  /** redistribute 完成事件 */
@@ -109562,6 +110966,7 @@ var init_Table = __esmMin((() => {
109562
110966
  void 0
109563
110967
  );
109564
110968
  this.colWidths = options.colWidths;
110969
+ this.tblPr = options.tblPr;
109565
110970
  }
109566
110971
  get width() {
109567
110972
  var _this$colWidths;
@@ -109606,12 +111011,49 @@ var init_Table = __esmMin((() => {
109606
111011
  this.redistributeEvent.emit();
109607
111012
  }
109608
111013
  layout(x, y) {
109609
- this.layoutX = x;
111014
+ const page = this.getPage();
111015
+ const nestedInCell = this.isNestedInCell();
111016
+ if (page && !nestedInCell) {
111017
+ this.x = this.resolveOffsetX(page);
111018
+ this.layoutX = page.pl + this.x;
111019
+ } else this.layoutX = x;
109610
111020
  this.layoutY = y;
109611
111021
  this.forEachChild((child) => {
109612
111022
  child.layout(this.layoutX, this.layoutY + child.y);
109613
111023
  });
109614
111024
  }
111025
+ /**
111026
+ * 相对正文区左边缘的水平偏移
111027
+ * 对应 w:jc / w:tblInd;居中或右对齐且表格宽于正文区时可为负值
111028
+ */
111029
+ resolveOffsetX(page) {
111030
+ const contentWidth = page.contentMaxWidth;
111031
+ switch (this.getTableJc()) {
111032
+ case "center": return (contentWidth - this.width) / 2;
111033
+ case "end": return contentWidth - this.width;
111034
+ default: return this.getTblIndPx();
111035
+ }
111036
+ }
111037
+ /** 嵌套在单元格内的表格不使用页面级对齐 */
111038
+ isNestedInCell() {
111039
+ var _this$parent;
111040
+ return ((_this$parent = this.parent) === null || _this$parent === void 0 ? void 0 : _this$parent.component) === BuiltinComponentTypeConst.TableCell;
111041
+ }
111042
+ getTableJc() {
111043
+ var _this$tblPr;
111044
+ const raw = (_this$tblPr = this.tblPr) === null || _this$tblPr === void 0 ? void 0 : _this$tblPr.getAttrValue("w:jc", "w:val");
111045
+ if (raw === "center") return "center";
111046
+ if (raw === "end" || raw === "right") return "end";
111047
+ return "start";
111048
+ }
111049
+ getTblIndPx() {
111050
+ var _this$tblPr2, _this$tblPr3;
111051
+ const raw = (_this$tblPr2 = this.tblPr) === null || _this$tblPr2 === void 0 ? void 0 : _this$tblPr2.getAttrValue("w:tblInd", "w:w");
111052
+ if (!raw) return 0;
111053
+ if ((((_this$tblPr3 = this.tblPr) === null || _this$tblPr3 === void 0 ? void 0 : _this$tblPr3.getAttrValue("w:tblInd", "w:type")) ?? "dxa") !== "dxa") return 0;
111054
+ const value = parseInt(raw, 10);
111055
+ return Number.isFinite(value) ? UnitConverter.dxaToPixel(value) : 0;
111056
+ }
109615
111057
  updateCellOffsetInfo() {
109616
111058
  const map = /* @__PURE__ */ new Map();
109617
111059
  this.getChildren().forEach((row, rowIndex) => {
@@ -109777,7 +111219,7 @@ var init_Page = __esmMin((() => {
109777
111219
  var _this$headerBand3, _this$footerBand3;
109778
111220
  (_this$headerBand3 = this.headerBand) === null || _this$headerBand3 === void 0 || _this$headerBand3.layout(this.pl, this.section.headerSpacing);
109779
111221
  this.forEachChild((child) => {
109780
- child.layout(this.pl, this.pt + child.y);
111222
+ child.layout(this.pl + child.x, this.pt + child.y);
109781
111223
  });
109782
111224
  const footerStartY = this.height - this.pb;
109783
111225
  (_this$footerBand3 = this.footerBand) === null || _this$footerBand3 === void 0 || _this$footerBand3.layout(this.pl, footerStartY);
@@ -111955,6 +113397,11 @@ var init_TableCell = __esmMin((() => {
111955
113397
  };
111956
113398
  }));
111957
113399
  //#endregion
113400
+ //#region src/core/view/types/index.ts
113401
+ var init_types$3 = __esmMin((() => {
113402
+ init_layout_node_by_component();
113403
+ }));
113404
+ //#endregion
111958
113405
  //#region src/core/layout/table/split-table.ts
111959
113406
  /**
111960
113407
  * 工具函数:执行表格切分
@@ -111967,17 +113414,14 @@ var init_TableCell = __esmMin((() => {
111967
113414
  * const { cur, next } = splitTableByHeight(table, 500);
111968
113415
  */
111969
113416
  function splitTableByHeight(table, maxHeight) {
111970
- const key = "【splitTableByHeight】";
111971
- console.time(key);
111972
- const result = new TableSplitter(table, maxHeight).split();
111973
- console.timeEnd(key);
111974
- return result;
113417
+ return new TableSplitter(table, maxHeight).split();
111975
113418
  }
111976
113419
  var TableSplitter, MergeCellAdjuster, HeightCalculator;
111977
113420
  var init_split_table = __esmMin((() => {
111978
113421
  init_Table();
111979
113422
  init_TableRow();
111980
113423
  init_TableCell();
113424
+ init_types$3();
111981
113425
  init_core$1();
111982
113426
  init_defineProperty();
111983
113427
  TableSplitter = class {
@@ -111998,6 +113442,7 @@ var init_split_table = __esmMin((() => {
111998
113442
  * 执行表格切分主流程
111999
113443
  */
112000
113444
  split() {
113445
+ var _this$curTable, _this$nextTable;
112001
113446
  if (!this.needsSplit()) return {
112002
113447
  cur: this.table,
112003
113448
  next: void 0
@@ -112011,7 +113456,14 @@ var init_split_table = __esmMin((() => {
112011
113456
  next: this.table
112012
113457
  };
112013
113458
  } else if (this.splitCellIndex !== -1) this.splitRow();
112014
- else if (this.table.getChildren()[this.splitRowIndex].height > this.maxHeight && this.splitRowIndex === 0) this.splitRow();
113459
+ else if (this.table.getChildren()[this.splitRowIndex].height > this.maxHeight && this.splitRowIndex === 0) if (this.maxHeight - this.accumulatedHeight >= 20) this.splitRow();
113460
+ else {
113461
+ this.table.y = 0;
113462
+ return {
113463
+ cur: void 0,
113464
+ next: this.table
113465
+ };
113466
+ }
112015
113467
  this.createResultTables();
112016
113468
  this.copyRowsBeforeSplit();
112017
113469
  this.copyRemainingRows();
@@ -112024,6 +113476,8 @@ var init_split_table = __esmMin((() => {
112024
113476
  });
112025
113477
  this.fillCells();
112026
113478
  this.regenerateNextTableFirstRowIds();
113479
+ (_this$curTable = this.curTable) === null || _this$curTable === void 0 || _this$curTable.redistribute();
113480
+ (_this$nextTable = this.nextTable) === null || _this$nextTable === void 0 || _this$nextTable.redistribute();
112027
113481
  return {
112028
113482
  cur: this.curTable,
112029
113483
  next: this.nextTable
@@ -112061,6 +113515,7 @@ var init_split_table = __esmMin((() => {
112061
113515
  this.splitRowIndex = -1;
112062
113516
  this.splitCellIndex = -1;
112063
113517
  const rows = this.table.getChildren();
113518
+ const [padTop, , padBottom] = this.table.cellPadding;
112064
113519
  for (let i = 0; i < rows.length; i++) {
112065
113520
  const row = rows[i];
112066
113521
  if (!row) continue;
@@ -112068,16 +113523,12 @@ var init_split_table = __esmMin((() => {
112068
113523
  if (this.accumulatedHeight + rowHeight > this.maxHeight) {
112069
113524
  this.splitRowIndex = i;
112070
113525
  const remainHeight = this.maxHeight - this.accumulatedHeight;
112071
- const cells = row.getChildren();
112072
- for (let j = 0; j < cells.length; j++) {
112073
- const cell = cells[j];
112074
- const cellContent = cell.getChildren();
112075
- if (cellContent.length > 0) {
112076
- const para = cellContent.find((item) => item.height);
112077
- if (!para) continue;
112078
- const paraHeight = para.height;
112079
- const cellPadding = cell.table.cellPadding;
112080
- if (cellPadding[0] + paraHeight + cellPadding[2] <= remainHeight) this.splitCellIndex = j;
113526
+ if (remainHeight >= 20) {
113527
+ const contentRemain = remainHeight - padTop - padBottom;
113528
+ const cells = row.getChildren();
113529
+ for (let j = 0; j < cells.length; j++) {
113530
+ const cellContent = cells[j].getChildren();
113531
+ if (contentRemain > 0 && cellContent.some((item) => item.height > 0 && item.height <= contentRemain)) this.splitCellIndex = j;
112081
113532
  }
112082
113533
  }
112083
113534
  return;
@@ -112093,14 +113544,18 @@ var init_split_table = __esmMin((() => {
112093
113544
  x: this.table.x,
112094
113545
  y: this.table.y,
112095
113546
  width: this.table.width,
112096
- colWidths: this.table.colWidths
113547
+ colWidths: this.table.colWidths,
113548
+ tblPr: this.table.tblPr,
113549
+ modelRef: this.table.modelRef
112097
113550
  });
112098
113551
  this.nextTable = new Table({
112099
113552
  doc: this.table.doc,
112100
113553
  x: this.table.x,
112101
113554
  y: 0,
112102
113555
  width: this.table.width,
112103
- colWidths: this.table.colWidths
113556
+ colWidths: this.table.colWidths,
113557
+ tblPr: this.table.tblPr,
113558
+ modelRef: this.table.modelRef
112104
113559
  });
112105
113560
  }
112106
113561
  /**
@@ -112266,16 +113721,39 @@ var init_split_table = __esmMin((() => {
112266
113721
  const [topCell, bottomCell] = newCells;
112267
113722
  let accumulatedHeight = 0;
112268
113723
  let splitIndex = -1;
113724
+ let handled = false;
112269
113725
  for (let i = 0; i < originalCellContent.length; i++) {
112270
113726
  const child = originalCellContent[i];
112271
- accumulatedHeight += child.height;
112272
- if (accumulatedHeight <= topCell.getRemainingSize(true)) topCell.addChild(child);
112273
- else {
112274
- splitIndex = i;
112275
- break;
113727
+ const remaining = topCell.getRemainingSize(true) - accumulatedHeight;
113728
+ if (child.height <= remaining) {
113729
+ topCell.addChild(child);
113730
+ accumulatedHeight += child.height;
113731
+ continue;
113732
+ }
113733
+ if (isLayoutTable(child) && remaining >= 20) {
113734
+ const { cur, next } = splitTableByHeight(child, remaining);
113735
+ if (cur) {
113736
+ cur.y = accumulatedHeight;
113737
+ topCell.addChild(cur);
113738
+ if (next) {
113739
+ next.y = 0;
113740
+ bottomCell.clearChildren();
113741
+ bottomCell.addChild(next);
113742
+ let lastChild = next;
113743
+ originalCellContent.slice(i + 1).forEach((rest) => {
113744
+ rest.y = lastChild.y + lastChild.height;
113745
+ bottomCell.addChild(rest);
113746
+ lastChild = rest;
113747
+ });
113748
+ }
113749
+ handled = true;
113750
+ break;
113751
+ }
112276
113752
  }
113753
+ splitIndex = i;
113754
+ break;
112277
113755
  }
112278
- if (splitIndex !== -1) {
113756
+ if (!handled && splitIndex !== -1) {
112279
113757
  bottomCell === null || bottomCell === void 0 || bottomCell.clearChildren();
112280
113758
  let lastChild = null;
112281
113759
  originalCellContent.slice(splitIndex).forEach((child) => {
@@ -112874,8 +114352,7 @@ var init_TableInfoProvider = __esmMin((() => {
112874
114352
  return this.tableExpander.rows;
112875
114353
  }
112876
114354
  getCellContent(cell) {
112877
- var _this$tableExpander$g;
112878
- return ((_this$tableExpander$g = this.tableExpander.getModelById(cell.expandFromId)) === null || _this$tableExpander$g === void 0 ? void 0 : _this$tableExpander$g.children) ?? [];
114355
+ return this.tableExpander.getModelById(cell.expandFromId).children.filter((child) => child.name === "w:p" || child.name === "w:tbl");
112879
114356
  }
112880
114357
  getRowModelRef(row) {
112881
114358
  return { id: row.expandFromId };
@@ -113306,12 +114783,21 @@ var init_LayoutManager = __esmMin((() => {
113306
114783
  */
113307
114784
  layoutTable(provider, wtbl) {
113308
114785
  const page = this.pageContext.page;
114786
+ const table = this.buildTableLayout(provider, wtbl, { y: page.getContentHeight() });
114787
+ this.handleTablePagination(table, wtbl, provider);
114788
+ }
114789
+ /**
114790
+ * 构建表格 layout 节点(不含分页)
114791
+ */
114792
+ buildTableLayout(provider, wtbl, options = {}) {
113309
114793
  const colWidths = wtbl.colWidths.map((w) => UnitConverter.dxaToPixel(w));
113310
114794
  const table = new Table({
113311
114795
  doc: this.doc,
113312
114796
  colWidths,
114797
+ tblPr: wtbl.tblPr,
113313
114798
  x: 0,
113314
- y: page.getContentHeight()
114799
+ y: options.y ?? 0,
114800
+ modelRef: { id: wtbl.id }
113315
114801
  });
113316
114802
  provider.getRows().forEach((row, rIndex) => {
113317
114803
  const tableRow = new TableRow({
@@ -113346,10 +114832,10 @@ var init_LayoutManager = __esmMin((() => {
113346
114832
  });
113347
114833
  });
113348
114834
  table.redistribute();
113349
- this.handleTablePagination(table, wtbl, provider);
114835
+ return table;
113350
114836
  }
113351
114837
  /**
113352
- * 布局单元格内容
114838
+ * 布局单元格内容(段落 + 嵌套表 block 混排)
113353
114839
  */
113354
114840
  layoutCellContent(cellContent, tableCell) {
113355
114841
  const cellContext = new LayoutContext({
@@ -113358,12 +114844,22 @@ var init_LayoutManager = __esmMin((() => {
113358
114844
  cell: tableCell
113359
114845
  });
113360
114846
  cellContent.forEach((item) => {
113361
- var _cellContext$cell;
113362
- cellContext.resetModelRef(item.id);
113363
- cellContext.createNewParagraph((_cellContext$cell = cellContext.cell) === null || _cellContext$cell === void 0 ? void 0 : _cellContext$cell.getContentHeight());
113364
- item.runs.forEach((run) => {
113365
- this.layoutRun(cellContext, run);
113366
- });
114847
+ if (item.name === "w:p") {
114848
+ const wp = item;
114849
+ cellContext.resetModelRef(wp.id);
114850
+ cellContext.createNewParagraph(tableCell.getContentHeight());
114851
+ wp.runs.forEach((run) => {
114852
+ this.layoutRun(cellContext, run);
114853
+ });
114854
+ } else if (item.name === "w:tbl") {
114855
+ const nestedWtbl = item;
114856
+ const nestedProvider = new TableInfoProvider(nestedWtbl, new TableExpander(nestedWtbl, this.doc));
114857
+ const nestedTable = this.buildTableLayout(nestedProvider, nestedWtbl, {
114858
+ y: tableCell.getContentHeight(),
114859
+ hostCell: tableCell
114860
+ });
114861
+ tableCell.addChild(nestedTable);
114862
+ }
113367
114863
  });
113368
114864
  }
113369
114865
  /**
@@ -113376,7 +114872,13 @@ var init_LayoutManager = __esmMin((() => {
113376
114872
  const page = this.pageContext.page;
113377
114873
  const pageRemainingSize = page.getRemainingSize();
113378
114874
  const firstRowHeight = remainingTable === null || remainingTable === void 0 || (_remainingTable$child = remainingTable.children) === null || _remainingTable$child === void 0 || (_remainingTable$child = _remainingTable$child[0]) === null || _remainingTable$child === void 0 ? void 0 : _remainingTable$child._height;
113379
- if (firstRowHeight && firstRowHeight > pageRemainingSize) break;
114875
+ if (firstRowHeight && firstRowHeight > pageRemainingSize) {
114876
+ if (pageRemainingSize < 20 && pageRemainingSize < page.contentMaxHeight) {
114877
+ this.pageContext.createNewPage();
114878
+ remainingTable.y = this.pageContext.page.getContentHeight();
114879
+ continue;
114880
+ }
114881
+ }
113380
114882
  const { cur, next } = splitTableByHeight(remainingTable, pageRemainingSize);
113381
114883
  const newRowIds = [];
113382
114884
  const regions = ((cur === null || cur === void 0 ? void 0 : cur.getChildren().map((item) => {
@@ -114759,6 +116261,7 @@ var init_InteractionController = __esmMin((() => {
114759
116261
  index: payload.index,
114760
116262
  realRowIndex: payload.realRowIndex
114761
116263
  });
116264
+ this._setTableCursorSelection(payload.id, { rowRange: [payload.index, payload.index] });
114762
116265
  }
114763
116266
  onSelectTableCol(payload) {
114764
116267
  this.doc.interactionManager.set("tableSelection", {
@@ -114766,6 +116269,7 @@ var init_InteractionController = __esmMin((() => {
114766
116269
  axis: "col",
114767
116270
  index: payload.index
114768
116271
  });
116272
+ this._setTableCursorSelection(payload.id, { colRange: [payload.index, payload.index] });
114769
116273
  }
114770
116274
  onSelectTableAll(payload) {
114771
116275
  this.doc.interactionManager.set("tableSelection", {
@@ -114773,6 +116277,55 @@ var init_InteractionController = __esmMin((() => {
114773
116277
  axis: "all",
114774
116278
  index: -1
114775
116279
  });
116280
+ this._setTableCursorSelection(payload.id);
116281
+ }
116282
+ /**
116283
+ * 根据行/列范围设置 cursor selection,驱动 cellRangeIds 内容层高亮。
116284
+ *
116285
+ * @param tableId 目标表格 layout ID
116286
+ * @param options.rowRange [startRowIdx, endRowIdx](默认全表)
116287
+ * @param options.colRange [startColIdx, endColIdx](默认全列)
116288
+ */
116289
+ _setTableCursorSelection(tableId, options = {}) {
116290
+ const layoutMapper = this.doc.layoutMapper;
116291
+ const allPageIds = layoutMapper.getAllPageIds();
116292
+ const tableRows = [];
116293
+ for (const pageId of allPageIds) for (const lineId of layoutMapper.getLineIdsByPageId(pageId)) {
116294
+ const li = layoutMapper.getLineInfoById(lineId);
116295
+ if ((li === null || li === void 0 ? void 0 : li.type) === "tablerow" && li.tableId === tableId) tableRows.push(li);
116296
+ }
116297
+ if (!tableRows.length) return;
116298
+ const [rowStart, rowEnd] = options.rowRange ?? [0, tableRows.length - 1];
116299
+ const safeRowStart = Math.max(0, Math.min(rowStart, tableRows.length - 1));
116300
+ const safeRowEnd = Math.max(0, Math.min(rowEnd, tableRows.length - 1));
116301
+ const firstRow = tableRows[safeRowStart];
116302
+ const lastRow = tableRows[safeRowEnd];
116303
+ const colCount = firstRow.nextIds.length;
116304
+ const [colStart, colEnd] = options.colRange ?? [0, colCount - 1];
116305
+ const safeColStart = Math.max(0, Math.min(colStart, colCount - 1));
116306
+ const safeColEnd = Math.max(0, Math.min(colEnd, colCount - 1));
116307
+ const firstCellId = firstRow.nextIds[safeColStart];
116308
+ const lastCellId = lastRow.nextIds[safeColEnd];
116309
+ if (!firstCellId || !lastCellId) return;
116310
+ let firstAtomId;
116311
+ let lastAtomId;
116312
+ for (const atomId of layoutMapper.widgetIds) {
116313
+ const meta = layoutMapper.getBaseMetaNodeById(atomId);
116314
+ if (!(meta === null || meta === void 0 ? void 0 : meta.line)) continue;
116315
+ if (!firstAtomId && meta.line.tableCellId === firstCellId) firstAtomId = atomId;
116316
+ if (meta.line.tableCellId === lastCellId) lastAtomId = atomId;
116317
+ }
116318
+ if (!firstAtomId || !lastAtomId) return;
116319
+ this.doc.cursorManager.setSelection({
116320
+ anchor: {
116321
+ nodeId: firstAtomId,
116322
+ side: "before"
116323
+ },
116324
+ focus: {
116325
+ nodeId: lastAtomId,
116326
+ side: "after"
116327
+ }
116328
+ });
114776
116329
  }
114777
116330
  clearTableSelection() {
114778
116331
  this.doc.interactionManager.clear("tableSelection");
@@ -114783,9 +116336,15 @@ var init_InteractionController = __esmMin((() => {
114783
116336
  onSetActiveTableId(tableId) {
114784
116337
  this.doc.interactionManager.set("activeTableId", tableId);
114785
116338
  }
116339
+ onSetActiveTableScope(scope) {
116340
+ this.doc.interactionManager.set("activeTableScope", scope);
116341
+ }
114786
116342
  clearActiveTableId() {
114787
116343
  this.doc.interactionManager.clear("activeTableId");
114788
116344
  }
116345
+ clearActiveTableScope() {
116346
+ this.doc.interactionManager.clear("activeTableScope");
116347
+ }
114789
116348
  /** 填报模式下点击只读/禁用组件:与点空白一致,收起字段焦点并回到纸张 */
114790
116349
  settleFillModeNonInteractiveField(secRefId) {
114791
116350
  this.onActivePanelData({
@@ -114802,18 +116361,40 @@ var init_InteractionController = __esmMin((() => {
114802
116361
  });
114803
116362
  }
114804
116363
  syncActiveTableByMeta(meta) {
114805
- var _tableMeta$raw;
116364
+ var _tableMeta$raw, _tableModel$getTableS;
114806
116365
  if (!(meta === null || meta === void 0 ? void 0 : meta.line) || meta.line.lineType !== "tablerow" || isClickPaperWidgetAllNode(meta)) {
114807
116366
  this.clearActiveTableId();
116367
+ this.clearActiveTableScope();
116368
+ this.clearTableSelection();
114808
116369
  return;
114809
116370
  }
114810
- const tableId = meta.line.tableId;
114811
- const tableMeta = this.doc.layoutMapper.getBaseMetaNodeById(tableId);
116371
+ const tableLayoutId = meta.line.tableId;
116372
+ const tableMeta = this.doc.layoutMapper.getBaseMetaNodeById(tableLayoutId);
114812
116373
  if (!tableMeta) {
114813
116374
  this.clearActiveTableId();
116375
+ this.clearActiveTableScope();
116376
+ return;
116377
+ }
116378
+ const modelTableId = (_tableMeta$raw = tableMeta.raw) === null || _tableMeta$raw === void 0 || (_tableMeta$raw = _tableMeta$raw.modelRef) === null || _tableMeta$raw === void 0 ? void 0 : _tableMeta$raw.id;
116379
+ if (!modelTableId) {
116380
+ this.clearActiveTableId();
116381
+ this.clearActiveTableScope();
114814
116382
  return;
114815
116383
  }
114816
- this.onSetActiveTableId((_tableMeta$raw = tableMeta.raw) === null || _tableMeta$raw === void 0 ? void 0 : _tableMeta$raw.modelRef.id);
116384
+ const tableModel = this.doc.layoutMapper.getModelNodeById(modelTableId);
116385
+ const scope = tableModel === null || tableModel === void 0 || (_tableModel$getTableS = tableModel.getTableScope) === null || _tableModel$getTableS === void 0 ? void 0 : _tableModel$getTableS.call(tableModel);
116386
+ this.onSetActiveTableId(modelTableId);
116387
+ if (scope) {
116388
+ var _scope$hostCell;
116389
+ this.onSetActiveTableScope({
116390
+ wtblId: scope.wtbl.id,
116391
+ rootWtblId: scope.rootWtbl.id,
116392
+ depth: scope.depth,
116393
+ hostCellId: (_scope$hostCell = scope.hostCell) === null || _scope$hostCell === void 0 ? void 0 : _scope$hostCell.id
116394
+ });
116395
+ } else this.clearActiveTableScope();
116396
+ const sel = this.doc.interactionManager.get("tableSelection");
116397
+ if ((sel === null || sel === void 0 ? void 0 : sel.tableId) && sel.tableId !== tableLayoutId) this.clearTableSelection();
114817
116398
  }
114818
116399
  resolveIntent(id, hitId) {
114819
116400
  const meta = this.doc.layoutMapper.getBaseMetaNodeById(id);
@@ -115647,6 +117228,7 @@ var init_InteractionManager = __esmMin((() => {
115647
117228
  this.state = {
115648
117229
  tableSelection: null,
115649
117230
  activeTableId: "",
117231
+ activeTableScope: null,
115650
117232
  dragHoverId: "",
115651
117233
  hoverModelId: "",
115652
117234
  focusModelId: "",
@@ -116074,6 +117656,7 @@ function useInteraction(docRef) {
116074
117656
  const interactionTypes = [
116075
117657
  "tableSelection",
116076
117658
  "activeTableId",
117659
+ "activeTableScope",
116077
117660
  "panelData",
116078
117661
  "attachFieldTarget",
116079
117662
  "hoverModelId",
@@ -117738,6 +119321,8 @@ var init_dataGroupSlotCount = __esmMin((() => {}));
117738
119321
  var DocModel;
117739
119322
  var init_DocModel = __esmMin((() => {
117740
119323
  init_document();
119324
+ init_Serialization();
119325
+ init_base$2();
117741
119326
  init_styles();
117742
119327
  init_images();
117743
119328
  init_Wsettings();
@@ -117770,6 +119355,7 @@ var init_DocModel = __esmMin((() => {
117770
119355
  */
117771
119356
  static fromXmlJson(json) {
117772
119357
  if (!(json === null || json === void 0 ? void 0 : json.document)) throw new Error("Invalid document JSON: missing document root");
119358
+ WtblSerialization.resetImportGrandchildWarning();
117773
119359
  const model = new DocModel({
117774
119360
  document: null,
117775
119361
  headers: null,
@@ -117803,6 +119389,8 @@ var init_DocModel = __esmMin((() => {
117803
119389
  ];
117804
119390
  for (const key in json) if (!processedKeys.includes(key) && json.hasOwnProperty(key)) model[key] = json[key];
117805
119391
  console.log("model", model);
119392
+ const ignoredGrandchildCount = WtblSerialization.consumeImportGrandchildWarning();
119393
+ if (ignoredGrandchildCount > 0) GctMessage.warning(`文档中含有不支持的孙级嵌套表格(仅支持一层),已忽略 ${ignoredGrandchildCount} 处更深层级内容。`);
117806
119394
  return model;
117807
119395
  }
117808
119396
  /**
@@ -118530,6 +120118,7 @@ var init_selection_renderer_vue_vue_type_script_setup_true_name_selection_render
118530
120118
  },
118531
120119
  setup(__props) {
118532
120120
  const { docInst } = useDocPubApiContext();
120121
+ const cellRangeIds = inject("cellRangeIds");
118533
120122
  const props = __props;
118534
120123
  const rects = ref([]);
118535
120124
  let lastHash = null;
@@ -118550,13 +120139,16 @@ var init_selection_renderer_vue_vue_type_script_setup_true_name_selection_render
118550
120139
  lastHash = h;
118551
120140
  if (!sel) {
118552
120141
  rects.value = [];
120142
+ if (cellRangeIds) cellRangeIds.value = /* @__PURE__ */ new Set();
118553
120143
  return;
118554
120144
  }
118555
120145
  try {
118556
- const r = getSelectionRects(docInst.value, sel, isCellUpgrade) ?? [];
118557
- rects.value = Array.isArray(r) ? r : [];
120146
+ const result = getSelectionRects(docInst.value, sel, isCellUpgrade);
120147
+ rects.value = Array.isArray(result === null || result === void 0 ? void 0 : result.rects) ? result.rects : [];
120148
+ if (cellRangeIds) cellRangeIds.value = new Set((result === null || result === void 0 ? void 0 : result.cellRangeIds) ?? []);
118558
120149
  } catch (e) {
118559
120150
  rects.value = [];
120151
+ if (cellRangeIds) cellRangeIds.value = /* @__PURE__ */ new Set();
118560
120152
  }
118561
120153
  }, { immediate: true });
118562
120154
  return (_ctx, _cache) => {
@@ -118948,11 +120540,6 @@ var init_hidden_input = __esmMin((() => {
118948
120540
  hidden_input_default = /*#__PURE__*/ _plugin_vue_export_helper_default(hidden_input_vue_vue_type_script_setup_true_name_hidden_input_lang_default, [["__scopeId", "data-v-1b116d0d"]]);
118949
120541
  }));
118950
120542
  //#endregion
118951
- //#region src/core/view/types/index.ts
118952
- var init_types$3 = __esmMin((() => {
118953
- init_layout_node_by_component();
118954
- }));
118955
- //#endregion
118956
120543
  //#region src/core/index.ts
118957
120544
  var init_core = __esmMin((() => {
118958
120545
  init_Doc();
@@ -123319,709 +124906,6 @@ var init_useDependency = __esmMin((() => {
123319
124906
  init_form_value();
123320
124907
  }));
123321
124908
  //#endregion
123322
- //#region src/domain/table/design/ribbon-options.ts
123323
- /** 生成 Ribbon「数据表」「业务表」下拉选项 */
123324
- function getRibbonTableOptions() {
123325
- return {
123326
- dataTables: [TABLE_HEADER_RIBBON_OPTION, ...getProfilesByCategory("data").map((profile) => ({
123327
- value: profile.ribbonAction,
123328
- label: profile.label,
123329
- disabled: profile.enabled === false
123330
- }))],
123331
- businessTables: BUSINESS_RIBBON_GROUPS.map((group) => ({
123332
- label: group.label,
123333
- _showDivider: group.showDivider,
123334
- options: group.tableTypes.map((type) => getProfile(type)).filter((profile) => Boolean(profile)).map((profile) => ({
123335
- value: profile.ribbonAction,
123336
- label: profile.label,
123337
- disabled: profile.enabled === false
123338
- }))
123339
- }))
123340
- };
123341
- }
123342
- var TABLE_HEADER_RIBBON_OPTION, BUSINESS_RIBBON_GROUPS;
123343
- var init_ribbon_options = __esmMin((() => {
123344
- init_registry$5();
123345
- TABLE_HEADER_RIBBON_OPTION = {
123346
- value: "set-table-header",
123347
- label: "表头"
123348
- };
123349
- BUSINESS_RIBBON_GROUPS = [
123350
- {
123351
- label: "仓储",
123352
- tableTypes: [
123353
- "warehouse-in-out",
123354
- "warehouse-inventory",
123355
- "warehouse-allocate"
123356
- ]
123357
- },
123358
- {
123359
- label: "物料",
123360
- showDivider: true,
123361
- tableTypes: ["material-consume", "material-balance"]
123362
- },
123363
- {
123364
- label: "检验",
123365
- showDivider: true,
123366
- tableTypes: ["check-table"]
123367
- },
123368
- {
123369
- label: "灭菌",
123370
- showDivider: true,
123371
- tableTypes: ["entrust-steril-batch-list"]
123372
- },
123373
- {
123374
- label: "预处理",
123375
- showDivider: true,
123376
- tableTypes: ["pretreatment-list"]
123377
- }
123378
- ];
123379
- }));
123380
- //#endregion
123381
- //#region src/domain/table/design/theme/region-item-theme.ts
123382
- var REGION_ITEM_THEME;
123383
- var init_region_item_theme = __esmMin((() => {
123384
- REGION_ITEM_THEME = {
123385
- "table-header": {
123386
- label: "表头",
123387
- color: "#B54096",
123388
- background: "rgba(181,64,150,0.2)",
123389
- labelBjColor: "rgba(181,64,150,0.8)"
123390
- },
123391
- "data-group": {
123392
- label: "数据分组",
123393
- color: "#F84E92",
123394
- background: "rgba(248,78,146,0.2)",
123395
- labelBjColor: "rgba(248,78,146,0.8)"
123396
- },
123397
- "data-group-2d": {
123398
- label: "动态关联",
123399
- color: "#F84E92",
123400
- background: "rgba(248,78,146,0.2)",
123401
- labelBjColor: "rgba(248,78,146,0.8)"
123402
- }
123403
- };
123404
- }));
123405
- //#endregion
123406
- //#region src/domain/table/design/label.ts
123407
- /** 按 layout 类型获取展示名称(面板标题、设置项等) */
123408
- function getTableLabelByLayoutType(layoutType) {
123409
- var _getProfileByLayoutTy, _REGION_ITEM_THEME$la;
123410
- return ((_getProfileByLayoutTy = getProfileByLayoutType(layoutType)) === null || _getProfileByLayoutTy === void 0 ? void 0 : _getProfileByLayoutTy.label) ?? ((_REGION_ITEM_THEME$la = REGION_ITEM_THEME[layoutType]) === null || _REGION_ITEM_THEME$la === void 0 ? void 0 : _REGION_ITEM_THEME$la.label) ?? layoutType;
123411
- }
123412
- var init_label = __esmMin((() => {
123413
- init_registry$5();
123414
- init_region_item_theme();
123415
- }));
123416
- //#endregion
123417
- //#region src/domain/table/design/sub-model-matcher.ts
123418
- /**
123419
- * 判断 master_slave 字段是否为业务子模型
123420
- * refModelType 为空 → 数据子表;在业务注册表中 → 业务子表
123421
- */
123422
- function isBusinessSubModel(field, businessRefModelTypes = getAllBusinessRefModelTypes()) {
123423
- if (field.type !== FIELD_TYPE.MASTERSLAVE) return false;
123424
- const refType = field.refModelType;
123425
- if (!refType) return false;
123426
- return businessRefModelTypes.includes(refType);
123427
- }
123428
- /**
123429
- * 判断字段是否可用于指定表类型
123430
- * @returns true 表示该 master_slave 字段可作为此表的关联子模型
123431
- */
123432
- function matchSubModel(field, profile) {
123433
- if (field.type !== FIELD_TYPE.MASTERSLAVE) return false;
123434
- if (isDataTableProfile(profile)) return !isBusinessSubModel(field);
123435
- if (isBusinessSubTableProfile(profile)) return field.refModelType === profile.match.refModelType;
123436
- return false;
123437
- }
123438
- /**
123439
- * 生成「选择子模型」下拉选项
123440
- * @param tableTypeOrRibbonAction 表类型或 Ribbon action
123441
- * @param fields 主模型下所有字段
123442
- * @param usedKeys 文档中已占用的子模型 field key(不可重复绑定)
123443
- */
123444
- function getSubModelOptions(tableTypeOrRibbonAction, fields, usedKeys = []) {
123445
- const profile = getProfile(tableTypeOrRibbonAction) ?? getProfileByRibbonAction(tableTypeOrRibbonAction);
123446
- if (!profile) return [];
123447
- return fields.filter((field) => matchSubModel(field, profile)).map((field) => ({
123448
- label: field.name,
123449
- value: field.key,
123450
- disabled: usedKeys.includes(field.key)
123451
- }));
123452
- }
123453
- /**
123454
- * 动态关联模型下拉选项
123455
- * 仅可选普通子模型
123456
- */
123457
- function getDynamicLinkSubModelOptions(fields, usedKeys = []) {
123458
- return fields.filter((field) => matchSubModel(field, profile$8)).map((field) => ({
123459
- label: field.name,
123460
- value: field.key,
123461
- disabled: usedKeys.includes(field.key)
123462
- }));
123463
- }
123464
- /**
123465
- * 创建子表前兜底校验
123466
- * @throws 子模型与表类型不匹配时抛出 Error
123467
- */
123468
- function validateSubModelBinding(tableTypeOrRibbonAction, fieldKey, fields) {
123469
- const profile = getProfile(tableTypeOrRibbonAction) ?? getProfileByRibbonAction(tableTypeOrRibbonAction);
123470
- const field = fields.find((item) => item.key === fieldKey);
123471
- if (!profile) throw new Error(`未找到表类型配置:${tableTypeOrRibbonAction}`);
123472
- if (!field || !matchSubModel(field, profile)) throw new Error(`子模型「${(field === null || field === void 0 ? void 0 : field.name) ?? fieldKey}」不能用于「${profile.label}」`);
123473
- }
123474
- var init_sub_model_matcher = __esmMin((() => {
123475
- init_field_type();
123476
- init_two_d_table();
123477
- init_registry$5();
123478
- init_types$5();
123479
- }));
123480
- //#endregion
123481
- //#region src/domain/table/design/theme/table-theme.ts
123482
- function toStyleResult(label, theme) {
123483
- if (!theme) return null;
123484
- return {
123485
- strokeColor: theme.color,
123486
- backgroundColor: theme.background,
123487
- label,
123488
- labelBjColor: theme.labelBjColor
123489
- };
123490
- }
123491
- function fromRegionItemTheme(theme) {
123492
- return {
123493
- strokeColor: theme.color,
123494
- backgroundColor: theme.background,
123495
- label: theme.label,
123496
- labelBjColor: theme.labelBjColor
123497
- };
123498
- }
123499
- /**
123500
- * 解析子表区域样式
123501
- */
123502
- function getTableStyle(options) {
123503
- const { layoutType, regionItemType } = options;
123504
- if (layoutType) {
123505
- const layoutProfile = getProfileByLayoutType(layoutType);
123506
- const layoutStyle = layoutProfile && toStyleResult(layoutProfile.label, layoutProfile.theme);
123507
- if (layoutStyle) return layoutStyle;
123508
- }
123509
- if (regionItemType) {
123510
- const regionTheme = REGION_ITEM_THEME[regionItemType];
123511
- if (regionTheme) return fromRegionItemTheme(regionTheme);
123512
- }
123513
- return DEFAULT_TABLE_STYLE;
123514
- }
123515
- /**
123516
- * 获取子表设计态样式
123517
- */
123518
- function getStyleByType(type) {
123519
- if (REGION_ITEM_OUTLINE_TYPES.has(type)) return getTableStyle({ regionItemType: type });
123520
- return getTableStyle({ layoutType: type });
123521
- }
123522
- var REGION_ITEM_OUTLINE_TYPES, DEFAULT_TABLE_STYLE;
123523
- var init_table_theme = __esmMin((() => {
123524
- init_registry$5();
123525
- init_region_item_theme();
123526
- REGION_ITEM_OUTLINE_TYPES = new Set(Object.keys(REGION_ITEM_THEME));
123527
- DEFAULT_TABLE_STYLE = {
123528
- strokeColor: "#000",
123529
- backgroundColor: "transparent",
123530
- label: "",
123531
- labelBjColor: "#666"
123532
- };
123533
- }));
123534
- //#endregion
123535
- //#region src/domain/table/runtime/engines/init-load-engine.ts
123536
- var InitLoadEngine;
123537
- var init_init_load_engine = __esmMin((() => {
123538
- init_biz_service_api();
123539
- init_runtime_handlers();
123540
- init_table_runtime_utils();
123541
- init_core$1();
123542
- init_defineProperty();
123543
- InitLoadEngine = class {
123544
- constructor(doc) {
123545
- _defineProperty(this, "doc", void 0);
123546
- this.doc = doc;
123547
- }
123548
- async apply(ctx) {
123549
- var _ctx$region$widgetMet;
123550
- const config = ctx.profile.initLoad;
123551
- if (!config) return;
123552
- const regionProps = (_ctx$region$widgetMet = ctx.region.widgetMeta) === null || _ctx$region$widgetMet === void 0 ? void 0 : _ctx$region$widgetMet.props;
123553
- if (!this.isEnabled(config, regionProps)) return;
123554
- const subFieldKey = ctx.subFieldKey;
123555
- if (this.shouldSkip(subFieldKey, config)) return;
123556
- const query = {};
123557
- for (const item of config.listQuery ?? []) {
123558
- const value = readContextParam(this.doc, item.fromContext.paramKey);
123559
- if (value !== void 0) query[item.queryKey] = value;
123560
- }
123561
- if (Object.keys(query).length === 0) return;
123562
- const res = await callBizService(config.api, { ...query });
123563
- const records = unwrapBizServiceList(res);
123564
- const dict = unwrapBizServiceDict(res);
123565
- if (!records.length) return;
123566
- const groupBy = shouldGroupByWhenFieldAbsent((fieldKey) => ctx.hasFieldWidget(fieldKey), config.groupByWhenFieldAbsent);
123567
- let rows = mapInitLoadRecords(ctx.profile.type, config.mapRecords, records, {
123568
- doc: this.doc,
123569
- runtimeCtx: ctx,
123570
- groupBy,
123571
- dict
123572
- });
123573
- const fills = (ctx.profile.contextAssignments ?? []).filter((a) => a.when === "onInitLoad");
123574
- if (fills.length) rows = rows.map((row) => {
123575
- const next = { ...row };
123576
- for (const fill of fills) {
123577
- const contextValue = readContextParam(this.doc, fill.paramKey);
123578
- if (contextValue === void 0) continue;
123579
- if (fill.onlyIfEmpty && isPresent(next[fill.fieldKey])) continue;
123580
- next[fill.fieldKey] = contextValue;
123581
- }
123582
- return next;
123583
- });
123584
- if (config.rowPatch) rows = rows.map((row) => ({
123585
- ...row,
123586
- ...config.rowPatch
123587
- }));
123588
- const deletedRows = this.readExistingRows(subFieldKey).filter((row) => row.deleted_);
123589
- this.doc.dataManager.set(subFieldKey, [...rows, ...deletedRows], "hydrate");
123590
- }
123591
- isEnabled(config, regionProps) {
123592
- if (config.enabled === true) return true;
123593
- if (config.enabledByWidgetProp) return !!(regionProps === null || regionProps === void 0 ? void 0 : regionProps[config.enabledByWidgetProp]);
123594
- return false;
123595
- }
123596
- /**
123597
- * 判断当前子字段是否需要跳过赋值逻辑
123598
- * @param subFieldKey 子字段数据存储的key
123599
- * @param skipIfRowHasAny 存在任意一个指定字段有值时,就跳过该子字段
123600
- * @returns true-跳过,false-不跳过
123601
- */
123602
- shouldSkip(subFieldKey, config) {
123603
- const existingRows = this.readExistingRows(subFieldKey).filter((row) => !row.deleted_);
123604
- if (existingRows.length === 0) return false;
123605
- if (config.skipWhenNonemptyRows && this.hasNonemptyRow(existingRows)) return true;
123606
- const skipIfRowHasAny = config.skipIfRowHasAny;
123607
- if (!(skipIfRowHasAny === null || skipIfRowHasAny === void 0 ? void 0 : skipIfRowHasAny.length)) return false;
123608
- return existingRows.some((row) => skipIfRowHasAny.some((key) => isPresent(row[key])));
123609
- }
123610
- readExistingRows(subFieldKey) {
123611
- const raw = this.doc.dataManager.getRawData()[subFieldKey];
123612
- if (Array.isArray(raw)) return raw;
123613
- if (raw && typeof raw === "object" && Array.isArray(raw.data)) return raw.data;
123614
- return [];
123615
- }
123616
- hasNonemptyRow(rows) {
123617
- const metaKeys = /* @__PURE__ */ new Set([
123618
- "_DICT",
123619
- "_OPCT",
123620
- "__FOREIGN__",
123621
- "__CHILDREN__",
123622
- "deleted_",
123623
- "group_",
123624
- "data_version_"
123625
- ]);
123626
- return rows.some((row) => Object.entries(row).some(([key, value]) => {
123627
- if (metaKeys.has(key) || key.startsWith("__gw_")) return false;
123628
- return value != null && value !== "";
123629
- }));
123630
- }
123631
- };
123632
- }));
123633
- //#endregion
123634
- //#region src/domain/table/runtime/engines/main-field-bind-engine.ts
123635
- var MainFieldBindEngine;
123636
- var init_main_field_bind_engine = __esmMin((() => {
123637
- init_core$1();
123638
- init_table_runtime_utils();
123639
- init_defineProperty();
123640
- MainFieldBindEngine = class {
123641
- constructor(doc) {
123642
- _defineProperty(this, "doc", void 0);
123643
- this.doc = doc;
123644
- }
123645
- apply(bindings) {
123646
- const entries = getWidgetFieldEntries(this.doc);
123647
- const updates = {};
123648
- for (const binding of bindings) {
123649
- if (binding.source.type !== "context") continue;
123650
- const contextValue = readContextParam(this.doc, binding.source.paramKey);
123651
- if (contextValue === void 0) continue;
123652
- for (const { field, valuePath } of entries) {
123653
- var _binding$excludeField;
123654
- if (field.subFieldKey) continue;
123655
- if (field.fieldType !== binding.fieldType) continue;
123656
- const fieldKey = getLastSegment$1(field.fieldLink);
123657
- if ((_binding$excludeField = binding.excludeFieldKeys) === null || _binding$excludeField === void 0 ? void 0 : _binding$excludeField.includes(fieldKey)) continue;
123658
- if (!valuePath) continue;
123659
- updates[valuePath] = contextValue;
123660
- }
123661
- }
123662
- if (Object.keys(updates).length > 0) this.doc.dataManager.setMultiple(updates, "hydrate");
123663
- }
123664
- };
123665
- }));
123666
- //#endregion
123667
- //#region src/domain/table/runtime/table-runtime.ts
123668
- var TableRuntime;
123669
- var init_table_runtime = __esmMin((() => {
123670
- init_data();
123671
- init_rule_engine();
123672
- init_linkage_engine();
123673
- init_row_runtime_engine();
123674
- init_remote_sync_engine();
123675
- init_init_load_engine();
123676
- init_main_field_bind_engine();
123677
- init_table_runtime_context();
123678
- init_computed();
123679
- init_autofill_runtime();
123680
- init_defineProperty();
123681
- TableRuntime = class {
123682
- constructor(doc) {
123683
- _defineProperty(this, "doc", void 0);
123684
- _defineProperty(this, "contexts", void 0);
123685
- _defineProperty(this, "rule", void 0);
123686
- _defineProperty(this, "linkage", void 0);
123687
- _defineProperty(this, "row", void 0);
123688
- _defineProperty(this, "remoteSync", void 0);
123689
- _defineProperty(this, "initLoad", void 0);
123690
- _defineProperty(this, "mainFieldBind", void 0);
123691
- this.doc = doc;
123692
- this.contexts = TableRuntimeContext.collectAll(doc);
123693
- this.rule = new RuleEngine(doc);
123694
- this.linkage = new LinkageEngine(doc);
123695
- this.row = new RowRuntimeEngine(doc);
123696
- this.remoteSync = new RemoteSyncEngine(doc);
123697
- this.initLoad = new InitLoadEngine(doc);
123698
- this.mainFieldBind = new MainFieldBindEngine(doc);
123699
- }
123700
- /** 文档是否包含业务子表 */
123701
- get hasBusinessTables() {
123702
- return this.contexts.length > 0;
123703
- }
123704
- /** 文档初始化时执行全套运行时逻辑 */
123705
- async onInit() {
123706
- var _this$doc$isInEditMod, _this$doc, _this$contexts$find;
123707
- if ((_this$doc$isInEditMod = (_this$doc = this.doc).isInEditMode) === null || _this$doc$isInEditMod === void 0 ? void 0 : _this$doc$isInEditMod.call(_this$doc)) return;
123708
- const bindings = (_this$contexts$find = this.contexts.find((ctx) => ctx.profile.mainFieldBindings)) === null || _this$contexts$find === void 0 ? void 0 : _this$contexts$find.profile.mainFieldBindings;
123709
- if (bindings === null || bindings === void 0 ? void 0 : bindings.length) this.mainFieldBind.apply(bindings);
123710
- for (const ctx of this.contexts) {
123711
- await this.initLoad.apply(ctx);
123712
- this.row.applyRowInitForAllRows(ctx);
123713
- this.linkage.applyForSubTable(ctx);
123714
- this.rule.applyOnInit(ctx);
123715
- this.remoteSync.applyOnInit(ctx);
123716
- }
123717
- }
123718
- /**
123719
- * 子表新增行初始化:rowInit → 字段态规则 → 级联 → 数据填充。
123720
- */
123721
- onRowInit(subFieldKey, rowIndex, rowSource) {
123722
- var _this$doc$isInEditMod2, _this$doc2;
123723
- if ((_this$doc$isInEditMod2 = (_this$doc2 = this.doc).isInEditMode) === null || _this$doc$isInEditMod2 === void 0 ? void 0 : _this$doc$isInEditMod2.call(_this$doc2)) return;
123724
- const ctx = this.findContext(subFieldKey);
123725
- if (ctx) {
123726
- this.row.applyRowInit(ctx, rowIndex, rowSource);
123727
- this.rule.applyOnRowInit(ctx, rowIndex);
123728
- this.linkage.applyForSubTable(ctx, { rowIndex });
123729
- }
123730
- applyAutofillOnSubTableRowInit(this.doc, subFieldKey, rowIndex, fetchAutofillSource);
123731
- hydrateSubtableRowLabels(this.doc, subFieldKey, [rowIndex]);
123732
- }
123733
- /**
123734
- * 批量字段变更:对每个变更只解析路径、查上下文一次,再分派给各 engine。
123735
- * 仅处理 source=user 的变更(hydrate/dependency/enrichment 不应触发业务副作用)。
123736
- */
123737
- onFieldChanges(changedMap, options) {
123738
- var _this$doc$isInEditMod3, _this$doc3;
123739
- if ((_this$doc$isInEditMod3 = (_this$doc3 = this.doc).isInEditMode) === null || _this$doc$isInEditMod3 === void 0 ? void 0 : _this$doc$isInEditMod3.call(_this$doc3)) return;
123740
- if ((options === null || options === void 0 ? void 0 : options.batchSource) && options.batchSource !== "user") return;
123741
- const userEntries = Object.entries(changedMap).filter(([, detail]) => detail.source === "user");
123742
- if (!userEntries.length) return;
123743
- for (const [changedPath, fieldChange] of userEntries) {
123744
- if (isDerivedDataPath(changedPath)) continue;
123745
- const change = parseBusinessFieldChange(changedPath);
123746
- if (!change) continue;
123747
- if (fieldChange && isSameFieldValue(fieldChange.oldValue, fieldChange.newValue)) continue;
123748
- if (change.kind === "subtable") {
123749
- const ctx = this.findContext(change.subFieldKey);
123750
- if (!ctx) continue;
123751
- this.row.applyRowHandlersOnFieldChange(ctx, change, fieldChange);
123752
- this.rule.applyOnFieldChange(ctx, change, fieldChange);
123753
- this.linkage.applyForSubTable(ctx, {
123754
- rowIndex: change.rowIndex,
123755
- changedFieldKey: change.fieldKey,
123756
- fieldChange
123757
- });
123758
- this.remoteSync.applyOnFieldChange(ctx, change, fieldChange);
123759
- continue;
123760
- }
123761
- }
123762
- }
123763
- /**
123764
- * 解析下拉字段级联联动信息(联动启用状态 + 上游值),供下拉组件使用。
123765
- */
123766
- resolveSelectLinkage(options) {
123767
- const { subFieldKey, fieldKey, runtimeValuePath } = options;
123768
- if (!subFieldKey || !fieldKey) return null;
123769
- const ctx = this.findContext(subFieldKey);
123770
- if (!ctx) return null;
123771
- return this.linkage.resolveSelectLinkage(ctx, fieldKey, runtimeValuePath);
123772
- }
123773
- /**
123774
- * 解析业务表字段的下拉数据源 / 列覆盖(selectSource)。
123775
- */
123776
- resolveSelectSource(options) {
123777
- var _ctx$findFieldProfile;
123778
- const { subFieldKey, fieldKey } = options;
123779
- if (!subFieldKey || !fieldKey) return null;
123780
- const ctx = this.findContext(subFieldKey);
123781
- if (!ctx) return null;
123782
- return ((_ctx$findFieldProfile = ctx.findFieldProfile(fieldKey)) === null || _ctx$findFieldProfile === void 0 ? void 0 : _ctx$findFieldProfile.selectSource) ?? null;
123783
- }
123784
- /**
123785
- * 下拉选中后从选项反向回填同行字段,供 onChange 使用。
123786
- */
123787
- buildSelectReverseFill(options) {
123788
- var _this$doc$isInEditMod4, _this$doc4;
123789
- if ((_this$doc$isInEditMod4 = (_this$doc4 = this.doc).isInEditMode) === null || _this$doc$isInEditMod4 === void 0 ? void 0 : _this$doc$isInEditMod4.call(_this$doc4)) return {};
123790
- const ctx = this.findContext(options.subFieldKey);
123791
- if (!ctx) return {};
123792
- return this.linkage.buildSelectReverseFill(ctx, options.fieldKey, options.rowIndex, options.selectedOption);
123793
- }
123794
- /**
123795
- * 选中下拉项后,按 profile.fillFromOption 同步填充同行字段(以 enrichment 写入,不触发 remoteSync)。
123796
- */
123797
- buildFillFromOption(options) {
123798
- var _this$doc$isInEditMod5, _this$doc5;
123799
- if ((_this$doc$isInEditMod5 = (_this$doc5 = this.doc).isInEditMode) === null || _this$doc$isInEditMod5 === void 0 ? void 0 : _this$doc$isInEditMod5.call(_this$doc5)) return {};
123800
- const ctx = this.findContext(options.subFieldKey);
123801
- if (!ctx) return {};
123802
- return this.linkage.buildFillFromOption(ctx, options.fieldKey, options.rowIndex, options.selectedOption);
123803
- }
123804
- /**
123805
- * 批量构建因字段变更需清空的级联下游字段更新集合(写入前预清空)。
123806
- * 区分子表内字段变更 / 主表隐式联动字段变更两种场景。
123807
- */
123808
- buildDownstreamClears(pendingUpdates) {
123809
- var _this$doc$isInEditMod6, _this$doc6;
123810
- if ((_this$doc$isInEditMod6 = (_this$doc6 = this.doc).isInEditMode) === null || _this$doc$isInEditMod6 === void 0 ? void 0 : _this$doc$isInEditMod6.call(_this$doc6)) return {};
123811
- const updates = {};
123812
- for (const [changedPath, newValue] of Object.entries(pendingUpdates)) {
123813
- if (isDerivedDataPath(changedPath)) continue;
123814
- if (isSameFieldValue(this.doc.dataManager.get(changedPath), newValue)) continue;
123815
- const change = parseBusinessFieldChange(changedPath);
123816
- if (!change) continue;
123817
- if (change.kind === "subtable") {
123818
- const ctx = this.findContext(change.subFieldKey);
123819
- if (!ctx) continue;
123820
- const ruleCtx = ctx.buildRuleContext(change.rowIndex, change.fieldKey);
123821
- Object.assign(updates, this.linkage.collectClearUpdates(ctx, ruleCtx, change.fieldKey));
123822
- continue;
123823
- }
123824
- for (const ctx of this.contexts) {
123825
- if (!ctx.isImplicitLinkField(change.fieldKey)) continue;
123826
- ctx.eachRow({ changedFieldKey: change.fieldKey }, (ruleCtx) => {
123827
- Object.assign(updates, this.linkage.collectClearUpdates(ctx, ruleCtx, change.fieldKey));
123828
- });
123829
- }
123830
- }
123831
- return updates;
123832
- }
123833
- findContext(subFieldKey) {
123834
- return this.contexts.find((ctx) => ctx.subFieldKey === subFieldKey);
123835
- }
123836
- };
123837
- }));
123838
- //#endregion
123839
- //#region src/domain/table/design/hooks/on-subtable-create.ts
123840
- /**
123841
- * 从当前文档收集已被子表占用的 master_slave field key
123842
- */
123843
- function collectUsedSubModelKeys(docModel) {
123844
- var _docModel$document;
123845
- if (!(docModel === null || docModel === void 0 || (_docModel$document = docModel.document) === null || _docModel$document === void 0 || (_docModel$document = _docModel$document.body) === null || _docModel$document === void 0 ? void 0 : _docModel$document.children)) return [];
123846
- return docModel.document.body.children.flatMap((widget) => {
123847
- if (!(widget.name === "w:tbl" && (widget.hasBounded || widget.hasCheckTable || widget.hasRepeating || widget.has2DTable || widget.hasMaterialConsumeTable))) return [];
123848
- return [
123849
- ...widget.bounded,
123850
- ...widget.checkTable,
123851
- ...widget.repeating,
123852
- ...widget._2DTable,
123853
- ...widget.materialConsumeTable
123854
- ].flatMap((region) => [region.subFieldKey, region.linkFieldKey].filter(Boolean));
123855
- });
123856
- }
123857
- /**
123858
- * 确认创建子表:校验子模型绑定合法性,返回应执行的 Doc 命令
123859
- * @throws 校验失败时抛出 Error
123860
- */
123861
- function confirmSubTableCreate(options) {
123862
- const { ribbonAction, subFieldKey, fields } = options;
123863
- const profile = getProfileByRibbonAction(ribbonAction);
123864
- if (!profile) throw new Error(`未找到表类型配置:${ribbonAction}`);
123865
- validateSubModelBinding(ribbonAction, subFieldKey, fields);
123866
- return profile.command;
123867
- }
123868
- /** 解析 Ribbon action 对应的表 Profile */
123869
- function resolveSubTableProfile(ribbonAction) {
123870
- return getProfileByRibbonAction(ribbonAction) ?? getProfile(ribbonAction);
123871
- }
123872
- var init_on_subtable_create = __esmMin((() => {
123873
- init_sub_model_matcher();
123874
- init_registry$5();
123875
- }));
123876
- //#endregion
123877
- //#region src/domain/table/design/hooks/on-field-attach.ts
123878
- function matchBusinessField(field, profile) {
123879
- const { fieldKey, bizType } = profile.match;
123880
- if (fieldKey) {
123881
- if ((Array.isArray(fieldKey) ? fieldKey : [fieldKey]).includes(field.key)) return true;
123882
- }
123883
- if (bizType) {
123884
- if ((field.bizType ?? field.type) === bizType) return true;
123885
- }
123886
- return false;
123887
- }
123888
- /** 在业务表 fields 配置中匹配当前拖入字段 */
123889
- function resolveBusinessFieldProfile(field, fieldProfiles = []) {
123890
- return fieldProfiles.find((profile) => matchBusinessField(field, profile));
123891
- }
123892
- function applyLockedProps(props, locked) {
123893
- if (!(locked === null || locked === void 0 ? void 0 : locked.length)) return;
123894
- if (locked.includes("disabled")) props.disabled = true;
123895
- if (locked.includes("required")) props.required = true;
123896
- if (locked.includes("readonly")) props.viewState = ViewStateTypeConst.Readonly;
123897
- }
123898
- /**
123899
- * 字段拖入画布时应用业务表字段 Profile
123900
- * - 合并 defaultProps
123901
- * - 应用 locked 属性
123902
- * - 展开 autofillTemplates → autofillRules
123903
- */
123904
- function applyFieldProfileOnAttach(widget, field, options = {}) {
123905
- var _businessProfile$fiel, _fieldProfile$autofil;
123906
- if (!options.parentFieldKey || !options.refModelType) return widget;
123907
- const businessProfile = getBusinessProfileByRefModelType(options.refModelType);
123908
- if (!(businessProfile === null || businessProfile === void 0 || (_businessProfile$fiel = businessProfile.fields) === null || _businessProfile$fiel === void 0 ? void 0 : _businessProfile$fiel.length)) return widget;
123909
- const fieldProfile = resolveBusinessFieldProfile(field, businessProfile.fields);
123910
- if (!fieldProfile) return widget;
123911
- const props = {
123912
- ...widget.props,
123913
- ...fieldProfile.defaultProps ?? {}
123914
- };
123915
- applyLockedProps(props, fieldProfile.locked);
123916
- if ((_fieldProfile$autofil = fieldProfile.autofillTemplates) === null || _fieldProfile$autofil === void 0 ? void 0 : _fieldProfile$autofil.length) {
123917
- const inSubTable = Boolean(options.parentFieldKey);
123918
- props.autofillRules = expandAutofillTemplates(fieldProfile.autofillTemplates, {
123919
- sourceFieldKey: field.key,
123920
- toModelKey: inSubTable ? field.modelKey : void 0,
123921
- toSubModel: inSubTable ? 1 : void 0,
123922
- toSubFieldKey: inSubTable ? options.parentFieldKey : void 0
123923
- });
123924
- props.autofillEnabled = true;
123925
- }
123926
- return {
123927
- ...widget,
123928
- props
123929
- };
123930
- }
123931
- var init_on_field_attach = __esmMin((() => {
123932
- init_enum();
123933
- init_autofill_expander();
123934
- init_registry$5();
123935
- }));
123936
- //#endregion
123937
- //#region src/domain/table/design/validate-table-selection.ts
123938
- /** 解析已有逻辑区域的展示名称 */
123939
- function resolveTableRegionLabel(region) {
123940
- if (region.type === "repeating") return getTableLabelByLayoutType(region.layoutType);
123941
- if (region.type === "table-header") return REGION_ITEM_THEME["table-header"].label;
123942
- if (region.type === "sub-table-header") return "子表表头";
123943
- const layoutType = REGION_TYPE_LAYOUT[region.type];
123944
- if (layoutType) return getTableLabelByLayoutType(layoutType);
123945
- return "子表";
123946
- }
123947
- /** 从当前光标选区解析表格单元格范围 */
123948
- function resolveTableCellSelectionBounds(doc) {
123949
- var _startCell$parent, _endCell$parent;
123950
- const cursor = doc.cursorManager;
123951
- if (cursor.isCollapsed()) return null;
123952
- const selection = cursor.getSelection();
123953
- if (!selection) return null;
123954
- const info = getSelectLinesInfo(doc, selection, true);
123955
- if (!info) return null;
123956
- const { tableMode, rangeWidgetIds } = info;
123957
- if (tableMode !== "cell-range" && tableMode !== "cell-full") return null;
123958
- if (!(rangeWidgetIds === null || rangeWidgetIds === void 0 ? void 0 : rangeWidgetIds.length)) return null;
123959
- const mapper = doc.layoutMapper;
123960
- const startCell = mapper.getModelNodeByLayoutId(rangeWidgetIds[0]);
123961
- const endCell = mapper.getModelNodeByLayoutId(rangeWidgetIds[rangeWidgetIds.length - 1]);
123962
- if (!startCell || !endCell) return null;
123963
- const table = startCell.table;
123964
- if (!table || startCell.table !== endCell.table) return null;
123965
- return {
123966
- table,
123967
- start: {
123968
- row: (_startCell$parent = startCell.parent) === null || _startCell$parent === void 0 ? void 0 : _startCell$parent.getCurrentIndex(),
123969
- col: startCell.getCurrentIndex()
123970
- },
123971
- end: {
123972
- row: (_endCell$parent = endCell.parent) === null || _endCell$parent === void 0 ? void 0 : _endCell$parent.getCurrentIndex(),
123973
- col: endCell.getCurrentIndex()
123974
- }
123975
- };
123976
- }
123977
- /**
123978
- * 校验是否已选中合法的表格单元格区域
123979
- */
123980
- function validateTableSelection(doc, options) {
123981
- if (!doc) return false;
123982
- const bounds = resolveTableCellSelectionBounds(doc);
123983
- if (!bounds) {
123984
- GctMessage.warning(`请选择${options.targetLabel}区域`);
123985
- return false;
123986
- }
123987
- const crossRegion = bounds.table.findCrossRegion(bounds);
123988
- if (!crossRegion) return true;
123989
- if (new Set(options.ignoreOverlapTypes ?? []).has(crossRegion.type)) return true;
123990
- const existingLabel = resolveTableRegionLabel(crossRegion);
123991
- GctMessage.warning(`当前选区与已有「${existingLabel}」重叠,请重新选择空白区域`);
123992
- return false;
123993
- }
123994
- var REGION_TYPE_LAYOUT;
123995
- var init_validate_table_selection = __esmMin((() => {
123996
- init_base$2();
123997
- init_logic$1();
123998
- init_label();
123999
- init_region_item_theme();
124000
- REGION_TYPE_LAYOUT = {
124001
- bounded: "fixed-table",
124002
- "2d-table": "two-d-table",
124003
- "check-table": "check-table",
124004
- "material-consume-table": "material-consume-table"
124005
- };
124006
- }));
124007
- //#endregion
124008
- //#region src/domain/table/index.ts
124009
- var init_table$1 = __esmMin((() => {
124010
- init_types$5();
124011
- init_registry$5();
124012
- init_ribbon_options();
124013
- init_label();
124014
- init_sub_model_matcher();
124015
- init_autofill_expander();
124016
- init_region_item_theme();
124017
- init_table_theme();
124018
- init_table_runtime();
124019
- init_on_subtable_create();
124020
- init_on_field_attach();
124021
- init_on_repeating_default_props();
124022
- init_validate_table_selection();
124023
- }));
124024
- //#endregion
124025
124909
  //#region src/sdk/doc-runtime/factories/document-initializer.ts
124026
124910
  init_core();
124027
124911
  init_data$1();
@@ -124287,6 +125171,7 @@ async function finalizeDesignModelImport(doc, docModel) {
124287
125171
  doc.eventManager.cursorController.clearCursor();
124288
125172
  doc.interactionManager.clear("tableSelection");
124289
125173
  doc.interactionManager.clear("activeTableId");
125174
+ doc.interactionManager.clear("activeTableScope");
124290
125175
  doc.interactionManager.clear("dragHoverId");
124291
125176
  doc.interactionManager.clear("hoverModelId");
124292
125177
  doc.interactionManager.clear("focusModelId");
@@ -132369,15 +133254,21 @@ var init_table_lines = __esmMin((() => {
132369
133254
  }));
132370
133255
  //#endregion
132371
133256
  //#region src/runtime/canvas/table/shared/table-cell.vue?vue&type=script&setup=true&name=table-cell&lang.ts
132372
- var CORNER_SIZE, table_cell_vue_vue_type_script_setup_true_name_table_cell_lang_default;
133257
+ var CORNER_SIZE, SELECTION_COLOR, SELECTION_OPACITY, table_cell_vue_vue_type_script_setup_true_name_table_cell_lang_default;
132373
133258
  var init_table_cell_vue_vue_type_script_setup_true_name_table_cell_lang = __esmMin((() => {
132374
133259
  init_widget_component();
132375
133260
  CORNER_SIZE = 6;
133261
+ SELECTION_COLOR = "rgb(85,165,255)";
133262
+ SELECTION_OPACITY = .5;
132376
133263
  table_cell_vue_vue_type_script_setup_true_name_table_cell_lang_default = /*@__PURE__*/ defineComponent({
132377
133264
  __name: "table-cell",
132378
133265
  props: { rows: {} },
132379
133266
  setup(__props) {
132380
133267
  const props = __props;
133268
+ const cellRangeIds = inject("cellRangeIds");
133269
+ function isCellSelected(cellId) {
133270
+ return (cellRangeIds === null || cellRangeIds === void 0 ? void 0 : cellRangeIds.value.has(cellId)) ?? false;
133271
+ }
132381
133272
  const computedRows = computed(() => props.rows.map((row) => ({
132382
133273
  ...row,
132383
133274
  cells: row.cells.map((cell) => ({
@@ -132387,7 +133278,9 @@ var init_table_cell_vue_vue_type_script_setup_true_name_table_cell_lang = __esmM
132387
133278
  roundWidth: Math.round(cell.width),
132388
133279
  roundHeight: Math.round(cell.height),
132389
133280
  pl: cell.pl ?? 2,
132390
- pt: cell.pt ?? 2
133281
+ pr: cell.pr ?? 2,
133282
+ pt: cell.pt ?? 2,
133283
+ pb: cell.pb ?? 2
132391
133284
  }))
132392
133285
  })));
132393
133286
  return (_ctx, _cache) => {
@@ -132403,7 +133296,7 @@ var init_table_cell_vue_vue_type_script_setup_true_name_table_cell_lang = __esmM
132403
133296
  y: cell.roundY,
132404
133297
  width: cell.roundWidth,
132405
133298
  height: cell.roundHeight,
132406
- fill: cell.backgroundColor,
133299
+ fill: cell.backgroundColor || (cell.isNested ? "white" : "transparent"),
132407
133300
  id: cell.id
132408
133301
  }, null, 8, [
132409
133302
  "x",
@@ -132413,17 +133306,32 @@ var init_table_cell_vue_vue_type_script_setup_true_name_table_cell_lang = __esmM
132413
133306
  "fill",
132414
133307
  "id"
132415
133308
  ])) : createCommentVNode("", true),
132416
- !cell.mergeFromId ? (openBlock(), createBlock(_component_v_rect, {
133309
+ !cell.mergeFromId && isCellSelected(cell.id) ? (openBlock(), createBlock(_component_v_rect, {
132417
133310
  key: 1,
132418
133311
  x: cell.roundX,
132419
133312
  y: cell.roundY,
133313
+ width: cell.roundWidth,
133314
+ height: cell.roundHeight,
133315
+ fill: SELECTION_COLOR,
133316
+ opacity: SELECTION_OPACITY,
133317
+ listening: false
133318
+ }, null, 8, [
133319
+ "x",
133320
+ "y",
133321
+ "width",
133322
+ "height"
133323
+ ])) : createCommentVNode("", true),
133324
+ !cell.mergeFromId ? (openBlock(), createBlock(_component_v_rect, {
133325
+ key: 2,
133326
+ x: cell.roundX,
133327
+ y: cell.roundY,
132420
133328
  width: CORNER_SIZE,
132421
133329
  height: CORNER_SIZE,
132422
133330
  fill: "transparent",
132423
133331
  id: "cellHitPoint"
132424
133332
  }, null, 8, ["x", "y"])) : createCommentVNode("", true),
132425
133333
  !cell.mergeFromId ? (openBlock(), createBlock(_component_v_rect, {
132426
- key: 2,
133334
+ key: 3,
132427
133335
  x: cell.roundX + cell.roundWidth - CORNER_SIZE,
132428
133336
  y: cell.roundY + cell.roundHeight - CORNER_SIZE,
132429
133337
  width: CORNER_SIZE,
@@ -132432,18 +133340,28 @@ var init_table_cell_vue_vue_type_script_setup_true_name_table_cell_lang = __esmM
132432
133340
  id: "cellHitPoint"
132433
133341
  }, null, 8, ["x", "y"])) : createCommentVNode("", true),
132434
133342
  !cell.mergeFromId ? (openBlock(), createBlock(_component_v_group, {
132435
- key: 3,
133343
+ key: 4,
132436
133344
  config: {
132437
- x: cell.roundX + cell.pl,
132438
- y: cell.roundY + cell.pt
133345
+ x: cell.roundX,
133346
+ y: cell.roundY,
133347
+ clipX: 0,
133348
+ clipY: 0,
133349
+ clipWidth: Math.max(0, cell.roundWidth),
133350
+ clipHeight: Math.max(0, cell.roundHeight)
132439
133351
  }
132440
133352
  }, {
132441
- default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(cell.children, (node) => {
132442
- return openBlock(), createBlock(widget_component_default, {
132443
- key: node.id,
132444
- widget: node
132445
- }, null, 8, ["widget"]);
132446
- }), 128))]),
133353
+ default: withCtx(() => [createVNode(_component_v_group, { config: {
133354
+ x: cell.pl,
133355
+ y: cell.pt
133356
+ } }, {
133357
+ default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(cell.children, (node) => {
133358
+ return openBlock(), createBlock(widget_component_default, {
133359
+ key: node.id,
133360
+ widget: node
133361
+ }, null, 8, ["widget"]);
133362
+ }), 128))]),
133363
+ _: 2
133364
+ }, 1032, ["config"])]),
132447
133365
  _: 2
132448
133366
  }, 1032, ["config"])) : createCommentVNode("", true)
132449
133367
  ], 64);
@@ -132932,6 +133850,7 @@ var init_index_vue_vue_type_script_setup_true_name_table_action_lang = __esmMin(
132932
133850
  init_base$2();
132933
133851
  init_useTableSelection();
132934
133852
  init_core();
133853
+ init_constants$1();
132935
133854
  _hoisted_1$115 = { class: "col-headers" };
132936
133855
  _hoisted_2$69 = ["onMouseenter"];
132937
133856
  _hoisted_3$50 = ["onClick"];
@@ -132973,8 +133892,10 @@ var init_index_vue_vue_type_script_setup_true_name_table_action_lang = __esmMin(
132973
133892
  });
132974
133893
  const tableId = computed(() => props.widget.id);
132975
133894
  const isCurrentTableActive = computed(() => {
132976
- var _props$widget$modelRe;
132977
- return interaction.activeTableId === ((_props$widget$modelRe = props.widget.modelRef) === null || _props$widget$modelRe === void 0 ? void 0 : _props$widget$modelRe.id);
133895
+ var _props$widget$modelRe, _interaction$activeTa;
133896
+ const modelTableId = (_props$widget$modelRe = props.widget.modelRef) === null || _props$widget$modelRe === void 0 ? void 0 : _props$widget$modelRe.id;
133897
+ if (!modelTableId) return false;
133898
+ return ((_interaction$activeTa = interaction.activeTableScope) === null || _interaction$activeTa === void 0 ? void 0 : _interaction$activeTa.wtblId) === modelTableId || interaction.activeTableId === modelTableId;
132978
133899
  });
132979
133900
  const pageBaseOffset = computed(() => {
132980
133901
  const node = props.doc.layoutMapper.getBaseMetaNodeById(tableId.value);
@@ -133158,7 +134079,7 @@ var init_index_vue_vue_type_script_setup_true_name_table_action_lang = __esmMin(
133158
134079
  return isTargetReady.value ? (openBlock(), createBlock(Teleport, {
133159
134080
  key: 0,
133160
134081
  to: `#doc-konva-wrap-${__props.doc.id}`
133161
- }, [!unref(interaction).isHeaderFooterEdit && isCurrentTableActive.value ? (openBlock(), createElementBlock("div", {
134082
+ }, [!unref(interaction).isHeaderFooterEdit && isCurrentTableActive.value && !isPreview.value ? (openBlock(), createElementBlock("div", {
133162
134083
  key: 0,
133163
134084
  class: normalizeClass(["table-action", { preview: isPreview.value }]),
133164
134085
  style: normalizeStyle(actionPos.value)
@@ -133292,17 +134213,17 @@ var init_index_vue_vue_type_script_setup_true_name_table_action_lang = __esmMin(
133292
134213
  });
133293
134214
  }));
133294
134215
  //#endregion
133295
- //#region src/runtime/canvas/table/design/table-action-overlay/index.vue?vue&type=style&index=0&scoped=c40eef9f&lang.less
133296
- var init_index_vue_vue_type_style_index_0_scoped_c40eef9f_lang = __esmMin((() => {}));
134216
+ //#region src/runtime/canvas/table/design/table-action-overlay/index.vue?vue&type=style&index=0&scoped=c49cd3d6&lang.less
134217
+ var init_index_vue_vue_type_style_index_0_scoped_c49cd3d6_lang = __esmMin((() => {}));
133297
134218
  //#endregion
133298
134219
  //#region src/runtime/canvas/table/design/table-action-overlay/index.vue
133299
134220
  var table_action_overlay_default;
133300
134221
  var init_table_action_overlay = __esmMin((() => {
133301
134222
  init_index_vue_vue_type_script_setup_true_name_table_action_lang();
133302
134223
  init_index_vue_vue_type_script_setup_true_name_table_action_lang();
133303
- init_index_vue_vue_type_style_index_0_scoped_c40eef9f_lang();
134224
+ init_index_vue_vue_type_style_index_0_scoped_c49cd3d6_lang();
133304
134225
  init__plugin_vue_export_helper();
133305
- table_action_overlay_default = /*#__PURE__*/ _plugin_vue_export_helper_default(index_vue_vue_type_script_setup_true_name_table_action_lang_default, [["__scopeId", "data-v-c40eef9f"]]);
134226
+ table_action_overlay_default = /*#__PURE__*/ _plugin_vue_export_helper_default(index_vue_vue_type_script_setup_true_name_table_action_lang_default, [["__scopeId", "data-v-c49cd3d6"]]);
133306
134227
  }));
133307
134228
  //#endregion
133308
134229
  //#region src/runtime/canvas/table/design/table-guide-line.vue?vue&type=script&setup=true&name=table-guide-line&lang.ts
@@ -133508,14 +134429,25 @@ var init_table_design_vue_vue_type_script_setup_true_lang = __esmMin((() => {
133508
134429
  rows: {},
133509
134430
  colWidths: {},
133510
134431
  colLefts: {},
133511
- mergeRects: {}
134432
+ mergeRects: {},
134433
+ isNested: { type: Boolean }
133512
134434
  },
133513
134435
  setup(__props) {
133514
- const widget = toRef(__props, "widget");
134436
+ const props = __props;
134437
+ const widget = toRef(props, "widget");
133515
134438
  const guideLineHover = ref(null);
133516
134439
  const removeHoverBool = ref(false);
133517
134440
  const tableWidth = computed(() => Math.round(widget.value.width));
133518
134441
  const tableHeight = computed(() => Math.round(widget.value.height));
134442
+ const contentSteps = computed(() => props.isNested ? [
134443
+ "highlight",
134444
+ "cells",
134445
+ "overlay"
134446
+ ] : [
134447
+ "overlay",
134448
+ "highlight",
134449
+ "cells"
134450
+ ]);
133519
134451
  return (_ctx, _cache) => {
133520
134452
  const _component_v_group = resolveComponent("v-group");
133521
134453
  return openBlock(), createBlock(_component_v_group, { config: {
@@ -133560,35 +134492,40 @@ var init_table_design_vue_vue_type_script_setup_true_lang = __esmMin((() => {
133560
134492
  "tableHeight",
133561
134493
  "guideLineHover"
133562
134494
  ]),
133563
- createVNode(table_structure_overlay_default$1, {
133564
- rows: __props.rows,
133565
- widget: widget.value,
133566
- doc: widget.value.doc
133567
- }, null, 8, [
133568
- "rows",
133569
- "widget",
133570
- "doc"
133571
- ]),
133572
- createVNode(table_cell_highlight_default, {
133573
- rows: __props.rows,
133574
- doc: widget.value.doc,
133575
- "table-id": widget.value.id,
133576
- colWidths: __props.colWidths,
133577
- colLefts: __props.colLefts,
133578
- tableWidth: tableWidth.value,
133579
- tableHeight: tableHeight.value,
133580
- removeHoverBool: removeHoverBool.value
133581
- }, null, 8, [
133582
- "rows",
133583
- "doc",
133584
- "table-id",
133585
- "colWidths",
133586
- "colLefts",
133587
- "tableWidth",
133588
- "tableHeight",
133589
- "removeHoverBool"
133590
- ]),
133591
- createVNode(table_cell_default, { rows: __props.rows }, null, 8, ["rows"]),
134495
+ (openBlock(true), createElementBlock(Fragment, null, renderList(contentSteps.value, (step) => {
134496
+ return openBlock(), createElementBlock(Fragment, { key: step }, [step === "overlay" ? (openBlock(), createBlock(table_structure_overlay_default$1, {
134497
+ key: 0,
134498
+ rows: __props.rows,
134499
+ widget: widget.value,
134500
+ doc: widget.value.doc
134501
+ }, null, 8, [
134502
+ "rows",
134503
+ "widget",
134504
+ "doc"
134505
+ ])) : step === "highlight" ? (openBlock(), createBlock(table_cell_highlight_default, {
134506
+ key: 1,
134507
+ rows: __props.rows,
134508
+ doc: widget.value.doc,
134509
+ "table-id": widget.value.id,
134510
+ colWidths: __props.colWidths,
134511
+ colLefts: __props.colLefts,
134512
+ tableWidth: tableWidth.value,
134513
+ tableHeight: tableHeight.value,
134514
+ removeHoverBool: removeHoverBool.value
134515
+ }, null, 8, [
134516
+ "rows",
134517
+ "doc",
134518
+ "table-id",
134519
+ "colWidths",
134520
+ "colLefts",
134521
+ "tableWidth",
134522
+ "tableHeight",
134523
+ "removeHoverBool"
134524
+ ])) : step === "cells" ? (openBlock(), createBlock(table_cell_default, {
134525
+ key: 2,
134526
+ rows: __props.rows
134527
+ }, null, 8, ["rows"])) : createCommentVNode("", true)], 64);
134528
+ }), 128)),
133592
134529
  createVNode(table_background_default, {
133593
134530
  width: tableWidth.value,
133594
134531
  height: tableHeight.value
@@ -134239,12 +135176,19 @@ var init_table_vue_vue_type_script_setup_true_name_table_lang = __esmMin((() =>
134239
135176
  init_table_design();
134240
135177
  init_table_render();
134241
135178
  init_core();
135179
+ init_constants$1();
134242
135180
  table_vue_vue_type_script_setup_true_name_table_lang_default = /*@__PURE__*/ defineComponent({
134243
135181
  __name: "table",
134244
135182
  props: { widget: {} },
134245
135183
  setup(__props) {
134246
135184
  const widget = toRef(__props, "widget");
135185
+ const roundX = computed(() => Math.round(widget.value.x));
135186
+ const roundY = computed(() => Math.round(widget.value.y));
134247
135187
  const { isDesignMode } = useDocPubApiContext();
135188
+ const isNested = computed(() => {
135189
+ var _widget$value$parent;
135190
+ return ((_widget$value$parent = widget.value.parent) === null || _widget$value$parent === void 0 ? void 0 : _widget$value$parent.component) === BuiltinComponentTypeConst.TableCell;
135191
+ });
134248
135192
  const rows = computed(() => widget.value.getChildren().map((row) => ({
134249
135193
  id: row.id,
134250
135194
  y: row.y,
@@ -134259,9 +135203,12 @@ var init_table_vue_vue_type_script_setup_true_name_table_lang = __esmMin((() =>
134259
135203
  height: cell.height,
134260
135204
  mergeFromId: cell.mergeFromId,
134261
135205
  backgroundColor: cell.backgroundColor,
135206
+ isNested: isNested.value,
134262
135207
  subRenderer: cell.subRenderer,
134263
135208
  pl: cell.pl,
135209
+ pr: cell.pr,
134264
135210
  pt: cell.pt,
135211
+ pb: cell.pb,
134265
135212
  children: cell.getChildren(),
134266
135213
  rowspan: cell.rowspan || 1,
134267
135214
  colspan: cell.colspan || 1
@@ -134289,8 +135236,8 @@ var init_table_vue_vue_type_script_setup_true_name_table_lang = __esmMin((() =>
134289
135236
  return (_ctx, _cache) => {
134290
135237
  const _component_v_group = resolveComponent("v-group");
134291
135238
  return openBlock(), createBlock(_component_v_group, { config: {
134292
- x: widget.value.x,
134293
- y: widget.value.y,
135239
+ x: roundX.value,
135240
+ y: roundY.value,
134294
135241
  id: widget.value.id
134295
135242
  } }, {
134296
135243
  default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(unref(isDesignMode) ? table_design_default : table_render_default), {
@@ -134298,13 +135245,15 @@ var init_table_vue_vue_type_script_setup_true_name_table_lang = __esmMin((() =>
134298
135245
  rows: rows.value,
134299
135246
  colWidths: colWidths.value,
134300
135247
  colLefts: colLefts.value,
134301
- mergeRects: mergeRects.value
135248
+ mergeRects: mergeRects.value,
135249
+ isNested: isNested.value
134302
135250
  }, null, 8, [
134303
135251
  "widget",
134304
135252
  "rows",
134305
135253
  "colWidths",
134306
135254
  "colLefts",
134307
- "mergeRects"
135255
+ "mergeRects",
135256
+ "isNested"
134308
135257
  ]))]),
134309
135258
  _: 1
134310
135259
  }, 8, ["config"]);
@@ -136740,14 +137689,25 @@ init_core();
136740
137689
  init__register_();
136741
137690
  init_table$1();
136742
137691
  init_useTableSelection();
137692
+ init_logic$1();
136743
137693
  var _hoisted_1$103 = { class: "ribbon-tab-item" };
136744
137694
  var _hoisted_2$62 = { class: "option-svg-icon" };
136745
137695
  var _hoisted_3$45 = { class: "option-svg-icon" };
136746
137696
  var table_ribbon_group_vue_vue_type_script_setup_true_name_table_ribbon_group_lang_default = /*@__PURE__*/ defineComponent({
136747
137697
  __name: "table-ribbon-group",
136748
137698
  setup(__props) {
136749
- const { docInst } = useDocPubApiContext();
137699
+ const { docInst, updateTick } = useDocPubApiContext();
136750
137700
  const { interaction } = useTableSelection();
137701
+ const cursorTick = ref(0);
137702
+ let unsubscribeCursorChanged;
137703
+ onMounted(() => {
137704
+ unsubscribeCursorChanged = docInst.value.eventManager.eventBus.on("cursor:change", () => {
137705
+ cursorTick.value++;
137706
+ });
137707
+ });
137708
+ onUnmounted(() => {
137709
+ unsubscribeCursorChanged === null || unsubscribeCursorChanged === void 0 || unsubscribeCursorChanged();
137710
+ });
136751
137711
  const { fields } = useModelData(toRef(docInst.value, "mainModelKey"));
136752
137712
  const ribbonOptions = getRibbonTableOptions();
136753
137713
  const dataTableOptions = ribbonOptions.dataTables;
@@ -136762,6 +137722,11 @@ var table_ribbon_group_vue_vue_type_script_setup_true_name_table_ribbon_group_la
136762
137722
  });
136763
137723
  return actions;
136764
137724
  });
137725
+ const activeTableScope = computed(() => {
137726
+ updateTick.value;
137727
+ cursorTick.value;
137728
+ return resolveTableScopeFromCursor(docInst.value);
137729
+ });
136765
137730
  const handleTableTypeChange = (value) => {
136766
137731
  handleAction(String(value));
136767
137732
  };
@@ -136800,11 +137765,15 @@ var table_ribbon_group_vue_vue_type_script_setup_true_name_table_ribbon_group_la
136800
137765
  });
136801
137766
  };
136802
137767
  const handleSubTableModalOpen = (ribbonAction) => {
137768
+ var _activeTableScope$val;
136803
137769
  const profile = resolveSubTableProfile(ribbonAction);
136804
137770
  if (!profile) {
136805
137771
  GctMessage.error("未找到表类型配置");
136806
137772
  return;
136807
137773
  }
137774
+ const bounds = resolveTableCellSelectionBounds(docInst.value);
137775
+ const mutexTable = (bounds === null || bounds === void 0 ? void 0 : bounds.table) ?? ((_activeTableScope$val = activeTableScope.value) === null || _activeTableScope$val === void 0 ? void 0 : _activeTableScope$val.wtbl);
137776
+ if (mutexTable && !assertSubTableRegionPlacement(mutexTable, bounds)) return;
136808
137777
  if (!validateTableSelection(docInst.value, { targetLabel: profile.label })) return;
136809
137778
  if (profile.enabled === false) {
136810
137779
  GctMessage.info("该业务表尚未开放");
@@ -136951,7 +137920,7 @@ var table_ribbon_group_vue_vue_type_script_setup_true_name_table_ribbon_group_la
136951
137920
  //#endregion
136952
137921
  //#region src/runtime/designer/ribbon/components/table-ribbon-group.vue
136953
137922
  init__plugin_vue_export_helper();
136954
- var table_ribbon_group_default = /*#__PURE__*/ _plugin_vue_export_helper_default(table_ribbon_group_vue_vue_type_script_setup_true_name_table_ribbon_group_lang_default, [["__scopeId", "data-v-eed40e28"]]);
137923
+ var table_ribbon_group_default = /*#__PURE__*/ _plugin_vue_export_helper_default(table_ribbon_group_vue_vue_type_script_setup_true_name_table_ribbon_group_lang_default, [["__scopeId", "data-v-a6ebfeaa"]]);
136955
137924
  //#endregion
136956
137925
  //#region src/runtime/designer/ribbon/constant/font.ts
136957
137926
  /** 字重 */
@@ -139561,6 +140530,13 @@ var doc_layout_vue_vue_type_script_setup_true_name_doc_layout_lang_default = /*@
139561
140530
  setup(__props, { expose: __expose }) {
139562
140531
  const props = __props;
139563
140532
  const { docInst } = useDocPubApiContext();
140533
+ /**
140534
+ * cell-range 选区的单元格 ID 集合。
140535
+ * 由 selection-renderer.vue(最近的子孙)写入,由 table-cell.vue 消费,
140536
+ * 目的是在内容层内部渲染选中高亮,让嵌套内表格的单元格背景天然覆盖外表格高亮。
140537
+ */
140538
+ const cellRangeIds = ref(/* @__PURE__ */ new Set());
140539
+ provide("cellRangeIds", cellRangeIds);
139564
140540
  const stageRef = ref(null);
139565
140541
  const contextMenuRef = ref(null);
139566
140542
  const contentLayerRef = ref(null);
@@ -139741,7 +140717,7 @@ var doc_layout_vue_vue_type_script_setup_true_name_doc_layout_lang_default = /*@
139741
140717
  //#endregion
139742
140718
  //#region src/runtime/canvas/doc-layout.vue
139743
140719
  init__plugin_vue_export_helper();
139744
- var doc_layout_default = /*#__PURE__*/ _plugin_vue_export_helper_default(doc_layout_vue_vue_type_script_setup_true_name_doc_layout_lang_default, [["__scopeId", "data-v-fcaa8330"]]);
140720
+ var doc_layout_default = /*#__PURE__*/ _plugin_vue_export_helper_default(doc_layout_vue_vue_type_script_setup_true_name_doc_layout_lang_default, [["__scopeId", "data-v-855b01d5"]]);
139745
140721
  //#endregion
139746
140722
  //#region src/runtime/designer/main/editable-canvas.vue?vue&type=script&setup=true&name=editable-canvas&lang.ts
139747
140723
  init_core();