rj-grid 0.2.3 → 0.2.5
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/README.md +9 -9
- package/dist/rj-grid.js +39 -12
- package/dist/types/src/RjGrid.vue.d.ts +29 -0
- package/dist/types/src/RjQueryBar.vue.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<h1 align="center">rj-grid</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<b>零第三方依赖的企业级 Vue 3 数据网格 —— 对标 AG Grid 的全功能,MIT 免费、gzip 约
|
|
8
|
+
<b>零第三方依赖的企业级 Vue 3 数据网格 —— 对标 AG Grid 的全功能,MIT 免费、gzip 约 110 KB。</b><br/>
|
|
9
9
|
虚拟滚动 · 冻结列 · 分组透视 · 树形 · 编辑撤销 · 公式引擎 · SSRM 服务端行模型 · 主题 & i18n · 打印/CSV/Excel/PDF · 离线自然语言查询(NLQ)
|
|
10
10
|
</p>
|
|
11
11
|
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
<a href="https://gitee.com/rjding/rj-grid"><img src="https://img.shields.io/badge/Gitee-rj--grid-orange?logo=gitee&logoColor=white" alt="Gitee mirror"/></a>
|
|
16
16
|
<a href="https://github.com/rjding/rjGrid/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License MIT"/></a>
|
|
17
17
|
<a href="https://gitee.com/rjding/rj-grid"><img src="https://img.shields.io/badge/third--party%20deps-0-blue.svg" alt="Zero dependencies"/></a>
|
|
18
|
-
<img src="https://img.shields.io/badge/gzip-~
|
|
18
|
+
<img src="https://img.shields.io/badge/gzip-~110KB-lightgrey.svg" alt="Bundle size"/>
|
|
19
19
|
<a href="https://vuejs.org/"><img src="https://img.shields.io/badge/vue-3.x-brightgreen.svg?logo=vuedotjs" alt="Vue 3"/></a>
|
|
20
|
-
<img src="https://img.shields.io/badge/tests-
|
|
20
|
+
<img src="https://img.shields.io/badge/tests-407%20passed-yellowgreen.svg" alt="Tests"/>
|
|
21
21
|
<img src="https://img.shields.io/badge/types-TypeScript-blue.svg?logo=typescript" alt="TypeScript"/>
|
|
22
22
|
</p>
|
|
23
23
|
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
想象一下:一个 `<rj-grid>` 标签,就能替换掉你项目里那些「几万行就卡死、想加个分组又得换库」的表格——而**不额外引入任何第三方依赖**,也不用给商业表格库交授权费。
|
|
39
39
|
|
|
40
40
|
- **真·零依赖**:运行时只需 `vue`,连可选的图表都是按需 `import('echarts')`。不捆绑、不污染你的 lockfile。
|
|
41
|
-
- **小得离谱**:gzip 约
|
|
41
|
+
- **小得离谱**:gzip 约 110 KB,却装下了别人几个库加起来的功能量。
|
|
42
42
|
- **10 万行丝滑**:行列双向虚拟滚动,实测 100,000 行 × 12 列秒开(生成仅约 12 ms)。
|
|
43
43
|
- **对标 AG Grid 全功能**:树形 / 分组 / 透视 / SSRM / 公式 / 主题 / i18n / 导出 / NLQ 一应俱全。
|
|
44
44
|
- **TypeScript 原生**:完整的类型推导与 `.d.ts`,编辑器全程提示,不是「先跑起来再说」的糙活。
|
|
@@ -50,14 +50,14 @@
|
|
|
50
50
|
|
|
51
51
|
| 分类 | 你会得到的能力 |
|
|
52
52
|
|---|---|
|
|
53
|
-
| 渲染 | 行列虚拟滚动(10
|
|
53
|
+
| 渲染 | 行列虚拟滚动(10 万行流畅)、冻结列、多级表头、密度三档、钉行、全宽行;**单击单元格即选中行**(`selectOnCellClick`,无需勾复选框) |
|
|
54
54
|
| 数据 | 客户端 / 分页 / 无限滚动 / **SSRM 服务端行模型**(按需块缓存)四种模式 |
|
|
55
55
|
| 分组 | 树形任意深度、拖拽分组、多级分组 + 组页脚聚合、列透视(含高基数护栏) |
|
|
56
56
|
| 编辑 | 8 类编辑器、校验、撤销/重做、批量事务回填、内置新增/编辑行弹窗 |
|
|
57
57
|
| 公式 | 零依赖 Excel 风格公式:`=B2*C2`、`SUM/COUNTIF/SUMIF`、区域引用、循环引用检测 |
|
|
58
58
|
| 筛选 | 列头漏斗 / 浮动筛选行 / 快速搜索 / 高级过滤(跨列 AND/OR 表达式树)四路叠加 |
|
|
59
59
|
| 外观 | 主题引擎(4 预设 × 明暗 × 强调色 × 自定义 CSS 变量)、i18n(中/英 + 文案覆盖)、图标替换 |
|
|
60
|
-
| 输出 | 打印 / CSV / Excel / PDF,支持选中行 / 当前视图 /
|
|
60
|
+
| 输出 | 打印 / CSV / Excel / PDF,支持选中行 / 当前视图 / 后端导出三种范围;四个按钮可逐个显隐(`showPrint`/`showCsv`/`showPdf`/`showExcel`) |
|
|
61
61
|
| AI | 纯离线确定性 **NLQ**,中英双语随 i18n 切换:中文用「数量大于50 按单价降序」、英文用 `qty > 50 sort by price desc`,回显随语言 |
|
|
62
62
|
| 状态 | `stateKey` 自动持久化 + `getState/setState` 编程式存取,刷新不丢视图 |
|
|
63
63
|
|
|
@@ -206,7 +206,7 @@ const rows: RjRowData[] = [
|
|
|
206
206
|
|---|---|---|
|
|
207
207
|
| 授权 / 费用 | ✅ MIT 完全免费 | ⚠️ 企业级特性需商业授权 |
|
|
208
208
|
| 第三方运行时依赖 | ✅ 仅 `vue` | ⚠️ 自带框架与模块体系 |
|
|
209
|
-
| gzip 体积 | ✅ 约
|
|
209
|
+
| gzip 体积 | ✅ 约 110 KB | 显著更大 |
|
|
210
210
|
| Vue 3 原生 | ✅ 值导入即用,非二次封装 | 提供 Vue 封装层 |
|
|
211
211
|
| 离线自然语言查询 | ✅ 内置纯确定性 NLQ | ❌ 无 |
|
|
212
212
|
| 虚拟滚动 / 分组 / 透视 / SSRM / 公式 / 主题 / 导出 | ✅ 全部内置 | ✅ 部分在付费版 |
|
|
@@ -278,7 +278,7 @@ pnpm dev # 默认 http://localhost:5173
|
|
|
278
278
|
|---|---|
|
|
279
279
|
| `index.ts` | 包入口(值导出 `RjGrid` + NLQ / 查询条件内核 + 全部公共类型) |
|
|
280
280
|
| `src/` | 组件与引擎源码(`src/types.ts` 是类型权威) |
|
|
281
|
-
| `__tests__/` |
|
|
281
|
+
| `__tests__/` | 407 个单测用例,入口 `__tests__/run.ts` |
|
|
282
282
|
| `build/rjDistCheck.mjs` | 产物体检五守卫(构建末尾自动跑) |
|
|
283
283
|
| `vite.lib.config.ts` | 库构建:ESM 单文件 + 单 `style.css`,external `vue`/`echarts`,不出 sourcemap |
|
|
284
284
|
| `playground/` | 8 标签演示页 |
|
|
@@ -288,7 +288,7 @@ pnpm dev # 默认 http://localhost:5173
|
|
|
288
288
|
### 开发命令
|
|
289
289
|
|
|
290
290
|
```bash
|
|
291
|
-
pnpm test # 单测
|
|
291
|
+
pnpm test # 单测 407 passed
|
|
292
292
|
pnpm ts # vue-tsc --noEmit
|
|
293
293
|
pnpm lint # eslint + stylelint
|
|
294
294
|
pnpm build # vite lib → vue-tsc 产 d.ts → 产物体检五守卫
|
package/dist/rj-grid.js
CHANGED
|
@@ -9131,7 +9131,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
|
9131
9131
|
actions: {},
|
|
9132
9132
|
selectedRows: {}
|
|
9133
9133
|
},
|
|
9134
|
-
emits: ["update:modelValue", "search", "action-click"],
|
|
9134
|
+
emits: ["update:modelValue", "search", "reset", "action-click"],
|
|
9135
9135
|
setup(__props, { emit: __emit }) {
|
|
9136
9136
|
const props = __props;
|
|
9137
9137
|
const emit = __emit;
|
|
@@ -9214,8 +9214,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
|
9214
9214
|
emitList(next);
|
|
9215
9215
|
}
|
|
9216
9216
|
function clearAll() {
|
|
9217
|
-
|
|
9218
|
-
emit("search");
|
|
9217
|
+
emit("reset");
|
|
9219
9218
|
}
|
|
9220
9219
|
function readVal(ev, numeric) {
|
|
9221
9220
|
const raw = ev.target.value;
|
|
@@ -10149,9 +10148,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
10149
10148
|
showGroupPanel: { type: Boolean, default: true },
|
|
10150
10149
|
chartable: { type: Boolean, default: true },
|
|
10151
10150
|
exportable: { type: Boolean, default: true },
|
|
10151
|
+
showPrint: { type: Boolean, default: true },
|
|
10152
|
+
showCsv: { type: Boolean, default: true },
|
|
10153
|
+
showPdf: { type: Boolean, default: true },
|
|
10154
|
+
showExcel: { type: Boolean, default: true },
|
|
10152
10155
|
colReorder: { type: Boolean, default: true },
|
|
10153
10156
|
resizable: { type: Boolean, default: true },
|
|
10154
10157
|
rowSelection: { type: [Boolean, String], default: false },
|
|
10158
|
+
selectOnCellClick: { type: Boolean, default: true },
|
|
10155
10159
|
keepSelectionCrossPage: { type: Boolean },
|
|
10156
10160
|
editable: { type: Boolean, default: false },
|
|
10157
10161
|
rangeSelection: { type: Boolean, default: true },
|
|
@@ -10507,6 +10511,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
10507
10511
|
emit("filter-change");
|
|
10508
10512
|
dispatchEvent("filterChanged", {});
|
|
10509
10513
|
}
|
|
10514
|
+
function onQueryReset() {
|
|
10515
|
+
const cur = savedViews.views.value.find((v) => v.id === currentViewId.value);
|
|
10516
|
+
queryConditions.value = cur ? cloneConditions(cur.conditions || []) : [];
|
|
10517
|
+
onQuerySearch();
|
|
10518
|
+
}
|
|
10510
10519
|
function applyView(v, viewId) {
|
|
10511
10520
|
var _a2;
|
|
10512
10521
|
const view = "conditions" in v ? v : null;
|
|
@@ -10899,6 +10908,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
10899
10908
|
}
|
|
10900
10909
|
notifySelection();
|
|
10901
10910
|
}
|
|
10911
|
+
function selectRowByClick(d) {
|
|
10912
|
+
if (selection.size === 1 && selection.has(d.key))
|
|
10913
|
+
return;
|
|
10914
|
+
selection.clear();
|
|
10915
|
+
if (props.keepSelectionCrossPage)
|
|
10916
|
+
preserveMap.clear();
|
|
10917
|
+
selection.add(d.key);
|
|
10918
|
+
if (props.keepSelectionCrossPage)
|
|
10919
|
+
preserveMap.set(d.key, d.data);
|
|
10920
|
+
notifySelection();
|
|
10921
|
+
}
|
|
10902
10922
|
function selectedRows() {
|
|
10903
10923
|
const rows = rowModel.processed.value.displayRows.filter((d) => selection.has(d.key)).map((d) => d.data);
|
|
10904
10924
|
Array.from(preserveMap.values()).forEach((r) => {
|
|
@@ -12019,6 +12039,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
12019
12039
|
colIndex: pos.c,
|
|
12020
12040
|
column: leaf.col
|
|
12021
12041
|
});
|
|
12042
|
+
if (props.selectOnCellClick && e.button === 0 && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey && drow && drow.type === "row" && !(e.target instanceof Element && e.target.closest(".rj-checkbox")))
|
|
12043
|
+
selectRowByClick(drow);
|
|
12022
12044
|
}
|
|
12023
12045
|
if (!props.rangeSelection || e.button !== 0 || !pos)
|
|
12024
12046
|
return;
|
|
@@ -13852,6 +13874,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
13852
13874
|
actions: _ctx.queryActions,
|
|
13853
13875
|
"selected-rows": selectedRows(),
|
|
13854
13876
|
onSearch: onQuerySearch,
|
|
13877
|
+
onReset: onQueryReset,
|
|
13855
13878
|
onActionClick: runQueryAction
|
|
13856
13879
|
}, createSlots({ _: 2 }, [
|
|
13857
13880
|
_ctx.$slots["query-actions"] ? {
|
|
@@ -13994,27 +14017,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
13994
14017
|
class: normalizeClass(["rj-btn", { "is-active": panelOpen.value }]),
|
|
13995
14018
|
onClick: _cache[16] || (_cache[16] = ($event) => panelOpen.value = !panelOpen.value)
|
|
13996
14019
|
}, toDisplayString(t("panel")), 3)) : createCommentVNode("", true),
|
|
13997
|
-
_ctx.exportable ? (openBlock(), createElementBlock("div", _hoisted_14, [
|
|
13998
|
-
|
|
14020
|
+
_ctx.exportable && (_ctx.showPrint || _ctx.showCsv || _ctx.showPdf || _ctx.showExcel) ? (openBlock(), createElementBlock("div", _hoisted_14, [
|
|
14021
|
+
_ctx.showPrint ? (openBlock(), createElementBlock("button", {
|
|
14022
|
+
key: 0,
|
|
13999
14023
|
class: "rj-btn rj-btn-export rj-export-btn",
|
|
14000
14024
|
"data-tip": t("printTip"),
|
|
14001
14025
|
onClick: _cache[17] || (_cache[17] = ($event) => openRangeMenu($event, "print"))
|
|
14002
|
-
}, toDisplayString(t("printBtn")), 9, _hoisted_15),
|
|
14003
|
-
|
|
14026
|
+
}, toDisplayString(t("printBtn")), 9, _hoisted_15)) : createCommentVNode("", true),
|
|
14027
|
+
_ctx.showCsv ? (openBlock(), createElementBlock("button", {
|
|
14028
|
+
key: 1,
|
|
14004
14029
|
class: "rj-btn rj-btn-export rj-export-btn",
|
|
14005
14030
|
"data-tip": t("csvTip"),
|
|
14006
14031
|
onClick: _cache[18] || (_cache[18] = ($event) => openRangeMenu($event, "csv"))
|
|
14007
|
-
}, " CSV ", 8, _hoisted_16),
|
|
14008
|
-
|
|
14032
|
+
}, " CSV ", 8, _hoisted_16)) : createCommentVNode("", true),
|
|
14033
|
+
_ctx.showPdf ? (openBlock(), createElementBlock("button", {
|
|
14034
|
+
key: 2,
|
|
14009
14035
|
class: "rj-btn rj-btn-export rj-export-btn",
|
|
14010
14036
|
"data-tip": t("pdfTip"),
|
|
14011
14037
|
onClick: _cache[19] || (_cache[19] = ($event) => openRangeMenu($event, "pdf"))
|
|
14012
|
-
}, " PDF ", 8, _hoisted_17),
|
|
14013
|
-
|
|
14038
|
+
}, " PDF ", 8, _hoisted_17)) : createCommentVNode("", true),
|
|
14039
|
+
_ctx.showExcel ? (openBlock(), createElementBlock("button", {
|
|
14040
|
+
key: 3,
|
|
14014
14041
|
class: "rj-btn rj-btn-export rj-export-btn",
|
|
14015
14042
|
"data-tip": t("excelTip"),
|
|
14016
14043
|
onClick: _cache[20] || (_cache[20] = ($event) => openRangeMenu($event, "excel"))
|
|
14017
|
-
}, " Excel ", 8, _hoisted_18)
|
|
14044
|
+
}, " Excel ", 8, _hoisted_18)) : createCommentVNode("", true)
|
|
14018
14045
|
])) : createCommentVNode("", true),
|
|
14019
14046
|
_ctx.stateKey ? (openBlock(), createElementBlock("button", {
|
|
14020
14047
|
key: 6,
|
|
@@ -46,9 +46,16 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
|
|
|
46
46
|
showGroupPanel?: boolean | undefined;
|
|
47
47
|
chartable?: boolean | undefined;
|
|
48
48
|
exportable?: boolean | undefined;
|
|
49
|
+
/** 工具栏各导出/打印按钮单独显隐(仅在 exportable 为真时生效);默认全 true,可按需关掉其中任意几个 */
|
|
50
|
+
showPrint?: boolean | undefined;
|
|
51
|
+
showCsv?: boolean | undefined;
|
|
52
|
+
showPdf?: boolean | undefined;
|
|
53
|
+
showExcel?: boolean | undefined;
|
|
49
54
|
colReorder?: boolean | undefined;
|
|
50
55
|
resizable?: boolean | undefined;
|
|
51
56
|
rowSelection?: false | "multiple" | "single" | undefined;
|
|
57
|
+
/** 单击数据行单元格即选中该行(替换式,无需再点复选框);按住 Ctrl/Shift/Alt 仍走区域选择,复选框保留多选,双击仍编辑。默认 true */
|
|
58
|
+
selectOnCellClick?: boolean | undefined;
|
|
52
59
|
keepSelectionCrossPage?: boolean | undefined;
|
|
53
60
|
editable?: boolean | undefined;
|
|
54
61
|
rangeSelection?: boolean | undefined;
|
|
@@ -157,9 +164,14 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
|
|
|
157
164
|
showGroupPanel: boolean;
|
|
158
165
|
chartable: boolean;
|
|
159
166
|
exportable: boolean;
|
|
167
|
+
showPrint: boolean;
|
|
168
|
+
showCsv: boolean;
|
|
169
|
+
showPdf: boolean;
|
|
170
|
+
showExcel: boolean;
|
|
160
171
|
colReorder: boolean;
|
|
161
172
|
resizable: boolean;
|
|
162
173
|
rowSelection: boolean;
|
|
174
|
+
selectOnCellClick: boolean;
|
|
163
175
|
editable: boolean;
|
|
164
176
|
rangeSelection: boolean;
|
|
165
177
|
clipboard: boolean;
|
|
@@ -260,9 +272,16 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
|
|
|
260
272
|
showGroupPanel?: boolean | undefined;
|
|
261
273
|
chartable?: boolean | undefined;
|
|
262
274
|
exportable?: boolean | undefined;
|
|
275
|
+
/** 工具栏各导出/打印按钮单独显隐(仅在 exportable 为真时生效);默认全 true,可按需关掉其中任意几个 */
|
|
276
|
+
showPrint?: boolean | undefined;
|
|
277
|
+
showCsv?: boolean | undefined;
|
|
278
|
+
showPdf?: boolean | undefined;
|
|
279
|
+
showExcel?: boolean | undefined;
|
|
263
280
|
colReorder?: boolean | undefined;
|
|
264
281
|
resizable?: boolean | undefined;
|
|
265
282
|
rowSelection?: false | "multiple" | "single" | undefined;
|
|
283
|
+
/** 单击数据行单元格即选中该行(替换式,无需再点复选框);按住 Ctrl/Shift/Alt 仍走区域选择,复选框保留多选,双击仍编辑。默认 true */
|
|
284
|
+
selectOnCellClick?: boolean | undefined;
|
|
266
285
|
keepSelectionCrossPage?: boolean | undefined;
|
|
267
286
|
editable?: boolean | undefined;
|
|
268
287
|
rangeSelection?: boolean | undefined;
|
|
@@ -371,9 +390,14 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
|
|
|
371
390
|
showGroupPanel: boolean;
|
|
372
391
|
chartable: boolean;
|
|
373
392
|
exportable: boolean;
|
|
393
|
+
showPrint: boolean;
|
|
394
|
+
showCsv: boolean;
|
|
395
|
+
showPdf: boolean;
|
|
396
|
+
showExcel: boolean;
|
|
374
397
|
colReorder: boolean;
|
|
375
398
|
resizable: boolean;
|
|
376
399
|
rowSelection: boolean;
|
|
400
|
+
selectOnCellClick: boolean;
|
|
377
401
|
editable: boolean;
|
|
378
402
|
rangeSelection: boolean;
|
|
379
403
|
clipboard: boolean;
|
|
@@ -465,9 +489,14 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
|
|
|
465
489
|
showGroupPanel: boolean;
|
|
466
490
|
chartable: boolean;
|
|
467
491
|
exportable: boolean;
|
|
492
|
+
showPrint: boolean;
|
|
493
|
+
showCsv: boolean;
|
|
494
|
+
showPdf: boolean;
|
|
495
|
+
showExcel: boolean;
|
|
468
496
|
colReorder: boolean;
|
|
469
497
|
resizable: boolean;
|
|
470
498
|
rowSelection: false | "multiple" | "single";
|
|
499
|
+
selectOnCellClick: boolean;
|
|
471
500
|
rangeSelection: boolean;
|
|
472
501
|
clipboard: boolean;
|
|
473
502
|
contextMenu: boolean | ((ctx: any) => RjMenuItem[]);
|
|
@@ -9,6 +9,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
|
|
|
9
9
|
}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
10
|
"update:modelValue": (v: RjQueryCondition[]) => void;
|
|
11
11
|
search: () => void;
|
|
12
|
+
reset: () => void;
|
|
12
13
|
"action-click": (a: RjQueryAction) => void;
|
|
13
14
|
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
|
|
14
15
|
fields: RjQueryFieldDef[];
|
|
@@ -19,6 +20,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
|
|
|
19
20
|
selectedRows?: RjRowData[] | undefined;
|
|
20
21
|
}>>> & Readonly<{
|
|
21
22
|
onSearch?: (() => any) | undefined;
|
|
23
|
+
onReset?: (() => any) | undefined;
|
|
22
24
|
"onUpdate:modelValue"?: ((v: RjQueryCondition[]) => any) | undefined;
|
|
23
25
|
"onAction-click"?: ((a: RjQueryAction) => any) | undefined;
|
|
24
26
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>, Readonly<{
|