@ai-table/state 0.1.41 → 0.1.43

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.
@@ -1,9 +1,9 @@
1
1
  import * as Y from 'yjs';
2
2
  import { UndoManager } from 'yjs';
3
- import { getShareTypeNumberPath, ActionName, translateArrayEvent, getSharedRecordIndex, getSharedMapValueIndex, toMapSyncElement, getIdBySystemFieldValuesType, setRecordUpdatedInfo, getPositionsByRecordSyncElement, setRecordPositions as setRecordPositions$1, toRecordSyncElement, AI_TABLE_CONTENT_FIELD_NAME, getValuesByCustomFieldValues, getPositionsBySystemFieldValues, getTrackableEntityBySystemFieldValues, getShortIdBySystemFieldValues, getIdBySystemFieldValues, sortByViewPosition, AITableFilterLogical, AITableFilterOperation, AITableFieldType, isEmpty, AI_TABLE_DEFAULT_MIN_UNFROZEN_WIDTH, AI_TABLE_MIN_FROZEN_COLUMN_COUNT, idCreator } from '@ai-table/utils';
3
+ import { getShareTypeNumberPath, ActionName, translateArrayEvent, getSharedRecordIndex, getSharedMapValueIndex, toMapSyncElement, getIdBySystemFieldValuesType, setRecordUpdatedInfo, getPositionsByRecordSyncElement, setRecordPositions as setRecordPositions$1, toRecordSyncElement, AI_TABLE_CONTENT_FIELD_NAME, getValuesByCustomFieldValues, getPositionsBySystemFieldValues, getTrackableEntityBySystemFieldValues, getShortIdBySystemFieldValues, getIdBySystemFieldValues, SortDirection, AITableFilterLogical, AITableFilterOperation, AITableFieldType, isEmpty, sortByViewPosition, AI_TABLE_DEFAULT_MIN_UNFROZEN_WIDTH, AI_TABLE_MIN_FROZEN_COLUMN_COUNT, idCreator } from '@ai-table/utils';
4
4
  import * as i0 from '@angular/core';
5
5
  import { signal, Injectable } from '@angular/core';
6
- import { FieldModelMap, AITableQueries, isSystemField, AITableRowType, AITable, getColumnIndicesSizeMap, shortIdCreator, generateNewName, getDefaultFieldValue, AI_TABLE_GROUP_MAX_LEVEL, idsCreator, shortIdsCreator, setSelection, AI_TABLE_GRID_FIELD_SERVICE_MAP, clearSelection, buildClipboardData, writeToClipboard, getI18nTextByKey, AITableGridI18nKey, isMac, writeToAITable } from '@ai-table/grid';
6
+ import { FieldModelMap, AITableQueries, isSystemField, AITableRowType, AITable, getColumnIndicesSizeMap, shortIdCreator, generateNewName, getDefaultFieldValue, AI_TABLE_GROUP_MAX_LEVEL, idsCreator, shortIdsCreator, closeExpendCell, setSelection, AI_TABLE_GRID_FIELD_SERVICE_MAP, clearSelection, buildClipboardData, writeToClipboard, getI18nTextByKey, AITableGridI18nKey, isMac, writeToAITable } from '@ai-table/grid';
7
7
  import { nanoid } from 'nanoid';
8
8
  import * as _ from 'lodash';
9
9
  import ___default from 'lodash';
@@ -410,14 +410,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
410
410
  }] });
411
411
 
412
412
  function getSortRecords(aiTable, records, activeView, sortKeysMap) {
413
- if (!activeView?.settings || !activeView.settings.sorts?.length) {
414
- return sortByViewPosition(records, activeView);
415
- }
416
- const { is_keep_sort, sorts } = activeView.settings;
417
- if (is_keep_sort && sorts?.length) {
418
- return sortRecordsBySortInfo(aiTable, records, activeView, sortKeysMap);
419
- }
420
- return sortByViewPosition(records, activeView);
413
+ const shallowRecords = [...records];
414
+ const groups = activeView.settings?.groups;
415
+ return shallowRecords.sort((record1, record2) => {
416
+ // 分组排序(高优先级)
417
+ if (groups && groups.length > 0) {
418
+ const groupCompareResult = compareByGroups(aiTable, record1, record2, groups);
419
+ if (groupCompareResult !== 0) {
420
+ return groupCompareResult;
421
+ }
422
+ }
423
+ // sorts排序(中优先级)
424
+ let shouldSkipPositionSort = false;
425
+ if (activeView.settings?.sorts?.length) {
426
+ const { is_keep_sort, sorts } = activeView.settings;
427
+ if (sorts?.length) {
428
+ const sortsCompareResult = compareBySorts(record1, record2, sorts, aiTable, sortKeysMap);
429
+ if (sortsCompareResult !== 0) {
430
+ return sortsCompareResult;
431
+ }
432
+ shouldSkipPositionSort = Boolean(is_keep_sort);
433
+ }
434
+ }
435
+ // position排序(低优先级)
436
+ if (shouldSkipPositionSort) {
437
+ // is_keep_sort为true,禁用position排序
438
+ return 0;
439
+ }
440
+ return compareByPosition(record1, record2, activeView);
441
+ });
421
442
  }
422
443
  function sortRecordsBySortInfo(aiTable, records, activeView, sortKeysMap) {
423
444
  const shallowRows = [...records];
@@ -444,6 +465,59 @@ function sortRecordsBySortInfo(aiTable, records, activeView, sortKeysMap) {
444
465
  }
445
466
  return shallowRows;
446
467
  }
