@zzusp/dingtalk-dsh-observer 0.5.0 → 0.5.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/package.json +1 -1
- package/web-client.js +36 -10
package/package.json
CHANGED
package/web-client.js
CHANGED
|
@@ -4,7 +4,7 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
const module = { exports: {} }
|
|
5
5
|
const React = require('react')
|
|
6
6
|
const { Button, Menu, Pill, StateDot } = require('@deepseek-ai/dsh-client-ui-primitives')
|
|
7
|
-
const { useCallback, useEffect, useState } = React
|
|
7
|
+
const { useCallback, useEffect, useLayoutEffect, useRef, useState } = React
|
|
8
8
|
const ENDPOINT = 'http://127.0.0.1:18998'
|
|
9
9
|
const colors = {
|
|
10
10
|
surface: 'var(--dsw-alias-bg-base, #fff)',
|
|
@@ -69,7 +69,7 @@ window.__ModuleLoader__.load({
|
|
|
69
69
|
}
|
|
70
70
|
const authorizationTag = (label, state) => {
|
|
71
71
|
const tone = statusTone[state] || colors.muted
|
|
72
|
-
return React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap:
|
|
72
|
+
return React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 5, minWidth: 58, minHeight: 22, boxSizing: 'border-box', border: `1px solid color-mix(in srgb, ${tone} 18%, transparent)`, borderRadius: 6, background: `color-mix(in srgb, ${tone} 7%, transparent)`, color: tone, padding: '2px 7px', fontSize: 11, fontWeight: 500, lineHeight: 1.35, whiteSpace: 'nowrap' } }, React.createElement(StateDot, { state, size: 6 }), label)
|
|
73
73
|
}
|
|
74
74
|
function SelectMenu({ label, value, options, onChange, minWidth = 150 }) {
|
|
75
75
|
const [open, setOpen] = useState(false)
|
|
@@ -144,11 +144,12 @@ window.__ModuleLoader__.load({
|
|
|
144
144
|
const [authorizationFilter, setAuthorizationFilter] = useState('all')
|
|
145
145
|
const [selectedAuthorizationId, setSelectedAuthorizationId] = useState('')
|
|
146
146
|
const [sidebarWidth, setSidebarWidth] = useState(280)
|
|
147
|
+
const overlayRef = useRef()
|
|
147
148
|
const refresh = useCallback(async () => {
|
|
148
149
|
try { setData(await load()); setUpdatedAt(new Date()); setError(undefined) }
|
|
149
150
|
catch (cause) { setError(cause instanceof Error ? cause.message : String(cause)) }
|
|
150
151
|
}, [])
|
|
151
|
-
|
|
152
|
+
useLayoutEffect(() => {
|
|
152
153
|
if (!isOpen) return undefined
|
|
153
154
|
refresh()
|
|
154
155
|
const timer = window.setInterval(refresh, 5000)
|
|
@@ -164,14 +165,38 @@ window.__ModuleLoader__.load({
|
|
|
164
165
|
sidebar = sidebar.parentElement
|
|
165
166
|
}
|
|
166
167
|
const update = () => {
|
|
167
|
-
const
|
|
168
|
-
if (Number.isFinite(
|
|
168
|
+
const right = sidebar?.getBoundingClientRect().right
|
|
169
|
+
if (Number.isFinite(right) && right >= 40 && right <= 400) {
|
|
170
|
+
const roundedRight = Math.round(right)
|
|
171
|
+
if (overlayRef.current) overlayRef.current.style.paddingLeft = `${roundedRight}px`
|
|
172
|
+
setSidebarWidth((current) => current === roundedRight ? current : roundedRight)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
let animationFrame
|
|
176
|
+
let trackingUntil = 0
|
|
177
|
+
const trackTransition = () => {
|
|
178
|
+
trackingUntil = performance.now() + 700
|
|
179
|
+
if (animationFrame) return
|
|
180
|
+
const track = () => {
|
|
181
|
+
update()
|
|
182
|
+
if (performance.now() < trackingUntil) animationFrame = window.requestAnimationFrame(track)
|
|
183
|
+
else animationFrame = undefined
|
|
184
|
+
}
|
|
185
|
+
animationFrame = window.requestAnimationFrame(track)
|
|
169
186
|
}
|
|
170
187
|
update()
|
|
171
188
|
const observer = sidebar && typeof ResizeObserver === 'function' ? new ResizeObserver(update) : undefined
|
|
172
189
|
if (sidebar && observer) observer.observe(sidebar)
|
|
190
|
+
sidebar?.addEventListener('transitionrun', trackTransition)
|
|
191
|
+
document.addEventListener('click', trackTransition, true)
|
|
173
192
|
window.addEventListener('resize', update)
|
|
174
|
-
return () => {
|
|
193
|
+
return () => {
|
|
194
|
+
observer?.disconnect()
|
|
195
|
+
sidebar?.removeEventListener('transitionrun', trackTransition)
|
|
196
|
+
document.removeEventListener('click', trackTransition, true)
|
|
197
|
+
window.removeEventListener('resize', update)
|
|
198
|
+
if (animationFrame) window.cancelAnimationFrame(animationFrame)
|
|
199
|
+
}
|
|
175
200
|
}, [isOpen])
|
|
176
201
|
useEffect(() => {
|
|
177
202
|
const closeForSession = (event) => {
|
|
@@ -313,7 +338,8 @@ window.__ModuleLoader__.load({
|
|
|
313
338
|
})
|
|
314
339
|
const menu = React.createElement('nav', { 'aria-label': '运行看板视图', style: { minWidth: 0, height: 38, display: 'flex', alignItems: 'stretch', gap: 28, overflowX: 'auto', padding: '0 24px' } },
|
|
315
340
|
...pages.map((page) => React.createElement('button', { key: page.id, type: 'button', onClick: () => setActivePage(page.id), 'aria-current': activePage === page.id ? 'page' : undefined, style: { position: 'relative', border: 0, borderBottom: activePage === page.id ? '2px solid #4d6bfe' : '2px solid transparent', borderRadius: 0, padding: '0 0 8px', cursor: 'pointer', font: 'inherit', fontSize: 13, fontWeight: 400, color: activePage === page.id ? '#4d6bfe' : colors.muted, background: 'transparent', outline: 'none', whiteSpace: 'nowrap' } }, page.label)))
|
|
316
|
-
const
|
|
341
|
+
const refreshIcon = React.createElement('svg', { width: 14, height: 14, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true }, React.createElement('path', { d: 'M20 11a8 8 0 1 0-2.34 5.66' }), React.createElement('path', { d: 'M20 4v7h-7' }))
|
|
342
|
+
const header = React.createElement('header', { style: { position: 'sticky', top: 0, zIndex: 2, borderBottom: `1px solid ${colors.border}`, background: colors.surface, pointerEvents: 'auto' } },
|
|
317
343
|
React.createElement('div', { style: { height: 52, boxSizing: 'border-box', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 24, padding: '0 24px' } },
|
|
318
344
|
React.createElement('div', { style: { minWidth: 0, display: 'flex', alignItems: 'center', gap: 14 } },
|
|
319
345
|
React.createElement('span', { style: { fontSize: 15, fontWeight: 400, whiteSpace: 'nowrap' } }, '运行看板'),
|
|
@@ -322,7 +348,7 @@ window.__ModuleLoader__.load({
|
|
|
322
348
|
React.createElement('span', { style: { color: updatedAt ? statusTone.done : colors.muted } }, updatedAt ? '运行正常' : '正在连接'),
|
|
323
349
|
updatedAt ? React.createElement('span', { 'aria-hidden': true, style: { width: 1, height: 12, background: colors.border } }) : null,
|
|
324
350
|
updatedAt ? React.createElement('span', { title: fmt(updatedAt) }, `更新于 ${fmtTime(updatedAt)}`) : null)),
|
|
325
|
-
React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', onClick: refresh }, '刷新')),
|
|
351
|
+
React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', onClick: refresh, style: { gap: 6 } }, '刷新', refreshIcon)),
|
|
326
352
|
menu)
|
|
327
353
|
const dataViewTabs = React.createElement('div', { role: 'tablist', 'aria-label': '群聊数据视图', style: { display: 'flex', alignSelf: 'stretch', gap: 20 } },
|
|
328
354
|
...[{ id: 'messages', label: `群消息 ${selectedMessages.length}` }, { id: 'outbox', label: `Outbox ${selectedOutbox.length}` }].map((item) => React.createElement('button', { key: item.id, role: 'tab', 'aria-selected': groupTableView === item.id, type: 'button', onClick: () => setGroupTableView(item.id), style: { border: 0, borderBottom: groupTableView === item.id ? `2px solid ${colors.accent}` : '2px solid transparent', background: 'transparent', color: groupTableView === item.id ? colors.accent : colors.muted, padding: '0 2px', fontFamily: 'inherit', fontSize: 12, cursor: 'pointer' } }, item.label)))
|
|
@@ -429,12 +455,12 @@ window.__ModuleLoader__.load({
|
|
|
429
455
|
)
|
|
430
456
|
const pageContent = activePage === 'tasks' ? tasksPage : activePage === 'authorizations' ? authorizationsPage : activePage === 'archive' ? archivePage : activePage === 'alerts' ? alertsPage : groupsPage
|
|
431
457
|
const pageViewport = React.createElement('div', { style: { minHeight: 'calc(100dvh - 138px)', boxSizing: 'border-box' } }, pageContent)
|
|
432
|
-
const main = React.createElement('main', { style: { maxWidth: activePage === 'tasks' ? 1480 : 1240, minHeight: 'calc(100dvh - 90px)', boxSizing: 'border-box', margin: '0 auto', padding: '24px 24px 32px', display: 'grid', alignContent: 'start', gap: 20 } },
|
|
458
|
+
const main = React.createElement('main', { style: { maxWidth: activePage === 'tasks' ? 1480 : 1240, minHeight: 'calc(100dvh - 90px)', boxSizing: 'border-box', margin: '0 auto', padding: '24px 24px 32px', display: 'grid', alignContent: 'start', gap: 20, pointerEvents: 'auto' } },
|
|
433
459
|
error ? React.createElement('div', { style: { ...card, borderColor: colors.danger, color: colors.danger } }, `无法连接 resident 插件:${error}`) : null,
|
|
434
460
|
navigationError ? React.createElement('div', { style: { ...card, borderColor: colors.danger, color: colors.danger } }, `无法打开 DSH Session:${navigationError}`) : null,
|
|
435
461
|
pageViewport
|
|
436
462
|
)
|
|
437
|
-
return React.createElement('div', { style: { position: 'fixed',
|
|
463
|
+
return React.createElement('div', { ref: overlayRef, style: { position: 'fixed', inset: 0, paddingLeft: sidebarWidth, boxSizing: 'border-box', zIndex: 900, minWidth: 0, background: colors.surface, color: 'inherit', overflow: 'auto', pointerEvents: 'none' } }, header, main)
|
|
438
464
|
}
|
|
439
465
|
function apply(ctx) {
|
|
440
466
|
ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({ name: 'sidebar.footer.action', id: 'dingtalk-dsh-observer-entry', order: 5, inject: () => ({}) }, SidebarAction))
|