dsh-data-cleaning-agent 0.8.23 → 0.9.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 +14 -0
- package/README.en.md +8 -3
- package/README.md +9 -4
- package/docs/COMPATIBILITY.md +24 -2
- package/docs/UI-V1.5.0-ADOPTION.md +43 -0
- package/install.sh +10 -2
- package/lib/better-sidebar-adapter.js +76 -0
- package/lib/client.js +309 -509
- package/lib/install-preflight.js +49 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.1] - 2026-09-10
|
|
8
|
+
|
|
9
|
+
- 新宿主 uiWorkspace 生命周期适配:新会话不再复用清洗空会话,普通草稿与菜单隔离。
|
|
10
|
+
- 修复纯本地清洗完成后结果下载被外部补全状态门禁阻断。
|
|
11
|
+
- 安装前只读组合预检,精确阻断已知双向不兼容;安装脚本须从完整包运行。
|
|
12
|
+
- 260 项检查通过;新组合真实隔离 XLSX 导入、映射、清洗、导出、预览与普通会话验证通过。真实 MCP/OCR 和四产品共存尚未验证。
|
|
13
|
+
|
|
14
|
+
## [0.9.0] - 2026-09-10
|
|
15
|
+
|
|
16
|
+
- 工作台迁移到 Better Sidebar Session 单例 Tab;移除自有固定抽屉、宽度拖拽、展开/关闭按钮和中央会话让位逻辑。
|
|
17
|
+
- 按 Session 隔离任务视图;关闭或折叠 Tab 不取消任务,五流程入口复用同一 Tab。
|
|
18
|
+
- 可选 Provider 生命周期探测,缺失时提示安装/升级,不回退到旧抽屉;需要 targetedOpen 和 stateSubscription。
|
|
19
|
+
- 完整 256 项测试及 10 组隔离 React/Chromium 回归通过;真实 DSH 四插件组合联调尚未完成,详见 docs/UI-V1.5.0-ADOPTION.md。
|
|
20
|
+
|
|
7
21
|
## [0.8.23] - 2026-09-09
|
|
8
22
|
|
|
9
23
|
- 工作台顶部仅保留产品标题和展开、关闭按钮,移除重复状态与技术标识。
|
package/README.en.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# dsh-data-cleaning-agent
|
|
2
2
|
|
|
3
|
+
> 0.9.1 upgrade: the workbench now uses a Session-singleton Better Sidebar Tab, requiring `targetedOpen` and `stateSubscription`. Missing providers show an install/upgrade message, not a private drawer. See the [adoption and validation record](docs/UI-V1.5.0-ADOPTION.md).
|
|
4
|
+
|
|
3
5
|
Data cleaning and data enrichment for CSV/XLSX/JSON enterprise lists in DeepSeek Harness, including spreadsheet cleaning, deduplication, profiling, optional Qichacha MCP and exports.
|
|
4
6
|
|
|
5
7
|
Install a pinned release using the command in the [Chinese quick start](README.md), review the preview or evidence before confirming, and keep the previous version and task-directory backup for rollback. Qichacha calls use the customer's authorized account.
|
|
@@ -8,7 +10,7 @@ Related agents: [数据清洗补全](https://github.com/duhu2000/dsh-data-cleani
|
|
|
8
10
|
|
|
9
11
|
> A data cleaning & completion agent plugin for DeepSeek Harness: local CSV/XLSX/JSON engine plus optional Qichacha (QCC) MCP enterprise-data enrichment. Initiated and maintained by the Qichacha (QCC) team.
|
|
10
12
|
>
|
|
11
|
-
> Current source version / 当前源码版本: **0.
|
|
13
|
+
> Current source version / 当前源码版本: **0.9.1** (stable release)
|
|
12
14
|
|
|
13
15
|
This release unifies spreadsheet previews, column mapping, and enrichment scope across the prompt wizard and workbench. Mapping statuses use color and text; mapped fields automatically enter the scope, with optional extra fields collapsed. Multiple confirmed output columns may share a non-identity field while preserving non-empty values. It fixes saved drafts resetting the scope to five defaults and detects stale Host versions. Preparing a draft does not query QCC; sending starts execution. Fully restart DSH after upgrading. Existing download artifacts are not rewritten.
|
|
14
16
|
|
|
@@ -70,10 +72,13 @@ temporary files. The local server uploads the explicitly submitted file to the Q
|
|
|
70
72
|
Both use the current customer's own QCC account and quota. Without the local connector,
|
|
71
73
|
image intake fails closed with actionable guidance; text and spreadsheet paths remain available.
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
Check the complete DSH `0.1.2-rc.1` + Better Sidebar `0.18.1` combination first. Context is optional; an existing `0.36.0` installation must be upgraded to `0.48.0`. Preflight does not upgrade the global host or prove business acceptance.
|
|
76
|
+
|
|
77
|
+
Run from a full checkout or unpacked npm package with the actual `dsh` CLI (streamed shell installation is no longer supported):
|
|
74
78
|
|
|
75
79
|
```bash
|
|
76
|
-
|
|
80
|
+
node lib/install-preflight.js "$DSH_HOME/profiles/web"
|
|
81
|
+
bash install.sh
|
|
77
82
|
```
|
|
78
83
|
|
|
79
84
|
Or let an agent install it for you:
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# dsh-data-cleaning-agent
|
|
2
2
|
|
|
3
|
+
> 0.9.1 升级说明:工作台已迁移到 Better Sidebar 的 Session 单例 Tab,需要兼容的 `dsh-better-sidebar`(`targetedOpen`、`stateSubscription`)。缺失时会提示安装/升级,不回退到自有抽屉;本轮验证边界见 [采用记录](docs/UI-V1.5.0-ADOPTION.md)。
|
|
4
|
+
|
|
3
5
|
本版统一向导与工作台的 Host 执行闭环:发送后自动生成新 Excel,原文件不修改,工作台入口可恢复;发布记录见 [发布说明](docs/RELEASE-0.8.22.md)。
|
|
4
6
|
|
|
5
7
|
## 安装与三分钟上手
|
|
@@ -7,7 +9,7 @@
|
|
|
7
9
|
数据清洗补全智能体:面向 Excel/CSV/JSON 企业名单,提供数据清洗、表格清洗、清洗补全、去重、企业数据补全与字段补全,支持企查查 MCP 和结果导出。
|
|
8
10
|
|
|
9
11
|
```sh
|
|
10
|
-
dsh plugin --profile web add dsh-data-cleaning-agent@0.
|
|
12
|
+
dsh plugin --profile web add dsh-data-cleaning-agent@0.9.1
|
|
11
13
|
```
|
|
12
14
|
|
|
13
15
|
请先满足下文的 DSH、连接器及侧边栏依赖要求;安装后完整停止并重启对应 Profile。
|
|
@@ -25,7 +27,7 @@ dsh plugin --profile web add dsh-data-cleaning-agent@0.8.23
|
|
|
25
27
|
|
|
26
28
|
> 在 DeepSeek Harness 中清洗、补全、画像企业名单数据的智能体插件:本地 CSV/XLSX/JSON 引擎 + 可选企查查(Qichacha/QCC)MCP 企业数据补全,由企查查(Qichacha/QCC)团队发起并维护。
|
|
27
29
|
>
|
|
28
|
-
> 当前源码版本 / Current source version: **0.
|
|
30
|
+
> 当前源码版本 / Current source version: **0.9.1**(正式版本)
|
|
29
31
|
|
|
30
32
|
本版上传表格后展示完整清单及空白数量,用绿色、琥珀色、红色及文字区分已通过、待确认和未匹配映射。已映射字段自动纳入补全范围,额外字段默认折叠;多个原列可经确认使用同一非主体字段,分别补空并保留非空原值。修复 Host 草稿重置为默认五字段的问题,增加前后端版本错配提示。生成说明不查询,发送才执行;升级后需完整重启 DSH,历史下载文件不自动改写。
|
|
31
33
|
|
|
@@ -79,10 +81,13 @@ Composer 图片附件,因此不支持视觉输入的文本模型也能调度 A
|
|
|
79
81
|
或分发凭据。本地服务会把用户明确提交的图片上传到企查查文档解析网关;未连接本地服务时功能会
|
|
80
82
|
fail closed,并明确提示配置要求,文本与 Excel 流程不受影响。
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
安装前请核验完整 DSH `0.1.2-rc.1` + Better Sidebar `0.18.1`。context 不是必装依赖;若已装 `0.36.0`,需先升级到 `0.48.0`。预检不会升级全局宿主,也不代表业务验收通过。
|
|
85
|
+
|
|
86
|
+
从完整源码或解压的 npm 包运行安装脚本(需要实际 `dsh` CLI;不再支持流式脚本):
|
|
83
87
|
|
|
84
88
|
```bash
|
|
85
|
-
|
|
89
|
+
node lib/install-preflight.js "$DSH_HOME/profiles/web"
|
|
90
|
+
bash install.sh
|
|
86
91
|
```
|
|
87
92
|
|
|
88
93
|
或直接让 Agent 安装:
|
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
# 兼容性 / Compatibility
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.9.0:Session 单例 Tab
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
工作台通过可选 `ctx.inject(['betterSidebar'], ...)` 接入 Provider,探测 `targetedOpen` 与 `stateSubscription`;缺失时保留会话和 Host 工具,不提供私有抽屉回退。当前仅完成隔离模拟服务与 Chromium 回归,尚未实装组合验收;旧版本的 Host/UI 验证不自动覆盖此次迁移。详见 [采用记录](UI-V1.5.0-ADOPTION.md)。
|
|
6
|
+
|
|
7
|
+
## 当前加固目标(2026-09-10)
|
|
8
|
+
|
|
9
|
+
完整 DSH `0.1.2-rc.1` + Better Sidebar `0.18.1`;可选 context 共存版本 `0.48.0`。版本预检通过仅代表排除已知版本冲突,不代表模块加载、服务激活或业务闭环已通过。其他版本提示未验证,旧宿主配 Sidebar 0.18.1、rc.1 配 Sidebar 0.17.1 或 context 0.36.0 阻断安装。反向冲突证据由 AI 填表隔离验收共享:`/tmp/ff-compat-oldhost.log`(实际宿主为 rc.1,文件名并非版本依据),缺少 `settingsNamespace` 导致导入失败。不推断整个版本区间。
|
|
10
|
+
|
|
11
|
+
安装前从完整包运行 `node lib/install-preflight.js <目标Profile目录> [实际dsh可执行文件]`;只读取包版本并执行 CLI `--version`,不读取密钥或修改安装。先备份 Profile 与锁文件,由宿主管理者升级完整宿主,不能只升级 Session 子包;回滚须还原成套宿主和插件锁定版本,不能把 Sidebar 0.18.1 留在旧宿主上。
|
|
12
|
+
|
|
13
|
+
## 1. 历史基线(不代表 0.9.0 新组合承诺)
|
|
14
|
+
|
|
15
|
+
### 本轮隔离证据(2026-09-10,候选未发布)
|
|
16
|
+
|
|
17
|
+
- Node `v25.9.0`;临时根 `/private/tmp/dcq-host-rc1`,独立 DSH_HOME `home`,端口 `43278`。未访问正式 Profile,未调用真实 MCP。
|
|
18
|
+
- npm pack 候选安装到临时 Profile,完整 DSH `0.1.2-rc.1` / Sidebar `0.18.1` / context `0.48.0`:Host apply、真实浏览器入口和 Session Tab 可见,pageErrors 为 0。未用旧 runtime 模块替身。
|
|
19
|
+
- 合成 XLSX(2 行)实际上传、自动映射、规则确认、质量体检、本地确定性清洗、本地补全、生成 XLSX 均执行;导出工作表 `清洗补全结果` 可反向解析,预览 HTTP 200。
|
|
20
|
+
- 实证修复:纯本地任务完成后仍被下载导航的外部补全状态门禁阻断。现在只在非 QCC 目标、规则已确认且确有本地结果时允许进入下载;QCC 目标仍保持原门禁。
|
|
21
|
+
- 第二处实证修复:rc.1 原生 New Session 已迁至 `uiWorkspace.startSession`,旧桥挂在 `workspaces.startSession` 因而失效。现在通过可选服务注入跟随 `uiWorkspace` 生命周期挂载/恢复兼容桥,保留旧接口回退。重打包安装后 New Session 切换、清洗 dock 隐藏、普通会话自写草稿均通过,pageErrors=0。
|
|
22
|
+
- **待验收**:真实 QCC、图片 OCR、候选确认、多插件完整共存和关闭/恢复回归尚未在此组合完成;不能以本地合成闭环代替这些验收。
|
|
23
|
+
- 环境调整:初次跳过 peer 安装缺失宿主依赖,补全后启动;文件监听 EMFILE,测试 Profile 设 `patchReload: startup` 并关闭 settings/credentials watch。磁盘 ENOSPC 曾阻断工作区创建,清理本轮下载缓存后重试成功。上述不是产品兼容通过依据。
|
|
24
|
+
- 重现脚本:`DCQ_PLAYWRIGHT=<playwright模块路径> DCQ_SMOKE_ROOT=/private/tmp/dcq-host-rc1 node scripts/host-rc1-smoke.cjs`。仅对该布局、指定独立端口运行;需先按上文安装包、注册 bundle 并启动测试 Host,脚本不启动或升级宿主。脚本包含普通会话隔离断言,修复后通过。
|
|
25
|
+
- 本机证据:`/private/tmp/dcq-host-rc1/business-result.log`、`startup.png`、`workbench.png`,全量单测/发布包检查 `/private/tmp/dcq-compat-check.log`(260 通过)。本轮 tarball 是未发布候选,沿用基线版本用于隔离安装,**不允许覆盖发布 npm 0.9.0**。
|
|
26
|
+
|
|
27
|
+
以下是旧发布的历史证据,不继承为当前组合验收:
|
|
6
28
|
|
|
7
29
|
| 基线 | 框架 npm 包线 | 备注 |
|
|
8
30
|
| --- | --- | --- |
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# v1.5.0 统一侧拉采用记录(0.9.0 采用记录)
|
|
2
|
+
|
|
3
|
+
开发基线 main / 623408e(0.8.23)。2026-09-10 用户授权推进 commit、push、tag 和 npm 发布,本次版本为 0.9.0;不包含市场条目更新。
|
|
4
|
+
|
|
5
|
+
已完整阅读规范第 7、13.4、14、15、15.1 节,并检查配套 Mockup 的 Session 单例、历史同 Tab 和宿主管理几何语义。
|
|
6
|
+
|
|
7
|
+
## 主链路与采用范围
|
|
8
|
+
|
|
9
|
+
- lib/client.js 不再注册 shell.overlay 工作台。移除固定抽屉、拖拽分隔条、width/expanded 状态、容器展开/关闭按钮、全局 resize 与中央会话 padding/位移逻辑。
|
|
10
|
+
- WorkbenchContent 只渲染当前任务、五阶段、任务历史和结果操作。Header 由 Host Tab 提供;业务状态集中在任务进度卡。窄栏采用容器查询,不依赖浏览器窗口宽度判断布局。
|
|
11
|
+
- lib/better-sidebar-adapter.js 注册稳定命名空间 id:dsh-data-cleaning-agent:workbench,single:true。显式传入 Session scope;五个快捷入口、Header 恢复、执行进度自动打开均经过同一 adapter。
|
|
12
|
+
- 插件级控制器按 Session 保存独立业务 store,Tab 只是视图。关闭/隐藏 Tab 不删除、取消或重跑 Host 任务;重新打开恢复原数据和内部视图。读取已有任务绑定不再隐式新建任务。
|
|
13
|
+
- 跨作用域事件由一个带引用计数的控制器接收,提示词准备/OCR/数据暂存无需先挂载 Tab。跨 Session 不共用业务 store;非前台 Session reveal 等待订阅切换后消费,不挤占当前会话布局。
|
|
14
|
+
- 使用可选 ctx.inject(['betterSidebar'], ...) 子生命周期,避免访问未授予的 Cordis 服务;Provider 缺失或移除不卸载业务控制器、会话入口和 Host 工具。
|
|
15
|
+
- 缺依赖/过旧契约/Tab 禁用时显示可行动提示,无旧抽屉回退。Provider 卸载释放描述符和状态订阅;插件卸载移除事件监听、pending intent 和本地命令观察,Host 任务不受影响。
|
|
16
|
+
- 任务、规则、字段目录、OCR、MCP 和制品后端契约未重写。
|
|
17
|
+
|
|
18
|
+
## 接口与构建边界
|
|
19
|
+
|
|
20
|
+
探测 registerTab/openTab/isTabEnabled/getSnapshot/subscribeState 和 targetedOpen/stateSubscription。
|
|
21
|
+
type-only openTab 后通过该 Tab 的公开 store.reduce reveal 所在右侧/底部容器;浮窗不变更几何。
|
|
22
|
+
未使用 tabLifecycle,所以没有依赖该能力。
|
|
23
|
+
|
|
24
|
+
参考类型:本地 Better Sidebar 0.17.1 的 service 声明及 Cordis 4.0.1 的 inject/Fiber 生命周期。
|
|
25
|
+
不据此宣称其他 Provider 版本或真实组合场景已经验收。
|
|
26
|
+
|
|
27
|
+
现有 ModuleLoader 为单文件 CJS 工厂:scripts/sync-sidebar-adapter.mjs 将被测试的 adapter 嵌入 client.js。
|
|
28
|
+
修改 adapter 后运行 node scripts/sync-sidebar-adapter.mjs --write;静态测试校验嵌入内容一致,防止源码与运行代码漂移。
|
|
29
|
+
|
|
30
|
+
## 本地验证
|
|
31
|
+
|
|
32
|
+
- npm run check:语法、文档、营销/打包门禁与完整 256 项测试通过。
|
|
33
|
+
- npm run test:ui:隔离 React/Chromium + 模拟 Better Sidebar,10 组明暗主题/窗口尺寸;另外验证桌面 320px 与宽 Tab。
|
|
34
|
+
- 浏览器覆盖:上传/替换失败保留旧数据、映射搜索和重复列、表格横向滚动和固定表头、提示词准备、执行后自动打开、结果制品操作、Tab 关闭重开、宿主折叠恢复、Session 离开与普通会话隔离。
|
|
35
|
+
- 单元/静态覆盖:单例注册和入口幂等、Session store 隔离、inactive pending reveal、底部/浮窗 reveal、依赖缺失/过旧/禁用、Provider 到达/移除、重复卸载幂等、无固定几何/中央让位、无任务取消删除副作用。
|
|
36
|
+
- 证据:_scratch/ui-layout/results.json 与同目录截图(本地夹具产物,不进入 npm)。
|
|
37
|
+
- 没有调用真实 QCC,不消耗用户额度;没有覆盖上传源文件。
|
|
38
|
+
|
|
39
|
+
## 真实 DSH 验收限制与发布门
|
|
40
|
+
|
|
41
|
+
本轮未替换运行中 3080 Profile,未进行真实 DSH + Better Sidebar 或四插件共存安装验收。
|
|
42
|
+
真实侧栏生命周期、底部停靠/浮窗、四插件切换、Host 动态移除 Provider、实际 OCR/授权链路需在隔离 Profile 联调。
|
|
43
|
+
本地 UI 模拟通过不等于真实 Provider 验收;用户已授权在上述已知限制下发布 0.9.0;真实组合联调仍需补做,不将发布成功视为联调通过。
|
package/install.sh
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
# dsh-data-cleaning-agent 一键安装脚本(DeepSeek Harness)
|
|
3
3
|
# 用法:
|
|
4
4
|
# 本地: bash install.sh
|
|
5
|
-
#
|
|
6
|
-
#
|
|
5
|
+
# 请从完整 npm 包或源码目录运行,确保随包预检可用。
|
|
6
|
+
# 需要实际 dsh CLI 通过预检;脚本不会升级全局宿主。
|
|
7
7
|
# 幂等:重复执行不会重复注册或破坏已有配置。
|
|
8
8
|
set -euo pipefail
|
|
9
9
|
|
|
@@ -21,6 +21,14 @@ if [ ! -d "$PROFILE_DIR" ]; then
|
|
|
21
21
|
exit 1
|
|
22
22
|
fi
|
|
23
23
|
|
|
24
|
+
# 在任何安装/配置写入前,只读检查实际 CLI 与目标 Profile 的组合。
|
|
25
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
if [ ! -f "$SCRIPT_DIR/lib/install-preflight.js" ]; then
|
|
27
|
+
echo "错误:缺少随包预检。请解压 npm pack dsh-data-cleaning-agent 的完整包后运行 bash package/install.sh;不再支持流式执行脚本。"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
node "$SCRIPT_DIR/lib/install-preflight.js" "$PROFILE_DIR"
|
|
31
|
+
|
|
24
32
|
# ── 1) 安装依赖 ──
|
|
25
33
|
if command -v dsh >/dev/null 2>&1; then
|
|
26
34
|
echo "==> dsh plugin --profile $PROFILE add $PKG"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** Public Better Sidebar seam. No business task creation, cancellation or geometry. */
|
|
2
|
+
export const CLEANING_TAB_ID = 'dsh-data-cleaning-agent:workbench';
|
|
3
|
+
export const SIDEBAR_DEPENDENCY_MESSAGE = '请安装或升级兼容的 dsh-better-sidebar 并重启 DSH(需要 targetedOpen 和 stateSubscription 能力),然后重新点击流程按钮。现有任务和文件不会删除。';
|
|
4
|
+
|
|
5
|
+
export function sidebarCompatibility(service) {
|
|
6
|
+
const methods = ['registerTab', 'openTab', 'isTabEnabled', 'getSnapshot', 'subscribeState'];
|
|
7
|
+
return Boolean(service && methods.every(key => typeof service[key] === 'function')
|
|
8
|
+
&& ['targetedOpen', 'stateSubscription'].every(key => service.features?.includes(key)));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function contains(node, id) {
|
|
12
|
+
if (!node) return false;
|
|
13
|
+
return node.kind === 'leaf' ? node.tabs.some(tab => tab.id === id)
|
|
14
|
+
: node.children.some(child => contains(child, id));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function revealCleaningTab(state, id) {
|
|
18
|
+
if (state.floats?.some(item => item.tab.id === id)) return state;
|
|
19
|
+
if (contains(state.bottomSplits, id)) return state.bottomOpen ? state : { ...state, bottomOpen: true };
|
|
20
|
+
if (contains(state.splits, id)) return state.panelOpen ? state : { ...state, panelOpen: true };
|
|
21
|
+
return state;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** One adapter per plugin activation. Session navigation survives closing its Tab. */
|
|
25
|
+
export function createCleaningSidebarAdapter(service, { component, icon, onUnavailable = () => {} }) {
|
|
26
|
+
const targets = new Map();
|
|
27
|
+
const destinations = new Map();
|
|
28
|
+
const pending = new Set();
|
|
29
|
+
let disposed = false;
|
|
30
|
+
const compatible = sidebarCompatibility(service);
|
|
31
|
+
const applyPending = sessionId => {
|
|
32
|
+
if (disposed || service.getSnapshot().sessionId !== sessionId || !pending.has(sessionId)) return;
|
|
33
|
+
const target = targets.get(sessionId);
|
|
34
|
+
if (!target) return;
|
|
35
|
+
pending.delete(sessionId);
|
|
36
|
+
target.navigate(destinations.get(sessionId));
|
|
37
|
+
target.store.reduce(state => revealCleaningTab(state, target.tabId));
|
|
38
|
+
};
|
|
39
|
+
const unregister = compatible ? service.registerTab({
|
|
40
|
+
id: CLEANING_TAB_ID, title: '数据清洗补全', icon, order: 30, single: true, component,
|
|
41
|
+
}) : () => {};
|
|
42
|
+
const unsubscribe = compatible ? service.subscribeState(() => {
|
|
43
|
+
const sessionId = service.getSnapshot().sessionId;
|
|
44
|
+
if (sessionId) applyPending(sessionId);
|
|
45
|
+
}) : () => {};
|
|
46
|
+
return {
|
|
47
|
+
compatible,
|
|
48
|
+
open(scope, destination = 'upload') {
|
|
49
|
+
if (disposed) return false;
|
|
50
|
+
if (!compatible || !service.isTabEnabled(CLEANING_TAB_ID)) {
|
|
51
|
+
onUnavailable(compatible ? '请在 Better Sidebar 设置中启用「数据清洗补全」Tab。' : SIDEBAR_DEPENDENCY_MESSAGE);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (!scope?.sessionId) throw new Error('A target Session is required');
|
|
55
|
+
destinations.set(scope.sessionId, destination);
|
|
56
|
+
pending.add(scope.sessionId);
|
|
57
|
+
service.openTab({ type: CLEANING_TAB_ID }, scope);
|
|
58
|
+
applyPending(scope.sessionId);
|
|
59
|
+
return true;
|
|
60
|
+
},
|
|
61
|
+
attach(scope, target) {
|
|
62
|
+
if (disposed) return () => {};
|
|
63
|
+
targets.set(scope.sessionId, target);
|
|
64
|
+
// Without a pending shortcut, preserve the Session business store's current view.
|
|
65
|
+
// Closing/reopening a Tab must not rewind an in-progress task to an older shortcut.
|
|
66
|
+
applyPending(scope.sessionId);
|
|
67
|
+
return () => { if (targets.get(scope.sessionId) === target) targets.delete(scope.sessionId); };
|
|
68
|
+
},
|
|
69
|
+
dispose() {
|
|
70
|
+
if (disposed) return;
|
|
71
|
+
disposed = true;
|
|
72
|
+
unsubscribe(); unregister();
|
|
73
|
+
targets.clear(); pending.clear(); destinations.clear();
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|