rj-grid 0.1.0
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.
- package/LICENSE +201 -0
- package/README.md +92 -0
- package/dist/rj-grid.js +14074 -0
- package/dist/style.css +2050 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/src/RjAdvGroup.vue.d.ts +32 -0
- package/dist/types/src/RjAdvancedFilterDialog.vue.d.ts +38 -0
- package/dist/types/src/RjCell.vue.d.ts +82 -0
- package/dist/types/src/RjChartDialog.vue.d.ts +22 -0
- package/dist/types/src/RjColumnMenu.vue.d.ts +109 -0
- package/dist/types/src/RjConfirmDialog.vue.d.ts +23 -0
- package/dist/types/src/RjContextMenu.vue.d.ts +26 -0
- package/dist/types/src/RjEditor.vue.d.ts +28 -0
- package/dist/types/src/RjFilterMenu.vue.d.ts +58 -0
- package/dist/types/src/RjGrid.vue.d.ts +1046 -0
- package/dist/types/src/RjHeader.vue.d.ts +80 -0
- package/dist/types/src/RjImgList.vue.d.ts +29 -0
- package/dist/types/src/RjPager.vue.d.ts +41 -0
- package/dist/types/src/RjQueryBar.vue.d.ts +47 -0
- package/dist/types/src/RjRowFormDialog.vue.d.ts +50 -0
- package/dist/types/src/RjSlotRender.d.ts +56 -0
- package/dist/types/src/RjSparkline.vue.d.ts +43 -0
- package/dist/types/src/RjToolPanel.vue.d.ts +103 -0
- package/dist/types/src/RjViewManager.vue.d.ts +28 -0
- package/dist/types/src/editHistory.d.ts +27 -0
- package/dist/types/src/export.d.ts +24 -0
- package/dist/types/src/expression.d.ts +19 -0
- package/dist/types/src/filtering.d.ts +29 -0
- package/dist/types/src/formula.d.ts +88 -0
- package/dist/types/src/icons.d.ts +35 -0
- package/dist/types/src/locale.d.ts +21 -0
- package/dist/types/src/nlq.d.ts +51 -0
- package/dist/types/src/print.d.ts +37 -0
- package/dist/types/src/query.d.ts +28 -0
- package/dist/types/src/rowForm.d.ts +41 -0
- package/dist/types/src/serverGroups.d.ts +52 -0
- package/dist/types/src/ssrm.d.ts +102 -0
- package/dist/types/src/theme.d.ts +33 -0
- package/dist/types/src/types.d.ts +624 -0
- package/dist/types/src/useColumnState.d.ts +70 -0
- package/dist/types/src/useInteraction.d.ts +150 -0
- package/dist/types/src/useQueryViews.d.ts +16 -0
- package/dist/types/src/useRowModel.d.ts +225 -0
- package/dist/types/src/utils.d.ts +130 -0
- package/package.json +90 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { RjFindMatch, RjRowData } from './types';
|
|
2
|
+
import type { RjLeafCol } from './useColumnState';
|
|
3
|
+
import type { RjDisplayRow } from './useRowModel';
|
|
4
|
+
export interface InteractionCtx {
|
|
5
|
+
/** 全局列序:冻结左 + 普通 + 冻结右(与视觉顺序一致) */
|
|
6
|
+
gridCols: () => RjLeafCol[];
|
|
7
|
+
displayRows: () => RjDisplayRow[];
|
|
8
|
+
offsets: () => number[];
|
|
9
|
+
rowHeight: () => number;
|
|
10
|
+
getCellValue: (row: RjRowData, colIndex: number) => any;
|
|
11
|
+
/**
|
|
12
|
+
* 单元格的「文本」视图:复制/查找用。与 getCellValue 分离——图片列的原始值是
|
|
13
|
+
* data URI / URL 列表,直接写进剪贴板或被查找匹配都会污染结果。
|
|
14
|
+
*/
|
|
15
|
+
getCellText?: (row: RjRowData, colIndex: number) => any;
|
|
16
|
+
setCellValue: (row: RjRowData, colId: string, value: any) => void;
|
|
17
|
+
isCellEditable: (row: RjRowData, colIndex: number) => boolean;
|
|
18
|
+
startEdit: (r: number, c: number) => void;
|
|
19
|
+
scrollToCell: (r: number, c: number) => void;
|
|
20
|
+
viewportSize: () => {
|
|
21
|
+
w: number;
|
|
22
|
+
h: number;
|
|
23
|
+
};
|
|
24
|
+
gridLeft: () => number;
|
|
25
|
+
gridTop: () => number;
|
|
26
|
+
onCellsChanged: (changes: {
|
|
27
|
+
row: RjRowData;
|
|
28
|
+
colId: string;
|
|
29
|
+
newValue: any;
|
|
30
|
+
oldValue: any;
|
|
31
|
+
}[]) => void;
|
|
32
|
+
rangeChanged?: (range: RangePos | null) => void;
|
|
33
|
+
/** 复制时是否附带表头行(列标题) */
|
|
34
|
+
copyHeaders?: () => boolean;
|
|
35
|
+
/** 粘贴前对原始剪贴板文本的转换钩子(返回转换后文本) */
|
|
36
|
+
pasteTransformer?: (text: string) => string;
|
|
37
|
+
}
|
|
38
|
+
export interface CellPos {
|
|
39
|
+
r: number;
|
|
40
|
+
c: number;
|
|
41
|
+
}
|
|
42
|
+
export interface RangePos {
|
|
43
|
+
start: CellPos;
|
|
44
|
+
end: CellPos;
|
|
45
|
+
}
|
|
46
|
+
export declare function useInteraction(ctx: InteractionCtx): {
|
|
47
|
+
active: import("vue").Ref<{
|
|
48
|
+
r: number;
|
|
49
|
+
c: number;
|
|
50
|
+
} | null, CellPos | {
|
|
51
|
+
r: number;
|
|
52
|
+
c: number;
|
|
53
|
+
} | null>;
|
|
54
|
+
range: import("vue").Ref<{
|
|
55
|
+
start: {
|
|
56
|
+
r: number;
|
|
57
|
+
c: number;
|
|
58
|
+
};
|
|
59
|
+
end: {
|
|
60
|
+
r: number;
|
|
61
|
+
c: number;
|
|
62
|
+
};
|
|
63
|
+
} | null, RangePos | {
|
|
64
|
+
start: {
|
|
65
|
+
r: number;
|
|
66
|
+
c: number;
|
|
67
|
+
};
|
|
68
|
+
end: {
|
|
69
|
+
r: number;
|
|
70
|
+
c: number;
|
|
71
|
+
};
|
|
72
|
+
} | null>;
|
|
73
|
+
extraRanges: import("vue").Ref<{
|
|
74
|
+
start: {
|
|
75
|
+
r: number;
|
|
76
|
+
c: number;
|
|
77
|
+
};
|
|
78
|
+
end: {
|
|
79
|
+
r: number;
|
|
80
|
+
c: number;
|
|
81
|
+
};
|
|
82
|
+
}[], RangePos[] | {
|
|
83
|
+
start: {
|
|
84
|
+
r: number;
|
|
85
|
+
c: number;
|
|
86
|
+
};
|
|
87
|
+
end: {
|
|
88
|
+
r: number;
|
|
89
|
+
c: number;
|
|
90
|
+
};
|
|
91
|
+
}[]>;
|
|
92
|
+
allRanges: () => RangePos[];
|
|
93
|
+
rangeRectOf: (rp: RangePos) => {
|
|
94
|
+
left: number;
|
|
95
|
+
top: number;
|
|
96
|
+
width: number;
|
|
97
|
+
height: number;
|
|
98
|
+
} | null;
|
|
99
|
+
selectColumn: (colIndex: number, additive?: boolean) => void;
|
|
100
|
+
selectRow: (rowIndex: number, additive?: boolean) => void;
|
|
101
|
+
commitRange: () => void;
|
|
102
|
+
draggingRange: import("vue").Ref<boolean, boolean>;
|
|
103
|
+
draggingFill: import("vue").Ref<boolean, boolean>;
|
|
104
|
+
startFill: () => void;
|
|
105
|
+
rangeRect: import("vue").ComputedRef<{
|
|
106
|
+
left: number;
|
|
107
|
+
top: number;
|
|
108
|
+
width: number;
|
|
109
|
+
height: number;
|
|
110
|
+
} | null>;
|
|
111
|
+
activeRect: import("vue").ComputedRef<{
|
|
112
|
+
left: number;
|
|
113
|
+
top: number;
|
|
114
|
+
width: number;
|
|
115
|
+
height: number;
|
|
116
|
+
} | null>;
|
|
117
|
+
cellFromPoint: (x: number, y: number) => CellPos | null;
|
|
118
|
+
onPointerDown: (pos: CellPos, e: PointerEvent) => void;
|
|
119
|
+
onPointerMove: (pos: CellPos | null, e: PointerEvent) => void;
|
|
120
|
+
onPointerUp: () => void;
|
|
121
|
+
onKeydown: (e: KeyboardEvent, editing: boolean) => boolean;
|
|
122
|
+
onPaste: (e: ClipboardEvent) => boolean;
|
|
123
|
+
editingRef: import("vue").Ref<boolean, boolean>;
|
|
124
|
+
copyRange: (cut?: boolean) => Promise<boolean>;
|
|
125
|
+
pasteFromText: (text: string) => Promise<boolean>;
|
|
126
|
+
rangeMatrix: () => any[][] | null;
|
|
127
|
+
clearSelection: () => void;
|
|
128
|
+
moveActive: (dr: number, dc: number, extend?: boolean) => void;
|
|
129
|
+
findOpen: import("vue").Ref<boolean, boolean>;
|
|
130
|
+
findQuery: import("vue").Ref<string, string>;
|
|
131
|
+
findMatches: import("vue").Ref<{
|
|
132
|
+
rowIndex: number;
|
|
133
|
+
colId: string;
|
|
134
|
+
start: number;
|
|
135
|
+
end: number;
|
|
136
|
+
}[], RjFindMatch[] | {
|
|
137
|
+
rowIndex: number;
|
|
138
|
+
colId: string;
|
|
139
|
+
start: number;
|
|
140
|
+
end: number;
|
|
141
|
+
}[]>;
|
|
142
|
+
findActive: import("vue").Ref<number, number>;
|
|
143
|
+
gotoMatch: (i: number) => void;
|
|
144
|
+
matchOf: (rowIndex: number, colId: string) => RjFindMatch[] | null;
|
|
145
|
+
activeMatchOf: (rowIndex: number, colId: string) => RjFindMatch | null;
|
|
146
|
+
bindScroll: (fn: () => {
|
|
147
|
+
top: number;
|
|
148
|
+
left: number;
|
|
149
|
+
}) => void;
|
|
150
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
import type { RjSavedView } from './types';
|
|
3
|
+
/** 读取自建视图;损坏或非数组时返回空数组(不让网格崩) */
|
|
4
|
+
export declare function loadSavedViews(stateKey?: string): RjSavedView[];
|
|
5
|
+
export declare function persistViews(stateKey: string | undefined, views: RjSavedView[]): void;
|
|
6
|
+
export declare function newViewId(): string;
|
|
7
|
+
/**
|
|
8
|
+
* 视图列表状态容器:内置视图(宿主传入,只读,恒在前)+ 自建视图(localStorage)。
|
|
9
|
+
* stateKey 为空时降级为仅内存/仅内置。
|
|
10
|
+
*/
|
|
11
|
+
export declare function useSavedViews(stateKey: () => string | undefined, builtin?: () => RjSavedView[]): {
|
|
12
|
+
views: Ref<RjSavedView[]>;
|
|
13
|
+
reload: () => RjSavedView[];
|
|
14
|
+
upsert: (v: RjSavedView) => RjSavedView[];
|
|
15
|
+
remove: (id: string) => RjSavedView[];
|
|
16
|
+
};
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import type { RjColumn, RjDataMode, RjFilterModel, RjLoadServerParams, RjRowData, RjSortState, RjTransaction, RjQueryCondition } from './types';
|
|
2
|
+
import { type AdvFilterGroup } from './filtering';
|
|
3
|
+
import { SsrmStore, SsrmTxBatcher } from './ssrm';
|
|
4
|
+
import { type SgNeedLoad } from './serverGroups';
|
|
5
|
+
/** 虚拟行类型 */
|
|
6
|
+
export interface RjDisplayRow {
|
|
7
|
+
key: string | number;
|
|
8
|
+
type: 'row' | 'group' | 'detail' | 'fullwidth';
|
|
9
|
+
data: RjRowData;
|
|
10
|
+
level: number;
|
|
11
|
+
parentKey?: string | number;
|
|
12
|
+
expanded?: boolean;
|
|
13
|
+
height: number;
|
|
14
|
+
/** group 行附加信息 */
|
|
15
|
+
groupField?: string;
|
|
16
|
+
groupValue?: any;
|
|
17
|
+
groupCount?: number;
|
|
18
|
+
/** 服务端权威分组:该组行是否可展开(false 时不显示三角;缺省视为可展开) */
|
|
19
|
+
expandable?: boolean;
|
|
20
|
+
/** 分组页脚行(复用 group 类型,但展示于组底部) */
|
|
21
|
+
isFooter?: boolean;
|
|
22
|
+
/** 合成行(合计行 / 顶部与底部钉行):不参与行拖拽排序 */
|
|
23
|
+
noDrag?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function rowKeyOf(row: RjRowData, keyField?: string): string | number;
|
|
26
|
+
export declare const FILTER_OPS: Record<string, {
|
|
27
|
+
label: string;
|
|
28
|
+
labelKey: string;
|
|
29
|
+
value: string;
|
|
30
|
+
v2?: boolean;
|
|
31
|
+
}[]>;
|
|
32
|
+
declare function filterTypeOf(col: RjColumn): string;
|
|
33
|
+
/** 浮动筛选行文本匹配:text 包含;number 支持 >=/>/<=/</=/~/.. 区间;date 同理;select 逗号枚举 */
|
|
34
|
+
export declare function matchFloatFilter(cellVal: any, raw: string, type: string): boolean;
|
|
35
|
+
/** 单元格原始值(编辑/导出/排序/过滤统一入口;优先返回公式计算结果) */
|
|
36
|
+
export declare function cellRawValue(col: RjColumn, row: RjRowData): any;
|
|
37
|
+
/**
|
|
38
|
+
* 透视度量列判定。生成组合列(buildPivotCols)与聚合取值(buildPivotRows)必须共用这一条
|
|
39
|
+
* 判定,否则表头里存在的组合列在行 __agg 中找不到键。
|
|
40
|
+
*/
|
|
41
|
+
export declare function isPivotValueCol(c: RjColumn): boolean;
|
|
42
|
+
/** 透视度量列的稳定指标键:只有 colId 没有 field 的表达式列也要能唯一编码进组合列 id */
|
|
43
|
+
export declare function pivotValueKey(c: RjColumn): string;
|
|
44
|
+
export interface RowModelOptions {
|
|
45
|
+
rowKey: () => string | undefined;
|
|
46
|
+
rowHeight: () => number;
|
|
47
|
+
detailHeight: () => number;
|
|
48
|
+
fullWidthHeight: () => number;
|
|
49
|
+
hasDetailSlot: () => boolean;
|
|
50
|
+
/** 是否启用分组页脚行 */
|
|
51
|
+
groupFooter?: () => boolean;
|
|
52
|
+
/**
|
|
53
|
+
* 组行显示标签的取法(客户端分组专用):用被分组列的 formatter 把组值转成显示文本。
|
|
54
|
+
* 不给就原样用原始值。只影响 __groupLabels 的显示,__groupValue/组键/组 path 仍为原始值。
|
|
55
|
+
*/
|
|
56
|
+
groupLabelOf?: (col: RjColumn | undefined, value: any, row: RjRowData) => any;
|
|
57
|
+
/** 服务端权威分组:分组/聚合由后端完成,客户端不重建组树 */
|
|
58
|
+
serverGrouping?: () => boolean;
|
|
59
|
+
/** SSRM:判定某行是否为可展开的服务端分组行(缺省按组行有子行即可展开) */
|
|
60
|
+
isServerSideGroup?: (data: RjRowData) => boolean;
|
|
61
|
+
isFullWidthRow: (row: RjRowData) => boolean;
|
|
62
|
+
loadData?: (params: RjLoadServerParams) => Promise<{
|
|
63
|
+
list?: any[];
|
|
64
|
+
rows?: any[];
|
|
65
|
+
total: number;
|
|
66
|
+
}>;
|
|
67
|
+
dataMode: () => RjDataMode;
|
|
68
|
+
pageSize: () => number;
|
|
69
|
+
treeData: () => boolean;
|
|
70
|
+
childrenField: () => string;
|
|
71
|
+
parentField: () => string;
|
|
72
|
+
/** SSRM:每块行数(serverSide 模式) */
|
|
73
|
+
ssrmBlockSize?: () => number;
|
|
74
|
+
/** SSRM:缓存中最多保留的已加载块数 */
|
|
75
|
+
ssrmMaxBlocks?: () => number;
|
|
76
|
+
/** SSRM:视口外额外保留块数 */
|
|
77
|
+
ssrmOverflow?: () => number;
|
|
78
|
+
/** 公式:有序叶子列(按可见顺序,A/B/C 字母按索引映射),由主组件注入 */
|
|
79
|
+
formulaColumns?: () => RjColumn[];
|
|
80
|
+
/** 公式:单元格级公式表,key=`${rowKey}::${colId}` → 公式文本 */
|
|
81
|
+
cellFormulas?: () => Map<string, string>;
|
|
82
|
+
/** 引擎生成列/行的文案(透视总计等),由主组件按当前语言注入;缺省回落中文 */
|
|
83
|
+
labels?: () => {
|
|
84
|
+
total: string;
|
|
85
|
+
grandTotal: string;
|
|
86
|
+
totalOf: (title: string) => string;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 服务端加载上下文:loadData 透出的排序 / 过滤 / 分组 / 查询条件快照。
|
|
91
|
+
* 声明在模块层并导出:useRowModel 的返回值携带 setLoadCtx,留在函数体内会让生成的
|
|
92
|
+
* .d.ts 出现 TS4060(private name),发布类型声明就断了。
|
|
93
|
+
*/
|
|
94
|
+
export interface LoadCtx {
|
|
95
|
+
sort: RjSortState[];
|
|
96
|
+
filters: {
|
|
97
|
+
field: string;
|
|
98
|
+
model: RjFilterModel;
|
|
99
|
+
}[];
|
|
100
|
+
quickFilterText: string;
|
|
101
|
+
floatFilters?: {
|
|
102
|
+
colId: string;
|
|
103
|
+
value: string;
|
|
104
|
+
}[];
|
|
105
|
+
rowGroup?: {
|
|
106
|
+
field: string;
|
|
107
|
+
aggFunc?: string;
|
|
108
|
+
}[];
|
|
109
|
+
advancedFilter?: AdvFilterGroup | null;
|
|
110
|
+
queryConditions?: RjQueryCondition[];
|
|
111
|
+
}
|
|
112
|
+
export declare function useRowModel(userRows: () => RjRowData[], opts: RowModelOptions): {
|
|
113
|
+
rev: import("vue").Ref<number, number>;
|
|
114
|
+
quickFilter: import("vue").Ref<string, string>;
|
|
115
|
+
filterModels: import("vue").Reactive<Map<string, RjFilterModel>>;
|
|
116
|
+
floatFilters: import("vue").Reactive<Map<string, string>>;
|
|
117
|
+
advancedFilter: import("vue").Ref<{
|
|
118
|
+
operator: "or" | "and";
|
|
119
|
+
items: (any | {
|
|
120
|
+
colId: string;
|
|
121
|
+
condition: {
|
|
122
|
+
op: string;
|
|
123
|
+
value1?: any;
|
|
124
|
+
value2?: any;
|
|
125
|
+
};
|
|
126
|
+
filterType?: string | undefined;
|
|
127
|
+
})[];
|
|
128
|
+
} | null, AdvFilterGroup | {
|
|
129
|
+
operator: "or" | "and";
|
|
130
|
+
items: (any | {
|
|
131
|
+
colId: string;
|
|
132
|
+
condition: {
|
|
133
|
+
op: string;
|
|
134
|
+
value1?: any;
|
|
135
|
+
value2?: any;
|
|
136
|
+
};
|
|
137
|
+
filterType?: string | undefined;
|
|
138
|
+
})[];
|
|
139
|
+
} | null>;
|
|
140
|
+
queryConditions: import("vue").Ref<{
|
|
141
|
+
field: string;
|
|
142
|
+
operator: import("./types").RjQueryOperator;
|
|
143
|
+
value?: any;
|
|
144
|
+
value1?: any;
|
|
145
|
+
value2?: any;
|
|
146
|
+
valueText?: string | undefined;
|
|
147
|
+
}[], RjQueryCondition[] | {
|
|
148
|
+
field: string;
|
|
149
|
+
operator: import("./types").RjQueryOperator;
|
|
150
|
+
value?: any;
|
|
151
|
+
value1?: any;
|
|
152
|
+
value2?: any;
|
|
153
|
+
valueText?: string | undefined;
|
|
154
|
+
}[]>;
|
|
155
|
+
sortStates: import("vue").Ref<{
|
|
156
|
+
field: string;
|
|
157
|
+
dir: "desc" | "asc";
|
|
158
|
+
}[], RjSortState[] | {
|
|
159
|
+
field: string;
|
|
160
|
+
dir: "desc" | "asc";
|
|
161
|
+
}[]>;
|
|
162
|
+
rowGroupFields: import("vue").Ref<string[], string[]>;
|
|
163
|
+
rowLimit: import("vue").Ref<number, number>;
|
|
164
|
+
pivotState: import("vue").Ref<{
|
|
165
|
+
cols: string[];
|
|
166
|
+
values: string[];
|
|
167
|
+
active: boolean;
|
|
168
|
+
}, {
|
|
169
|
+
cols: string[];
|
|
170
|
+
values: string[];
|
|
171
|
+
active: boolean;
|
|
172
|
+
} | {
|
|
173
|
+
cols: string[];
|
|
174
|
+
values: string[];
|
|
175
|
+
active: boolean;
|
|
176
|
+
}>;
|
|
177
|
+
expandedGroups: import("vue").Ref<Set<string> & Omit<Set<string>, keyof Set<any>>, Set<string> | (Set<string> & Omit<Set<string>, keyof Set<any>>)>;
|
|
178
|
+
expandedTree: import("vue").Ref<Set<string> & Omit<Set<string>, keyof Set<any>>, Set<string> | (Set<string> & Omit<Set<string>, keyof Set<any>>)>;
|
|
179
|
+
expandedDetails: import("vue").Ref<Set<string | number> & Omit<Set<string | number>, keyof Set<any>>, Set<string | number> | (Set<string | number> & Omit<Set<string | number>, keyof Set<any>>)>;
|
|
180
|
+
serverGroupCollapsed: import("vue").Ref<Set<string> & Omit<Set<string>, keyof Set<any>>, Set<string> | (Set<string> & Omit<Set<string>, keyof Set<any>>)>;
|
|
181
|
+
defaultExpandAll: import("vue").Ref<boolean, boolean>;
|
|
182
|
+
flashRows: import("vue").Ref<Set<string | number> & Omit<Set<string | number>, keyof Set<any>>, Set<string | number> | (Set<string | number> & Omit<Set<string | number>, keyof Set<any>>)>;
|
|
183
|
+
processed: import("vue").ComputedRef<{
|
|
184
|
+
displayRows: RjDisplayRow[];
|
|
185
|
+
filteredCount: number;
|
|
186
|
+
}>;
|
|
187
|
+
offsets: import("vue").ComputedRef<number[]>;
|
|
188
|
+
totalHeight: import("vue").ComputedRef<number>;
|
|
189
|
+
summaryRow: import("vue").ComputedRef<RjRowData | null>;
|
|
190
|
+
pivotCols: (allCols: RjColumn[]) => RjColumn[];
|
|
191
|
+
setPipelineColumns: (cols: RjColumn[]) => void;
|
|
192
|
+
sourceRows: () => RjRowData[];
|
|
193
|
+
applyTransaction: (tx: RjTransaction) => void;
|
|
194
|
+
setRowValue: (row: RjRowData, col: RjColumn, value: any) => boolean;
|
|
195
|
+
setRowData: (rows: RjRowData[]) => void;
|
|
196
|
+
touch: () => void;
|
|
197
|
+
touchOrder: () => void;
|
|
198
|
+
expandGroup: (path: string, expand: boolean) => void;
|
|
199
|
+
toggleTree: (key: string) => void;
|
|
200
|
+
toggleDetail: (key: string | number) => void;
|
|
201
|
+
expandAll: () => void;
|
|
202
|
+
collapseAll: () => void;
|
|
203
|
+
isServerGroupView: () => boolean;
|
|
204
|
+
setServerGroupCollapsed: (path: string, isCollapsed: boolean) => void;
|
|
205
|
+
resetServerGroupView: (clearCollapsed?: boolean) => void;
|
|
206
|
+
loadServerGroupChildren: (info: SgNeedLoad) => Promise<void>;
|
|
207
|
+
filterTypeOf: typeof filterTypeOf;
|
|
208
|
+
comparatorOf: (col: RjColumn | undefined, dir: 'asc' | 'desc') => (a: RjRowData, b: RjRowData) => number;
|
|
209
|
+
serverRows: import("vue").Ref<RjRowData[], RjRowData[]>;
|
|
210
|
+
serverTotal: import("vue").Ref<number, number>;
|
|
211
|
+
serverLoading: import("vue").Ref<boolean, boolean>;
|
|
212
|
+
loadingMore: import("vue").Ref<boolean, boolean>;
|
|
213
|
+
fetchMore: () => void;
|
|
214
|
+
fetchPage: (page: number, size: number) => Promise<void>;
|
|
215
|
+
reloadServer: () => void;
|
|
216
|
+
setLoadCtx: (ctx: LoadCtx) => void;
|
|
217
|
+
allServerLoaded: () => boolean;
|
|
218
|
+
firstExpansionDone: import("vue").Ref<boolean, boolean>;
|
|
219
|
+
ssrmStore: () => SsrmStore;
|
|
220
|
+
ensureServerBlocks: (first: number, last: number) => Promise<void>;
|
|
221
|
+
refreshServerSide: (purge?: boolean) => Promise<void>;
|
|
222
|
+
purgeServerSideCache: () => void;
|
|
223
|
+
ssrmBatcher: SsrmTxBatcher;
|
|
224
|
+
};
|
|
225
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { RjAgg, RjAggFunc, RjColumn, RjExportScope, RjExportScopeResolved, RjRowData } from './types';
|
|
2
|
+
/** a.b.c 路径取值 */
|
|
3
|
+
export declare function getValueByPath(obj: any, path?: string): any;
|
|
4
|
+
/** a.b.c 路径写值(沿途对象不存在则忽略) */
|
|
5
|
+
export declare function setValueByPath(obj: any, path: string, value: any): boolean;
|
|
6
|
+
/** 深拷贝(数据友好型,跳过函数/DOM) */
|
|
7
|
+
export declare function cloneValue<T>(v: T): T;
|
|
8
|
+
/** 列唯一 id */
|
|
9
|
+
export declare function colIdOf(col?: RjColumn | null): string;
|
|
10
|
+
/** 收集叶子列(展开多级表头) */
|
|
11
|
+
export declare function collectLeaves(cols: RjColumn[]): RjColumn[];
|
|
12
|
+
/**
|
|
13
|
+
* 组装公式求值上下文的列清单:当前布局列(可见列 / 透视生成列)在前,
|
|
14
|
+
* 被隐藏的声明列追加在后。
|
|
15
|
+
*
|
|
16
|
+
* 公式引用的是数据字段,不该受列显隐影响:只喂可见列时,
|
|
17
|
+
* `=usedVolume / capacityVolume` 在依赖列隐藏时标识符解析不到,单元格只能降级 #NAME?。
|
|
18
|
+
* 隐藏列必须追加在尾部:A1/B2 这类字母引用按上下文下标映射,
|
|
19
|
+
* 插在中间会让历史单元格公式整体错位。
|
|
20
|
+
* pivot=true 时列源已被引擎生成的 __pv* 列顶替(既有守卫),原样返回不掺声明列。
|
|
21
|
+
*/
|
|
22
|
+
export declare function formulaColumnContext(shown: RjColumn[], declared: RjColumn[], isHidden: (colId: string) => boolean, pivot?: boolean): RjColumn[];
|
|
23
|
+
/** 行集合来源(由主组件按当前状态交进来,本层不做任何副作用) */
|
|
24
|
+
export interface RjExportRowSource {
|
|
25
|
+
/** 选中行(含跨页保留) */
|
|
26
|
+
selected: RjRowData[];
|
|
27
|
+
/** 展示行(含分组/页脚,按屏上顺序) */
|
|
28
|
+
display: {
|
|
29
|
+
type: string;
|
|
30
|
+
isFooter?: boolean;
|
|
31
|
+
data: RjRowData;
|
|
32
|
+
}[];
|
|
33
|
+
/** 源数据全集(未过滤/排序) */
|
|
34
|
+
source: RjRowData[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* auto 落地:有选中就导选中,否则导当前视图;其余档原样返回。
|
|
38
|
+
* 没选中时不得落成 selected,否则用户得到一份只有表头的空文件。
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveExportScope(scope: RjExportScope | undefined, selCount: number): RjExportScopeResolved;
|
|
41
|
+
/**
|
|
42
|
+
* 范围 → 行集合(CSV / Excel / 打印 / PDF 共用一套判定,不再各写一分支)。
|
|
43
|
+
* withGroups:CSV 与打印把分组行也写进文档(分组的「数据」与「分组」两个口径都在同一张表里);
|
|
44
|
+
* Excel 有独立「分组」sheet,数据 sheet 只要干细行,故传 false。
|
|
45
|
+
*/
|
|
46
|
+
export declare function pickExportRows(scope: RjExportScopeResolved, src: RjExportRowSource, withGroups: boolean): RjRowData[];
|
|
47
|
+
export declare function uid(prefix?: string): string;
|
|
48
|
+
/** 列宽限幅 */
|
|
49
|
+
export declare function clampWidth(w: number, col?: RjColumn): number;
|
|
50
|
+
/** 字符串的加权显示宽度(全角计 2,半角计 1) */
|
|
51
|
+
export declare function textWidthUnits(s: string): number;
|
|
52
|
+
export declare function measureColWidth(title: string, texts: string[], opt?: {
|
|
53
|
+
unitW?: number;
|
|
54
|
+
padPx?: number;
|
|
55
|
+
min?: number;
|
|
56
|
+
max?: number;
|
|
57
|
+
}): number;
|
|
58
|
+
export declare function formatDate(v: any, datetime?: boolean): string;
|
|
59
|
+
/**
|
|
60
|
+
* 图片值转可读文本(导出 / 剪贴板 / 拖拽浮影 / tooltip 共用):
|
|
61
|
+
* 取 URL 文件名,多值用 ", " 连接;data: 内联图无文件名,跳过以免把巨长 URI 写进单元格。
|
|
62
|
+
*/
|
|
63
|
+
export declare function imageText(value: any): string;
|
|
64
|
+
/** 按列预设类型格式化单元格值(导出与默认渲染共用);布尔列文案由调用端按语言传入 */
|
|
65
|
+
export declare function formatByType(col: RjColumn, value: any, boolLabels?: [string, string]): string;
|
|
66
|
+
/**
|
|
67
|
+
* 解析用户输入的数字串(会计/货币友好),供数字编辑器提交前统一转换:
|
|
68
|
+
* - 容忍千分位逗号 / 空格 / 下划线、货币符号(¥ $ € £ ₹)、前后正负号
|
|
69
|
+
* - 会计负数括号:`(1,234.50)` → -1234.5
|
|
70
|
+
* - 无法解析(空串、纯符号、乱码)返回 null
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseNumericInput(raw: any): number | null;
|
|
73
|
+
/**
|
|
74
|
+
* 选项打字匹配排序(RichSelect 型前:前缀匹配优先于包含匹配,保持各档原相对顺序)。
|
|
75
|
+
* 空查询原样返回;无任何命中返回空数组(供 UI 显示"无匹配项")。
|
|
76
|
+
*/
|
|
77
|
+
export declare function rankOptions<T extends {
|
|
78
|
+
label?: any;
|
|
79
|
+
value?: any;
|
|
80
|
+
}>(options: T[], query: string): T[];
|
|
81
|
+
/** 智能比较:数字/日期/中文字符串 */
|
|
82
|
+
export declare function defaultComparator(a: any, b: any): number;
|
|
83
|
+
export declare const AGG_FUNCS: Record<RjAggFunc, (rows: RjRowData[], values: any[]) => any>;
|
|
84
|
+
export declare function runAgg(func: RjAgg | undefined, rows: RjRowData[], values: any[]): any;
|
|
85
|
+
/** 聚合函数 → 文案 key(由调用端经 t() 取词,保证语言切换时聚合标签同步) */
|
|
86
|
+
export declare const AGG_LABELS: Record<RjAggFunc, string>;
|
|
87
|
+
/** 二分查找:有序数组 arr 中找第一个 >= target 的下标 */
|
|
88
|
+
export declare function lowerBound(arr: number[] | {
|
|
89
|
+
length: number;
|
|
90
|
+
[i: number]: number;
|
|
91
|
+
}, target: number, key?: (i: number) => number): number;
|
|
92
|
+
/**
|
|
93
|
+
* 行拖拽落位换算:把「被拖行从显示槽 from 移到显示槽 to」换算为
|
|
94
|
+
* 「从源数据数组移除被拖行后,应把被拖行插入的下标」。
|
|
95
|
+
* - rowCount:显示行总数
|
|
96
|
+
* - isData(i):第 i 个显示行是否为参与重排的数据行(组行 / 页脚行等不计入)
|
|
97
|
+
* - isMoved(i):第 i 个显示行是否为被拖拽的那一行
|
|
98
|
+
*
|
|
99
|
+
* 落位后被拖行占据显示槽 to:排在它之前的数据行 = 显示下标 < to 的数据行(不含被拖行自身)。
|
|
100
|
+
* 下移(from < to)时,原本位于槽 to 的那一行会因让位上移到 to-1,仍排在被拖行之前,故再 +1;
|
|
101
|
+
* 上移(from > to)时被拖行本就不在 [0, to) 内,无需修正。
|
|
102
|
+
* (行拖拽仅在无排序 / 分组 / 透视 / 树形态下开放,此时槽 to 必为数据行,+1 不会越界。)
|
|
103
|
+
*/
|
|
104
|
+
export declare function rowMoveInsertIndex(rowCount: number, isData: (i: number) => boolean, isMoved: (i: number) => boolean, from: number, to: number): number;
|
|
105
|
+
/**
|
|
106
|
+
* 拖拽整行快照的宽度预算:按列宽顺序累计,达到 maxW 即止(至少保留 1 格),
|
|
107
|
+
* 返回要渲染的单元格数量,使跟手浮影不会宽过视口。cells 为空返回 0。
|
|
108
|
+
*/
|
|
109
|
+
export declare function ghostCellCount<T extends {
|
|
110
|
+
w: number;
|
|
111
|
+
}>(cells: T[], maxW: number): number;
|
|
112
|
+
/**
|
|
113
|
+
* 自然语言「取前 N 行」(TopN) 的截断:limit<=0 或非有限数视为不限量,原样返回。
|
|
114
|
+
* limit 落在 (0, len] 时截取前 limit 行;纯函数便于单测,调用点负责响应式。
|
|
115
|
+
*/
|
|
116
|
+
export declare function applyRowLimit<T>(rows: T[], limit: number): T[];
|
|
117
|
+
export declare function throttleRaf<T extends (...args: any[]) => void>(fn: T): T;
|
|
118
|
+
export declare function debounce<T extends (...args: any[]) => void>(fn: T, wait?: number): T & {
|
|
119
|
+
cancel: () => void;
|
|
120
|
+
};
|
|
121
|
+
/** 是否 Mac(Ctrl/Cmd 适配) */
|
|
122
|
+
export declare const isMac: () => boolean;
|
|
123
|
+
/** 触发下载 */
|
|
124
|
+
export declare function downloadBlob(blob: Blob, fileName: string): void;
|
|
125
|
+
/** 取元素在容器内的相对坐标 */
|
|
126
|
+
export declare function inRect(el: Element | null, rect: DOMRect): {
|
|
127
|
+
x: number;
|
|
128
|
+
y: number;
|
|
129
|
+
} | null;
|
|
130
|
+
export declare const stop: (e: Event) => void;
|
package/package.json
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rj-grid",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "零第三方依赖的自研 Vue3 虚拟表格:虚拟滚动 / 冻结列 / 行拖拽 / 分组透视 / 公式 / SSRM / 主题 i18n / 自然语言查询",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "rjding",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://gitee.com/rjding/rj-grid.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://gitee.com/rjding/rj-grid/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://gitee.com/rjding/rj-grid#readme",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public",
|
|
18
|
+
"registry": "https://registry.npmjs.org/"
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/rj-grid.js",
|
|
21
|
+
"module": "./dist/rj-grid.js",
|
|
22
|
+
"types": "./dist/types/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/types/index.d.ts",
|
|
26
|
+
"import": "./dist/rj-grid.js",
|
|
27
|
+
"default": "./dist/rj-grid.js"
|
|
28
|
+
},
|
|
29
|
+
"./style.css": "./dist/style.css",
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"sideEffects": [
|
|
33
|
+
"*.css"
|
|
34
|
+
],
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"vue": "^3.4.0",
|
|
41
|
+
"echarts": ">=5.0.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependenciesMeta": {
|
|
44
|
+
"echarts": {
|
|
45
|
+
"optional": true
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"dev": "vite --config vite.playground.config.ts",
|
|
50
|
+
"build:play": "vite build --config vite.playground.config.ts",
|
|
51
|
+
"preview:play": "vite preview --config vite.playground.config.ts",
|
|
52
|
+
"build": "node ./node_modules/vite/bin/vite.js build --config vite.lib.config.ts && node --max_old_space_size=8192 ./node_modules/vue-tsc/bin/vue-tsc.js -p tsconfig.types.json && node build/rjDistCheck.mjs",
|
|
53
|
+
"check:dist": "node build/rjDistCheck.mjs",
|
|
54
|
+
"test": "esbuild __tests__/run.ts --bundle --platform=node --format=cjs --external:vue --outfile=node_modules/.cache/rjtest.cjs --log-level=error && node node_modules/.cache/rjtest.cjs",
|
|
55
|
+
"lint": "eslint --fix --ext .ts,.vue index.ts src __tests__ playground && stylelint \"src/styles/*.scss\"",
|
|
56
|
+
"ts": "node --max_old_space_size=8192 ./node_modules/vue-tsc/bin/vue-tsc.js --noEmit -p tsconfig.json",
|
|
57
|
+
"size": "node ./node_modules/vite/bin/vite.js build --config vite.size.config.ts && node build/rjSizeReport.mjs",
|
|
58
|
+
"prepublishOnly": "pnpm build && pnpm test"
|
|
59
|
+
},
|
|
60
|
+
"keywords": [
|
|
61
|
+
"vue3",
|
|
62
|
+
"virtual-table",
|
|
63
|
+
"data-grid",
|
|
64
|
+
"rj-grid"
|
|
65
|
+
],
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/node": "^20.11.0",
|
|
68
|
+
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
|
69
|
+
"@typescript-eslint/parser": "^7.1.0",
|
|
70
|
+
"@vitejs/plugin-vue": "^5.0.4",
|
|
71
|
+
"echarts": "^5.5.0",
|
|
72
|
+
"element-plus": "^2.11.7",
|
|
73
|
+
"esbuild": "^0.19.12",
|
|
74
|
+
"eslint": "^8.57.1",
|
|
75
|
+
"eslint-config-prettier": "^9.1.0",
|
|
76
|
+
"eslint-plugin-vue": "^9.33.0",
|
|
77
|
+
"postcss-html": "^1.6.0",
|
|
78
|
+
"sass": "^1.69.5",
|
|
79
|
+
"stylelint": "^16.22.0",
|
|
80
|
+
"stylelint-config-html": "^1.1.0",
|
|
81
|
+
"stylelint-config-recommended": "^14.0.0",
|
|
82
|
+
"stylelint-config-standard": "^36.0.1",
|
|
83
|
+
"stylelint-order": "^6.0.4",
|
|
84
|
+
"typescript": "5.3.3",
|
|
85
|
+
"vite": "5.1.4",
|
|
86
|
+
"vue": "3.5.12",
|
|
87
|
+
"vue-eslint-parser": "^9.3.2",
|
|
88
|
+
"vue-tsc": "^1.8.27"
|
|
89
|
+
}
|
|
90
|
+
}
|