468
+ function compareByGroups(aiTable, record1, record2, groups) {
469
+ return groups.reduce((result, groupField) => {
470
+ if (result !== 0)
471
+ return result;
472
+ const field = aiTable.fieldsMap()[groupField.field_id];
473
+ if (!field)
474
+ return 0;
475
+ const value1 = AITableQueries.getFieldValue(aiTable, [record1._id, field._id]);
476
+ const value2 = AITableQueries.getFieldValue(aiTable, [record2._id, field._id]);
477
+ const fieldModel = FieldModelMap[field.type];
478
+ if (!fieldModel)
479
+ return 0;
480
+ const compareResult = fieldModel.compare(value1, value2, aiTable.context.references(), undefined, {
481
+ aiTable,
482
+ field
483
+ });
484
+ return compareResult * (groupField.direction === SortDirection.ascending ? 1 : -1);
485
+ }, 0);
486
+ }
487
+ function compareBySorts(record1, record2, sorts, aiTable, sortKeysMap) {
488
+ return sorts.reduce((acc, rule) => {
489
+ const field = aiTable.fieldsMap()[rule.sort_by];
490
+ if (!field || acc !== 0) {
491
+ return acc;
492
+ }
493
+ const fieldMethod = FieldModelMap[field.type];
494
+ const sortKey = sortKeysMap?.[field.type];
495
+ const cellValue1 = AITableQueries.getFieldValue(aiTable, [record1._id, field._id]);
496
+ const cellValue2 = AITableQueries.getFieldValue(aiTable, [record2._id, field._id]);
497
+ const references = aiTable.context.references();
498
+ const res = fieldMethod.compare(cellValue1, cellValue2, references, sortKey, {
499
+ aiTable,
500
+ field
501
+ });
502
+ return res * rule.direction;
503
+ }, 0);
504
+ }
505
+ function compareByPosition(record1, record2, activeView) {
506
+ const hasPosition1 = record1.positions && record1.positions[activeView._id] !== undefined;
507
+ const hasPosition2 = record2.positions && record2.positions[activeView._id] !== undefined;
508
+ if (hasPosition1 && hasPosition2) {
509
+ return record1.positions[activeView._id] - record2.positions[activeView._id];
510
+ }
511
+ // 如果只有一个有位置信息,有位置的排在前面
512
+ if (hasPosition1 && !hasPosition2) {
513
+ return -1;
514
+ }
515
+ if (!hasPosition1 && hasPosition2) {
516
+ return 1;
517
+ }
518
+ // 如果都没有位置信息,保持原有顺序
519
+ return 0;
520
+ }
447
521
 
