dsh-desktop-windows 0.2.2 → 0.2.3
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/package.json +1 -1
- package/src/screenshot.html +150 -56
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-desktop-windows",
|
|
3
3
|
"productName": "DeepSeek Harness Desktop",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"description": "DeepSeek Harness 桌面版(Windows)· Electron desktop shell for DeepSeek Harness (dsh web) — 双击即用,无需终端 / double-click to run the harness in a standalone window",
|
|
6
6
|
"main": "src/main.js",
|
|
7
7
|
"license": "MIT",
|
package/src/screenshot.html
CHANGED
|
@@ -8,9 +8,22 @@
|
|
|
8
8
|
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; cursor: crosshair; }
|
|
9
9
|
#stage { position: fixed; inset: 0; }
|
|
10
10
|
#stage img { width: 100%; height: 100%; object-fit: fill; display: block; }
|
|
11
|
-
|
|
12
|
-
#sel {
|
|
13
|
-
|
|
11
|
+
.mask { position: fixed; background: rgba(0, 0, 0, 0.45); pointer-events: none; }
|
|
12
|
+
#sel {
|
|
13
|
+
position: fixed; border: 1.5px solid #2563eb;
|
|
14
|
+
background: rgba(37, 99, 235, 0.10);
|
|
15
|
+
display: none; pointer-events: none; z-index: 3;
|
|
16
|
+
}
|
|
17
|
+
#sel .sz {
|
|
18
|
+
position: absolute; left: 0; top: -22px;
|
|
19
|
+
background: #2563eb; color: #fff;
|
|
20
|
+
font: 11px/18px sans-serif; padding: 0 6px; border-radius: 4px; white-space: nowrap;
|
|
21
|
+
}
|
|
22
|
+
.handle {
|
|
23
|
+
position: fixed; width: 9px; height: 9px; background: #2563eb;
|
|
24
|
+
border: 1px solid #fff; border-radius: 2px; display: none;
|
|
25
|
+
pointer-events: auto; z-index: 4;
|
|
26
|
+
}
|
|
14
27
|
#toolbar {
|
|
15
28
|
position: fixed; display: none; align-items: center; gap: 8px;
|
|
16
29
|
background: rgba(15, 23, 42, 0.92); border: 1px solid #334155;
|
|
@@ -30,92 +43,173 @@
|
|
|
30
43
|
position: fixed; left: 50%; top: 20px; transform: translateX(-50%);
|
|
31
44
|
background: rgba(15, 23, 42, 0.85); color: #e2e8f0;
|
|
32
45
|
font: 13px/1 sans-serif; padding: 8px 16px; border-radius: 8px;
|
|
33
|
-
z-index: 5; pointer-events: none;
|
|
46
|
+
z-index: 5; pointer-events: none; transition: opacity .15s;
|
|
34
47
|
}
|
|
35
48
|
</style>
|
|
36
49
|
</head>
|
|
37
50
|
<body>
|
|
38
51
|
<div id="stage"><img id="bg" alt=""></div>
|
|
39
|
-
<div id="mask"></div>
|
|
52
|
+
<div id="maskTop" class="mask"></div>
|
|
53
|
+
<div id="maskBottom" class="mask"></div>
|
|
54
|
+
<div id="maskLeft" class="mask"></div>
|
|
55
|
+
<div id="maskRight" class="mask"></div>
|
|
40
56
|
<div id="sel"><div class="sz"></div></div>
|
|
57
|
+
<div id="hN" class="handle" style="cursor:n-resize"></div>
|
|
58
|
+
<div id="hS" class="handle" style="cursor:s-resize"></div>
|
|
59
|
+
<div id="hE" class="handle" style="cursor:e-resize"></div>
|
|
60
|
+
<div id="hW" class="handle" style="cursor:w-resize"></div>
|
|
61
|
+
<div id="hNE" class="handle" style="cursor:ne-resize"></div>
|
|
62
|
+
<div id="hNW" class="handle" style="cursor:nw-resize"></div>
|
|
63
|
+
<div id="hSE" class="handle" style="cursor:se-resize"></div>
|
|
64
|
+
<div id="hSW" class="handle" style="cursor:sw-resize"></div>
|
|
41
65
|
<div id="toolbar">
|
|
42
|
-
<span class="tip"
|
|
66
|
+
<span class="tip" id="tip">拖动边框微调选区</span>
|
|
43
67
|
<button id="okBtn">✔ 确定</button>
|
|
44
68
|
<button id="cancelBtn">✕ 取消 (Esc)</button>
|
|
45
69
|
</div>
|
|
46
|
-
<div id="hint">拖动鼠标框选要截取的区域 · Esc 取消</div>
|
|
70
|
+
<div id="hint">拖动鼠标框选要截取的区域 · 画完后可拖拽边框微调 · Esc 取消</div>
|
|
47
71
|
|
|
48
72
|
<script>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
73
|
+
var bg = document.getElementById('bg')
|
|
74
|
+
var sel = document.getElementById('sel')
|
|
75
|
+
var toolbar = document.getElementById('toolbar')
|
|
76
|
+
var hint = document.getElementById('hint')
|
|
77
|
+
var tip = document.getElementById('tip')
|
|
78
|
+
var sz = sel.querySelector('.sz')
|
|
79
|
+
var masks = {
|
|
80
|
+
top: document.getElementById('maskTop'),
|
|
81
|
+
bottom: document.getElementById('maskBottom'),
|
|
82
|
+
left: document.getElementById('maskLeft'),
|
|
83
|
+
right: document.getElementById('maskRight'),
|
|
84
|
+
}
|
|
85
|
+
var handles = {
|
|
86
|
+
n: document.getElementById('hN'), s: document.getElementById('hS'),
|
|
87
|
+
e: document.getElementById('hE'), w: document.getElementById('hW'),
|
|
88
|
+
ne: document.getElementById('hNE'), nw: document.getElementById('hNW'),
|
|
89
|
+
se: document.getElementById('hSE'), sw: document.getElementById('hSW'),
|
|
90
|
+
}
|
|
91
|
+
var W = window.innerWidth, H = window.innerHeight
|
|
92
|
+
var MIN = 8
|
|
93
|
+
var rect = null
|
|
94
|
+
var mode = 'draw' // draw | adjust
|
|
95
|
+
var drag = null
|
|
58
96
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
bg.onload = () => {
|
|
97
|
+
window.__screenshot.onData(function (dataUrl) {
|
|
98
|
+
bg.onload = function () {
|
|
62
99
|
window.__screenshot.loaded()
|
|
63
|
-
setTimeout(()
|
|
100
|
+
setTimeout(function () { hint.style.opacity = '0.9' }, 100)
|
|
64
101
|
}
|
|
65
102
|
bg.src = dataUrl
|
|
66
103
|
})
|
|
67
104
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
105
|
+
function clampRect(r) {
|
|
106
|
+
var x = Math.max(0, Math.min(W - MIN, r.x))
|
|
107
|
+
var y = Math.max(0, Math.min(H - MIN, r.y))
|
|
108
|
+
var w = Math.min(r.w, W - x)
|
|
109
|
+
var h = Math.min(r.h, H - y)
|
|
110
|
+
w = Math.max(MIN, w); h = Math.max(MIN, h)
|
|
111
|
+
return { x: x, y: y, w: w, h: h }
|
|
74
112
|
}
|
|
75
113
|
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
drawing = true
|
|
80
|
-
rect = null
|
|
81
|
-
sel.style.display = 'none'
|
|
82
|
-
toolbar.style.display = 'none'
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
document.addEventListener('mousemove', (e) => {
|
|
86
|
-
if (!drawing) return
|
|
87
|
-
const x = Math.min(startX, e.clientX)
|
|
88
|
-
const y = Math.min(startY, e.clientY)
|
|
89
|
-
const w = Math.abs(e.clientX - startX)
|
|
90
|
-
const h = Math.abs(e.clientY - startY)
|
|
91
|
-
rect = { x, y, w, h }
|
|
114
|
+
function layout() {
|
|
115
|
+
if (!rect) return
|
|
116
|
+
var x = rect.x, y = rect.y, w = rect.w, h = rect.h
|
|
92
117
|
sel.style.display = 'block'
|
|
93
118
|
sel.style.left = x + 'px'; sel.style.top = y + 'px'
|
|
94
119
|
sel.style.width = w + 'px'; sel.style.height = h + 'px'
|
|
95
120
|
sz.textContent = Math.round(w) + ' × ' + Math.round(h)
|
|
96
|
-
|
|
121
|
+
// 遮罩(4 块)
|
|
122
|
+
masks.top.style.cssText = 'left:0;top:0;width:' + W + 'px;height:' + y + 'px;display:block'
|
|
123
|
+
masks.bottom.style.cssText = 'left:0;top:' + (y + h) + 'px;width:' + W + 'px;height:' + (H - y - h) + 'px;display:block'
|
|
124
|
+
masks.left.style.cssText = 'left:0;top:' + y + 'px;width:' + x + 'px;height:' + h + 'px;display:block'
|
|
125
|
+
masks.right.style.cssText = 'left:' + (x + w) + 'px;top:' + y + 'px;width:' + (W - x - w) + 'px;height:' + h + 'px;display:block'
|
|
126
|
+
// 手柄
|
|
127
|
+
if (mode === 'adjust') {
|
|
128
|
+
var half = 4.5
|
|
129
|
+
handles.n.style.cssText = 'left:' + (x + w / 2 - half) + 'px;top:' + (y - half) + 'px;display:block'
|
|
130
|
+
handles.s.style.cssText = 'left:' + (x + w / 2 - half) + 'px;top:' + (y + h - half) + 'px;display:block'
|
|
131
|
+
handles.e.style.cssText = 'left:' + (x + w - half) + 'px;top:' + (y + h / 2 - half) + 'px;display:block'
|
|
132
|
+
handles.w.style.cssText = 'left:' + (x - half) + 'px;top:' + (y + h / 2 - half) + 'px;display:block'
|
|
133
|
+
handles.ne.style.cssText = 'left:' + (x + w - half) + 'px;top:' + (y - half) + 'px;display:block'
|
|
134
|
+
handles.nw.style.cssText = 'left:' + (x - half) + 'px;top:' + (y - half) + 'px;display:block'
|
|
135
|
+
handles.se.style.cssText = 'left:' + (x + w - half) + 'px;top:' + (y + h - half) + 'px;display:block'
|
|
136
|
+
handles.sw.style.cssText = 'left:' + (x - half) + 'px;top:' + (y + h - half) + 'px;display:block'
|
|
137
|
+
} else {
|
|
138
|
+
Object.keys(handles).forEach(function (k) { handles[k].style.display = 'none' })
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function inside(e, r) {
|
|
143
|
+
return e.clientX >= r.x && e.clientX <= r.x + r.w && e.clientY >= r.y && e.clientY <= r.y + r.h
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
document.addEventListener('mousedown', function (e) {
|
|
147
|
+
if (e.button !== 0) return
|
|
148
|
+
if (mode === 'draw') {
|
|
149
|
+
drag = { type: 'draw', x0: e.clientX, y0: e.clientY }
|
|
150
|
+
} else {
|
|
151
|
+
// 调整模式:手柄 / 拖动移动 / 外部重画
|
|
152
|
+
var hKey = null
|
|
153
|
+
for (var k in handles) if (e.target === handles[k]) { hKey = k; break }
|
|
154
|
+
if (hKey) {
|
|
155
|
+
drag = { type: 'resize', dir: hKey, x0: e.clientX, y0: e.clientY, orig: { x: rect.x, y: rect.y, w: rect.w, h: rect.h } }
|
|
156
|
+
} else if (inside(e, rect)) {
|
|
157
|
+
drag = { type: 'move', x0: e.clientX, y0: e.clientY, orig: { x: rect.x, y: rect.y } }
|
|
158
|
+
} else {
|
|
159
|
+
// 点击选区外 → 重新画
|
|
160
|
+
mode = 'draw'
|
|
161
|
+
rect = null
|
|
162
|
+
sel.style.display = 'none'
|
|
163
|
+
toolbar.style.display = 'none'
|
|
164
|
+
Object.keys(handles).forEach(function (k) { handles[k].style.display = 'none' })
|
|
165
|
+
masks.top.style.display = masks.bottom.style.display = masks.left.style.display = masks.right.style.display = 'none'
|
|
166
|
+
hint.style.opacity = '0.9'
|
|
167
|
+
drag = { type: 'draw', x0: e.clientX, y0: e.clientY }
|
|
168
|
+
}
|
|
169
|
+
}
|
|
97
170
|
})
|
|
98
171
|
|
|
99
|
-
document.addEventListener('
|
|
100
|
-
if (!
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
172
|
+
document.addEventListener('mousemove', function (e) {
|
|
173
|
+
if (!drag) return
|
|
174
|
+
var dx = e.clientX - drag.x0
|
|
175
|
+
var dy = e.clientY - drag.y0
|
|
176
|
+
if (drag.type === 'draw') {
|
|
177
|
+
rect = clampRect({ x: Math.min(drag.x0, e.clientX), y: Math.min(drag.y0, e.clientY), w: Math.abs(e.clientX - drag.x0), h: Math.abs(e.clientY - drag.y0) })
|
|
178
|
+
layout()
|
|
179
|
+
} else if (drag.type === 'move') {
|
|
180
|
+
rect = clampRect({ x: drag.orig.x + dx, y: drag.orig.y + dy, w: rect.w, h: rect.h })
|
|
181
|
+
layout()
|
|
182
|
+
} else if (drag.type === 'resize') {
|
|
183
|
+
var o = drag.orig
|
|
184
|
+
var r = { x: o.x, y: o.y, w: o.w, h: o.h }
|
|
185
|
+
if (drag.dir.indexOf('e') !== -1) r.w = o.w + dx
|
|
186
|
+
if (drag.dir.indexOf('s') !== -1) r.h = o.h + dy
|
|
187
|
+
if (drag.dir.indexOf('w') !== -1) { r.x = o.x + dx; r.w = o.w - dx }
|
|
188
|
+
if (drag.dir.indexOf('n') !== -1) { r.y = o.y + dy; r.h = o.h - dy }
|
|
189
|
+
rect = clampRect(r)
|
|
190
|
+
layout()
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
document.addEventListener('mouseup', function () {
|
|
195
|
+
if (!drag) return
|
|
196
|
+
drag = null
|
|
197
|
+
if (mode === 'draw' && rect && rect.w >= MIN && rect.h >= MIN) {
|
|
198
|
+
mode = 'adjust'
|
|
199
|
+
var t = document.getElementById('toolbar')
|
|
104
200
|
t.style.display = 'flex'
|
|
105
|
-
t.style.left = Math.min(rect.x + rect.w + 10,
|
|
106
|
-
t.style.top = (rect.y + rect.h +
|
|
201
|
+
t.style.left = Math.min(rect.x + rect.w + 10, W - 230) + 'px'
|
|
202
|
+
t.style.top = (rect.y + rect.h + 14 > H - 60 ? rect.y - 58 : rect.y + rect.h + 14) + 'px'
|
|
107
203
|
hint.style.opacity = '0'
|
|
108
|
-
|
|
109
|
-
rect = null; sel.style.display = 'none'
|
|
204
|
+
layout() // 显示手柄
|
|
110
205
|
}
|
|
111
206
|
})
|
|
112
207
|
|
|
113
|
-
document.getElementById('okBtn').onclick = ()
|
|
208
|
+
document.getElementById('okBtn').onclick = function () {
|
|
114
209
|
if (rect) window.__screenshot.done(rect)
|
|
115
210
|
}
|
|
116
|
-
document.getElementById('cancelBtn').onclick = ()
|
|
117
|
-
|
|
118
|
-
document.addEventListener('keydown', (e) => {
|
|
211
|
+
document.getElementById('cancelBtn').onclick = function () { window.__screenshot.cancel() }
|
|
212
|
+
document.addEventListener('keydown', function (e) {
|
|
119
213
|
if (e.key === 'Escape') window.__screenshot.cancel()
|
|
120
214
|
if (e.key === 'Enter' && rect) window.__screenshot.done(rect)
|
|
121
215
|
})
|