dsh-data-cleaning-agent 0.8.8 → 0.8.10
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 +20 -0
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/lib/client.js +224 -29
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
本文件记录 `dsh-data-cleaning-agent` 的版本变更。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.8.10] - 2026-09-07
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- 依据共享 DSH-UX-001 v1.3.0 / UX-39,为自有右侧工作台补充左侧连续拖拽分隔条、方向键和 Home/End 调宽、双击复位、拖动取消、手动宽度恢复;中央会话按实际面板宽度同步让位。
|
|
11
|
+
- 按宿主会话区域实际可用宽度约束上下限,空间不足时全屏降级;关闭、切换或卸载恢复自有布局变量并清理监听,不改变 Host 任务、QCC 调用或发送机制。
|
|
12
|
+
|
|
13
|
+
### Tests
|
|
14
|
+
- 补充实际拖拽、取消、展开转手动、键盘调宽、关闭重开、宿主区域尺寸变化及让位清理回归;发布前通过 214 项检查测试与 10 组隔离 Chromium UI 回归。
|
|
15
|
+
|
|
16
|
+
## [0.8.9] - 2026-09-07
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- 按共享 DSH-UX-001 v1.1.2 对齐招投标工作台的阶段菜单:单行五个等宽分栏、上图标下短标题、分隔线及选中蓝色底线;取消数字前缀和横向滚动布局。说明与状态仅保留在内容区和工作台头部。
|
|
20
|
+
- 窄屏缩小图标与字号,长标题在分栏内省略并保留完整可访问名称和悬停提示;阶段导航、质量体检子视图及 Host 工作流保持不变。
|
|
21
|
+
|
|
22
|
+
### Tests
|
|
23
|
+
- 增补五阶段图标/标题结构断言与隔离 Chromium 深浅色布局回归,覆盖 320px 窄屏、普通/展开工作台、长标题防溢出,以及切换阶段不修改 Host 任务。
|
|
24
|
+
|
|
5
25
|
## [0.8.8] - 2026-09-06
|
|
6
26
|
|
|
7
27
|
### Changed
|
package/README.en.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
> 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.
|
|
4
4
|
>
|
|
5
|
-
> Current source version / 当前源码版本: **0.8.
|
|
5
|
+
> Current source version / 当前源码版本: **0.8.10** (stable release)
|
|
6
6
|
|
|
7
|
-
This release
|
|
7
|
+
This release adds continuous resizing from the workbench's left edge, keeping the native composer clear. Arrow keys, Home/End, double-click reset, and width restoration on reopening are supported. Constrained layouts use a full-screen drawer. All 128 fields, QCC-blue menus, existing workflows, and native DSH input and send behavior are preserved.
|
|
8
8
|
|
|
9
9
|
[](https://github.com/duhu2000/dsh-data-cleaning-agent/actions/workflows/ci.yml)
|
|
10
10
|
[](https://www.npmjs.com/package/dsh-data-cleaning-agent)
|
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
> 在 DeepSeek Harness 中清洗、补全、画像企业名单数据的智能体插件:本地 CSV/XLSX/JSON 引擎 + 可选企查查(Qichacha/QCC)MCP 企业数据补全,由企查查(Qichacha/QCC)团队发起并维护。
|
|
4
4
|
>
|
|
5
|
-
> 当前源码版本 / Current source version: **0.8.
|
|
5
|
+
> 当前源码版本 / Current source version: **0.8.10**(正式版本)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
本版支持拖动右侧工作台左边缘连续调宽,中央输入区同步让位;支持方向键微调、Home/End 边界、双击恢复默认和关闭重开保留宽度。空间不足时全屏降级。保留企查查蓝菜单、全部 128 个字段和原有工作流,不替换 DSH 原生输入和发送机制。
|
|
8
8
|
|
|
9
9
|
[](https://github.com/duhu2000/dsh-data-cleaning-agent/actions/workflows/ci.yml)
|
|
10
10
|
[](https://www.npmjs.com/package/dsh-data-cleaning-agent)
|
package/lib/client.js
CHANGED
|
@@ -63,6 +63,137 @@ window.__ModuleLoader__.load({
|
|
|
63
63
|
h('path', { d: DATABASE_PATH }));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// 阶段只展示线性图标和短标题;说明、状态与操作保留在内容区。
|
|
67
|
+
const STAGE_ICON_PATHS = {
|
|
68
|
+
upload: 'M12 16V3m-4 4 4-4 4 4M4 14v6h16v-6',
|
|
69
|
+
check: 'M9 6h11M9 12h11M9 18h11M3 6l1 1 2-2M3 12l1 1 2-2M3 18l1 1 2-2',
|
|
70
|
+
search: 'M16 16l5 5M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0',
|
|
71
|
+
database: DATABASE_PATH,
|
|
72
|
+
table: 'M4 3h16v18H4zM4 8h16M4 13h16M4 17h16M10 8v13',
|
|
73
|
+
};
|
|
74
|
+
function StageIcon({ kind }) {
|
|
75
|
+
return h('svg', { width: 20, height: 20, viewBox: '0 0 24 24', fill: 'none',
|
|
76
|
+
stroke: 'currentColor', strokeWidth: 1.7, strokeLinecap: 'round', strokeLinejoin: 'round',
|
|
77
|
+
'aria-hidden': true, focusable: false }, h('path', { d: STAGE_ICON_PATHS[kind] }));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function workbenchWidthBounds(viewport, available = viewport) {
|
|
81
|
+
const mobile = viewport <= 760 || available < 740;
|
|
82
|
+
return { mobile, min: mobile ? viewport : 320, max: mobile ? viewport : Math.max(320, available - 420) };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 自有抽屉的可逆兼容适配;不改 Better Sidebar 或其他插件的面板偏好。
|
|
86
|
+
function installWorkbenchSizing(drawer, { preferredWidth, expanded, onWidthChange }) {
|
|
87
|
+
const doc = drawer.ownerDocument;
|
|
88
|
+
const view = doc.defaultView;
|
|
89
|
+
const handle = drawer.querySelector('.dcAgentResizeHandle');
|
|
90
|
+
if (!handle || !view) return () => {};
|
|
91
|
+
const reservations = new Map();
|
|
92
|
+
let requested = expanded ? 980 : preferredWidth;
|
|
93
|
+
let current = 0;
|
|
94
|
+
let drag = null;
|
|
95
|
+
const boundsForView = () => workbenchWidthBounds(view.innerWidth,
|
|
96
|
+
doc.querySelector('[data-conversation-scroll]')?.getBoundingClientRect().width || view.innerWidth);
|
|
97
|
+
const reserve = () => {
|
|
98
|
+
const width = boundsForView().mobile ? 0 : drawer.getBoundingClientRect().width;
|
|
99
|
+
for (const el of doc.querySelectorAll('[data-conversation-scroll]')) {
|
|
100
|
+
if (!reservations.has(el)) {
|
|
101
|
+
reservations.set(el, {
|
|
102
|
+
value: el.style.getPropertyValue('--dc-agent-workbench-reserve'),
|
|
103
|
+
priority: el.style.getPropertyPriority('--dc-agent-workbench-reserve'),
|
|
104
|
+
});
|
|
105
|
+
sizeObserver?.observe(el, { box: 'border-box' });
|
|
106
|
+
}
|
|
107
|
+
if (el.style.getPropertyValue('--dc-agent-workbench-reserve') !== `${width}px`) {
|
|
108
|
+
el.style.setProperty('--dc-agent-workbench-reserve', `${width}px`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const apply = (value) => {
|
|
113
|
+
const bounds = boundsForView();
|
|
114
|
+
const fallback = view.innerWidth <= 1040 ? Math.min(420, view.innerWidth * .48) : Math.min(460, view.innerWidth * .42);
|
|
115
|
+
current = Math.round(Math.min(bounds.max, Math.max(bounds.min, Number.isFinite(value) ? value : fallback)));
|
|
116
|
+
drawer.dataset.narrow = String(bounds.mobile);
|
|
117
|
+
drawer.style.setProperty('--dc-agent-panel-width', `${current}px`);
|
|
118
|
+
handle.setAttribute('aria-valuemin', String(bounds.min));
|
|
119
|
+
handle.setAttribute('aria-valuemax', String(bounds.max));
|
|
120
|
+
handle.setAttribute('aria-valuenow', String(current));
|
|
121
|
+
handle.setAttribute('aria-valuetext', `${current} 像素`);
|
|
122
|
+
reserve();
|
|
123
|
+
};
|
|
124
|
+
const end = (cancel = false) => {
|
|
125
|
+
if (!drag) return;
|
|
126
|
+
const previous = drag;
|
|
127
|
+
drag = null;
|
|
128
|
+
drawer.classList.remove('is-resizing');
|
|
129
|
+
if (handle.hasPointerCapture?.(previous.id)) handle.releasePointerCapture(previous.id);
|
|
130
|
+
if (cancel) apply(requested);
|
|
131
|
+
else { requested = current; onWidthChange(current); }
|
|
132
|
+
};
|
|
133
|
+
const down = (event) => {
|
|
134
|
+
if (event.button !== 0 || drag || boundsForView().mobile) return;
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
handle.focus();
|
|
137
|
+
drag = { id: event.pointerId, startX: event.clientX, startWidth: current };
|
|
138
|
+
handle.setPointerCapture(event.pointerId);
|
|
139
|
+
drawer.classList.add('is-resizing');
|
|
140
|
+
};
|
|
141
|
+
const move = (event) => {
|
|
142
|
+
if (drag?.id !== event.pointerId) return;
|
|
143
|
+
apply(drag.startWidth + drag.startX - event.clientX);
|
|
144
|
+
};
|
|
145
|
+
const up = (event) => { if (drag?.id === event.pointerId) end(); };
|
|
146
|
+
const cancel = () => end(true);
|
|
147
|
+
const keydown = (event) => {
|
|
148
|
+
if (event.key === 'Escape' && drag) {
|
|
149
|
+
event.preventDefault(); event.stopPropagation(); cancel(); return;
|
|
150
|
+
}
|
|
151
|
+
if (drag || boundsForView().mobile) return;
|
|
152
|
+
const bounds = boundsForView();
|
|
153
|
+
const delta = event.shiftKey ? 48 : 16;
|
|
154
|
+
const value = { ArrowLeft: current + delta, ArrowRight: current - delta, Home: bounds.min, End: bounds.max }[event.key];
|
|
155
|
+
if (value === undefined) return;
|
|
156
|
+
event.preventDefault(); event.stopPropagation();
|
|
157
|
+
requested = value; apply(value); onWidthChange(current);
|
|
158
|
+
};
|
|
159
|
+
const reset = () => { cancel(); requested = null; apply(null); onWidthChange(null); };
|
|
160
|
+
const resize = () => { cancel(); apply(requested); };
|
|
161
|
+
const sizeObserver = typeof view.ResizeObserver === 'function' ? new view.ResizeObserver(resize) : null;
|
|
162
|
+
handle.addEventListener('pointerdown', down);
|
|
163
|
+
handle.addEventListener('pointermove', move);
|
|
164
|
+
handle.addEventListener('pointerup', up);
|
|
165
|
+
handle.addEventListener('pointercancel', cancel);
|
|
166
|
+
handle.addEventListener('lostpointercapture', cancel);
|
|
167
|
+
handle.addEventListener('keydown', keydown);
|
|
168
|
+
handle.addEventListener('dblclick', reset);
|
|
169
|
+
view.addEventListener('resize', resize);
|
|
170
|
+
view.addEventListener('blur', cancel);
|
|
171
|
+
// 会话挂载点可被宿主替换;只对当前存在的滚动区设置自有让位变量。
|
|
172
|
+
const observer = typeof view.MutationObserver === 'function' ? new view.MutationObserver(reserve) : null;
|
|
173
|
+
observer?.observe(doc.body, { childList: true, subtree: true });
|
|
174
|
+
apply(requested);
|
|
175
|
+
return () => {
|
|
176
|
+
cancel();
|
|
177
|
+
observer?.disconnect();
|
|
178
|
+
sizeObserver?.disconnect();
|
|
179
|
+
handle.removeEventListener('pointerdown', down);
|
|
180
|
+
handle.removeEventListener('pointermove', move);
|
|
181
|
+
handle.removeEventListener('pointerup', up);
|
|
182
|
+
handle.removeEventListener('pointercancel', cancel);
|
|
183
|
+
handle.removeEventListener('lostpointercapture', cancel);
|
|
184
|
+
handle.removeEventListener('keydown', keydown);
|
|
185
|
+
handle.removeEventListener('dblclick', reset);
|
|
186
|
+
view.removeEventListener('resize', resize);
|
|
187
|
+
view.removeEventListener('blur', cancel);
|
|
188
|
+
drawer.style.removeProperty('--dc-agent-panel-width');
|
|
189
|
+
delete drawer.dataset.narrow;
|
|
190
|
+
for (const [el, previous] of reservations) {
|
|
191
|
+
if (previous.value) el.style.setProperty('--dc-agent-workbench-reserve', previous.value, previous.priority);
|
|
192
|
+
else el.style.removeProperty('--dc-agent-workbench-reserve');
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
66
197
|
// 搜索仅改变可见字段,绝不清除已选字段或改变 Host 的字段目录。
|
|
67
198
|
function visibleCatalogFields(group, query) {
|
|
68
199
|
const needle = String(query || '').trim().toLowerCase();
|
|
@@ -152,12 +283,13 @@ window.__ModuleLoader__.load({
|
|
|
152
283
|
}
|
|
153
284
|
|
|
154
285
|
.dcAgentWorkbench {
|
|
286
|
+
position: relative;
|
|
155
287
|
box-sizing: border-box;
|
|
156
288
|
display: flex;
|
|
157
289
|
flex-direction: column;
|
|
158
|
-
width: min(460px, 42vw);
|
|
290
|
+
width: var(--dc-agent-panel-width, min(460px, 42vw));
|
|
159
291
|
max-width: calc(100vw - 420px);
|
|
160
|
-
min-width:
|
|
292
|
+
min-width: 320px;
|
|
161
293
|
height: 100vh;
|
|
162
294
|
border: 1px solid var(--dc-border);
|
|
163
295
|
border-radius: 12px 0 0 12px;
|
|
@@ -167,7 +299,14 @@ window.__ModuleLoader__.load({
|
|
|
167
299
|
overflow: hidden;
|
|
168
300
|
pointer-events: auto;
|
|
169
301
|
}
|
|
170
|
-
.dcAgentWorkbench.is-expanded { width: min(980px, calc(100vw -
|
|
302
|
+
.dcAgentWorkbench.is-expanded { width: var(--dc-agent-panel-width, min(980px, calc(100vw - 420px))); }
|
|
303
|
+
.dcAgentResizeHandle { position: absolute; left: 0; top: 0; bottom: 0; width: 8px; z-index: 5; cursor: col-resize; touch-action: none; outline: none; }
|
|
304
|
+
.dcAgentResizeHandle::after { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: transparent; }
|
|
305
|
+
.dcAgentResizeHandle:hover::after, .dcAgentResizeHandle:focus-visible::after, .is-resizing .dcAgentResizeHandle::after { background: var(--dc-action); }
|
|
306
|
+
.dcAgentWorkbench.is-resizing { user-select: none; }
|
|
307
|
+
.dcAgentWorkbench[data-narrow="true"] { width: 100vw; max-width: none; min-width: 0; border-radius: 0; }
|
|
308
|
+
.dcAgentWorkbench[data-narrow="true"] .dcAgentResizeHandle { display: none; }
|
|
309
|
+
.dcAgentOverlay:has(.dcAgentWorkbench[data-narrow="true"]) { background: rgba(8, 10, 14, 0.22); pointer-events: auto; }
|
|
171
310
|
|
|
172
311
|
.dcAgentCapabilities {
|
|
173
312
|
display: flex;
|
|
@@ -525,32 +664,65 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
525
664
|
|
|
526
665
|
.dcAgentStepper {
|
|
527
666
|
display: grid;
|
|
528
|
-
grid-template-columns: repeat(
|
|
529
|
-
|
|
530
|
-
padding: 12px 18px;
|
|
667
|
+
grid-template-columns: repeat(var(--dc-stage-count, 5), minmax(0, 1fr));
|
|
668
|
+
min-width: 0;
|
|
531
669
|
border-bottom: 1px solid var(--dc-border);
|
|
532
|
-
background: var(--dc-
|
|
670
|
+
background: var(--dc-surface);
|
|
533
671
|
}
|
|
534
672
|
|
|
535
673
|
.dcAgentStep {
|
|
674
|
+
position: relative;
|
|
675
|
+
min-width: 0;
|
|
536
676
|
display: flex;
|
|
677
|
+
flex-direction: column;
|
|
537
678
|
align-items: center;
|
|
538
679
|
justify-content: center;
|
|
539
|
-
gap:
|
|
540
|
-
padding:
|
|
541
|
-
border:
|
|
542
|
-
border-
|
|
680
|
+
gap: 8px;
|
|
681
|
+
padding: 12px 4px;
|
|
682
|
+
border: 0;
|
|
683
|
+
border-right: 1px solid var(--dc-border);
|
|
684
|
+
border-radius: 0;
|
|
543
685
|
background: transparent;
|
|
544
686
|
color: var(--dc-muted);
|
|
545
687
|
font-size: 12px;
|
|
688
|
+
font-weight: 600;
|
|
546
689
|
cursor: pointer;
|
|
547
|
-
white-space: nowrap;
|
|
548
690
|
}
|
|
691
|
+
.dcAgentStep:last-child { border-right: 0; }
|
|
692
|
+
.dcAgentStep:hover { background: var(--dc-page); }
|
|
549
693
|
.dcAgentStep.is-active {
|
|
550
694
|
color: var(--dc-action);
|
|
551
|
-
border-color: var(--dc-action);
|
|
552
695
|
background: var(--dc-selected);
|
|
553
696
|
}
|
|
697
|
+
.dcAgentStep.is-active::after {
|
|
698
|
+
content: '';
|
|
699
|
+
position: absolute;
|
|
700
|
+
bottom: 0;
|
|
701
|
+
left: 8px;
|
|
702
|
+
right: 8px;
|
|
703
|
+
height: 3px;
|
|
704
|
+
border-radius: 3px 3px 0 0;
|
|
705
|
+
background: var(--dc-action);
|
|
706
|
+
}
|
|
707
|
+
.dcAgentStepIcon {
|
|
708
|
+
display: grid;
|
|
709
|
+
place-items: center;
|
|
710
|
+
width: 30px;
|
|
711
|
+
height: 30px;
|
|
712
|
+
flex: none;
|
|
713
|
+
border: 1px solid var(--dc-border);
|
|
714
|
+
border-radius: 8px;
|
|
715
|
+
}
|
|
716
|
+
.dcAgentStepIcon svg { display: block; }
|
|
717
|
+
.dcAgentStepLabel {
|
|
718
|
+
display: block;
|
|
719
|
+
width: 100%;
|
|
720
|
+
min-width: 0;
|
|
721
|
+
line-height: 18px;
|
|
722
|
+
white-space: nowrap;
|
|
723
|
+
overflow: hidden;
|
|
724
|
+
text-overflow: ellipsis;
|
|
725
|
+
}
|
|
554
726
|
|
|
555
727
|
.dcAgentWbBody {
|
|
556
728
|
flex: 1 1 auto;
|
|
@@ -800,25 +972,25 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
800
972
|
@media (min-width: 1041px) {
|
|
801
973
|
body:has(.dcAgentWorkbench) [data-conversation-scroll] {
|
|
802
974
|
box-sizing: border-box;
|
|
803
|
-
padding-right: min(460px, 42vw);
|
|
975
|
+
padding-right: var(--dc-agent-workbench-reserve, min(460px, 42vw));
|
|
804
976
|
}
|
|
805
977
|
}
|
|
806
978
|
@media (min-width: 761px) and (max-width: 1040px) {
|
|
807
979
|
body:has(.dcAgentWorkbench) [data-conversation-scroll] {
|
|
808
980
|
box-sizing: border-box;
|
|
809
|
-
padding-right: min(420px, 48vw);
|
|
981
|
+
padding-right: var(--dc-agent-workbench-reserve, min(420px, 48vw));
|
|
810
982
|
}
|
|
811
983
|
}
|
|
812
984
|
@media (min-width: 761px) {
|
|
813
985
|
body:has(.dcAgentWorkbench.is-expanded) [data-conversation-scroll] {
|
|
814
986
|
box-sizing: border-box;
|
|
815
|
-
padding-right: min(980px, calc(100vw - 420px));
|
|
987
|
+
padding-right: var(--dc-agent-workbench-reserve, min(980px, calc(100vw - 420px)));
|
|
816
988
|
}
|
|
817
989
|
}
|
|
818
990
|
@media (max-width: 760px) {
|
|
819
991
|
.dcAgentWorkbench, .dcAgentWorkbench.is-expanded { width: 100vw; max-width: none; min-width: 0; border-radius: 0; }
|
|
820
992
|
.dcAgentOverlay { background: rgba(8, 10, 14, 0.22); pointer-events: auto; }
|
|
821
|
-
.
|
|
993
|
+
.dcAgentResizeHandle { display: none; }
|
|
822
994
|
.dcAgentQccBadge, .dcAgentJobsPill { display: none; }
|
|
823
995
|
.dcAgentCandidate { grid-template-columns: 1fr; }
|
|
824
996
|
.dcAgentCapabilities { justify-content: flex-start; padding-inline: 12px; }
|
|
@@ -831,18 +1003,20 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
831
1003
|
.dcAgentMappingRow > b { display: none; }
|
|
832
1004
|
}
|
|
833
1005
|
@media (min-width: 761px) and (max-width: 1040px) {
|
|
834
|
-
.dcAgentWorkbench { width:
|
|
1006
|
+
.dcAgentWorkbench { width: var(--dc-agent-panel-width, 420px); }
|
|
835
1007
|
.dcAgentQccBadge, .dcAgentJobsPill { display: none; }
|
|
836
1008
|
}
|
|
1009
|
+
@media (max-width: 360px) {
|
|
1010
|
+
.dcAgentStep { font-size: 11px; padding: 10px 3px; gap: 6px; }
|
|
1011
|
+
.dcAgentStepIcon { width: 26px; height: 26px; }
|
|
1012
|
+
.dcAgentStepIcon svg { width: 18px; height: 18px; }
|
|
1013
|
+
}
|
|
837
1014
|
/* Distinct levels: management tabs → compact task steps → working content. */
|
|
838
1015
|
.dcAgentWorkbench, .dcAgentPromptPanel { font-size: 14px; line-height: 1.5; }
|
|
839
1016
|
.dcAgentWbHeader, .dcAgentManagement, .dcAgentStepper { flex: none; }
|
|
840
1017
|
.dcAgentManagement { display: flex; gap: 24px; padding: 0 18px; border-bottom: 1px solid var(--dc-border); }
|
|
841
1018
|
.dcAgentManagement .dcAgentButton { border: 0; border-bottom: 3px solid transparent; border-radius: 0; padding: 10px 0; background: transparent; }
|
|
842
1019
|
.dcAgentManagement .dcAgentButton[aria-pressed="true"] { border-bottom-color: var(--dc-action); color: var(--dc-action); font-weight: 600; }
|
|
843
|
-
.dcAgentStepper { display: flex; overflow-x: auto; gap: 4px; padding: 10px 12px; }
|
|
844
|
-
.dcAgentStep { flex: 0 0 auto; border-color: transparent; padding: 7px 8px; }
|
|
845
|
-
.dcAgentStep.is-active { border-color: transparent; }
|
|
846
1020
|
.dcAgentCapability { border-radius: 8px; }
|
|
847
1021
|
.dcAgentWbBody { min-height: 0; }
|
|
848
1022
|
.dcAgentTable th { background: var(--dc-table-head); color: var(--dc-text); }
|
|
@@ -913,11 +1087,11 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
913
1087
|
}
|
|
914
1088
|
|
|
915
1089
|
const STEPS = [
|
|
916
|
-
{ key: 'upload', label: '导入与核验', icon: '
|
|
917
|
-
{ key: 'rules', label: '规则与体检', icon: '
|
|
918
|
-
{ key: 'match', label: '主体匹配', icon: '
|
|
919
|
-
{ key: 'enrich', label: '字段补全', icon: '
|
|
920
|
-
{ key: 'download', label: '结果下载', icon: '
|
|
1090
|
+
{ key: 'upload', label: '导入与核验', icon: 'upload' },
|
|
1091
|
+
{ key: 'rules', label: '规则与体检', icon: 'check' },
|
|
1092
|
+
{ key: 'match', label: '主体匹配', icon: 'search' },
|
|
1093
|
+
{ key: 'enrich', label: '字段补全', icon: 'database' },
|
|
1094
|
+
{ key: 'download', label: '结果下载', icon: 'table' },
|
|
921
1095
|
];
|
|
922
1096
|
|
|
923
1097
|
const CAPABILITIES = [
|
|
@@ -1439,6 +1613,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
1439
1613
|
init: () => ({
|
|
1440
1614
|
open: false,
|
|
1441
1615
|
expanded: false,
|
|
1616
|
+
preferredWidth: null,
|
|
1442
1617
|
step: 'upload',
|
|
1443
1618
|
busy: false,
|
|
1444
1619
|
error: null,
|
|
@@ -1473,6 +1648,10 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
1473
1648
|
},
|
|
1474
1649
|
close: (draft) => { draft.open = false; },
|
|
1475
1650
|
toggleExpanded: (draft) => { draft.expanded = !draft.expanded; },
|
|
1651
|
+
setPreferredWidth: (draft, width) => {
|
|
1652
|
+
draft.preferredWidth = Number.isFinite(width) ? width : null;
|
|
1653
|
+
draft.expanded = false;
|
|
1654
|
+
},
|
|
1476
1655
|
setStep: (draft, step) => { draft.step = step; },
|
|
1477
1656
|
setActiveSession: (draft, sessionId) => { draft.activeSessionId = sessionId ?? null; },
|
|
1478
1657
|
setBusy: (draft, busy) => { draft.busy = busy; },
|
|
@@ -2920,6 +3099,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
2920
3099
|
const open = useStore((state) => state.open);
|
|
2921
3100
|
const step = useStore((state) => state.step);
|
|
2922
3101
|
const expanded = useStore((state) => state.expanded);
|
|
3102
|
+
const preferredWidth = useStore((state) => state.preferredWidth);
|
|
2923
3103
|
const busy = useStore((state) => state.busy);
|
|
2924
3104
|
const error = useStore((state) => state.error);
|
|
2925
3105
|
const input = useStore((state) => state.input);
|
|
@@ -2945,6 +3125,13 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
2945
3125
|
const activeSessionId = useStore((state) => state.activeSessionId);
|
|
2946
3126
|
const [fieldQuery, setFieldQuery] = react.useState('');
|
|
2947
3127
|
|
|
3128
|
+
react.useEffect(() => {
|
|
3129
|
+
if (!open || typeof document === 'undefined') return undefined;
|
|
3130
|
+
const drawer = document.querySelector('.dcAgentWorkbench');
|
|
3131
|
+
if (!drawer) return undefined;
|
|
3132
|
+
return installWorkbenchSizing(drawer, { preferredWidth, expanded, onWidthChange: actions.setPreferredWidth });
|
|
3133
|
+
}, [open, expanded, preferredWidth, actions]);
|
|
3134
|
+
|
|
2948
3135
|
react.useEffect(() => {
|
|
2949
3136
|
rootWorkbenchActions = actions;
|
|
2950
3137
|
const handleOpen = (event) => {
|
|
@@ -3056,7 +3243,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3056
3243
|
view?.removeEventListener?.('resize', align);
|
|
3057
3244
|
reset();
|
|
3058
3245
|
};
|
|
3059
|
-
}, [open, expanded]);
|
|
3246
|
+
}, [open, expanded, preferredWidth]);
|
|
3060
3247
|
|
|
3061
3248
|
// DSH 的 useStore 基于 React hooks;所有订阅必须在每次渲染时以相同顺序调用。
|
|
3062
3249
|
// 把关闭态 guard 放在全部 useStore 之后,避免首次关闭、随后打开时触发
|
|
@@ -3931,6 +4118,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3931
4118
|
'aria-modal': 'false',
|
|
3932
4119
|
'aria-label': '数据清洗补全工作台',
|
|
3933
4120
|
'data-session-id': activeSessionId ?? undefined,
|
|
4121
|
+
id: 'dc-agent-workbench',
|
|
3934
4122
|
onKeyDown: (event) => {
|
|
3935
4123
|
if (event.key === 'Escape') {
|
|
3936
4124
|
event.preventDefault();
|
|
@@ -3939,6 +4127,9 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3939
4127
|
}
|
|
3940
4128
|
},
|
|
3941
4129
|
},
|
|
4130
|
+
h('div', { className: 'dcAgentResizeHandle', role: 'separator', tabIndex: 0,
|
|
4131
|
+
'aria-label': '调整工作台宽度', 'aria-orientation': 'vertical', 'aria-controls': 'dc-agent-workbench',
|
|
4132
|
+
title: '拖动调整宽度;左右方向键微调,Home/End 最小/最大,双击恢复默认' }),
|
|
3942
4133
|
h('header', { className: 'dcAgentWbHeader' },
|
|
3943
4134
|
h('div', { className: 'dcAgentWbTitle' },
|
|
3944
4135
|
h('span', { className: 'dcAgentWbIcon', 'aria-hidden': 'true' }, h(DatabaseLogo, { size: 22 })),
|
|
@@ -3977,15 +4168,18 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3977
4168
|
h('button', { type: 'button', className: 'dcAgentButton', 'aria-pressed': step === 'history',
|
|
3978
4169
|
onClick: () => actions.setStep('history') }, '任务历史'),
|
|
3979
4170
|
),
|
|
3980
|
-
step !== 'history' ? h('nav', { className: 'dcAgentStepper', 'aria-label': '清洗流程'
|
|
4171
|
+
step !== 'history' ? h('nav', { className: 'dcAgentStepper', 'aria-label': '清洗流程',
|
|
4172
|
+
style: { '--dc-stage-count': STEPS.length } },
|
|
3981
4173
|
STEPS.map((st) => h('button', {
|
|
3982
4174
|
key: st.key,
|
|
3983
4175
|
type: 'button',
|
|
3984
4176
|
className: `dcAgentStep${(step === 'profile' ? 'rules' : step) === st.key ? ' is-active' : ''}`,
|
|
3985
4177
|
'aria-label': st.label,
|
|
4178
|
+
title: st.label,
|
|
3986
4179
|
'aria-current': (step === 'profile' ? 'rules' : step) === st.key ? 'step' : undefined,
|
|
3987
4180
|
onClick: () => actions.setStep(st.key),
|
|
3988
|
-
},
|
|
4181
|
+
}, h('span', { className: 'dcAgentStepIcon' }, h(StageIcon, { kind: st.icon })),
|
|
4182
|
+
h('span', { className: 'dcAgentStepLabel' }, st.label))),
|
|
3989
4183
|
) : null,
|
|
3990
4184
|
h('div', { className: 'dcAgentWbBody' },
|
|
3991
4185
|
error ? h('div', { className: 'dcAgentError', role: 'alert' }, error) : null,
|
|
@@ -4102,6 +4296,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4102
4296
|
exports.inject = inject;
|
|
4103
4297
|
// 测试用纯函数,不构成 Host / DSH 稳定 API。
|
|
4104
4298
|
exports.__testing = {
|
|
4299
|
+
workbenchWidthBounds,
|
|
4105
4300
|
DatabaseLogo,
|
|
4106
4301
|
visibleCatalogFields,
|
|
4107
4302
|
installCapabilityMount,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-data-cleaning-agent",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"description": "Clean, complete, and profile enterprise name lists in DeepSeek Harness — a data cleaning & completion agent plugin with local CSV/XLSX/JSON engine and optional Qichacha (QCC) MCP enrichment. Maintained by Qichacha/QCC.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|