448
522
  function getFilteredRecords(aiTable, records, fields, activeView) {
449
523
  const { conditions, condition_logical } = activeView.settings || {};
@@ -593,57 +667,34 @@ function buildFieldStatType(data, activeView) {
593
667
  }
594
668
 
595
669
  class GroupCalculator {
596
- constructor(groups, aiTable, collapseState) {
670
+ constructor(aiTable, groups, collapseState) {
671
+ this.aiTable = aiTable;
597
672
  this.groups = groups;
598
673
  this.groupBreakpoints = new Map();
599
674
  this.groupCollapseState = new Set(collapseState || []);
600
- this.aiTable = aiTable;
675
+ this.fieldsMap = this.aiTable.fieldsMap();
601
676
  }
602
- calculateLinearRows(records, fields) {
603
- const sortedRecords = this.sortRecordsByGroup(records, fields);
604
- this.detectGroupBreakpoints(sortedRecords, fields);
605
- return this.generateLinearRows(sortedRecords, fields);
606
- }
607
- sortRecordsByGroup(records, fields) {
608
- const fieldsMap = new Map(fields.map((field) => [field._id, field]));
609
- return [...records].sort((record1, record2) => {
610
- return (this.groups.reduce((result, groupField) => {
611
- if (result !== 0)
612
- return result;
613
- const field = fieldsMap.get(groupField.fieldId);
614
- if (!field)
615
- return 0;
616
- const value1 = AITableQueries.getFieldValue(this.aiTable, [record1._id, field._id]);
617
- const value2 = AITableQueries.getFieldValue(this.aiTable, [record2._id, field._id]);
618
- const fieldModel = FieldModelMap[field.type];
619
- if (!fieldModel)
620
- return 0;
621
- const compareResult = fieldModel.compare(value1, value2, this.aiTable.context.references(), undefined, {
622
- aiTable: this.aiTable,
623
- field
624
- });
625
- return compareResult * (groupField.desc ? -1 : 1);
626
- }, 0) || 1);
627
- });
677
+ calculateLinearRows(records) {
678
+ this.detectGroupBreakpoints(records);
679
+ return this.generateLinearRows(records);
628
680
  }
629
681
  // 检测断点
630
- detectGroupBreakpoints(records, fields) {
682
+ detectGroupBreakpoints(records) {
631
683
  this.groupBreakpoints.clear();
632
684
  if (records.length === 0)
633
685
  return;
634
- const fieldsMap = new Map(fields.map((field) => [field._id, field]));
635
686
  let previousRecord = null;
636
687
  records.forEach((record, index) => {
637
688
  if (previousRecord === null) {
638
689
  // 第一条记录,所有分组字段都是断点
639
690
  this.groups.forEach((groupField) => {
640
- this.addBreakpoint(groupField.fieldId, index);
691
+ this.addBreakpoint(groupField.field_id, index);
641
692
  });
642
693
  }
643
694
  else {
644
695
  // 检查每个分组字段是否发生变化
645
696
  this.groups.forEach((groupField, groupIndex) => {
646
- const field = fieldsMap.get(groupField.fieldId);
697
+ const field = this.fieldsMap[groupField.field_id];
647
698
  if (!field)
648
699
  return;
649
700
  const prevValue = AITableQueries.getFieldValue(this.aiTable, [previousRecord._id, field._id]);
@@ -658,7 +709,7 @@ class GroupCalculator {
658
709
  if (compareResult !== 0) {
659
710
  // 值发生变化,从当前层级开始的所有层级都是断点
660
711
  for (let i = groupIndex; i < this.groups.length; i++) {
661
- this.addBreakpoint(this.groups[i].fieldId, index);
712
+ this.addBreakpoint(this.groups[i].field_id, index);
662
713
  }
663
714
  return;
664
715
  }
@@ -678,9 +729,8 @@ class GroupCalculator {
678
729
  }
679
730
  }
680
731
  // 生成GroupLinearRows
681
- generateLinearRows(records, fields) {
732
+ generateLinearRows(records) {
682
733
  const linearRows = [];
683
- const fieldsMap = new Map(fields.map((field) => [field._id, field]));
684
734
  let lastGroupDepth = -1;
685
735
  let currentGroupRecords = [];
686
736
  let currentGroupIds = [];
@@ -693,7 +743,7 @@ class GroupCalculator {
693
743
  });
694
744
  records.forEach((record, index) => {
695
745
  // 生成分组标签
696
- const groupTabRows = this.generateGroupTabRows(record, index, fieldsMap);
746
+ const groupTabRows = this.generateGroupTabRows(record, index, records.length);
697
747
  if (groupTabRows.length > 0) {
698
748
  // 如果有新的分组标签,先处理上一个分组的结束
699
749
  if (currentGroupRecords.length > 0) {
@@ -740,7 +790,7 @@ class GroupCalculator {
740
790
  let groupDisplayRowIndex = 0;
741
791
  currentGroupRecords.forEach((record, i) => {
742
792
  const recordIndex = currentGroupRecordIndices?.[i] ?? 0;
743
- if (this.shouldShowRecord(record, recordIndex)) {
793
+ if (this.shouldShowRecord(recordIndex)) {
744
794
  groupDisplayRowIndex++;
745
795
  linearRows.push({
746
796
  type: AITableRowType.record,
@@ -752,53 +802,71 @@ class GroupCalculator {
752
802
  });
753
803
  // 分组未折叠,为每个分组添加add新增行
754
804
  if (currentGroupRecords.length > 0 && this.shouldShowAddRow(currentGroupIds)) {
805
+ let startRecordIndex = 0;
806
+ let endRecordIndex = 0;
807
+ if (currentGroupRecordIndices) {
808
+ // 当前添加按钮对于的记录范围
809
+ startRecordIndex = Math.min(...currentGroupRecordIndices);
810
+ endRecordIndex = Math.max(...currentGroupRecordIndices);
811
+ }
755
812
  linearRows.push({
756
813
  type: AITableRowType.add,
757
- _id: '',
758
- depth: this.groups.length
814
+ _id: nanoid(),
815
+ depth: this.groups.length,
816
+ range: [startRecordIndex, endRecordIndex]
759
817
  });
760
818
  }
761
819
  }
762
820
  // 生成分组标签
763
- generateGroupTabRows(record, recordIndex, fieldsMap) {
821
+ generateGroupTabRows(record, recordIndex, totalRecords) {
764
822
  const groupTabRows = [];
765
823
  this.groups.forEach((groupField, depth) => {
766
- const breakpoints = this.groupBreakpoints.get(groupField.fieldId) || [];
824
+ const breakpoints = this.groupBreakpoints.get(groupField.field_id) || [];
767
825
  if (breakpoints.includes(recordIndex)) {
768
- const field = fieldsMap.get(groupField.fieldId);
826
+ const field = this.fieldsMap[groupField.field_id];
769
827
  if (!field)
770
828
  return;
771
829
  const groupValue = AITableQueries.getFieldValue(this.aiTable, [record._id, field._id]);
772
830
  const breakpointIndex = breakpoints.indexOf(recordIndex);
773
- const groupId = this.generateGroupId(groupField.fieldId, depth, breakpointIndex);
774
- const recordCount = this.calculateGroupRecordCount(record, recordIndex, depth);
831
+ const groupId = this.generateGroupId(groupField.field_id, depth, breakpointIndex);
832
+ const recordRange = this.calculateGroupRecordRange(groupField.field_id, breakpointIndex, totalRecords);
775
833
  groupTabRows.push({
776
834
  type: AITableRowType.group,
777
835
  _id: nanoid(),
778
836
  depth,
779
- fieldId: groupField.fieldId,
837
+ fieldId: groupField.field_id,
780
838
  groupValue,
781
839
  isCollapsed: this.groupCollapseState.has(groupId),
782
- recordCount,
840
+ range: recordRange,
783
841
  groupId
784
842
  });
785
843
  }
786
844
  });
787
845
  return groupTabRows;
788
846
  }
847
+ calculateGroupRecordRange(fieldId, breakpointIndex, totalRecords) {
848
+ const breakpoints = this.groupBreakpoints.get(fieldId) || [];
849
+ const startIndex = breakpoints[breakpointIndex] || 0;
850
+ let endIndex;
851
+ if (breakpointIndex + 1 < breakpoints.length) {
852
+ // 如果不是最后一个分组,结束位置是下一个断点的前一个位置
853
+ endIndex = breakpoints[breakpointIndex + 1] - 1;
854
+ }
855
+ else {
856
+ // 如果是最后一个分组,结束位置是最后一条记录
857
+ endIndex = totalRecords - 1;
858
+ }
859
+ return [startIndex, endIndex];
860
+ }
789
861
  // 生成分组ID
790
862
  generateGroupId(fieldId, depth, breakpointIndex) {
791
863
  // 通过字段ID、深度和断点索引确保唯一
792
864
  return `${fieldId}_${depth}_${breakpointIndex}`;
793
865
  }
794
- calculateGroupRecordCount(_record, _recordIndex, _depth) {
795
- // TODO: 实现精确的分组记录数计算
796
- return 1;
797
- }
798
- shouldShowRecord(_record, recordIndex) {
866
+ shouldShowRecord(recordIndex) {
799
867
  for (let depth = 0; depth < this.groups.length; depth++) {
800
868
  const groupField = this.groups[depth];
801
- const breakpoints = this.groupBreakpoints.get(groupField.fieldId) || [];
869
+ const breakpoints = this.groupBreakpoints.get(groupField.field_id) || [];
802
870
  // 找到当前记录所属的分组断点
803
871
  let belongsToBreakpointIndex = -1;
804
872
  for (let i = breakpoints.length - 1; i >= 0; i--) {
@@ -808,7 +876,7 @@ class GroupCalculator {
808
876
  }
809
877
  }
810
878
  if (belongsToBreakpointIndex >= 0) {
811
- const groupId = this.generateGroupId(groupField.fieldId, depth, belongsToBreakpointIndex);
879
+ const groupId = this.generateGroupId(groupField.field_id, depth, belongsToBreakpointIndex);
812
880
  if (this.groupCollapseState.has(groupId)) {
813
881
  return false; // 父级分组被折叠,不显示记录
814
882
  }
@@ -853,6 +921,28 @@ class GroupCalculator {
853
921
  }
854
922
  }
855
923
 
924
+ function getParentLinearRowGroups(aiTable, targetId) {
925
+ const linearRows = aiTable.context.linearRows();
926
+ const targetIndex = aiTable.context.visibleRowsIndexMap().get(targetId);
927
+ if (targetIndex === -1) {
928
+ return [];
929
+ }
930
+ const targetRow = linearRows[targetIndex];
931
+ const parentGroups = [];
932
+ let parentDepthPointer = targetRow.depth - 1;
933
+ for (let i = targetIndex - 1; i >= 0 && parentDepthPointer >= 0; i--) {
934
+ const row = linearRows[i];
935
+ if (row.type === AITableRowType.group) {
936
+ const rowDepth = row.depth || 0;
937
+ if (rowDepth <= parentDepthPointer) {
938
+ parentGroups.push(row);
939
+ parentDepthPointer--;
940
+ }
941
+ }
942
+ }
943
+ return parentGroups;
944
+ }
945
+
856
946
  function buildRecordsByView(aiTable, records, fields, activeView, sortKeysMap) {
857
947
  const filteredRecords = getFilteredRecords(aiTable, records, fields, activeView);
858
948
  return getSortRecords(aiTable, filteredRecords, activeView, sortKeysMap);
@@ -861,14 +951,13 @@ function buildFieldsByView(aiTable, fields, activeView) {
861
951
  const sortFields = getSortFields(aiTable, fields, activeView);
862
952
  return buildFieldStatType(sortFields, activeView);
863
953
  }
864
- function buildGroupLinearRows(aiTable, records, fields, activeView) {
865
- if (activeView?.settings?.groups?.length && fields && aiTable) {
954
+ function buildGroupLinearRows(aiTable, activeView, records) {
955
+ if (aiTable && activeView?.settings?.groups?.length) {
866
956
  try {
867
957
  const groups = activeView.settings?.groups;
868
- const collapsedGroupIds = activeView.settings?.collapsedGroupIds;
869
- const calculator = new GroupCalculator(groups, aiTable, collapsedGroupIds);
870
- const filteredRecords = getFilteredRecords(aiTable, records, fields, activeView);
871
- return calculator.calculateLinearRows(filteredRecords, fields);
958
+ const collapsedGroupIds = activeView.settings?.collapsed_group_ids;
959
+ const calculator = new GroupCalculator(aiTable, groups, collapsedGroupIds);
960
+ return calculator.calculateLinearRows(records);
872
961
  }
873
962
  catch (error) {
874
963
  console.warn('Grouped build failed, using the default build method:', error);
@@ -1651,12 +1740,7 @@ function addRecord(aiTable, record) {
1651
1740
  }
1652
1741
  function addRecords$1(aiTable, records, options) {
1653
1742
  const invalidFieldValues = [];
1654
- const sortRecords = options?.sortRecords ||
1655
- getSortRecords(aiTable, aiTable.records(), aiTable.views().find((item) => item._id === aiTable.activeViewId()));
1656
- const targetIndex = options?.targetId
1657
- ? sortRecords.findIndex((item) => item._id === options.targetId)
1658
- : options?.targetIndex || sortRecords.length - 1;
1659
- const positions = createMultiplePositions(aiTable.views(), aiTable.activeViewId(), sortRecords, targetIndex, records.length, options?.isInsertBefore);
1743
+ const positions = getNewRecordsPosition(aiTable, options);
1660
1744
  records.forEach((record, index) => {
1661
1745
  Object.entries(record.values).every(([fieldId, value]) => {
1662
1746
  const field = AITableQueries.getField(aiTable, [fieldId]);
@@ -1705,7 +1789,7 @@ function setViewGroup(aiTable, groups) {
1705
1789
  const newSettings = {
1706
1790
  ...currentSettings,
1707
1791
  groups: groups || [],
1708
- collapsedGroupIds: [] // 重置折叠
1792
+ collapsed_group_ids: [] // 重置折叠
1709
1793
  };
1710
1794
  const operation = {
1711
1795
  type: ActionName.SetView,
@@ -1723,7 +1807,7 @@ function setCollapsedGroup(aiTable, collapsedGroupIds) {
1723
1807
  const currentSettings = view.settings || {};
1724
1808
  const newSettings = {
1725
1809
  ...currentSettings,
1726
- collapsedGroupIds
1810
+ collapsed_group_ids: collapsedGroupIds
1727
1811
  };
1728
1812
  const operation = {
1729
1813
  type: ActionName.SetView,
@@ -1735,29 +1819,28 @@ function setCollapsedGroup(aiTable, collapsedGroupIds) {
1735
1819
  }
1736
1820
  // 折叠
1737
1821
  function toggleGroupCollapse(aiTable, groupId) {
1738
- const viewId = aiTable.activeViewId();
1739
- const view = aiTable.views().find((v) => v._id === viewId);
1740
- if (!view)
1822
+ const activeView = aiTable.viewsMap()[aiTable.activeViewId()];
1823
+ if (!activeView)
1741
1824
  return;
1742
- const currentCollapse = view.settings?.collapsedGroupIds || [];
1825
+ const currentCollapse = activeView.settings?.collapsed_group_ids || [];
1743
1826
  const newCollapse = currentCollapse.includes(groupId) ? currentCollapse.filter((id) => id !== groupId) : [...currentCollapse, groupId];
1744
1827
  setCollapsedGroup(aiTable, newCollapse);
1745
1828
  }
1746
1829
  // 添加分组
1747
- function addGroupField(aiTable, fieldId, desc = false) {
1748
- const view = aiTable.views().find((v) => v._id === aiTable.activeViewId());
1749
- if (!view)
1830
+ function addGroupField(aiTable, fieldId, direction = SortDirection.ascending) {
1831
+ const activeView = aiTable.viewsMap()[aiTable.activeViewId()];
1832
+ if (!activeView)
1750
1833
  return;
1751
- const currentGroups = view.settings?.groups || [];
1834
+ const currentGroups = activeView.settings?.groups || [];
1752
1835
  // 是否已存在
1753
- if (currentGroups.some((group) => group.fieldId === fieldId)) {
1836
+ if (currentGroups.some((group) => group.field_id === fieldId)) {
1754
1837
  throw new Error('The field has been used for grouping.');
1755
1838
  }
1756
1839
  // 层级限制
1757
1840
  if (currentGroups.length >= AI_TABLE_GROUP_MAX_LEVEL) {
1758
1841
  throw new Error(`The maximum number of groups is ${AI_TABLE_GROUP_MAX_LEVEL}.`);
1759
1842
  }
1760
- const newGroups = [...currentGroups, { fieldId, desc }];
1843
+ const newGroups = [...currentGroups, { field_id: fieldId, direction }];
1761
1844
  setViewGroup(aiTable, newGroups);
1762
1845
  }
1763
1846
  // 删除分组
@@ -1766,16 +1849,16 @@ function removeGroupField(aiTable, fieldId) {
1766
1849
  if (!view)
1767
1850
  return;
1768
1851
  const currentGroups = view.settings?.groups || [];
1769
- const newGroups = currentGroups.filter((group) => group.fieldId !== fieldId);
1852
+ const newGroups = currentGroups.filter((group) => group.field_id !== fieldId);
1770
1853
  setViewGroup(aiTable, newGroups.length > 0 ? newGroups : null);
1771
1854
  }
1772
1855
  // 更新排序方向
1773
- function updateGroupFieldDirection(aiTable, fieldId, desc) {
1856
+ function updateGroupFieldDirection(aiTable, fieldId, direction) {
1774
1857
  const view = aiTable.views().find((v) => v._id === aiTable.activeViewId());
1775
1858
  if (!view)
1776
1859
  return;
1777
1860
  const currentGroups = view.settings?.groups || [];
1778
- const newGroups = currentGroups.map((group) => (group.fieldId === fieldId ? { ...group, desc } : group));
1861
+ const newGroups = currentGroups.map((group) => (group.field_id === fieldId ? { ...group, direction } : group));
1779
1862
  setViewGroup(aiTable, newGroups);
1780
1863
  }
1781
1864
  // 重新排序,拖拽顺序
@@ -1821,35 +1904,146 @@ function moveFields(aiTable, options) {
1821
1904
  Actions.moveField(aiTable, path, newPath);
1822
1905
  }
1823
1906
 
1824
- function moveRecords(aiTable, options, updatedInfo) {
1825
- const gridRecords = aiTable.gridData().records;
1907
+ function findNextRecordForTargetInOriginalRecords(aiTable, targetRecordId) {
1908
+ const viewId = aiTable.activeViewId();
1909
+ const records = aiTable.records();
1910
+ const recordsMap = aiTable.recordsMap();
1911
+ const targetRecord = recordsMap[targetRecordId];
1912
+ const targetPosition = targetRecord.positions[viewId] || 0;
1913
+ let nextRecord = null;
1914
+ for (const record of records) {
1915
+ const pos = record.positions[viewId] || 0;
1916
+ // 找到所有position大于目标position的记录中最小的
1917
+ if (pos > targetPosition && (nextRecord === null || pos < nextRecord.positions[viewId])) {
1918
+ nextRecord = record;
1919
+ }
1920
+ }
1921
+ return nextRecord;
1922
+ }
1923
+ function findPrevRecordForTargetInOriginalRecords(aiTable, targetRecordId) {
1924
+ const viewId = aiTable.activeViewId();
1925
+ const records = aiTable.records();
1926
+ const recordsMap = aiTable.recordsMap();
1927
+ const targetRecord = recordsMap[targetRecordId];
1928
+ const targetPosition = targetRecord.positions[viewId] || 0;
1929
+ let prevRecord = null;
1930
+ for (const record of records) {
1931
+ const pos = record.positions[viewId] || 0;
1932
+ // 找到所有position小于目标记录position的记录中最大的
1933
+ if (pos < targetPosition && (prevRecord === null || pos > prevRecord.positions[viewId])) {
1934
+ prevRecord = record;
1935
+ }
1936
+ }
1937
+ return prevRecord;
1938
+ }
1939
+ function getPositionByAfterOrBeforeRecordId(aiTable, options) {
1940
+ const recordsMap = aiTable.recordsMap();
1826
1941
  const activeViewId = aiTable.activeViewId();
1827
- const activeView = aiTable.views().find((view) => view._id === activeViewId);
1828
- const { recordIds, newPath } = options;
1942
+ const originalRecords = aiTable.records();
1943
+ const { afterRecordId, beforeRecordId } = options;
1829
1944
  let targetPosition = 0;
1830
1945
  let prevPosition = 0;
1831
- if (newPath[0] === 0) {
1832
- targetPosition = gridRecords[0].positions[activeViewId];
1833
- prevPosition = targetPosition - 1;
1946
+ if (afterRecordId) {
1947
+ // 移动到指定记录之后
1948
+ const targetRecord = recordsMap[afterRecordId];
1949
+ if (!targetRecord) {
1950
+ throw new Error(`Target record with id ${afterRecordId} not found`);
1951
+ }
1952
+ prevPosition = targetRecord.positions[activeViewId] || 0;
1953
+ const nextPosition = findNextRecordForTargetInOriginalRecords(aiTable, afterRecordId);
1954
+ if (nextPosition !== null) {
1955
+ targetPosition = nextPosition.positions[activeViewId] || 0;
1956
+ }
1957
+ else {
1958
+ // 最后一个
1959
+ targetPosition = getMaxPosition(originalRecords, activeViewId) + 1;
1960
+ }
1834
1961
  }
1835
- else if (newPath[0] >= gridRecords.length) {
1836
- targetPosition = getMaxPosition(gridRecords, activeViewId) + 1;
1837
- prevPosition = gridRecords[gridRecords.length - 1].positions[activeViewId];
1962
+ else if (beforeRecordId) {
1963
+ // 移动到指定记录之前
1964
+ const targetRecord = recordsMap[beforeRecordId];
1965
+ if (!targetRecord) {
1966
+ throw new Error(`Target record with id ${beforeRecordId} not found`);
1967
+ }
1968
+ targetPosition = targetRecord.positions[activeViewId] || 0;
1969
+ const previousPosition = findPrevRecordForTargetInOriginalRecords(aiTable, beforeRecordId);
1970
+ if (previousPosition !== null) {
1971
+ prevPosition = previousPosition.positions[activeViewId] || 0;
1972
+ }
1973
+ else {
1974
+ // 第一个
1975
+ prevPosition = targetPosition - 1;
1976
+ }
1838
1977
  }
1839
1978
  else {
1840
- targetPosition = gridRecords[newPath[0]].positions[activeViewId];
1841
- prevPosition = gridRecords[newPath[0] - 1].positions[activeViewId];
1979
+ throw new Error('Either afterRecordId or beforeRecordId must be provided');
1842
1980
  }
1843
- const records = aiTable.records();
1844
- const recordsIndexMap = new Map(records.map((row, index) => [row._id, index]));
1981
+ return {
1982
+ targetPosition,
1983
+ prevPosition
1984
+ };
1985
+ }
1986
+ function getNewRecordsPosition(aiTable, options) {
1987
+ options = options || {};
1988
+ if (!options.afterRecordId && !options.beforeRecordId) {
1989
+ options.afterRecordId = aiTable.gridData().records[aiTable.gridData().records.length - 1]._id;
1990
+ }
1991
+ options.count = options.count || 1;
1992
+ const { targetPosition, prevPosition } = getPositionByAfterOrBeforeRecordId(aiTable, options);
1993
+ const interval = (targetPosition - prevPosition) / ((options.count || 1) + 1);
1994
+ const positionsOfItems = ___default.range(prevPosition + interval, targetPosition, interval);
1995
+ const views = aiTable.views();
1996
+ const activeViewId = aiTable.activeViewId();
1997
+ const viewsMaxPosition = {};
1998
+ views.forEach((view) => {
1999
+ viewsMaxPosition[view._id] = getMaxPosition(aiTable.records(), view._id);
2000
+ });
2001
+ const viewPositions = positionsOfItems.map((itemPositions) => {
2002
+ const viewPositions = {};
2003
+ views.forEach((view) => {
2004
+ if (view._id === activeViewId) {
2005
+ viewPositions[view._id] = itemPositions;
2006
+ }
2007
+ else {
2008
+ viewsMaxPosition[view._id] += 1;
2009
+ viewPositions[view._id] = viewsMaxPosition[view._id];
2010
+ }
2011
+ });
2012
+ return viewPositions;
2013
+ });
2014
+ return viewPositions;
2015
+ }
2016
+ function getParentGroupValuesByGroupId(aiTable, groupId) {
2017
+ const parentGroups = getParentLinearRowGroups(aiTable, groupId);
2018
+ return parentGroups.reduce((pre, cur) => {
2019
+ pre[cur.fieldId] = cur.groupValue;
2020
+ return pre;
2021
+ }, {});
2022
+ }
2023
+
2024
+ function moveRecords(aiTable, options, updatedInfo) {
2025
+ const activeViewId = aiTable.activeViewId();
2026
+ const activeView = aiTable.views().find((view) => view._id === activeViewId);
2027
+ const { recordIds, afterRecordId, beforeRecordId } = options;
2028
+ const originalRecords = aiTable.records();
2029
+ const recordsIndexMap = new Map(originalRecords.map((row, index) => [row._id, index]));
1845
2030
  const sourceRecords = [];
1846
- recordIds.forEach((idPath) => {
1847
- const index = recordsIndexMap.get(idPath[0]);
2031
+ recordIds.forEach((id) => {
2032
+ const index = recordsIndexMap.get(id);
1848
2033
  if (index === undefined) {
1849
- throw new Error(`Record with id ${idPath[0]} not found`);
2034
+ throw new Error(`Record with id ${id} not found`);
1850
2035
  }
1851
- sourceRecords.push(records[index]);
2036
+ sourceRecords.push(originalRecords[index]);
2037
+ });
2038
+ let { targetPosition, prevPosition } = getPositionByAfterOrBeforeRecordId(aiTable, {
2039
+ afterRecordId,
2040
+ beforeRecordId
1852
2041
  });
2042
+ const groups = activeView.settings?.groups;
2043
+ let needCopyGroupValuesMap = null;
2044
+ if (groups?.length && (afterRecordId || beforeRecordId)) {
2045
+ needCopyGroupValuesMap = getParentGroupValuesByGroupId(aiTable, (afterRecordId || beforeRecordId));
2046
+ }
1853
2047
  // 勾选多行顺序可能不一致,需要排序
1854
2048
  const sortedSourceRecords = sortByViewPosition(sourceRecords, activeView);
1855
2049
  let nextPosition = (prevPosition + targetPosition) / 2;
@@ -1858,6 +2052,16 @@ function moveRecords(aiTable, options, updatedInfo) {
1858
2052
  if (sourceIndex === undefined) {
1859
2053
  throw new Error(`Record with id ${record._id} not found`);
1860
2054
  }
2055
+ if (groups?.length && needCopyGroupValuesMap) {
2056
+ const updateFieldValues = [];
2057
+ groups.forEach((group) => {
2058
+ updateFieldValues.push({
2059
+ path: [record._id, group.field_id],
2060
+ value: needCopyGroupValuesMap[group.field_id]
2061
+ });
2062
+ });
2063
+ Actions.updateFieldValues(aiTable, updateFieldValues);
2064
+ }
1861
2065
  Actions.setRecordPositions(aiTable, { [activeViewId]: nextPosition }, [sourceIndex]);
1862
2066
  prevPosition = nextPosition;
1863
2067
  nextPosition = (prevPosition + targetPosition) / 2;
@@ -1899,6 +2103,10 @@ const buildRemoveFieldItem = (aiTable, getUpdatedInfo) => {
1899
2103
 
1900
2104
  function addRecords(aiTable, trackableEntity, options) {
1901
2105
  options = options || {};
2106
+ const newRecords = [];
2107
+ const activeViewId = aiTable.activeViewId();
2108
+ const activeView = aiTable.viewsMap()[activeViewId];
2109
+ const groups = activeView.settings?.groups;
1902
2110
  let { originId, isDuplicate, count = 1 } = options;
1903
2111
  const recordCount = aiTable.records().length;
1904
2112
  const maxRecordCount = aiTable.context?.maxRecords();
@@ -1906,14 +2114,31 @@ function addRecords(aiTable, trackableEntity, options) {
1906
2114
  count = maxRecordCount - recordCount;
1907
2115
  options.count = count;
1908
2116
  }
1909
- const activeView = aiTable.viewsMap()[aiTable.activeViewId()];
1910
2117
  const newRecordIds = idsCreator(count);
1911
2118
  const newRecordShortIds = shortIdsCreator(count);
1912
2119
  const newRecordValues = getDefaultRecordValues(aiTable, isDuplicate, originId);
1913
- const newRecords = [];
1914
2120
  const hiddenRecordIds = [];
2121
+ let needCopyGroupValuesMap = null;
2122
+ if (groups?.length && options.forGroupId) {
2123
+ needCopyGroupValuesMap = getParentGroupValuesByGroupId(aiTable, options.forGroupId);
2124
+ }
2125
+ const records = aiTable.gridData().records;
1915
2126
  newRecordIds.forEach((id, index) => {
1916
- const record = { _id: id, short_id: newRecordShortIds[index], values: newRecordValues, ...trackableEntity };
2127
+ const record = {
2128
+ _id: id,
2129
+ short_id: newRecordShortIds[index],
2130
+ values: newRecordValues,
2131
+ ...trackableEntity,
2132
+ positions: {
2133
+ [activeViewId]: getMaxPosition(records, activeViewId) + 1
2134
+ }
2135
+ };
2136
+ if (needCopyGroupValuesMap) {
2137
+ groups?.forEach((group) => {
2138
+ // 复制分组字段值
2139
+ record.values[group.field_id] = needCopyGroupValuesMap[group.field_id];
2140
+ });
2141
+ }
1917
2142
  const checkResult = checkConditions(aiTable, aiTable.fields(), record);
1918
2143
  if (!checkResult) {
1919
2144
  hiddenRecordIds.push(id);
@@ -1926,9 +2151,10 @@ function addRecords(aiTable, trackableEntity, options) {
1926
2151
  });
1927
2152
  }
1928
2153
  Actions.addRecords(aiTable, newRecords, options);
1929
- const recentAddRecord = options.isInsertBefore ? newRecords[newRecords.length - 1] : newRecords[0];
2154
+ const recentAddRecord = options.beforeRecordId ? newRecords[newRecords.length - 1] : newRecords[0];
1930
2155
  const activeRecordId = recentAddRecord._id;
1931
2156
  const activeFieldId = aiTable.gridData().fields[0]._id;
2157
+ closeExpendCell(aiTable);
1932
2158
  setSelection(aiTable, {
1933
2159
  selectedRecords: new Set([]),
1934
2160
  selectedFields: new Set([]),
@@ -2150,11 +2376,16 @@ const InsertUpwardRecords = (aiTable, actions) => {
2150
2376
  count: 1,
2151
2377
  exec: (aiTable, targetName, position, notifyService, count) => {
2152
2378
  let selectedRecordIds = AITable.getActiveRecordIds(aiTable);
2153
- actions.addRecord({
2154
- targetId: selectedRecordIds[0],
2155
- count,
2156
- isInsertBefore: true
2157
- });
2379
+ const aiViewTable = aiTable;
2380
+ const activeView = aiViewTable.viewsMap()[aiViewTable.activeViewId()];
2381
+ const addRecordOptions = {
2382
+ beforeRecordId: selectedRecordIds[0],
2383
+ count
2384
+ };
2385
+ if (activeView?.settings?.groups?.length) {
2386
+ addRecordOptions.forGroupId = selectedRecordIds[0];
2387
+ }
2388
+ actions.addRecord(addRecordOptions);
2158
2389
  }
2159
2390
  };
2160
2391
  };
@@ -2168,10 +2399,16 @@ const InsertDownwardRecords = (aiTable, actions) => {
2168
2399
  isInputNumber: true,
2169
2400
  exec: (aiTable, targetName, position, notifyService, count) => {
2170
2401
  let selectedRecordIds = AITable.getActiveRecordIds(aiTable);
2171
- actions.addRecord({
2172
- targetId: selectedRecordIds[0],
2402
+ const aiViewTable = aiTable;
2403
+ const activeView = aiViewTable.viewsMap()[aiViewTable.activeViewId()];
2404
+ const addRecordOptions = {
2405
+ afterRecordId: selectedRecordIds[0],
2173
2406
  count
2174
- });
2407
+ };
2408
+ if (activeView?.settings?.groups?.length) {
2409
+ addRecordOptions.forGroupId = selectedRecordIds[0];
2410
+ }
2411
+ actions.addRecord(addRecordOptions);
2175
2412
  }
2176
2413
  };
2177
2414
  };
@@ -2222,5 +2459,5 @@ const VIEW_ACTIONS = [ActionName.SetView, ActionName.AddView, ActionName.RemoveV
2222
2459
  * Generated bundle index. Do not edit.
2223
2460
  */
2224
2461
 
2225
- export { AITableStateI18nKey, AITableStateI18nText, Actions, CopyCellsItem, CopyFieldPropertyItem, DividerMenuItem, EditFieldPropertyItem, FLUSHING, GroupCalculator, InsertDownwardRecords, InsertUpwardRecords, PasteCellsItem, RemoveRecordsItem, UndoManagerService, VIEW_ACTIONS, YjsAITable, actionMappers, addFields, addRecords, addView, applyActionOps, applyActions, applyEvents, applyYjsEvents, buildFieldsByView, buildGroupLinearRows, buildRecordsByView, buildRemoveFieldItem, buildSetFieldAction, buildSetRecordPositionsActon, calculateAdaptiveFrozenColumnCount, checkConditions, createMultiplePositions, createPositions, createSharedType, doFilter, freezeToThisColumn, generateCopyName, getDataBySharedType, getDefaultI18nTextByKey, getDefaultRecordDataByFilter, getDefaultRecordValues, getFieldPositionInView, getFieldsSizeMap, getFilteredRecords, getFrozenFieldId, getMaxPosition, getPosition, getPositions, getRecordsBySharedJson, getSharedTypeByData, getSortFields, getSortRecords, getStateI18nTextByKey, isPathEqual, moveFields, moveRecords, removeView, restoreDefaultFrozenColumn, sortRecordsBySortInfo, sortViews, toSharedType, translateYjsEvent, updateFieldAndValues, updateFieldValues, withState };
2462
+ export { AITableStateI18nKey, AITableStateI18nText, Actions, CopyCellsItem, CopyFieldPropertyItem, DividerMenuItem, EditFieldPropertyItem, FLUSHING, GroupCalculator, InsertDownwardRecords, InsertUpwardRecords, PasteCellsItem, RemoveRecordsItem, UndoManagerService, VIEW_ACTIONS, YjsAITable, actionMappers, addFields, addRecords, addView, applyActionOps, applyActions, applyEvents, applyYjsEvents, buildFieldsByView, buildGroupLinearRows, buildRecordsByView, buildRemoveFieldItem, buildSetFieldAction, buildSetRecordPositionsActon, calculateAdaptiveFrozenColumnCount, checkConditions, createMultiplePositions, createPositions, createSharedType, doFilter, findNextRecordForTargetInOriginalRecords, findPrevRecordForTargetInOriginalRecords, freezeToThisColumn, generateCopyName, getDataBySharedType, getDefaultI18nTextByKey, getDefaultRecordDataByFilter, getDefaultRecordValues, getFieldPositionInView, getFieldsSizeMap, getFilteredRecords, getFrozenFieldId, getMaxPosition, getNewRecordsPosition, getParentGroupValuesByGroupId, getParentLinearRowGroups, getPosition, getPositionByAfterOrBeforeRecordId, getPositions, getRecordsBySharedJson, getSharedTypeByData, getSortFields, getSortRecords, getStateI18nTextByKey, isPathEqual, moveFields, moveRecords, removeView, restoreDefaultFrozenColumn, sortRecordsBySortInfo, sortViews, toSharedType, translateYjsEvent, updateFieldAndValues, updateFieldValues, withState };
2226
2463
  //# sourceMappingURL=ai-table-state.mjs.map