rj-grid 0.2.3 → 0.2.4

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 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 约 93 KB。</b><br/>
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-~93KB-lightgrey.svg" alt="Bundle size"/>
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-346%20passed-yellowgreen.svg" alt="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 约 93 KB,却装下了别人几个库加起来的功能量。
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 体积 | ✅ 约 93 KB | 显著更大 |
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__/` | 346 个单测用例,入口 `__tests__/run.ts` |
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 # 单测 346 passed
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
@@ -10149,9 +10149,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10149
10149
  showGroupPanel: { type: Boolean, default: true },
10150
10150
  chartable: { type: Boolean, default: true },
10151
10151
  exportable: { type: Boolean, default: true },
10152
+ showPrint: { type: Boolean, default: true },
10153
+ showCsv: { type: Boolean, default: true },
10154
+ showPdf: { type: Boolean, default: true },
10155
+ showExcel: { type: Boolean, default: true },
10152
10156
  colReorder: { type: Boolean, default: true },
10153
10157
  resizable: { type: Boolean, default: true },
10154
10158
  rowSelection: { type: [Boolean, String], default: false },
10159
+ selectOnCellClick: { type: Boolean, default: true },
10155
10160
  keepSelectionCrossPage: { type: Boolean },
10156
10161
  editable: { type: Boolean, default: false },
10157
10162
  rangeSelection: { type: Boolean, default: true },
@@ -10899,6 +10904,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10899
10904
  }
10900
10905
  notifySelection();
10901
10906
  }
10907
+ function selectRowByClick(d) {
10908
+ if (selection.size === 1 && selection.has(d.key))
10909
+ return;
10910
+ selection.clear();
10911
+ if (props.keepSelectionCrossPage)
10912
+ preserveMap.clear();
10913
+ selection.add(d.key);
10914
+ if (props.keepSelectionCrossPage)
10915
+ preserveMap.set(d.key, d.data);
10916
+ notifySelection();
10917
+ }
10902
10918
  function selectedRows() {
10903
10919
  const rows = rowModel.processed.value.displayRows.filter((d) => selection.has(d.key)).map((d) => d.data);
10904
10920
  Array.from(preserveMap.values()).forEach((r) => {
@@ -12019,6 +12035,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
12019
12035
  colIndex: pos.c,
12020
12036
  column: leaf.col
12021
12037
  });
12038
+ 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")))
12039
+ selectRowByClick(drow);
12022
12040
  }
12023
12041
  if (!props.rangeSelection || e.button !== 0 || !pos)
12024
12042
  return;
@@ -13994,27 +14012,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
13994
14012
  class: normalizeClass(["rj-btn", { "is-active": panelOpen.value }]),
13995
14013
  onClick: _cache[16] || (_cache[16] = ($event) => panelOpen.value = !panelOpen.value)
13996
14014
  }, toDisplayString(t("panel")), 3)) : createCommentVNode("", true),
13997
- _ctx.exportable ? (openBlock(), createElementBlock("div", _hoisted_14, [
13998
- createElementVNode("button", {
14015
+ _ctx.exportable && (_ctx.showPrint || _ctx.showCsv || _ctx.showPdf || _ctx.showExcel) ? (openBlock(), createElementBlock("div", _hoisted_14, [
14016
+ _ctx.showPrint ? (openBlock(), createElementBlock("button", {
14017
+ key: 0,
13999
14018
  class: "rj-btn rj-btn-export rj-export-btn",
14000
14019
  "data-tip": t("printTip"),
14001
14020
  onClick: _cache[17] || (_cache[17] = ($event) => openRangeMenu($event, "print"))
14002
- }, toDisplayString(t("printBtn")), 9, _hoisted_15),
14003
- createElementVNode("button", {
14021
+ }, toDisplayString(t("printBtn")), 9, _hoisted_15)) : createCommentVNode("", true),
14022
+ _ctx.showCsv ? (openBlock(), createElementBlock("button", {
14023
+ key: 1,
14004
14024
  class: "rj-btn rj-btn-export rj-export-btn",
14005
14025
  "data-tip": t("csvTip"),
14006
14026
  onClick: _cache[18] || (_cache[18] = ($event) => openRangeMenu($event, "csv"))
14007
- }, " CSV ", 8, _hoisted_16),
14008
- createElementVNode("button", {
14027
+ }, " CSV ", 8, _hoisted_16)) : createCommentVNode("", true),
14028
+ _ctx.showPdf ? (openBlock(), createElementBlock("button", {
14029
+ key: 2,
14009
14030
  class: "rj-btn rj-btn-export rj-export-btn",
14010
14031
  "data-tip": t("pdfTip"),
14011
14032
  onClick: _cache[19] || (_cache[19] = ($event) => openRangeMenu($event, "pdf"))
14012
- }, " PDF ", 8, _hoisted_17),
14013
- createElementVNode("button", {
14033
+ }, " PDF ", 8, _hoisted_17)) : createCommentVNode("", true),
14034
+ _ctx.showExcel ? (openBlock(), createElementBlock("button", {
14035
+ key: 3,
14014
14036
  class: "rj-btn rj-btn-export rj-export-btn",
14015
14037
  "data-tip": t("excelTip"),
14016
14038
  onClick: _cache[20] || (_cache[20] = ($event) => openRangeMenu($event, "excel"))
14017
- }, " Excel ", 8, _hoisted_18)
14039
+ }, " Excel ", 8, _hoisted_18)) : createCommentVNode("", true)
14018
14040
  ])) : createCommentVNode("", true),
14019
14041
  _ctx.stateKey ? (openBlock(), createElementBlock("button", {
14020
14042
  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[]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rj-grid",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "零第三方依赖的自研 Vue3 虚拟表格:虚拟滚动 / 冻结列 / 行拖拽 / 分组透视 / 公式 / SSRM / 主题 i18n / 自然语言查询",
5
5
  "type": "module",
6
6
  "license": "MIT",