ooxml-excel-editor 1.15.1 → 1.16.1
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/CHANGELOG.md +227 -0
- package/README.md +24 -12
- package/dist/chunks/index-CKf3q6pu.js +17081 -0
- package/dist/chunks/index-xD5935xY.js +20670 -0
- package/dist/chunks/{index.es-N4HpaZ5b.js → index.es-BZzDc3NP.js} +1 -1
- package/dist/chunks/{index.es-qiHokwgz.js → index.es-CaZDvCo1.js} +1 -1
- package/dist/chunks/{jspdf.es.min-DXY0IlZa.js → jspdf.es.min-BMIqrKfr.js} +2 -2
- package/dist/chunks/{jspdf.es.min-Dg8neDb_.js → jspdf.es.min-DJ2NWx1E.js} +2 -2
- package/dist/chunks/toolbar-builtins-IAxeMFn3.js +1653 -0
- package/dist/components/ExcelViewer.vue.d.ts +142 -3
- package/dist/components/RibbonBar.vue.d.ts +17 -0
- package/dist/components/ViewerToolbar.vue.d.ts +14 -0
- package/dist/components/ribbon-persist.d.ts +8 -0
- package/dist/components/ribbon-types.d.ts +143 -0
- package/dist/components/settings-dialog-host.d.ts +57 -0
- package/dist/components/toolbar-builtins.d.ts +13 -0
- package/dist/components/toolbar-types.d.ts +19 -2
- package/dist/core/edit/autofill.d.ts +13 -0
- package/dist/core/edit/clipboard-snapshot.d.ts +5 -0
- package/dist/core/edit/commands.d.ts +10 -1
- package/dist/core/edit/edit-controller.d.ts +69 -3
- package/dist/core/edit/flash-fill.d.ts +54 -0
- package/dist/core/edit/image-compress.d.ts +11 -0
- package/dist/core/edit/image-dpi.d.ts +19 -0
- package/dist/core/edit/permissions.d.ts +7 -0
- package/dist/core/export/exporter.d.ts +8 -0
- package/dist/core/export/ws-background.d.ts +3 -0
- package/dist/core/export/ws-protection.d.ts +3 -0
- package/dist/core/formula/builtin/catalog.d.ts +37 -0
- package/dist/core/formula/refs.d.ts +6 -0
- package/dist/core/index.d.ts +6 -1
- package/dist/core/layout/grid-metrics.d.ts +1 -1
- package/dist/core/model/dispimg.d.ts +9 -0
- package/dist/core/model/freeze-header.d.ts +2 -0
- package/dist/core/model/size-estimate.d.ts +7 -0
- package/dist/core/model/snapshot.d.ts +1 -0
- package/dist/core/model/types.d.ts +110 -0
- package/dist/core/parser/cell-image-parser.d.ts +1 -2
- package/dist/core/parser/exceljs-adapter.d.ts +5 -1
- package/dist/core/plugin.d.ts +207 -1
- package/dist/core/render/canvas-renderer.d.ts +24 -8
- package/dist/core/viewer/allow-edit-ranges-dialog-host.d.ts +25 -0
- package/dist/core/viewer/background-dialog-host.d.ts +20 -0
- package/dist/core/viewer/controller.d.ts +327 -25
- package/dist/core/viewer/data-validation-dialog-host.d.ts +30 -0
- package/dist/core/viewer/filter-engine.d.ts +57 -0
- package/dist/core/viewer/filter-popup-host.d.ts +36 -0
- package/dist/core/viewer/find-engine.d.ts +31 -0
- package/dist/core/viewer/find-replace-dialog-host.d.ts +69 -0
- package/dist/core/viewer/image-oversize-dialog-host.d.ts +18 -0
- package/dist/core/viewer/insert-function-dialog-host.d.ts +30 -0
- package/dist/core/viewer/overlay-manager.d.ts +14 -0
- package/dist/core/viewer/page-setup-dialog-host.d.ts +17 -0
- package/dist/core/viewer/paste-config-host.d.ts +7 -0
- package/dist/core/viewer/print-preview-dialog-host.d.ts +29 -0
- package/dist/core/viewer/protect-sheet-dialog-host.d.ts +20 -0
- package/dist/core/viewer/protect-workbook-dialog-host.d.ts +23 -0
- package/dist/core/viewer/remove-duplicates-dialog-host.d.ts +19 -0
- package/dist/core/viewer/series-dialog-host.d.ts +14 -0
- package/dist/core/viewer/shortcuts.d.ts +18 -0
- package/dist/core/viewer/sort-dialog-host.d.ts +24 -0
- package/dist/core/viewer/task-pane-host.d.ts +34 -0
- package/dist/core/viewer/text-to-columns-dialog-host.d.ts +14 -0
- package/dist/core.js +83 -73
- package/dist/demo-shared/demo-ribbon.d.ts +6 -0
- package/dist/index.js +2033 -1647
- package/dist/react/ExcelViewer.d.ts +40 -0
- package/dist/react.js +1444 -948
- package/dist/style.css +1 -1
- package/dist/vue2.css +1 -1
- package/dist/vue2.js +83 -73
- package/package.json +1 -1
- package/dist/chunks/index-C0COOyM4.js +0 -13481
- package/dist/chunks/index-D63is84s.js +0 -15055
- package/dist/chunks/toolbar-icons-BvcaTxkJ.js +0 -148
- package/dist/components/FilterPopup.vue.d.ts +0 -21
- package/dist/components/FindBar.vue.d.ts +0 -35
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,233 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 与 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [1.16.1] - 2026-07-16
|
|
6
|
+
|
|
7
|
+
> **查找和替换 WPS 1:1 深化** —— 内联查找栏升级为 **WPS 式「查找和替换」对话框**(框架无关 core DOM,三壳共用一份;模态脱浮动、标题栏可拖动、不遮网格)。查找/替换 双分页签 + 完整选项(范围 工作表/工作簿、搜索 按行/按列、查找范围 值/公式/批注、区分大小写、单元格匹配、通配符)+「全部查找」结果表。
|
|
8
|
+
|
|
9
|
+
### 新增 — 查找引擎(框架无关)
|
|
10
|
+
|
|
11
|
+
- **`core/viewer/find-engine.ts`**(纯模型层,不依赖渲染器):`buildMatcher`(区分大小写 / 单元格匹配 / 通配符 `* ? ~`)、`cellMatchText`(按 lookIn 取 值=显示文本 / 公式=`=公式` / 批注=comment 文本)、`searchWorkbook`(scope=sheet/workbook、direction=row/col 排序,产出**跨表命中** `FindHit[]` 带 sheet 下标 + 显示值)。因文本全走模型层 `getCellText` / `cell.formula` / `cell.comment`,**对非活动表也能搜**(工作簿范围)。11 单测。
|
|
12
|
+
- 渲染器 `searchCells` 匹配逻辑移出 → 只保留高亮绘制(`setFind` + `drawFind`);控制器把**当前活动表**命中喂进渲染器,`drawFind` 只高亮当前表。
|
|
13
|
+
|
|
14
|
+
### 新增 — 控制器 / 状态
|
|
15
|
+
|
|
16
|
+
- `FindState` 扩展:`scope`('sheet'|'workbook')、`direction`('row'|'col')、`lookIn`('value'|'formula'|'comment')、`wildcard`。新 setter `setFindScope/Direction/LookIn/Wildcard`。
|
|
17
|
+
- 跨表命中导航:`findNext/findPrev` 跨表(切表用 `onActiveSheetChange` 请求壳切表 + `pendingFindFocus` 在 rebuild 重跑查找后落位)。
|
|
18
|
+
- `getFindResults()`(全部查找结果:sheet 下标 + 表名 + 行列 + 显示值)、`gotoFindHit(gi)`(结果表点击跳转)。
|
|
19
|
+
- **替换**作用于**活动表**(跨表命令栈批处理不支持;工作簿范围下也只替当前表),`lookIn=comment` 仅查不替;`replaceInString` 支持通配符/单元格匹配整格替换 + 子串正则替换。
|
|
20
|
+
|
|
21
|
+
### 新增 — WPS 查找和替换对话框(core DOM,三壳共用)
|
|
22
|
+
|
|
23
|
+
- **`core/viewer/find-replace-dialog-host.ts`**:双分页签「查找 / 替换」(替换页仅 editable);查找内容 / 替换为 输入;选项区(范围 / 搜索 / 查找范围 三下拉 + 区分大小写 / 单元格匹配 / 通配符 三复选);计数「第 x 个,共 N 个 / 无结果」;按钮 全部查找 / 查找上一个 / 查找下一个 / 替换 / 全部替换;**「全部查找」结果表**(工作表 · 单元格 · 值,点行跳转,替换后自动刷新)。`position:fixed` 浮动、**标题栏可拖动**、Esc 关闭(焦点在对话框内时)。
|
|
24
|
+
- 控制器 `openFindReplaceDialog(tab?)` / `closeFindReplaceDialog()` / `isFindDialogOpen()`;`ViewerApi` + 三壳句柄(Vue3 `defineExpose` viewerApi / React `ExcelViewerHandle` / Vue2)全绑定。
|
|
25
|
+
- **三壳接入**:移除各自内联查找栏(Vue3 `FindBar.vue` 删除、React 内联 `rxl-findbar` / Vue2 `ov-findbar` 移除 + 死 CSS 清理);工具栏「查找」按钮 + Ctrl/⌘+F 改开这一 core 对话框。**一次落地即三壳视觉/交互 1:1。**
|
|
26
|
+
- 暂缓(未做):**格式查找/替换**(按字体/填充/边框匹配);批注**替换**(仅查);跨表**替换**。
|
|
27
|
+
|
|
28
|
+
### 测试
|
|
29
|
+
|
|
30
|
+
- 单测 `find-engine.test.ts`(11):matcher 各选项 / 通配符 / cellMatchText / searchWorkbook 范围+方向+显示值。
|
|
31
|
+
- e2e 重写:`find.e2e.ts`(计数 / 无结果 / 上下导航 / 全部查找结果表点击跳转 / 通配符 / Esc + 三壳打开同一 core 对话框)、`find-replace.e2e.ts`(三壳:替换页 全部替换 + undo)。选择器改 `.ooxml-finddlg`。
|
|
32
|
+
|
|
33
|
+
## [1.16.0] - 2026-07-10
|
|
34
|
+
|
|
35
|
+
> **WPS 式分组 Ribbon(工具板块)** —— 1:1 复刻 WPS 排版:选项卡 → 命名子组 → 大/小按钮混排 + 组名在底 + 组间竖分隔 + 小按钮严格两行。含**统一设置面板** + **板块布局持久化** + **一大批新工具**(把 core 已有能力接成按钮 + 少量新 core 能力)。三壳(Vue3/React/Vue2)1:1。
|
|
36
|
+
>
|
|
37
|
+
> **★ 默认即启用**:既不传 `ribbon` 也不传 `:toolbar` 数组时,**默认渲染内置 WPS 式 Ribbon `DEFAULT_RIBBON`(7 选项卡)**+ 齿轮设置面板。**想切回旧扁平工具栏 → 显式传 `:toolbar` 数组**(如 `['find','filter','sort']`);`ribbon={false}` / `:ribbon="false"` 完全不渲染。〔注:此前迭代中一度以"不传 = 旧扁平栏、零回归"为默认;本版按需求改为**默认开启 Ribbon**,旧栏改为显式 opt-in。〕
|
|
38
|
+
|
|
39
|
+
### 新增 — 数据选项卡(现有接线 + 数据有效性authoring + 删除重复 + 文本分列)
|
|
40
|
+
|
|
41
|
+
- **接现有**:数据透视表 / 排序 / 筛选 / 全部显示(clear-filter)/ 填充 按 WPS 版式摆进数据 tab;新 `reapply`(重新应用,重跑当前筛选,`controller.reapplyFilters`)。DEFAULT_RIBBON 数据 tab = 数据透视表组 + 排序和筛选组 + 数据工具组。
|
|
42
|
+
- **数据有效性 authoring**(此前只解析+拦截,无创建 UI):框架无关 [`data-validation-dialog-host.ts`](./src/core/viewer/data-validation-dialog-host.ts)(类型 列表/整数/小数/日期/时间/文本长度/自定义 + 运算符 + 操作数/列表来源/自定义公式 + 允许空值 + 出错警告 停止/警告/信息 + 错误信息)。`data-validation`(有效性)/ `dropdown-list`(下拉列表,直达 list)工具。命令 `edit.setDataValidation(rule|null, range)`(cloneWorkbook 单次撤销,同步 `dataValidations`/`dataValidationLists`);controller `openDataValidationDialog`/`setDataValidation` + `ViewerApi`(三壳)。**导出回写**:新 `writeDataValidationsTo`(rebuild + overlay 两路径,ExcelJS `dataValidations.add(range, dv)`;单测锁 list+whole 往返)。
|
|
43
|
+
- **删除重复项**:框架无关 [`remove-duplicates-dialog-host.ts`](./src/core/viewer/remove-duplicates-dialog-host.ts)(按哪些列判重 + 数据含标题)。`edit.removeDuplicates(range, keyCols, hasHeader)`:按 keyCols 组合判重、保留首次、降序删重复行,cloneWorkbook 单次撤销。工具 `remove-duplicates`。
|
|
44
|
+
- **文本分列**:框架无关 [`text-to-columns-dialog-host.ts`](./src/core/viewer/text-to-columns-dialog-host.ts)(制表/逗号/分号/空格/自定义)。`edit.textToColumns(range, delimiter)`:单列每格按分隔符拆分写入本行右侧列(向右覆盖,同 Excel 默认),cloneWorkbook 单次撤销。工具 `text-to-columns`。
|
|
45
|
+
- 仍未做(我们没有,已置灰/省略):分类汇总·创建组/分级显示(outline)·数据对比·合并计算·获取数据/全部刷新/股票·智能分析/数据校对/AI 分析/查找录入/数据查询。措辞对外中性。
|
|
46
|
+
|
|
47
|
+
### 新增 — 条件筛选(数字/文本/日期 + 前十项 + 高于/低于平均值)+ 统一筛选浮层(三壳共用 core DOM)
|
|
48
|
+
|
|
49
|
+
- **条件筛选引擎**(框架无关 [`core/viewer/filter-engine.ts`](./src/core/viewer/filter-engine.ts)):`FilterCondition` 支持 **数字**(=/≠/>/≥/</≤/介于/不介于)、**文本**(包含/不包含/开头是/结尾是/等于/不等于)、**日期**(早于/晚于/介于)、**前十项**(最大/最小 × 项/百分比 × n)、**高于平均值** / **低于平均值**。`inferFilterColType(values)` 按多数(≥60%)推断列类型;`resolveDynamicCondition` 把前十项/平均值折算成具体数值门槛(基于该列全部数值);`matchesCondition(cond, cell)` 单格判定。8 单测。
|
|
50
|
+
- **筛选态双路**:控制器 `filterState: Map<col, {values}|{cond}>`,`applyFilters()` 每列按"按值集合"或"按条件"两路各自命中;条件筛选与按值筛选**互斥**(同列后设覆盖先设)。
|
|
51
|
+
- **★ 统一筛选浮层 [`filter-popup-host.ts`](./src/core/viewer/filter-popup-host.ts)(框架无关 core DOM,三壳共用)**:**WPS 式分页签**布局 —— 顶部 `[按内容]`(值复选,带搜索 + 全选)/ `[数字·文本·日期 筛选]`(条件表单)+ `清除筛选`;上方 升序/降序。值列表**长值横向滚动、不截断**(对齐 WPS)。定位用视口坐标 `position:fixed`(挂 `document.body`,DPR 安全,由 `renderArea.getBoundingClientRect()` 换算)。**此件取代原来 Vue3 `FilterPopup.vue` / React 内联 `FilterPopup` 各自实现** —— 消除三壳漂移、**补齐此前完全缺失的 Vue 2 筛选浮层**,一次落地即三壳视觉/交互 1:1。
|
|
52
|
+
- **编程 API**:`toggleAutoFilter()` / `hasFilters()` / `clearAllFilters()` / `openFilterConditionDialog(col)` / `applyFilterCondition(col, cond|null)`,`ViewerApi` + 三壳句柄(Vue3 `defineExpose` viewerApi / React `ExcelViewerHandle` / Vue2)全绑定。
|
|
53
|
+
- 移除公共导出 `FilterPopupState` 类型(浮层内聚进 core,壳不再渲染它)。**按颜色筛选**暂缓(未做)。
|
|
54
|
+
- **修复「搜索框缩小值列表 → 直接确定 → 却没筛」**:对齐 WPS/Excel —— 搜索激活时 `确定` 应用 `搜索结果 ∩ 已勾选`(而非残留的全量勾选,此前"全选"默认态使 checked=全部 → 等于不筛)。「(全选)」在搜索时改标「(全选搜索结果)」,仅作用于可见匹配项。无搜索时 `shown=全部值`,行为与旧版等价(零回归)。`filter.e2e.ts` 加"搜索+确定"回归用例。
|
|
55
|
+
- e2e:[`filter-condition.e2e.ts`](./e2e/filter-condition.e2e.ts) 三壳(Vue3/React/Vue2)各跑数字>门槛 / 前十项 / 高于平均 / 清除还原;`filter.e2e.ts` / `sort.e2e.ts` 选择器改 `.ooxml-filterpop`。
|
|
56
|
+
|
|
57
|
+
### 新增 — 审阅选项卡(批注导航/显示 + 单元格锁定 + 工作表/工作簿保护 + 允许编辑区域)
|
|
58
|
+
|
|
59
|
+
- **批注组**:`comment-new`(新建批注,活动格开批注编辑器)/ `comment-delete`(删除批注,活动格无批注时禁用)/ `comment-prev` `comment-next`(上一条/下一条,按行列顺序循环移选区并滚动可见)/ `comment-show`(显示,常驻画所有批注**小黄框** + 引线,渲染器 `setShowAllComments` + `drawAllComments`,跨切表保留)。controller `hasAnyComment`/`activeHasComment`/`deleteActiveComment`/`gotoComment(±1)`/`toggleShowAllComments`/`isShowAllComments`。
|
|
60
|
+
- **锁定单元格**(`cell-lock`):模型 `CellStyle.protection?.{locked,hidden}`(**缺省锁定** = Excel/WPS 默认;仅"保护工作表"时生效)。`edit.setCellsLocked(range, locked)`(**不走 isEditable 闸门** —— 表已保护时锁定格自身只读、否则永远解不开,只要求 editing;cloneWorkbook 单次撤销)。工具 active 态 = 选区是否全锁(`isSelectionLocked`),点击 `toggleCellLock`。**导出/解析往返**:ExcelJS `cell.protection` + parser `extractStyle` 读回(只在显式解锁/隐藏时存,省 styleId 数)。
|
|
61
|
+
- **保护工作表**(`protect-sheet`):模型 `SheetModel.sheetProtection?.{protected,password,allow,raw}`。框架无关 [`protect-sheet-dialog-host.ts`](./src/core/viewer/protect-sheet-dialog-host.ts)(密码两次 + WPS 11 项"允许此工作表的所有用户进行"勾选;已保护 → 撤销模式输密码解除)。**拦截**:`resolveEditable` 加第 ⑤ 优先级 —— 保护开 + 该格锁定 + 不在允许编辑区 → 只读(文档级,独立于 app 配置,所有编辑/粘贴/右键统一走此闸门)。**导出/解析往返**:`writeSheetProtectionTo`(原件 raw 透传保 hash;app 新建按 password+allow 重建,有密码走 ExcelJS `ws.protect()` 生成 SHA-512)+ parser `parseSheetProtection`。
|
|
62
|
+
- **允许编辑区域**(`allow-edit-ranges`):模型 `SheetModel.protectedRanges?: ProtectedRange[]`。框架无关 [`allow-edit-ranges-dialog-host.ts`](./src/core/viewer/allow-edit-ranges-dialog-host.ts)(列出/新建[名称+引用+可选密码]/删除)。`edit.setProtectedRanges`;保护时区域内锁定格放行(见拦截逻辑)。
|
|
63
|
+
- **保护工作簿**(`protect-workbook`):模型 `WorkbookModel.protection?.{lockStructure,lockWindows,password}`。框架无关 [`protect-workbook-dialog-host.ts`](./src/core/viewer/protect-workbook-dialog-host.ts)。**导出**:ExcelJS 不建模 `<workbookProtection>` → zip 层回注 [`ws-protection.ts`](./src/core/export/ws-protection.ts)(按 schema 顺序插进 `xl/workbook.xml`)。〔限制:工作簿保护 ExcelJS 不解析,故打开已有保护工作簿时读不回;密码 hash 本版不写(lockStructure 已让 Excel/WPS 显示"结构已保护")。〕
|
|
64
|
+
- **共享工作簿**(`share-workbook`):该特性已被 Excel/WPS **官方弃用**,占位工具点击提示不实现(`shareWorkbookNotice`),不做假实现。
|
|
65
|
+
- undo/redo 支持:`clone.ts` 显式处理 `sheetProtection`/`protectedRanges`(缺键也列出,让 Object.assign 在"已保护→未保护"undo 时清键)+ `WorkbookModel.protection`(cloneWorkbook + restoreWorkbookInto)。
|
|
66
|
+
- `DEFAULT_RIBBON` 审阅 tab = 批注组 + 保护组。以上方法全暴露 `ViewerApi`,三壳(Vue3/React/Vue2)绑定齐,`buildStyleTool` 中性工具三壳零改自动一致。〔仅 1:1 复刻截图所示项;拼写检查/繁简转换/修订等 WPS 审阅项未做。〕
|
|
67
|
+
|
|
68
|
+
### 新增 — 修改标记 * + 导出下拉扩充 + 设置面板「快捷键」页
|
|
69
|
+
|
|
70
|
+
- **未保存修改指示(WPS `*`)**:标题栏文件名前显示红色 `*` 表示文档已被修改(哪怕一点);**彻底撤回(undo 到栈空)后视为未改动**,`*` 消失。core 脏状态语义改为**由真值现算**:`isDirty()=undoStack 非空 ∨ 跨会话脏`(undo 栈按切表/换簿清空,故切表前累积的编辑用 `priorSessionDirty` 单独记,换表后仍显示 `*`);`undo`/`redo`/`resetToOriginal`/`resetDirtyBaseline` 各自 `syncDirty()` 翻转时发 `dirty-change`。三壳标题栏(ViewerToolbar / rxl / ov)据 `dirty-change` 反映 `*`(1:1)。
|
|
71
|
+
- **导出下拉扩充**:标题栏「导出 ▾」+ 工具栏 `export` 菜单顶部新增**导出为 Excel (.xlsx) / CSV (.csv) / JSON (.json)**(= demo 原有的 ↓XLSX/↓CSV/↓JSON,`downloadXlsx`/`downloadCsv`/`downloadJson`),再是原有 PNG / PDF(位图)/ PDF(矢量)/ 打印 / 导出设置。三壳(标题栏 + 工具栏两处菜单)一致。
|
|
72
|
+
- **设置面板「快捷键」页**:齿轮设置面板新增第 4 个 tab「快捷键」,按分组(导航/选择/编辑/剪贴板/图片)列出**当前实际支持的全部键盘快捷键**(`<kbd>` 渲染,标「编辑模式」项需 editable)。单一真相源 [`core/viewer/shortcuts.ts`](./src/core/viewer/shortcuts.ts) `KEYBOARD_SHORTCUTS`(从 `/core` 导出),与 `onKeyDown` 实际绑定一一对应。
|
|
73
|
+
|
|
74
|
+
### 新增 — 视图选项卡(编辑栏 / 行号列标 / 网格线 / 任务窗格)
|
|
75
|
+
|
|
76
|
+
- **编辑栏**(`view-formula-bar`):切换公式栏显隐(`toggleFormulaBar`/`isFormulaBarVisible`)。壳级 UI —— 控制器持布尔 + 通知壳重渲,三壳公式栏 `v-if`/条件渲染读 `isFormulaBarVisible()`(Vue3 computed / React JSX / Vue2 render fn,均随 selVersion 重算)。
|
|
77
|
+
- **行号列标**(`view-headers`):切换行/列表头显隐(`toggleHeaders`/`areHeadersVisible`)。`GridMetrics` 加 `showHeaders` 参数 —— 隐藏时 `rowHeaderWidth`/`colHeaderHeight` 归 0,网格从 0,0 起;**命中/布局单一源于 metrics**(DPR 红线),故零头偏移下点击/选区/叠加层自动正确。渲染器 `setShowHeaders` 重建几何 + 刷内容尺寸 + 重定位叠加层。
|
|
78
|
+
- **网格线**(`view-gridlines`):切换网格线显隐(`toggleGridLines`/`isGridLinesVisible`,直接改当前表 `showGridLines`,渲染器已respect;非撤销,同 WPS 视图开关,`.xlsx` 亦反映)。
|
|
79
|
+
- **任务窗格**(`view-taskpane`):右停靠面板(框架无关 [`task-pane-host.ts`](./src/core/viewer/task-pane-host.ts),同透视字段面板停靠风格)—— 工作表列表(高亮当前)+ 当前选区统计(区域/计数/求和/平均)+ 三个显示开关镜像 checkbox;随选区/滚动 `refresh()`(JSON 签名去重,不每帧重排)。`toggleTaskPane`/`isTaskPaneOpen`。
|
|
80
|
+
- WPS 复选样式:四项均 small + `showLabel` + `active` 反映开/关状态。`DEFAULT_RIBBON` 视图 tab = 显示组(四开关)+ 窗口(冻结)+ 显示比例(缩放)+ 其它(模板)。全暴露 `ViewerApi`,三壳绑定齐;网格线/行号列标/任务窗格走中性 `buildStyleTool` 三壳零改,编辑栏另加三壳 3 处条件渲染。〔仅 1:1 复刻截图 4 项;冻结/拆分/并排/新建窗口等其它 WPS 视图项未做。〕
|
|
81
|
+
|
|
82
|
+
### 新增 — 公式选项卡(函数库 + 计算组 + 插入函数对话框)
|
|
83
|
+
|
|
84
|
+
- **函数库(只列我们支持的 75 个内置函数,按分类)**:`fn-insert`(插入函数 fx)/ `autosum`(求和)/ `fn-common`(常用)/ `fn-logical`(逻辑)/ `fn-text`(文本)/ `fn-datetime`(时间)/ `fn-lookup`(查找与引用)/ `fn-math`(数学和三角)/ `fn-more`(其他函数:统计+信息)。财务类无函数故省略。分类元数据 [`formula/builtin/catalog.ts`](./src/core/formula/builtin/catalog.ts)(`FUNCTION_CATEGORIES` + `parseSignature` + `functionMeta`;单测锁"无孤儿函数",全部 75 个函数都归了类)。
|
|
85
|
+
- **插入函数对话框**(框架无关 [`insert-function-dialog-host.ts`](./src/core/viewer/insert-function-dialog-host.ts),三壳共用):左搜索 + 分类 + 函数列表(名 + 签名),右按签名**逐参数输入** + **实时结果预览**(复用内置 `parseFormula`/`evalAst` 无副作用求值,读模型已提交值)+ 拼出的公式;确定 → 插入活动格。`controller.openInsertFunctionDialog(name?)` + `ViewerApi`(三壳)。分类下拉点函数直接定位其参数态。
|
|
86
|
+
- **计算组**:`calc-options`(计算选项 自动/手动)、`recalc-workbook`(重算工作簿)、`recalc-sheet`(计算工作表)。edit-controller 加 `calcMode`(**手动模式:编辑不级联重算**,待手动)+ `recalcAll(onlySheet?)`(引擎重灌整簿 → 写回全部公式格值,发 cell-change);`controller.recalcAll`/`recalcActiveSheet`/`get/setCalcMode` + `ViewerApi`。**auto 路径逐字不变,零回归**。
|
|
87
|
+
- **顺带修**:`inferCell` 存的用户/程序化公式带前导 `=`(与解析层"不带 ="不一致),`CellSnapshot.editText` 容错处理(formula 已带 `=` 则不再补),消除公式栏/编辑器/插入函数出现 `==` 的隐患。
|
|
88
|
+
- `DEFAULT_RIBBON` 公式选项卡重排为 函数库组 + 计算组(去掉原「格式」组;格式工具在开始 tab 仍在)。〔措辞对外已中性化,详见「商标与兼容性声明」;函数分类仅列本项目自研引擎支持的函数。〕
|
|
89
|
+
|
|
90
|
+
### 新增 — WPS 式分组 Ribbon(工具板块)
|
|
91
|
+
|
|
92
|
+
- **概念**:板块(选项卡)= 一等实体(可自定义名字、随时新建、重新划分);板块内再分**命名子组**(剪贴板/字体/对齐/数字/样式/单元格/编辑…);工具是可被任意组引用的实体。**默认启用内置 `DEFAULT_RIBBON`**;传自定义 **`ribbon: RibbonConfig`**(三壳同名)覆盖布局;传 `:toolbar` 数组切回旧扁平栏。新增中性 `isRibbonMode(ribbon, toolbar)` 判定当前是否 Ribbon 模式(决定齿轮 + 持久化,含默认 Ribbon);`resolveRibbon` 输出加 `ribbonMode` 字段;`DEFAULT_RIBBON` 从 [`ribbon-types.ts`](./src/components/ribbon-types.ts) 导出,三 demo 的 `DEMO_RIBBON` 即从此再导出(单一数据源不漂移)。
|
|
93
|
+
- **WPS 排版 1:1**:面板加高;工具按 `size`(large 图标在上文字在下 / small 小图标)混排;small 按钮用 `'/'`(rowbreak)**严格分两行**(第一行组合框+A⁺A⁻、第二行图标,跟 WPS 一致,非自动折行);字体名/字号是显当前值的组合框;组名居中在底、组间竖分隔;下拉菜单**透出面板**(修了 `overflow-x:auto` 把 `overflow-y` 也算成 auto 导致菜单被裁的坑)。
|
|
94
|
+
- **中性架构**:类型 + 注册表 + 解析/分段器全在中性 TS [`ribbon-types.ts`](./src/components/ribbon-types.ts)(三壳共用):`ToolSection`(含 `groups: ToolGroup[]`)/ `ToolMeta`(含 `size`)/ `TOOL_CATALOG` / 纯函数 `resolveRibbon` / `sectionGroups` / `segmentGroupItems`。行为收敛到中性 [`toolbar-builtins.ts`](./src/components/toolbar-builtins.ts) `buildStyleTool`,三壳 `builtinTool` 委托。Vue3 [`RibbonBar.vue`](./src/components/RibbonBar.vue) 参考实现,React `rxl-rb-*` / Vue2 `renderRibbonPanel()` 1:1 复刻。
|
|
95
|
+
- **切回旧栏**:显式传 `:toolbar` 数组 → 单个不可编辑板块 `__legacy`,单板块**不渲染选项卡/面板**、像素级等同旧扁平工具栏(`ActionToolbar` 仍在,守护 e2e 兜底);`ribbonMode=false` 时不显示齿轮、不并入持久化态。
|
|
96
|
+
|
|
97
|
+
### 新增 — 统一设置面板 + 板块布局持久化
|
|
98
|
+
|
|
99
|
+
- **设置面板**(中性 plain DOM [`settings-dialog-host.ts`](./src/components/settings-dialog-host.ts)):齿轮打开。① 工具板块管理 —— 板块 CRUD + ↑↓ 重排;**分组板块**按组管理(新建/改名/删组、组内勾选分配工具 + ↑↓ 重排);扁平板块直接勾选分配。② 视图 —— 运行时缩放。
|
|
100
|
+
- **持久化**([`ribbon-persist.ts`](./src/components/ribbon-persist.ts),localStorage,SSR 安全):改动即存,`mergeUserState` 并入(丢未知 id、回注锁定种子板块,分组板块按组过滤)。新 prop **`ribbonPersistKey`**(缺省内置 key;自定义字符串隔离多实例;`null` 关闭)。"重置板块布局"清存储回默认。
|
|
101
|
+
|
|
102
|
+
### 新增 — 工具集(WPS「开始/插入/公式/数据/审阅/视图」全套)
|
|
103
|
+
|
|
104
|
+
- **接线类(走已有 `setStyle` 等,需 `editable`)**:加粗/斜体/下划线/删除线、字体名/字号/增减字号(A⁺A⁻)、框线、填充色/字体颜色(调色板)、清除格式、左中右+上中下对齐、合并、增减缩进、数字格式/货币/百分比/千分位/增减小数位、复制/剪切/粘贴、行和列(插入删除)、批注。
|
|
105
|
+
- **新 core 能力**:**填充**(WPS 式:向下/右/**上/左** 四向;源是**公式**→自动改相对引用 `=A1`→`=A2`[`offsetFormulaRefs`];**序列对话框** 等差/等比/日期[日/工作日/月/年]/步长/终止值[`generateSeries`+`series-dialog-host`];**格式选项** 值+格式/仅值/仅格式;单次撤销[新 `fillCells` 批命令])、**表格样式**(表头强调+隔行底纹+边框,**单次撤销** —— 新加 `setStyleRegions` 批量样式命令,cloneWorkbook 快照)、**单元格样式**(8 预设画廊)、**转换**(文本↔数值)、**自动求和**(=SUM)。全部**入命令栈可撤销**;新方法同时暴露到 `ViewerApi`(三壳绑定)。
|
|
106
|
+
|
|
107
|
+
### 新增 — 冻结下拉 WPS 1:1(6 项动态标签 + 悬停高亮预览)
|
|
108
|
+
|
|
109
|
+
- **WPS 式 6 项 + 动态标签**(随活动格变):`冻结至第N行X列`(至活动格,行+列)/ `冻结至第N行`(**只冻行**到活动格)/ `冻结至第X列`(**只冻列**到活动格)/ `冻结表头`(智能识别)/ `冻结首行` / `冻结首列`,已冻结时追加 `取消冻结`。`controller.freezePanes` 加 `activeRow`/`activeCol`/`header` 模式(原 active/firstRow/firstCol/none 不变);标签在中性 [`toolbar-builtins.ts`](./src/components/toolbar-builtins.ts) 用 `getActiveCell()` + `colIndexToLetters` 现算(活动格 A1 时"至活动格/只冻行/只冻列"三项灰)。
|
|
110
|
+
- **冻结表头智能识别**(纯函数 [`model/freeze-header.ts`](./src/core/model/freeze-header.ts) `detectHeaderFreezeRows`,可单测):从顶扫,第一行「所有表列都填满」的行 = 表头,连上方标题行一起冻;**合并区覆盖格不计入填充**(整宽合并标题行不会被误判为满行)。样例(标题+表头)→ 冻前 2 行。
|
|
111
|
+
- **★ 悬停高亮预览**(WPS「一层灰 + 边框加重」):悬停任一冻结项 → canvas 高亮**将冻结的区域**(顶部 N 行 + 左侧 M 列灰底 `rgba(96,105,115,.16)` + 分割线加重 `#3c4149`),直观看清冻结范围;移出 / 应用 / 网格交互即清。`ResolvedToolbarItem` 加 `onHover`/`onHoverEnd`,三壳菜单(ToolbarMenu.vue / React / Vue2)`mouseenter`/`mouseleave` 接入;renderer `setFreezePreview` + `drawFreezePreview`(仅实时视图画,导出件不画);controller `previewFreezeMode`/`clearFreezePreview`(`onMouseDown` 兜底清)。
|
|
112
|
+
|
|
113
|
+
### 新增 — 页面选项卡 WPS 1:1(批 A:独立下拉拆分)
|
|
114
|
+
|
|
115
|
+
- **把「页面设置」大对话框拆成 WPS 式独立下拉**(底层能力早已具备,本批纯 UI 接线,零新增 core / 零导出改动):新增 5 个中性工具(全在 [`toolbar-builtins.ts`](./src/components/toolbar-builtins.ts),三壳 + 三 demo 自动 1:1)——
|
|
116
|
+
- `page-margins`(**页边距 ▾**:普通/窄/宽预设 + 自定义…,勾选反映当前;预设值对齐 Excel/WPS mm)
|
|
117
|
+
- `page-orientation`(**纸张方向 ▾**:纵向/横向,勾选反映当前)
|
|
118
|
+
- `paper-size`(**纸张大小 ▾**:A4/A3/Letter,勾选反映当前)
|
|
119
|
+
- `print-scale`(**打印缩放 ▾**:无缩放 100% / 整表打印在一页(fitToPage)/ 自定义…)
|
|
120
|
+
- `print-titles`(**打印标题**:开页面设置对话框到标题项)
|
|
121
|
+
- 全部走已有 `getPageSetup()` + `setPageSetup(merge)`(单次撤销、导出往返不变);`page-setup`(合并对话框)保留可用。
|
|
122
|
+
- **`DEFAULT_RIBBON` 页面选项卡重排成 WPS 版式**:页面设置组(页边距/方向/纸张/缩放 大按钮 + 打印区域/打印标题/页面设置 小按钮)· 分页组(分页符)· 背景组(**背景图片**,原「背景水印」按钮改名对齐 WPS,对话框功能不变)· 美化组(表格样式)· 输出组(导出)。
|
|
123
|
+
- 仍未做(批 C,已在难度评估中列出):页眉页脚 · 分页预览/显示分页符 · 文档主题。
|
|
124
|
+
|
|
125
|
+
### 新增 — 页面选项卡 WPS 1:1(批 B:打印选项 + 打印预览)
|
|
126
|
+
|
|
127
|
+
- **打印网格线 / 打印行号列标**(WPS 复选式)——新增 `PageSetupModel.printGridLines` / `printHeadings`;工具 `print-gridlines` / `print-headings`(带文字标签的小按钮切换,active 反映当前);`parsePageSetup` 解析 OOXML `<printOptions gridLines/headings>`(往返)、`writePageSetupTo` 回写 `ws.pageSetup.showGridLines`/`showRowColHeaders`(rebuild + overlay 两路径),`pageSetupDefaults` 把网格线喂进我方 PDF/打印底图(行号列标暂不画进底图,仅 .xlsx 往返 + 默认透传)。**小按钮显示文字**:`ResolvedToolbarItem` 加 `showLabel`,三壳(Vue3/React/Vue2)小按钮渲染 `(items || showLabel) && label` 才显字。
|
|
128
|
+
- **打印预览**(WPS「打印预览」)——纯只读可用(不 gate editable):`WorkbookExporter.buildPrintPages()` 复用 `buildSheetImage` + `sliceToPages`(与实际打印同一合成/分页管线)返回每页 canvas;框架无关 [`print-preview-dialog-host.ts`](./src/core/viewer/print-preview-dialog-host.ts) 全屏浮层展示页图 + 上/下页 + 页码 + 打印(走 `print(同 opts)`)+ 关闭(Esc / ← → 翻页);controller `openPrintPreview()` + `ViewerApi`(三壳绑定)。
|
|
129
|
+
- **页面选项卡补齐**:`DEFAULT_RIBBON` 页面 tab 头部加「打印」组(打印预览)+「打印选项」组(打印网格线 / 打印行号列标),更贴 WPS 版式。
|
|
130
|
+
|
|
131
|
+
### 新增 — 页面设置(页面选项卡·底层)
|
|
132
|
+
|
|
133
|
+
- **工具**(需 `editable`):`page-setup`(打开对话框:方向/纸张/缩放/页边距 mm/打印区域/打印标题)、`print-area`(设为选区 / 取消)、`page-breaks`(活动行列插入删除分页符 / 全部清除)。
|
|
134
|
+
- **框架无关对话框** [`page-setup-dialog-host.ts`](./src/core/viewer/page-setup-dialog-host.ts)(三壳共用,同 number-format 模式)。
|
|
135
|
+
- **命令 + 撤销**:新 `set-page-config` 命令(替换式,`pageSetup`/`pageBreaks` 各自单次撤销,前态含 `undefined` 也能还原);edit-controller `setPageConfig`;controller `setPageSetup`/`setPageBreaks`/`setPrintAreaFromSelection`/`togglePageBreakAt`/`clearPageBreaks`/`openPageSetupDialog`/`getPageSetup`,全暴露到 `ViewerApi`。
|
|
136
|
+
- **导出 .xlsx 往返**:新 `writePageSetupTo(ws, sheet)` 在 `xlsx-writer` **rebuild + overlay 两路径**都回写 `ws.pageSetup`(orientation/paperSize/scale/fitToPage/margins mm→inch/printArea/printTitlesRow/Column)+ 行分页符;导出后重解析 orientation/纸张/printArea/printTitleRows 存活(单测锁)。
|
|
137
|
+
|
|
138
|
+
### 新增 — 背景 / 水印
|
|
139
|
+
|
|
140
|
+
- **背景图片**(WPS「背景」):`background` 工具打开对话框选图片 → 平铺画在网格后(canvas-renderer `drawBackgroundImage`,复用内嵌图缓存加载器)。`SheetModel.background` + controller `setBackground`/`getBackground` + `ViewerApi`。**导出 .xlsx**:ExcelJS 无背景 API,故新 [`ws-background.ts`](./src/core/export/ws-background.ts) 在 zip 层注入 `xl/media` + `xl/worksheets/_rels` image 关系 + sheet `<picture r:id>` + Content_Types(同 wps-cellimages 模式;单测锁 media + `<picture>` 存在)。
|
|
141
|
+
- **文字水印**(WPS「水印」):文字/字号/透明度/颜色/角度,canvas `drawWatermark` 半透明旋转平铺画在网格上。`SheetModel.watermark` + `setWatermark`。**仅屏幕显示,不导出 .xlsx**(Excel 无原生单元格水印)。
|
|
142
|
+
- 二者共用框架无关 [`background-dialog-host.ts`](./src/core/viewer/background-dialog-host.ts) + `set-page-config` 命令(扩 `background`/`watermark` 键,各自单次撤销)。
|
|
143
|
+
|
|
144
|
+
### 修复
|
|
145
|
+
|
|
146
|
+
- **Vue 3 defineProps Boolean 转型坑**:`ribbon?: RibbonConfig | false` / `ribbonPersistKey?: string | false` 里的 `false` 会让 Vue 3 把该 prop 当 Boolean prop,**缺省时误转 `false`**(致真实消费方不传 `ribbon` 时整条工具栏被隐藏)。改:`ribbon?: RibbonConfig`(隐藏整条用 `toolbar:false`)、持久化关闭标记 `false`→`null`。三壳统一。
|
|
147
|
+
- **Ribbon 下拉被裁**:分组面板 `overflow-x:auto` 会让 `overflow-y` 也算 `auto`,下拉菜单被面板裁掉/内部滚动。改 `overflow:visible`。
|
|
148
|
+
- **背景图挂错表(多表 + 重排过 sheet)**:[`ws-background.ts`](./src/core/export/ws-background.ts) 原按 `sheetN.xml` 文件编号 positional 定位,当源件在编辑器里重排过 sheet(显示顺序 ≠ 文件编号)时会把背景挂到错误的表。改为按 `workbook.xml` `<sheets>` 顺序 + `workbook.xml.rels`(rId→Target)解析(同 pivot 恢复的按名/rels 映射思路),解析失败回退 positional。加重排回归单测(显示顺序反于文件编号时背景挂到正确表)。
|
|
149
|
+
|
|
150
|
+
### 待续(本版未做)
|
|
151
|
+
|
|
152
|
+
- **工作表**(增删/重命名 sheet):需新一层"sheet 变更命令"(模型 mutation + 命令栈 + SheetTabs),独立排。
|
|
153
|
+
- 视觉细节微调(颜色/间距/图标)按需迭代。
|
|
154
|
+
|
|
155
|
+
### 新增 — 简陋工具深化到 WPS 1:1(接线之后的"做深")
|
|
156
|
+
|
|
157
|
+
> 前述工具先把 core 能力**接成按钮**;本轮把其中"简化子集"的几个做到跟 WPS 对齐。全部纯增量、默认零回归、三壳共用(走中性 `toolbar-builtins` + controller,壳仅补 `ViewerApi` 绑定)。
|
|
158
|
+
|
|
159
|
+
- **单元格样式画廊**:8 预设 → **5 组 30+ 预设画廊**(好差适中 / 数据和模型[计算·检查·解释性·警告·链接·输入·注释·输出] / 标题[标题·标题1–4·汇总] / 主题[强调1–6] / 数字格式[货币·货币0·百分比·千位·千位0]),下拉带组名分隔。
|
|
160
|
+
- **表格样式画廊**:3 色 → **3 深浅(浅色/中等深浅/深色)× 7 色(蓝绿橙红紫青灰)= 21 预设**,每项带色块;`applyTableStyle(preset)` 参数放宽为 `<颜色>-<深浅>` 并从基色程序化算表头/隔行/边框(向白混合 / 压暗),兼容旧值 `green`/`blue`/`plain`。
|
|
161
|
+
- **选择性粘贴菜单**:`paste` 变分栏按钮(点=默认;▾ = 粘贴(全部) / 仅值 / 值和格式(合并式) / 粘贴行为…),复用已有 `PasteBehavior` 预设 + `openPasteConfigDialog`。
|
|
162
|
+
- **双下划线**:`Font` 加可选 `underlineStyle?: 'single' | 'double'`(向后兼容,不动既有 boolean 默认);`underline` 工具变分栏按钮(单/双/无);renderer 双线绘制;exceljs **读**(`'double'`/`'doubleAccounting'`→double)+ **写**(`.xlsx` `underline: 'double'`)往返;新 `setSelectionUnderline(none/single/double)`(三壳 `ViewerApi`)。
|
|
163
|
+
- **快速填充 Ctrl+E(Flash Fill)**:新框架无关启发式引擎 [`edit/flash-fill.ts`](./src/core/edit/flash-fill.ts)(零依赖,`synthesizeFlashFill`/`applyFlashProgram`/`inferFlashFill`,core 出口暴露)——从目标列样例推断左侧源列变换(拼接带分隔符 / 分词取段[含 fromEnd 取末段] / 域名账号提取 / 定长子串兜底),填其余空行(单次撤销)。controller `flashFill()`(Ctrl+E 键位 + `flash-fill` 工具 + `ViewerApi` 三壳);诚实边界:不做大小写/格式/条件/数值运算。
|
|
164
|
+
- **WPS「图片」插入工具**:新 `image` 工具(插入 tab)= WPS 图片下拉 1:1 —— 顶部**浮动式/嵌入到单元格**单选(`get/setImageInsertMode`)+ **本地图片(P)** + **批量插图(B)**(依次错开)+ 禁用「手机图片/拍照」。core 新 `insertImageBlob(blob, 'float'|'cell', at?)` + `openImagePicker(mode, {multiple})`(框架无关 `<input type=file>`,浮动图建 dataURL src);三壳 `ViewerApi` 绑定。原 `image-tools`(浮动⇄内嵌 DISPIMG 互转)保留,两者同在插入组。
|
|
165
|
+
|
|
166
|
+
### 变更 — 默认开启 Ribbon + 设置面板补全 + 齿轮更醒目
|
|
167
|
+
|
|
168
|
+
- **默认即 Ribbon**(见本版顶部说明):`resolveRibbon` 默认分支改走 `DEFAULT_RIBBON`;三 demo `ribbonMode` 默认 `true`(与库默认一致),demo 一进来即 WPS Ribbon。
|
|
169
|
+
- **设置面板加「常规」tab**:原「视图」tab → **「常规」**,新增 **编辑模式**开关 + **内嵌图贴合**(cellImageFit:拉伸铺满/等比留白/等比裁剪)+ 保留缩放。切换即 `onRuntimeChange({editable/cellImageFit})` → 组件运行时覆盖(`editableOverride`/`cellImageFitOverride`,`effectiveEditConfig` 用 `override ?? prop`;父组件更新 prop 时清覆盖让 prop 做主)+ 新 **`update:editable`/`update:cellImageFit`** 事件(Vue3/Vue2)/ **`onEditableChange`/`onCellImageFitChange`** 回调(React),三 demo `v-model`/回调双向同步。数据透视表/条件格式仍由 props 开启(面板内注明)。
|
|
170
|
+
- **设置面板加「粘贴」tab**:把原独立的「⚙ 粘贴配置」并进设置面板 —— 7 项粘贴行为下拉(字体样式/填充/行高/列宽/目标合并/源合并/图片)+ 覆盖式/仅值两预设,改即 `setPasteBehavior` 生效。字段与 `paste-config-host` 同源(导出 `PASTE_BEHAVIOR_FIELDS` 复用,UI 1:1)。三 demo 顶栏冗余的「⚙ 粘贴配置」按钮移除(编程 `openPasteConfigDialog()` API + 独立对话框仍保留)。
|
|
171
|
+
- **齿轮更醒目**:此前齿轮是无边框浅灰纯图标(易被忽略)→ 改为**带边框 + 「设置」文字**的胶囊按钮(三壳 `ribbon-gear`/`rxl-ribbon-gear`/`ov-ribbon-gear` 同款),hover 变绿。
|
|
172
|
+
|
|
173
|
+
### 新增 — 标题栏附文件信息(源文件大小 + 数据体积 + 堆增量)
|
|
174
|
+
|
|
175
|
+
- 标题栏文件名后附:**源文件 X**(sourceBuffer 字节,**精确** = .xlsx 磁盘大小;JSON 数据源无则不显示)· **数据约 Y**(新 core `estimateWorkbookBytes`:图片/媒体字节精确累加 + 单元格/字符串/样式按条目估算,**确定性、跨浏览器一致**;≠真实堆,实际堆约 1.5~3x,tooltip 注明)· **堆约 Z·粗略**(`readHeapUsed` 读 `performance.memory.usedJSHeapSize` 加载前后增量,**仅 Chromium、整页口径、被安全分桶粗化**,tooltip 注明)。
|
|
176
|
+
- 诚实边界:「仅 Excel 部分的真实堆占用」JS 层面**无法精准测量**(无按对象/模块的内存 API;`performance.memory` 整页+粗+仅 Chromium;`measureUserAgentSpecificMemory` 要跨源隔离且整页)。故提供"确定性数据体积估算"(准)+"整页堆增量"(粗)两个口径,各自标注。core 出 `estimateWorkbookBytes`/`formatBytes`/`readHeapUsed`;三壳标题栏 1:1。
|
|
177
|
+
|
|
178
|
+
### 新增 — WPS 浮动图(第一批:原图尺寸 + 右键菜单)
|
|
179
|
+
|
|
180
|
+
- **初始尺寸对齐 WPS(DPI 物理尺寸 + 上限)**:插入浮动图不再死写 120×90,也**不是**纯像素(纯像素对高像素照片会巨大)。而是按 WPS/Excel 的**物理尺寸** = 自然像素 ÷ **图片DPI** × 96 —— 新 [`image-dpi.ts`](./src/core/edit/image-dpi.ts) 解析 PNG `pHYs` / JPEG JFIF 密度拿真实 DPI(解不出兜底 96);再**上限拦截**(最长边 ≤ 600px,超了等比缩)防极端巨图。`computeInsertSize`/`parseImageDpi` 纯函数可单测。起点是活动格(光标所在格)。
|
|
181
|
+
- **浮动图右键菜单**(WPS 式):右键命中浮动图 → `图片嵌入到单元格` / `图片预览` / `重置为原图大小` / `删除图片`(复用 `convertImageToCellAuto` / `openImageLightbox` / 新 `resetImageSize` / `removeImage`);优先于单元格右键菜单。
|
|
182
|
+
|
|
183
|
+
### 新增 — WPS 浮动图(第二批:调整大小 8 控制点)
|
|
184
|
+
|
|
185
|
+
- **选中态 + 8 控制点拖拽 resize**:点浮动图 → 画绿色选框 + 8 控制点(nw/n/ne/e/se/s/sw/w,DOM 叠加层,`OverlayManager` 画);拖控制点改尺寸(角点改两维、边点改单维,锚对边,最小 12px 防翻转),入命令栈可撤销。选中态:Esc 取消、Delete/Backspace 删图、点空白/切表自动取消。图片增删/互转后清选中 + 重建 overlay(`afterImageStructChange`)。
|
|
186
|
+
- **DPR 安全**:控制点命中 `imageHandleAt` 走 `localXY`(CSS px)+ `metrics`,选框/控制点定位与 `<img>` 同象限、同 CSS 像素坐标系 —— 系统缩放/Retina 下点得准(遵守 [CLAUDE.md](./CLAUDE.md) 新钉的"屏幕分辨率安全"红线)。三壳零改动自动获得(壳只转发鼠标/键盘事件给 core)。
|
|
187
|
+
|
|
188
|
+
### 新增 — WPS 浮动图(第三批:超大图压缩提示)
|
|
189
|
+
|
|
190
|
+
- **超大图(>1MB)插入前弹框问是否压缩**:框架无关 [`image-oversize-dialog-host.ts`](./src/core/viewer/image-oversize-dialog-host.ts)(三壳共用)—— 压缩 / 保持原图 / 取消。选压缩走 [`image-compress.ts`](./src/core/edit/image-compress.ts):canvas 等比降采样到最长边 ≤ 1600px + JPEG 0.82 重编码(压完更大则退回原图);批量插入时一次决定应用到本批所有超大图。
|
|
191
|
+
|
|
192
|
+
### 新增 — WPS 浮动图(第四批:旋转)
|
|
193
|
+
|
|
194
|
+
- **旋转**:`ImageAnchor.rotation`(顺时针度,0~359)。渲染:浮动 `<img>` + 选框整组 CSS `transform:rotate`(围绕中心)。交互:选中态多一个**旋转柄**(顶边上方圆点),拖它自由旋转;右键菜单「图片旋转 → 向右/向左 90° / 重置」。命令栈可撤销。控制器 `setImageRotation`/`rotateImage`(+ `ViewerApi` 三壳)。
|
|
195
|
+
- **DPR + 旋转协同**:控制点/旋转柄命中把鼠标点**绕图心反旋转**回局部坐标系再判(`imageHandleAt`),resize 位移也反旋转 → 旋转后 8 控制点、旋转柄仍点得准、缩放手感自然(仍走 `localXY`+`metrics`,DPR 安全)。
|
|
196
|
+
- **导出回写暂缺(诚实说明)**:旋转是**屏幕 + 模型**完整;`.xlsx` 导出 `<a:xfrm rot>` 需 zip 层注入(ExcelJS 无此 API),为避免未充分验证的脆弱 XML 注入,**列为后续**,当前导出不含旋转角。
|
|
197
|
+
|
|
198
|
+
### 新增 — WPS 浮动图(第五批:裁剪)
|
|
199
|
+
|
|
200
|
+
- **裁剪**:`ImageAnchor.crop`(各边 0~1 隐藏比例,同 OOXML blipFill `srcRect`)。**渲染重构**:浮动图从裸 `<img>` 改成 `外层容器(overflow:hidden = ext 框)+ 里层 <img>`;裁剪时里层 img 放大到 `1/(1-l-r)` 宽 / `1/(1-t-b)` 高并左上偏移,让可见区填满容器(容器裁掉溢出)。旋转 transform 移到外层容器。
|
|
201
|
+
- **裁剪交互**:右键「图片裁剪 → 进入裁剪」进裁剪模式(拖 8 控制点=裁对应边,可见区至少留 10%),点空白 / Esc 确认退出;「重置裁剪」清除。命令栈可撤销(`cloneImageAnchor` 深拷 crop)。控制器 `setImageCrop`/`enterImageCrop`/`exitImageCrop`(+ `ViewerApi` 三壳)。
|
|
202
|
+
- **导出回写暂缺**:同旋转,`.xlsx` 的 `srcRect` 需 zip 层注入,列为后续;当前导出不含裁剪。OCR「提取文字」需外部 OCR 引擎(Tesseract.js/云),不内置。
|
|
203
|
+
|
|
204
|
+
### 修复 — 插入图片相关
|
|
205
|
+
|
|
206
|
+
- **浮动图插入后不显示**:`render()` 只 `overlays.position()`(重定位现有 `<img>`),不 `overlays.build()`(据 `sheet.images` 创建 `<img>`)→ 新插入的浮动图没有 DOM 元素、渲染不出来。`insertImageBlob`(float)/ `pasteImageBlob`(cell)插入后显式 `overlays.build()` + `render()` + 选中锚点格。(内嵌图画在 canvas 走 `getCellImageEl` 不受影响。)
|
|
207
|
+
- **冻结表里浮动图被"限死在小范围/拖不出去"**:两处叠加 ——(a)`setImageRect`(拖拽/移动)把锚点收敛成 `from={row:0,col:0}`+大偏移,`OverlayManager.quadrantOf` 又按 `from.row/col` 判象限 → 冻结表(如样例 xSplit=1/ySplit=2)下落 A1 的图被判进**极小的冻结角象限**(1列×2行)、被 `overflow:hidden` 裁死;(b)**拖拽只走 `position()` 不 `rebuild`**,而象限只在 `build()` 里定 → 拖出冻结区时 `<img>` 一直留在冻结角容器里出不来。修:① `quadrantOf` 改按图片**左上角实际落点**(`anchorRect`)相对冻结像素边界判象限;② **`position()` 每帧重判象限**,跨界(冻结↔正文)时把 `<img>` 迁到新象限容器再定位。现在冻结表里也能把浮动图从冻结角自由拖到正文区、全尺寸显示。无冻结不受影响。
|
|
208
|
+
- **图片下拉「嵌入到单元格」选不了**:模式单选点击后菜单立即关闭、选中态不刷新 → 像"没选上"。给 `ResolvedToolbarItem` 加 **`keepOpen`**(三壳 onPick respect:点了不关菜单),模式单选设 `keepOpen`;`setImageInsertMode` 触发 `onRenderTick` 让选中态即时更新。现可"选模式 → 点本地图片/批量插图"一气呵成。
|
|
209
|
+
- **浮动图拖进冻结区只剩左上角**:上一条只修了图片**左上角**落在冻结带时的判象限;但一幅**跨越冻结分割线**的浮动图(左上角进冻结带、其余在正文),`quadrantOf` 仍把它整幅判进极小的冻结象限(如 corner=1列×2行),被 `overflow:hidden` 裁成左上一小块;拖离才恢复。修:`quadrantOf` 改为**只有整幅图都落在冻结带内**才钉到冻结象限(`rect.top+height ≤ frozenHeight` / `rect.left+width ≤ frozenWidth`),跨界图归 `main` —— 由 `main` 象限在分割线处自然裁剪(等同 Excel/WPS 滚动到冻结线的行为),图整体可见。小图钉在冻结表头(整幅在带内)仍照常固定。
|
|
210
|
+
- **浮动图「嵌入到单元格」嵌错格(取中心而非图片处)**:`imageCellOf` 用图片**中心**反推目标格,图片跨格时会嵌到中心所在格,让人误以为"嵌到了鼠标处而非图片处"。改取图片**左上角**所在格(= 图片锚定/插入所在格),对齐 WPS 内嵌图语义。影响右键「图片嵌入到单元格」/「将此处浮动图嵌入单元格」及整列/整表批量嵌入的目标判定。
|
|
211
|
+
- **★ 双击「单元格内嵌图(DISPIMG)」格 → 图变文本框、图丢失**(编辑写入层语义缺陷,非外观):内嵌图本质是**公式格**(`formula:'=DISPIMG("id",1)'` + `dispImgId`),渲染器据 `dispImgId` 画图。双击 → 内联编辑器用**格式化结果**(DISPIMG 结果空)播种、提交走 `setCellValue/inferCell` **重建新 CellModel**,丢掉 `formula` + `dispImgId` → 下帧画文字,图永久消失。工具插入图与原始文件图**单元格形状完全一致**,所以两者同样丢(此前 `imageCellOf` 改动没引入不一致,只是让用户更易点到图片本格而暴露此 bug)。**取向(WPS 一致)= 内嵌图格当图片对象、不进文本编辑**:`beginEdit` 见 `cell.dispImgId` 直接返 false,一处挡住双击 / F2 / 键入即编辑三入口;替换/删除走右键菜单或 Delete。**加固**:`dispImgIdOf` 迁入 model 层([`model/dispimg.ts`](./src/core/model/dispimg.ts),parser re-export),`inferCell` 写入 `=DISPIMG(...)` 公式时**自动派生 `dispImgId`**(与 parser 回填同源、单一真相源),杜绝任何写入路径(公式栏/程序化)再把图写丢。
|
|
212
|
+
- **★ 双击图片应全屏看原图(WPS 一致),且只读/可编辑都生效**:内嵌图格改为"不进编辑"后只是拦住(无反馈),但 WPS 双击图片是**全屏展示原图**。改:`onDblClick` 命中图片(浮动图优先,其次单元格内嵌图 DISPIMG)→ `openImageLightbox` 全屏原图 + 下载,**只读 / 可编辑两种模式一致**,不进文本编辑。**同时移除**此前"只读模式单击即放大" —— 它与双击放大冲突(单击先开灯箱、双击第二下点到背景又把它关掉,产生竞态/闪烁)且非 WPS 行为;现单击仅选中,放大统一走**双击**(或右键「查看大图」),单一入口无竞态。
|
|
213
|
+
- **★ 双击公式格丢公式 / 双击格式化数值变文本**(与上同根因,用户要求一并修):内联编辑器一直用 `snapshot.text`(**格式化显示文本**)播种 —— 双击公式格显示的是结果、回车即把公式覆盖成字面值;双击 `¥5,999.00` 显示格式化串、回车被 `inferCell` 当**字符串**写回(数值+格式全变文本)。而公式栏走的是正确的 [`getCellEditString`](./src/core/viewer/controller.ts)(可编辑串)+ 空提交保护,内联编辑器从没采用。修:① `CellSnapshot` 加 **`editText`**(可编辑串:公式→`=…`、数值→原始数字串、布尔→TRUE/FALSE、其余→显示文本),`buildCellSnapshot` 计算;② 默认编辑器改用 `initialText ?? snapshot.editText ?? snapshot.text` 播种(`?? text` 兜底兼容);③ `getCellEditString` 改**复用** `snapshot.editText`(公式栏/内联编辑器同源,规则不再两处维护);④ `commitEdit` 加**空提交保护**(裸值 == 原 editText 则不入命令栈,免污染 undo,对齐 `commitActiveCellValue`)。现双击公式格显示 `=B3*C3`、双击货币格显示 `5999`,回车不改则公式/数值/格式都在。
|
|
214
|
+
|
|
215
|
+
### 测试 / 文档
|
|
216
|
+
|
|
217
|
+
- 单测 +59(`ribbon-types` 25 / `toolbar-builtins` 6 / `ribbon-persist` 8 / `page-setup` 6 含背景命令+zip 回注 / `fill-upgrade` 14 公式偏移+序列);**深化再 +19**(`toolbar-builtins` 画廊/粘贴/下划线/图片 +5 / `xlsx-writer` 双下划线往返 +1 / `flash-fill` 10 / `page-setup` 背景重排映射 +1 / `ribbon-types` 默认 Ribbon+isRibbonMode +2),共 **522** →(内嵌图/编辑写入层修复 +8;页面选项卡批 A `toolbar-builtins` WPS 页面下拉 +2;批 B `pagesetup` 打印选项 parse +1 / `xlsx-writer` printOptions 往返 +1;冻结 `freeze-header` 智能识别 +5;公式选项卡 `catalog` 分类/签名 +5;数据选项卡 `xlsx-writer` 数据有效性往返 +1;审阅选项卡 `protection` 权限+锁定+保护+undo 7 / `xlsx-writer` 单元格锁定+工作表保护+工作簿保护 zip 回注往返 +2;视图选项卡 `grid-metrics` 表头显隐 +2;修改标记 `edit-controller` 彻底撤回变净+跨会话脏 +2)**558 全过**(+ `size-estimate` 4 / `image-dpi` 7);e2e:[`ribbon.e2e.ts`](./e2e/ribbon.e2e.ts) 含 Ctrl+E 快速填充 / 默认即 Ribbon / 常规 tab 切编辑模式同步 / 粘贴 tab 配置 / 标题栏文件信息 / **WPS 浮动图全套**(插入·右键菜单·resize·压缩提示·旋转·裁剪·冻结拖出·冻结拖入不裁·**内嵌图格双击不进编辑**·**公式/数值格双击播种可编辑串**)·**页面选项卡 WPS 独立下拉**(方向/纸张/页边距/缩放直接生效)·**打印网格线/行号列标切换**·**打印预览浮层(只读可用)**·**冻结 WPS 6 项动态标签 + 悬停高亮预览**·**公式选项卡插入函数对话框(逐参+实时预览+插入)+ 计算选项手动/重算**·**数据选项卡数据有效性 authoring(下拉列表)+ 删除重复 + 文本分列**·**审阅选项卡新建批注/显示批注 toggle/保护工作表(锁定格变只读)/撤销保护·锁定单元格 toggle·保护工作簿**·**视图选项卡编辑栏/行号列标/网格线/任务窗格四开关**·**修改标记 `*`(编辑出现/彻底撤回消失)**·**导出下拉 xlsx/csv/json**·**设置面板快捷键页**,[`image-lightbox.e2e.ts`](./e2e/image-lightbox.e2e.ts) 加**双击图全屏(只读+可编辑两模式)**,全套 **228 e2e 全绿**。三壳 typecheck + build 全绿;**浮动图 + 审阅保护类 `ViewerApi` 方法三壳(Vue3/React/Vue2)绑定齐**。README / EXTENDING 同步。
|
|
218
|
+
|
|
219
|
+
## [1.15.2] - 2026-06-25
|
|
220
|
+
|
|
221
|
+
> 修筛选后复制仍复制整表 —— 对齐 Excel「只复制可见单元格」。纯增量,未筛选时行为字节级不变、零回归。
|
|
222
|
+
|
|
223
|
+
### 修复 — 筛选后复制只取可见行
|
|
224
|
+
|
|
225
|
+
- **现象**:自动筛选后 Ctrl+C / 右键复制,粘出来还是整张表(含被筛掉的行),和 Excel 不一致。
|
|
226
|
+
- **根因**:渲染靠 [grid-metrics](./src/core/layout/grid-metrics.ts) 把隐藏行**行高置 0** 跳过,而复制(`ViewerController.copySelection` / `copyMultiSelection`)是纯 `for (row = top..bottom)` 遍历数据模型、**无 `hidden` 判断** —— 两条路径对隐藏行处理不一致,被筛掉的行照抄进剪贴板。
|
|
227
|
+
- **修法**:复制的**三条产物(TSV / HTML / `data-ooxml-clip` 快照)一致跳过被筛掉的行**,仅在筛选激活时生效(复用 [`hasFilters()`](./src/core/viewer/controller.ts))。`serializeSnapshot` 新增可选 `rowVisible` 谓词:跳隐藏行并**压缩重排行号**(cells/merges/images/rowHeights),使内部粘贴还原的行连续、且保住 1:1 图片/格式保真;跨隐藏行的合并块丢弃、锚点落隐藏行的图片跳过。
|
|
228
|
+
- **边界**:未筛选时手动隐藏的行仍复制(对齐 Excel 默认);`rowVisible` 不传时 `serializeSnapshot` 行为完全不变。纯 core 修复,Vue 3 / React / Vue 2 三壳零改动自动获得。
|
|
229
|
+
- **状态栏统计同步修**:`selectionStats`([canvas-renderer.ts](./src/core/render/canvas-renderer.ts))筛选激活时(`filteredCols` 非空)也跳过隐藏行 —— 求和/计数/最值只算可见行,与 Excel 状态栏一致;单选 + Ctrl 多选(`getSelectionStats` 逐区累加)都覆盖。
|
|
230
|
+
- 追加单测:[`clipboard-snapshot.test.ts`](./src/core/edit/__tests__/clipboard-snapshot.test.ts) 4 测(跳过+压缩 / 不传谓词不变 / 合并丢弃 / 图片跳过)+ [`selection-stats-filter.test.ts`](./src/core/render/__tests__/selection-stats-filter.test.ts) 1 测(筛选只统计可见行);433 单测全过。
|
|
231
|
+
|
|
5
232
|
## [1.15.1] - 2026-06-25
|
|
6
233
|
|
|
7
234
|
> 修非 HTTPS / 内网 IP 部署下复制静默失败。纯增量,HTTPS / localhost 行为字节级不变、零回归。
|
package/README.md
CHANGED
|
@@ -47,18 +47,19 @@ const src = ref<File>() // 绑个 <input type="file" @change> 给它即可
|
|
|
47
47
|
- 🗓 **日期序列号**:含 Excel 1900 闰年 bug、1904 系统
|
|
48
48
|
- 🎨 **主题色 + tint**、indexed 调色板、合并单元格、边框(细/粗/虚/双线)、填充(纯色/图案/渐变)
|
|
49
49
|
- 🌈 **条件格式**:色阶 / 数据条 / 图标集 / cellIs / top10 渲染;开 `conditionalFormat` 后可**新建/编辑/删除全 6 类规则**(工具栏入口 + API,导出回写 .xlsx)
|
|
50
|
-
- 🖼 **图片 + 图表**(DrawingML → ECharts 近似还原)、**形状/文本框**、**迷你图**(sparklines)、**批注**、**数据验证**(列表型点格内箭头弹选可撤销;整数/小数/日期/文本长度等在编辑模式**拦截非法输入** +
|
|
50
|
+
- 🖼 **图片 + 图表**(DrawingML → ECharts 近似还原)、**形状/文本框**、**迷你图**(sparklines)、**批注**、**数据验证**(列表型点格内箭头弹选可撤销;整数/小数/日期/文本长度等在编辑模式**拦截非法输入** + 出错/输入提示)、**自动筛选**样式
|
|
51
51
|
- 📌 **WPS 单元格内嵌图(DISPIMG)**:识别并展示 WPS 私有的"嵌在格里的图"(普通工具会缺图);编辑模式下支持**一键浮动 ⇄ 嵌入互转**。见 [WPS 单元格内嵌图](#wps-单元格内嵌图dispimg)
|
|
52
|
-
- 🔍
|
|
52
|
+
- 🔍 **图片双击放大 + 下载原图**:网格里的图(内嵌图/浮动图)**双击**看全屏原图、下载原件 —— **只读 / 可编辑两种模式一致**(对齐 WPS「双击图看大图」),或右键「查看大图」。`imageLightbox` prop 控制(默认开),`openImageLightbox(src)` 命令式打开。〔1.16.0 起统一为**双击**触发;此前"只读模式单击即放大"与双击冲突且非 WPS 行为,已移除,单击仅选中。〕
|
|
53
53
|
- 📋 **从 Excel/WPS 富粘贴**:`Ctrl+V` 解析剪贴板 HTML → 还原字体/颜色/填充/边框/对齐/合并单元格,整块单次撤销。**Excel/WPS 把格式放在 `<style>` 块的 CSS 类里(`<td class="xl65">`),解析时会把类规则合并进每格** —— 不只读内联 `style=`。**`Ctrl+V` 走 `paste` 事件拿原始 HTML**;`navigator.clipboard.read()`(右键菜单粘贴用)会**净化**删掉 `<style>`/注释,所以右键粘贴从 WPS 拿的格式不如 `Ctrl+V` 全。图片走多通道:data-uri `<img>` / **WPS VML `o:gfxdata`**(区域复制的内嵌图藏在 VML 里,是个 zip,解出来落格)/ 单图 blob / 拖文件;**数字格式**(日期/货币)也从 `mso-number-format` 解析还原,不再变成裸序列号。**注**:Excel 某些版本只给 `file:///` 本地路径的 `<img>`(浏览器读不到)而不带 `o:gfxdata`,那种区域图仍救不回。
|
|
54
54
|
- 📋 **应用内 1:1 复制粘贴**:本组件自己 `Ctrl+C` 的内容会把**完整模型快照**嵌进剪贴板(`<table data-ooxml-clip>`),`Ctrl+V` 时识别并 1:1 还原 —— 数字不会退化成文本、边框/数字格式/合并/DISPIMG 图片/**行高**全保留;因为快照随剪贴板走,**Vue3/Vue2/React 三壳之间、跨标签页互相复制结果都一致**。粘到外部应用(Excel/WPS/Word)则读可见 `<table>`(近似)。**列宽以目标现有表头为准、不被源覆盖**(列宽整列共享,改了会动表头;同 Excel 默认粘贴)。
|
|
55
55
|
- 📝 **文本溢出**到相邻空格、**自动行高**
|
|
56
|
-
- 🖱 **交互**:单元格选区(合并感知)、拖选、公式栏、状态栏(计数/求和/均值/最值)、超链接可点、裁切文本悬停看全文、Ctrl+C 复制(**同应用内 1:1 保真**:含数字原始值/数字格式/边框/合并/图片/行高,跨 Vue3/Vue2/React 实例互相复制都一致;**列宽以目标表头为准不覆盖**;另带 TSV/HTML 供贴进 Excel/WPS)、**Ctrl+F
|
|
57
|
-
- 🖨 **导出 / 打印**:整表/选区/多表导出 **PNG/JPEG**、**PDF**(位图 + **矢量·文字可选可搜**两种)、**系统打印**(可另存 PDF);默认还原原生 `pageSetup`(
|
|
56
|
+
- 🖱 **交互**:单元格选区(合并感知)、拖选、公式栏、状态栏(计数/求和/均值/最值)、超链接可点、裁切文本悬停看全文、Ctrl+C 复制(**同应用内 1:1 保真**:含数字原始值/数字格式/边框/合并/图片/行高,跨 Vue3/Vue2/React 实例互相复制都一致;**列宽以目标表头为准不覆盖**;另带 TSV/HTML 供贴进 Excel/WPS)、**Ctrl+F 查找和替换**(WPS 式对话框,查找/替换 双分页签 + 范围 工作表/工作簿 + 搜索 按行/按列 + 查找范围 值/公式/批注 + 区分大小写/单元格匹配/通配符 + 全部查找结果表点击跳转;编辑模式带替换/全部替换;三壳共用同一 core 对话框)、**自动筛选**(点下拉真能筛,WPS 式分页签浮层:`[按内容]` 去重值多选 + 搜值 + 清除;`[条件筛选]` 数字/文本/日期条件 + 前十项 + 高于/低于平均值;三壳共用同一 core 浮层)、**自动填充柄**(编辑模式拖选区右下角填序列:等差/日期/星期月份/文本递增,见 [编辑](#编辑可选默认只读))、**快速填充 Ctrl+E**(编辑模式:目标列打 1~N 个样例 → 从左侧源列推断变换[拼接/分词取段/域名提取]填其余空行)、**不连续多选**(Ctrl/⌘ 点击行头/列头/格 加选不相邻区域,复制堆叠 + 状态栏跨区统计)
|
|
57
|
+
- 🖨 **导出 / 打印**:整表/选区/多表导出 **PNG/JPEG**、**PDF**(位图 + **矢量·文字可选可搜**两种)、**系统打印**(可另存 PDF)、**打印预览浮层**(`openPrintPreview()`,与实际打印同一分页管线、只读也可用);默认还原原生 `pageSetup`(纸张/方向/页边距/缩放/打印区域/**打印标题行列每页重复**/**打印网格线**/**打印行号列标**,`<printOptions>` 往返);宽表**横向跨页**(页矩阵);`beforeRenderPage` 注入页眉/页脚/水印、`configureDoc` 注册字体;内置「导出设置」对话框
|
|
58
58
|
- ⚡ **按需加载**(无图表文件不下载 echarts、不导出 PDF 不下载 jspdf)、**友好错误兜底**(损坏/加密/旧 .xls)、解析失败自动给出可读提示
|
|
59
59
|
|
|
60
60
|
- 📤 **数据读取 API**:不必自己再解析 —— `getCellText`/`getSheetData`/`sheetToJSON`/`getRangeData`(独立函数 + 组件 ref 方法),值/显示文本可选,合并/日期/数字格式都处理好
|
|
61
|
-
- ✏️ **编辑(可选,默认只读)**:开 `editable` 即可编辑 —— 单元格值 / 样式(粗体/对齐/填充)/ 列宽行高 / 浮动图片
|
|
61
|
+
- ✏️ **编辑(可选,默认只读)**:开 `editable` 即可编辑 —— 单元格值 / 样式(粗体/对齐/填充)/ 列宽行高 / 浮动图片 / 增删行列;**撤销重做**(Ctrl+Z/Y)、**前后完整快照事件**、**脏状态 + 一键还原原件**;可换**公式引擎**自动重算依赖格;可注入**自定义编辑器**(下拉/日期/图片选择器);**导出回 .xlsx / JSON / CSV**(所见即所得)。见 [编辑](#编辑可选默认只读)
|
|
62
|
+
- 🖼 **浮动图编辑**(编辑模式):**插入图片**(工具栏「图片」→ 浮动式/嵌入到单元格 + 本地图片/批量插图;起点在光标格;初始尺寸按图片 **DPI 物理尺寸**算 + 上限,不再纯像素;**超大图(>1MB)插入前提示压缩**)、**移动/调整大小**(点选出 8 控制点拖拽,旋转后控制点命中仍准)、**旋转**(选中态旋转柄自由旋转 / 右键 90°)、**裁剪**(右键进裁剪模式,拖控制点裁剪)、右键菜单(嵌入到单元格 / 预览 / 重置大小 / 删除)。均入命令栈可撤销;三壳一致(交互全在框架无关 core,壳只转发事件)。**注**:旋转/裁剪当前为屏幕+模型,`.xlsx` 导出回写(`xfrm rot`/`srcRect`)列为后续。
|
|
62
63
|
|
|
63
64
|
> 纯预览不需要公式引擎 —— .xlsx 缓存了公式结果,直接显示;仅开启**编辑 + 重算**时才用(可选 `hyperformula`)。详见 [EXCEL还原难点.md](./EXCEL还原难点.md)。
|
|
64
65
|
|
|
@@ -363,13 +364,15 @@ viewer.value.getRangeData(viewer.value.getSelection()) // 取"我选中的"区
|
|
|
363
364
|
| `formulaEngine` | `FormulaEngineFactory` | 自定义/自研公式引擎(默认 = 内置 MIT 引擎;可注入 `hyperFormulaEngineFactory` 或自研) |
|
|
364
365
|
| `pasteBehavior` | `Partial<PasteBehavior>` | 粘贴行为(默认 = 覆盖式 1:1)。逐项可配:`cellStyle`/`fill`(`overwrite`/`merge`/`skip`)·`rowHeight`(`source`/`keep`)·`colWidth`(`firstRowOnly`/`source`/`keep`)·`sourceMerges`(`apply`/`skip`)·`targetMerges`(`clear`/`keep`,默认清=修旧合并吞列)·`images`(`apply`/`skip`)。缺项回落默认。也可运行时 `viewer.setPasteBehavior(cfg)` / 右键「选择性粘贴」/ 工具栏「⚙ 粘贴配置」面板 |
|
|
365
366
|
| `readOnlyPrompt` | `'dialog' \| 'toast' \| 'none'` | 粘贴撞只读格的内置提醒(默认 `'dialog'`):`dialog` 弹窗**列出具体哪些格**只读 / `toast` 顶部气泡 / `none` 只发 `permission-denied` 事件。逐格精确(编辑模式下也可能有只读格) |
|
|
366
|
-
| `cellImageFit` | `'fill' \| 'contain' \| 'cover'` | WPS 单元格内嵌图贴合方式(默认 `
|
|
367
|
+
| `cellImageFit` | `'fill' \| 'contain' \| 'cover'` | WPS 单元格内嵌图贴合方式(默认 `fill` 拉伸铺满,与 WPS 渲染一致;`contain` 等比留白 / `cover` 等比裁切) |
|
|
367
368
|
| `imageLightbox` | `boolean` | 图片点击放大灯箱(默认 `true`;只读单击图放大、编辑右键「查看大图」) |
|
|
368
|
-
| `toolbar` | `false \| Array<string \| ToolbarItem>` |
|
|
369
|
+
| `toolbar` | `false \| Array<string \| ToolbarItem>` | **切回旧扁平工具栏用**(1.16.0 起默认是 Ribbon,见下)。传一个工具 id 数组 → 旧单条扁平栏(如 `['find','filter','sort']`);`false` 不渲染工具栏。内置 id 见 [操作工具栏](EXTENDING.md#操作工具栏可配置--可插件--响应式);可混入自定义项 |
|
|
370
|
+
| `ribbon` | `RibbonConfig` | **分组 Ribbon(工具板块,1.16.0)** —— 选项卡 → 命名子组 → 工具,采用主流电子表格软件常见的分组排版(大/小按钮混排、小按钮 `'/'` 强制两行、组名在底、组间竖分隔)。`{ sections: ToolSection[]; defaultSectionId? }`,`ToolSection = { id, name, editable, groups?: ToolGroup[] \| tools?: string[] }`,`ToolGroup = { id, name, tools: string[] }`(`tools` 里 `'/'`=换行、`'\|'`=竖分隔)。**★ 默认(既不传 `ribbon` 也不传 `:toolbar` 数组)= 内置分组 Ribbon `DEFAULT_RIBBON`(7 选项卡)** + 右侧齿轮设置面板(板块/组 CRUD + 勾选分配 + ↑↓ 重排,改动持久化);传自定义 `RibbonConfig` 覆盖默认布局。**想要旧扁平栏 → 显式传 `:toolbar` 数组**;`ribbon={false}`(React)/ `:ribbon="false"` 完全不渲染。工具 id 见 `TOOL_CATALOG`。三壳同名 |
|
|
371
|
+
| `ribbonPersistKey` | `string \| null` | Ribbon 板块布局持久化 key(localStorage,Ribbon 模式下生效 —— 含默认 Ribbon)。**缺省** = 用内置 key 存;传自定义字符串隔离多实例;传 **`null`** = 关闭持久化(设置面板改动仅当前会话)。⚠️ 关闭标记用 `null` 而非 `false`(避免 Vue 3 把含 `false` 的联合当 Boolean prop 误转) |
|
|
369
372
|
| `plugins` | `ExcelPlugin[]` | 插件数组(`definePlugin` 打包 theme/cellStyle/transformModel/events/overlay/toolbar/setup);见 [插件](EXTENDING.md#插件-defineplugin) |
|
|
370
373
|
| `openLinks` | `boolean` | 单击超链接是否自动打开(默认 `true`;`false` 只发 `@hyperlink` 事件,自己处理) |
|
|
371
374
|
|
|
372
|
-
> 编辑相关 props 详见下方 [编辑](#编辑可选默认只读) 章节;数据验证(开 `editable` 后**编辑时拦截非法输入** + 列表型下拉选值)无需额外 prop
|
|
375
|
+
> 编辑相关 props 详见下方 [编辑](#编辑可选默认只读) 章节;数据验证(开 `editable` 后**编辑时拦截非法输入** + 列表型下拉选值)无需额外 prop,解析到的规则自动生效。**1.16.0 起可创建/修改验证规则**(数据选项卡「有效性 / 下拉列表」→ 对话框:列表/整数/小数/日期/时间/文本长度/自定义 + 出错警告;`openDataValidationDialog()`/`setDataValidation()`,导出 `.xlsx` 往返)。同选项卡还有**删除重复项**(`openRemoveDuplicatesDialog()`)、**文本分列**(`openTextToColumnsDialog()`)、**重新应用筛选**、**条件筛选**(`toggleAutoFilter()` 开自动筛选;`openFilterConditionDialog(col)` 打开某列筛选浮层直达条件页;`applyFilterCondition(col, cond|null)` 程序化设/清列条件——`cond` 支持数字/文本/日期/前十项/高于·低于平均值;`hasFilters()`/`clearAllFilters()`)。**审阅选项卡(1.16.0)**:批注新建/删除/上一条/下一条/**显示批注常驻小黄框**(`gotoComment(±1)`/`toggleShowAllComments()`);**锁定单元格**(`toggleCellLock()`,`CellStyle.protection.locked` 缺省锁定,导出往返);**保护工作表**(`openProtectSheetDialog()`,开启后锁定格变只读、走统一可编辑闸门,密码 + 允许项,`.xlsx` 往返);**允许编辑区域**(`openAllowEditRangesDialog()`,保护时的可编辑例外);**保护工作簿**(`openProtectWorkbookDialog()`,结构锁定,zip 层回注 `<workbookProtection>`)。「共享工作簿」是官方已弃用特性,占位提示不实现。**视图选项卡(1.16.0)**:编辑栏(`toggleFormulaBar()`)、行号列标(`toggleHeaders()`,表头尺寸归 0)、网格线(`toggleGridLines()`)、任务窗格(`toggleTaskPane()`,右停靠面板:工作表列表 + 选区统计 + 显示开关)四个显示开关。**修改标记(1.16.0)**:标题栏文件名前显示红色 `*` 表示文档已被修改;**彻底撤回(undo 到栈空)后视为未改动**,`*` 消失(`isDirty()` + `dirty-change` 事件)。**导出下拉(1.16.0)**:标题栏「导出 ▾」新增导出为 **Excel(.xlsx)/ CSV / JSON**(+ 原有 PNG/PDF/打印)。**设置面板「快捷键」页(1.16.0)**:齿轮设置面板列出全部键盘快捷键(单一真相源 `KEYBOARD_SHORTCUTS`,从 `/core` 导出)。
|
|
373
376
|
|
|
374
377
|
| 事件 | 载荷 | 触发时机 |
|
|
375
378
|
|---|---|---|
|
|
@@ -418,7 +421,7 @@ viewer.value.getRangeData(viewer.value.getSelection()) // 取"我选中的"区
|
|
|
418
421
|
/>
|
|
419
422
|
```
|
|
420
423
|
|
|
421
|
-
开编辑后:**双击 / F2 / 直接打字**进格编辑(Enter 提交下移、Tab 右移、Esc 取消、Shift+Enter 插换行),**Ctrl+Z / Ctrl+Y** 撤销重做,拖列头/行头边界改宽高,拖浮动图片移动。只读格 /
|
|
424
|
+
开编辑后:**双击 / F2 / 直接打字**进格编辑(Enter 提交下移、Tab 右移、Esc 取消、Shift+Enter 插换行),**Ctrl+Z / Ctrl+Y** 撤销重做,拖列头/行头边界改宽高,拖浮动图片移动。只读格 / 区域不进编辑;**单元格内嵌图(DISPIMG)格视作图片内容,双击 = 全屏看原图(只读+可编辑一致),不进文本编辑**。普通格双击 / F2 播种为**可编辑串**(公式格显示 `=…`、带格式数值显示原始数字如 `5999` 而非 `¥5,999.00`),回车不改则公式/数值/格式原样保留(空提交不入撤销栈)。
|
|
422
425
|
|
|
423
426
|
**长文本编辑(WPS 风格, 1.2.1)**:默认编辑器是 `<textarea>`, 输入长文本自动**换行 + 向下浮起撑高**, 编辑期显示完整内容;提交后单元格行高保持原样(跟 WPS 一致, 不持久化撑高;如需永久保持多行, 单元格设 `wrapText=true`)。自定义编辑器可通过 `CellEditorReturn.getDesiredHeight(width)` 复用此撑高机制 + `ctx.reposition()` 主动触发重撑。
|
|
424
427
|
|
|
@@ -468,6 +471,7 @@ const myEditor: EditorResolver = (cell, pos) => {
|
|
|
468
471
|
不少 .xlsx 由 **WPS** 导出,其"嵌在单元格里的图"用了 WPS 私有存法(`xl/cellimages.xml` + 单元格 `=DISPIMG("id",1)` 公式),标准解析读不出来 → 普通工具打开会**缺图**。本组件:
|
|
469
472
|
|
|
470
473
|
- **自动识别并展示**:解析 `cellimages.xml` 登记表,把图**画进单元格内**(随行高列宽 / 滚动 / 裁剪 / 冻结 / 缩放),非浮动叠加。**贴合方式可配置** `cellImageFit`:`contain`(默认,等比缩放,**与 WPS 渲染一致**——WPS 打开导出文件时 DISPIMG 固定按 contain 显示)/ `fill`(拉伸铺满随格变形)/ `cover`(等比裁剪铺满)。`getCellImages()` 读登记表;`getCellSnapshot(row,col).cell.dispImgId` 看某格是否内嵌图。
|
|
474
|
+
- **内嵌图 = 受保护的图片内容,不进文本编辑**:内嵌图格**双击 = 全屏看原图**(对齐 WPS,只读+可编辑一致),**不会**变成文本框;`F2 / 键入`也不进编辑(否则会把图连同底层 `=DISPIMG(...)` 公式覆盖丢失,与 WPS「图片即单元格内容」不符)。要**替换/删除**用右键菜单(浮动化 / 删除)或选中后按 **Delete**。工具插入的内嵌图与原始文件里的内嵌图行为完全一致。
|
|
471
475
|
- **一键浮动 ⇄ 嵌入互转**(编辑模式):
|
|
472
476
|
- `convertImageToCellAuto(imgIdx)` —— **就近嵌入**:图压在哪个单元格上就嵌进哪格(几何反推,无需手指定目标格)。
|
|
473
477
|
- `convertAllImagesToCells(col?)` —— **整表/整列批量**就近嵌入(`col` 给定只嵌该列),一次进撤销栈(单次 Ctrl+Z 全撤),返回嵌入张数。
|
|
@@ -486,7 +490,7 @@ const myEditor: EditorResolver = (cell, pos) => {
|
|
|
486
490
|
|
|
487
491
|
### 数字格式 / 批注 / 查找替换(1.11.0)
|
|
488
492
|
|
|
489
|
-
-
|
|
493
|
+
- **查找和替换(1.16.1 WPS 1:1)**:`Ctrl+F` 打开 **WPS 式「查找和替换」对话框**(框架无关 core DOM,三壳共用;浮动可拖动、不遮网格)。查找/替换 双分页签(替换页需 editable)+ 选项区 **范围**(工作表/工作簿)、**搜索**(按行/按列)、**查找范围**(值/公式/批注)、**区分大小写 / 单元格匹配 / 通配符**(`* ? ~`);**全部查找**列出全部命中(工作表 · 单元格 · 值)点行跳转(工作簿范围跨表跳转);替换 / 全部替换(整体单次撤销,跳过只读格,作用于活动表)。程序化:`openFindReplaceDialog('find'|'replace')` / `closeFindReplaceDialog()` / `isFindDialogOpen()`。〔暂缓:格式查找、批注替换、跨表替换。〕
|
|
490
494
|
- **数字格式编辑器**:工具栏 `number-format` 入口打开对话框(框架无关 DOM,三壳共用)—— 分类(常规/数值/货币/百分比/日期/时间/文本/自定义)+ 选项(小数位数 / 千分位 / 负数红色 / 货币符号 / 日期时间预设)+ 实时预览 + 可直接编辑格式代码 → 确定即套到选区(单次撤销)。也可 `setSelectionNumberFormat(code)` / `openNumberFormatDialog()` 直调。
|
|
491
495
|
- **批注编辑**:右键单格「插入/编辑/删除批注」打开对话框(多行文本 + 确定/删除/取消);`getCellComment` / `setCellComment(row,col,text)`(空串删除)/ `openCommentEditor()` 直调,单次撤销;**导出 .xlsx 回写批注**(rebuild + overlay)。
|
|
492
496
|
|
|
@@ -508,6 +512,8 @@ const myEditor: EditorResolver = (cell, pos) => {
|
|
|
508
512
|
|
|
509
513
|
开 `:recalc` 后,编辑公式格或被公式引用的格 → 依赖格**自动级联重算**,每个变动都发 `cell-change`(`source: 'api'|'ui'|'undo'|'redo'`)。
|
|
510
514
|
|
|
515
|
+
**公式选项卡(1.16.0)**:分组 Ribbon 的「公式」选项卡按分类列出**内置引擎支持的函数**(逻辑/文本/时间/查找与引用/数学和三角/统计/信息;分类元数据 `FUNCTION_CATEGORIES`/`functionMeta` 从 `/core` 导出)。**插入函数对话框**(`openInsertFunctionDialog(name?)`):搜索 + 分类选函数 → 按签名逐参数填写 → **实时结果预览** → 插入活动格。**计算组**:`setCalcMode('auto'|'manual')`(手动模式编辑不级联,待手动)、`recalcAll()`(重算工作簿)、`recalcActiveSheet()`(重算当前表)。
|
|
516
|
+
|
|
511
517
|
**默认引擎(1.14.0 起)= 内置 MIT 引擎**:从零实现的解析 + 求值 + 依赖图 + 拓扑级联 + 循环检测,**零依赖、无 GPL**,覆盖日常 ~60 个常用函数(SUM/AVERAGE/IF/IFERROR/VLOOKUP/INDEX/MATCH/SUMIF/COUNTIF/ROUND/LEFT/MID/CONCAT/DATE/TODAY… 见 `FUNCTION_NAMES` 导出)。函数集比 HyperFormula 小,但日常足够。
|
|
512
518
|
|
|
513
519
|
需要更全覆盖:`:formula-engine="hyperFormulaEngineFactory"` 注入 **HyperFormula**(可选 peer `npm i hyperformula`,GPL-3.0/商业双授权,~395 函数),或注入自研引擎(实现 `FormulaEngine` 接口)。`isRecalcReady()` 查引擎是否就绪。**打开文件的显示值与引擎无关**(读原件缓存结果),引擎只在编辑后重算时介入。
|
|
@@ -521,7 +527,7 @@ const myEditor: EditorResolver = (cell, pos) => {
|
|
|
521
527
|
### v1 已知限制
|
|
522
528
|
|
|
523
529
|
- 增删行列**会自动重写公式引用**(`=A5` 上方插一行 → `=A6`,删被引用行 → `#REF!`,含跨表 `Sheet1!A5`)。
|
|
524
|
-
- 写回 .xlsx 默认从模型重建,丢 VBA
|
|
530
|
+
- 写回 .xlsx 默认从模型重建,丢 VBA/复杂 DrawingML 等(**工作表保护 + 单元格锁定自 1.16.0 起往返**;工作簿保护经 zip 回注,但 ExcelJS 不解析故读不回已有工作簿保护);需要更高保真可用 `exportXlsx({ fidelity: 'overlay' })` **重载原件叠加编辑**(见 [导出保真边界](EXTENDING.md#导出--打印))。
|
|
525
531
|
|
|
526
532
|
## 扩展 / 二开
|
|
527
533
|
|
|
@@ -538,7 +544,7 @@ const myEditor: EditorResolver = (cell, pos) => {
|
|
|
538
544
|
## 范围边界
|
|
539
545
|
|
|
540
546
|
- **编辑**已支持(默认只读;开 `editable`,见 [编辑](#编辑可选默认只读))。下列为暂不覆盖项:
|
|
541
|
-
- 增删行列**不自动重写公式引用**;写回 .xlsx 丢 VBA
|
|
547
|
+
- 增删行列**不自动重写公式引用**;写回 .xlsx 丢 VBA/复杂 DrawingML(工作表保护 + 单元格锁定 1.16.0 起往返)
|
|
542
548
|
- 透视表:已有透视表**数据按普通单元格显示**并显示只读字段按钮;`pivot-table` 入口可从当前选区选择生成位置,生成静态透视汇总表到当前表指定单元格或新建工作表,随后打开 WPS 风格右侧“数据透视表”字段面板。创建出的透视表**空白起步**(对齐 WPS/Excel:不自动猜字段),在右侧面板里选字段填充。面板支持搜索字段;**勾选字段列表的复选框** = 加入透视表(数值字段→值,其它→行),取消 = 移出;也可用 筛/列/行/Σ 按钮或拖拽把字段加入“筛选器 / 列 / 行 / 值”四区,并可拖到移除区删除字段。改动后即时重建结果:筛选器支持“全部 / 非空 / 多选(勾选要保留的具体值,WPS 风格)”,列区生成横向分组,行区生成纵向分组,值区可放多个字段且可切换“求和 / 计数 / 平均值 / 最大值 / 最小值”。**透视结果是“活”的**:① 编辑源数据区任意单元格(含撤销/重做)后,所有透视表自动按源区域重算;② 放两个及以上行字段时,外层分组带小计且可点行首 [−]/[+] 折叠/展开内层明细(单行字段为扁平结果,无折叠)。也可调用 `createPivotTable({ sourceRange, sourceSheetIndex, output, layout, showPanel })` 不经过页面直接创建;旧的 `createPivotTableFromSelection({ rowFieldIndex, valueFieldIndex, output })` 仍保留。创建出的 `PivotTableModel` 会保存 `source` 和 `layout` 元数据,供运行时重建与导出使用。失败时会提示原因。**整个透视表功能由 `pivotTable` 配置开启(默认关闭)**,关闭时入口/API/导出回注全部不生效、行为与历史版本一致。**导出 .xlsx 时回注真实 OOXML 透视表零件**(pivotCacheDefinition / pivotCacheRecords / pivotTableDefinition + 全套 rels,带 `refreshOnLoad`):Excel/WPS 打开导出件即识别为真透视表并按源区域重算原生布局;静态汇总结果仍在单元格里,不支持透视的查看器也能看。筛选器导出语义对齐 WPS:“= 具体值”写入页字段选中项(打开还原筛选状态),“多选/非空”映射为 `multipleItemSelectionAllowed` + 未选项隐藏(`item@h`),“全部”不写选中。原文件已有的透视表在 **overlay 导出模式**下从原件 zip 原样搬运整套零件(保持“打开→编辑→另存,透视表仍在”);rebuild 模式因结构可能被增删行列改动不搬运(退化为普通单元格)
|
|
543
549
|
- 条件格式编辑:解析时全 6 类规则(突出显示单元格 `cellIs` / 公式 `expression` / 色阶 `colorScale` / 数据条 `dataBar` / 图标集 `iconSet` / 项目选取 `top10`)都渲染;**开 `conditionalFormat`(还需 `editable`)后可新建/编辑/删除**。工具栏 `conditional-format` 入口打开**条件格式管理对话框**(框架无关 DOM,三壳共用一份,UI 天然 1:1):列出当前表所有规则(每条可「编辑」「删除」)+「新建规则」。新建时选规则类型,弹出对应编辑器 —— cellIs:运算符(大于/小于/介于/不介于/等于/不等于/大于等于/小于等于)+ 值(介于类两个值)+ 命中格式(填充色 / 字体色 / 加粗);expression:自定义公式 + 命中格式;colorScale:双色/三色 + 各色标取色;dataBar:条颜色 + 渐变开关;iconSet:7 种图标集(三色交通灯 / 三向箭头 / 三符号 / 三色旗 / 四等评级 / 五等评级 / 五象限)+ 反向;top10:前/后 + 个数 + 百分比开关 + 命中格式。**新建规则默认套到当前选区**;编辑保留原区域。所有改动**整体单次撤销**(`set-conditional` 命令替换整张规则集),改完即时重渲。也可不开对话框直接调 API:`getConditionalRules()` / `addConditionalRule(rule)`(返回新 id)/ `updateConditionalRule(id, patch)` / `removeConditionalRule(id)` / `setConditionalRules(rules)` / `openConditionalFormatDialog()`。**导出 .xlsx 回写条件格式**:`rebuild` 与 `overlay` 都回写(1.9.0 起 rebuild 不再丢条件格式);**从文件解析、未在 app 内编辑过的规则按原始 OOXML 原样回写**(保留色阶/数据条/图标集的 cfvo 阈值等不全建模字段,零退化),用户新建或编辑过的规则按模型重建(全 6 类)。整个功能由 `conditionalFormat` 配置开启(默认关闭),关闭时入口/API/导出回写全部不生效、行为与历史一致。当前限制:色阶/数据条/图标集的**阈值(cfvo)** 暂不在编辑器里微调(未编辑时靠原样回写保住,用户新建用默认阈值);文本包含等 OOXML 子类型用 `cellIs`/`expression` 表达。
|
|
544
550
|
- SmartArt;形状仅支持 rect/roundRect/ellipse + 文本(复杂自定义几何按矩形近似)
|
|
@@ -576,6 +582,12 @@ npm run build:demo # 构建 demo 站点
|
|
|
576
582
|
|
|
577
583
|
MIT
|
|
578
584
|
|
|
585
|
+
## 商标与兼容性声明
|
|
586
|
+
|
|
587
|
+
本项目是**独立的开源组件**,与 Microsoft、金山办公(WPS)等公司**无任何关联、赞助或背书**。所有代码、图标均为**自行从零实现**(clean-room),未复制任何第三方软件的源代码或美术资源。文中提及 "Excel""WPS""OOXML/DISPIMG" 等仅用于**描述文件格式兼容性与交互习惯的对齐**(为互操作目的),相关名称、商标归各自权利人所有。
|
|
588
|
+
|
|
589
|
+
*This is an independent open-source component, **not affiliated with, sponsored, or endorsed by** Microsoft or Kingsoft (WPS). All code and icons are original, clean-room implementations; no third-party source code or assets are copied. References to "Excel", "WPS", "OOXML/DISPIMG" are **descriptive** — for file-format interoperability and UI-convention parity only. All trademarks belong to their respective owners.*
|
|
590
|
+
|
|
579
591
|
---
|
|
580
592
|
|
|
581
593
|
<a name="english"></a>
|