@zzusp/dingtalk-dsh-observer 0.5.3 → 0.5.4
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 +34 -43
package/package.json
CHANGED
package/web-client.js
CHANGED
|
@@ -54,9 +54,11 @@ window.__ModuleLoader__.load({
|
|
|
54
54
|
const short = (value) => value ? String(value).replace(/^session-/, '').slice(0, 14) : '—'
|
|
55
55
|
const pill = (tone) => ({ display: 'inline-flex', alignItems: 'center', borderRadius: 999, padding: '3px 8px', fontSize: 12, color: tone, background: `color-mix(in srgb, ${tone} 12%, transparent)` })
|
|
56
56
|
const card = { border: `1px solid ${colors.border}`, borderRadius: 12, background: colors.cardSurface, padding: 16, boxShadow: '0 4px 16px rgba(15,23,42,.07)' }
|
|
57
|
-
const tableFrame = { border: `1px solid ${colors.border}`, borderRadius: 12, background: colors.cardSurface, overflow: 'hidden'
|
|
58
|
-
const tableHeadCell = { height:
|
|
59
|
-
const tableBodyCell = { padding: '12px', borderTop: `1px solid ${colors.border}`, fontSize: 12, lineHeight: 1.55, verticalAlign: '
|
|
57
|
+
const tableFrame = { border: `1px solid ${colors.border}`, borderRadius: 12, background: colors.cardSurface, overflow: 'hidden' }
|
|
58
|
+
const tableHeadCell = { height: 42, boxSizing: 'border-box', padding: '0 16px', color: colors.muted, fontSize: 11, fontWeight: 500, verticalAlign: 'middle' }
|
|
59
|
+
const tableBodyCell = { padding: '12px 16px', borderTop: `1px solid ${colors.border}`, fontSize: 12, lineHeight: 1.55, verticalAlign: 'middle' }
|
|
60
|
+
const tableBodyContent = { display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden', overflowWrap: 'anywhere' }
|
|
61
|
+
const clampTableContent = (...children) => React.createElement('div', { style: tableBodyContent }, ...children)
|
|
60
62
|
const tableFooter = { minHeight: 48, boxSizing: 'border-box', display: 'flex', justifyContent: 'flex-end', alignItems: 'center', gap: 8, padding: '8px 12px', borderTop: `1px solid ${colors.border}`, background: colors.surface2 }
|
|
61
63
|
const toolbar = { minHeight: 48, boxSizing: 'border-box', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, padding: '8px 12px', borderBottom: `1px solid ${colors.border}`, background: colors.cardSurface }
|
|
62
64
|
const statusTone = {
|
|
@@ -76,9 +78,6 @@ window.__ModuleLoader__.load({
|
|
|
76
78
|
const anchor = React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', 'aria-label': label, 'aria-expanded': open, onClick: () => setOpen((current) => !current), style: { minWidth, justifyContent: 'space-between', gap: 16, fontWeight: 400 } }, React.createElement('span', { style: { minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, selected?.label || value), React.createElement('span', { 'aria-hidden': true, style: { color: colors.muted, fontSize: 9, transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .15s ease' } }, '▼'))
|
|
77
79
|
return React.createElement(Menu, { open, anchor, items: options, selectedId: value, onSelect: (id) => { onChange(id); setOpen(false) }, onClose: () => setOpen(false), align: 'end', portal: true, dense: true, compact: true })
|
|
78
80
|
}
|
|
79
|
-
const pageHeader = (title, description) => React.createElement('div', { style: { minHeight: 44, marginBottom: 16 } },
|
|
80
|
-
React.createElement('h1', { style: { margin: 0, fontSize: 18, lineHeight: 1.45, fontWeight: 600 } }, title), React.createElement('p', { style: { margin: '4px 0 0', color: colors.muted, fontSize: 12, lineHeight: 1.5 } }, description))
|
|
81
|
-
const sectionHeader = (title, meta) => React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, marginBottom: 12 } }, React.createElement('h2', { style: { margin: 0, fontSize: 15, lineHeight: 1.45, fontWeight: 600 } }, title), meta ? React.createElement('span', { style: { color: colors.muted, fontSize: 11 } }, meta) : null)
|
|
82
81
|
const emptyState = (text) => React.createElement('div', { style: { minHeight: 112, display: 'grid', placeItems: 'center', color: colors.muted, fontSize: 12, border: `1px dashed ${colors.border}`, borderRadius: 10, background: colors.surface2 } }, text)
|
|
83
82
|
async function get(path) {
|
|
84
83
|
const response = await fetch(`${ENDPOINT}${path}`, { method: 'GET', headers: { accept: 'application/json' } })
|
|
@@ -209,13 +208,13 @@ window.__ModuleLoader__.load({
|
|
|
209
208
|
skipped: { label: '历史补拉·未投递', state: 'warning' },
|
|
210
209
|
unknown: { label: '历史状态未知', state: 'warning' },
|
|
211
210
|
}
|
|
212
|
-
const messageRows = visibleMessages.map((message) => {
|
|
211
|
+
const messageRows = visibleMessages.map((message, rowIndex) => {
|
|
213
212
|
const status = delivery[message.agentDeliveryStatus] || delivery.unknown
|
|
214
|
-
return React.createElement('tr', { key: message.messageId },
|
|
215
|
-
React.createElement('td', { style: { ...tableBodyCell, width:
|
|
216
|
-
React.createElement('td', {
|
|
217
|
-
React.createElement('td', {
|
|
218
|
-
React.createElement('td', { style: { ...tableBodyCell, width: 150 } }, React.createElement('code', { title: message.messageId, style: { fontSize: 10, color: colors.muted } }, `#${message.sequence ?? '—'} · ${short(message.messageId)}`)))
|
|
213
|
+
return React.createElement('tr', { key: message.messageId, style: { background: rowIndex % 2 ? `color-mix(in srgb, ${colors.surface2} 55%, transparent)` : colors.cardSurface } },
|
|
214
|
+
React.createElement('td', { style: { ...tableBodyCell, width: 104 }, title: message.agentDeliveryError || '' }, clampTableContent(statusTag(status.label, status.state))),
|
|
215
|
+
React.createElement('td', { style: { ...tableBodyCell, width: 160 } }, clampTableContent(React.createElement('strong', { style: { fontSize: 12 } }, message.senderName || message.senderOpenDingTalkId || '发送人未记录'), React.createElement('div', { style: { marginTop: 3, fontSize: 10.5, color: colors.muted } }, fmt(message.occurredAt)))),
|
|
216
|
+
React.createElement('td', { title: message.text, style: tableBodyCell }, clampTableContent(message.text || '(空消息)')),
|
|
217
|
+
React.createElement('td', { style: { ...tableBodyCell, width: 150 } }, clampTableContent(React.createElement('code', { title: message.messageId, style: { fontSize: 10, color: colors.muted } }, `#${message.sequence ?? '—'} · ${short(message.messageId)}`))))
|
|
219
218
|
})
|
|
220
219
|
const selectedOutbox = [...(selectedGroup?.outbox || [])].reverse()
|
|
221
220
|
const outboxState = (message) => message.recallStatus === 'recalled' ? 'recalled' : message.status === 'pending' && message.readbackRequired === true ? 'waiting' : 'confirmed'
|
|
@@ -229,16 +228,15 @@ window.__ModuleLoader__.load({
|
|
|
229
228
|
pending: { label: '已回读', state: 'done' },
|
|
230
229
|
recalled: { label: '已撤回', state: 'neutral' },
|
|
231
230
|
}
|
|
232
|
-
const outboxRows = visibleOutbox.map((message) => {
|
|
231
|
+
const outboxRows = visibleOutbox.map((message, rowIndex) => {
|
|
233
232
|
const status = message.recallStatus === 'recalled' ? outboundStatus.recalled : message.status === 'pending' && message.readbackRequired === true ? { label: '待回读', state: 'warning' } : outboundStatus[message.status] || outboundStatus.sent
|
|
234
|
-
return React.createElement('tr', { key: message.outboundId },
|
|
235
|
-
React.createElement('td', { style: { ...tableBodyCell, width:
|
|
236
|
-
React.createElement('td', { title: message.text, style:
|
|
233
|
+
return React.createElement('tr', { key: message.outboundId, style: { background: rowIndex % 2 ? `color-mix(in srgb, ${colors.surface2} 55%, transparent)` : colors.cardSurface } },
|
|
234
|
+
React.createElement('td', { style: { ...tableBodyCell, width: 104 } }, clampTableContent(statusTag(status.label, status.state))),
|
|
235
|
+
React.createElement('td', { title: message.text, style: tableBodyCell }, clampTableContent(message.text || '(空消息)')),
|
|
237
236
|
React.createElement('td', { style: { ...tableBodyCell, width: 180 } },
|
|
238
|
-
React.createElement('div', null, React.createElement('code', { title: message.sourceMessageId, style: { fontSize: 10, color: colors.muted } }, short(message.sourceMessageId))),
|
|
239
|
-
|
|
240
|
-
React.createElement('td', { style: { ...tableBodyCell, width:
|
|
241
|
-
React.createElement('td', { style: { ...tableBodyCell, width: 150 } }, React.createElement('code', { title: message.outboundId, style: { fontSize: 10, color: colors.muted } }, short(message.outboundId))))
|
|
237
|
+
clampTableContent(React.createElement('div', null, React.createElement('code', { title: message.sourceMessageId, style: { fontSize: 10, color: colors.muted } }, short(message.sourceMessageId))), message.replyToMessageId ? React.createElement('div', { style: { marginTop: 5, fontSize: 10.5, color: colors.muted } }, '回复 ', React.createElement('code', { title: message.replyToMessageId }, short(message.replyToMessageId))) : null)),
|
|
238
|
+
React.createElement('td', { style: { ...tableBodyCell, width: 170 } }, clampTableContent(React.createElement('code', { title: message.deliveredMessageId || '', style: { fontSize: 10, color: colors.muted } }, message.deliveredMessageId ? short(message.deliveredMessageId) : '历史未记录'))),
|
|
239
|
+
React.createElement('td', { style: { ...tableBodyCell, width: 150 } }, clampTableContent(React.createElement('code', { title: message.outboundId, style: { fontSize: 10, color: colors.muted } }, short(message.outboundId)))))
|
|
242
240
|
})
|
|
243
241
|
const renderTaskCard = (task) => {
|
|
244
242
|
const group = groupsById.get(task.groupId)
|
|
@@ -266,7 +264,7 @@ window.__ModuleLoader__.load({
|
|
|
266
264
|
React.createElement('div', { style: { display: 'grid', gap: 3 } }, React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 10.5, color: colors.muted } }, React.createElement(IconGoalOutline16, { size: 12, 'aria-label': '任务目标' }), '任务目标'), React.createElement('div', { title: displayObjective, style: { fontSize: 11, lineHeight: 1.5, display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical', overflow: 'hidden', overflowWrap: 'anywhere' } }, displayObjective)),
|
|
267
265
|
React.createElement('div', { style: { paddingTop: showCheckpoints ? 3 : 0 } },
|
|
268
266
|
showCheckpoints ? React.createElement('section', { style: { border: `1px solid ${colors.border}`, borderRadius: 10, background: `color-mix(in srgb, ${colors.muted} 6%, ${colors.cardSurface})`, overflow: 'hidden' } },
|
|
269
|
-
React.createElement('div', { role: 'button', tabIndex: 0, 'aria-expanded': checkpointsExpanded, 'aria-label': checkpointsExpanded ? '收起检查点' : `展开全部 ${checkpoints.length} 个检查点`, 'data-task-card-action': 'toggle-checkpoints', onClick: (event) => { event.stopPropagation(); setExpandedCheckpointTaskId(checkpointsExpanded ? '' : task.taskId) }, onKeyDown: (event) => { if (event.key !== 'Enter' && event.key !== ' ') return; event.preventDefault(); event.stopPropagation(); setExpandedCheckpointTaskId(checkpointsExpanded ? '' : task.taskId) }, style: { minHeight: 34, boxSizing: 'border-box', display: 'flex', alignItems: 'center', gap: 8, padding: '7px 9px', fontSize: 10.5, cursor: 'pointer' } }, React.createElement('span', { style: { flex: '0 0 auto', display: 'inline-flex', alignItems: 'center', gap: 4, color: colors.muted } }, React.createElement(IconChecklistOutline14, { size: 12, 'aria-label': '
|
|
267
|
+
React.createElement('div', { role: 'button', tabIndex: 0, 'aria-expanded': checkpointsExpanded, 'aria-label': checkpointsExpanded ? '收起检查点' : `展开全部 ${checkpoints.length} 个检查点`, 'data-task-card-action': 'toggle-checkpoints', onClick: (event) => { event.stopPropagation(); setExpandedCheckpointTaskId(checkpointsExpanded ? '' : task.taskId) }, onKeyDown: (event) => { if (event.key !== 'Enter' && event.key !== ' ') return; event.preventDefault(); event.stopPropagation(); setExpandedCheckpointTaskId(checkpointsExpanded ? '' : task.taskId) }, style: { minHeight: 34, boxSizing: 'border-box', display: 'flex', alignItems: 'center', gap: 8, padding: '7px 9px', fontSize: 10.5, cursor: 'pointer' } }, React.createElement('span', { style: { flex: '0 0 auto', display: 'inline-flex', alignItems: 'center', gap: 4, color: colors.muted } }, React.createElement(IconChecklistOutline14, { size: 12, 'aria-label': '任务' }), '任务'), React.createElement('div', { role: 'progressbar', 'aria-label': '检查点进度', 'aria-valuemin': 0, 'aria-valuemax': 100, 'aria-valuenow': progress, style: { flex: '1 1 auto', minWidth: 24, height: 4, borderRadius: 999, overflow: 'hidden', background: `color-mix(in srgb, ${colors.muted} 22%, transparent)` } }, React.createElement('div', { style: { width: `${progress}%`, height: '100%', borderRadius: 'inherit', background: completedCheckpointCount === checkpoints.length ? statusTone.done : colors.accent, transition: 'width 180ms ease' } })), React.createElement('span', { style: { flex: '0 0 auto', color: completedCheckpointCount === checkpoints.length ? statusTone.done : colors.muted } }, `${completedCheckpointCount} / ${checkpoints.length}`), React.createElement(checkpointsExpanded ? IconChevronUpOutline14 : IconChevronDownOutline14, { size: 14, 'aria-hidden': true, style: { flex: '0 0 auto', color: colors.muted } })),
|
|
270
268
|
checkpointsExpanded ? React.createElement('div', { style: { display: 'grid', gap: 4, padding: '2px 9px 9px' } }, ...checkpoints.map((checkpoint, index) => { const completed = completedCheckpointNames.has(checkpoint); const current = !completed && currentCheckpoint === checkpoint; const tone = completed ? statusTone.done : current ? colors.accent : colors.muted; const duration = checkpointDuration(checkpoint, currentCheckpointEvents, Date.now()); return React.createElement('div', { key: `${index}:${checkpoint}`, title: checkpoint, style: { minWidth: 0, display: 'grid', gridTemplateColumns: '12px minmax(0,1fr) 64px', gap: 5, alignItems: 'start', fontSize: 10.5, lineHeight: 1.4 } }, React.createElement('span', { 'aria-hidden': true, style: { width: 12, height: 14, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', color: tone } }, completed ? React.createElement(CheckpointDoneIcon, { size: 12 }) : current ? React.createElement(StateDot, { state: 'ongoing', size: 10 }) : '○'), React.createElement('span', { style: { color: 'inherit', display: '-webkit-box', WebkitLineClamp: 'unset', WebkitBoxOrient: 'vertical', overflow: 'hidden', overflowWrap: 'anywhere' } }, checkpoint), React.createElement('span', { title: `执行时长 ${duration}`, style: { width: 64, color: colors.muted, textAlign: 'right', whiteSpace: 'nowrap', fontVariantNumeric: 'tabular-nums' } }, duration)) })) : null) : null,
|
|
271
269
|
task.waitingReason ? React.createElement('div', { title: task.waitingReason, style: { fontSize: 10.5, lineHeight: 1.45, color: colors.warning } }, `等待:${task.waitingReason}`) : null),
|
|
272
270
|
React.createElement('div', { style: { minWidth: 0, marginTop: 3, paddingTop: 9, borderTop: `1px solid ${colors.border}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 } },
|
|
@@ -309,7 +307,7 @@ window.__ModuleLoader__.load({
|
|
|
309
307
|
const bucketColumns = taskBuckets.map((bucket) => {
|
|
310
308
|
const tasks = (data?.tasks || []).filter((task) => task.state === bucket.state && !task.archivedAt).sort((left, right) => String(right.updatedAt).localeCompare(String(left.updatedAt)))
|
|
311
309
|
const taskCards = tasks.length ? tasks.map(renderTaskCard) : [React.createElement('div', { key: 'empty', style: { border: `1px dashed ${colors.border}`, borderRadius: 10, minHeight: 90, display: 'grid', placeItems: 'center', color: colors.muted, fontSize: 12 } }, '暂无任务')]
|
|
312
|
-
return React.createElement('div', { key: bucket.state, style: { boxSizing: 'border-box', borderRadius: 14, background: bucket.background, padding: 10, display: 'flex', flexDirection: 'column', height: 'calc(100dvh -
|
|
310
|
+
return React.createElement('div', { key: bucket.state, style: { boxSizing: 'border-box', borderRadius: 14, background: bucket.background, padding: 10, display: 'flex', flexDirection: 'column', height: 'calc(100dvh - 116px)', minHeight: 420, maxHeight: 'calc(100dvh - 116px)', overflow: 'hidden' } },
|
|
313
311
|
React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8, padding: '4px 6px 10px' } }, React.createElement('strong', { style: { display: 'inline-flex', alignItems: 'center', borderRadius: 999, padding: '3px 9px', fontSize: 11.5, fontWeight: 650, lineHeight: 1.4, color: 'var(--dsw-alias-label-primary-inverted, #fff)', background: bucket.tone } }, bucket.label), React.createElement('span', { style: { borderRadius: 999, background: colors.cardSurface, padding: '2px 7px', fontSize: 10.5, color: colors.muted } }, tasks.length)),
|
|
314
312
|
React.createElement('div', { style: { flex: 1, minHeight: 0, padding: '8px 12px 16px 8px', display: 'flex', flexDirection: 'column', gap: 10, overflowY: 'scroll', scrollbarGutter: 'stable' } }, ...taskCards))
|
|
315
313
|
})
|
|
@@ -339,18 +337,16 @@ window.__ModuleLoader__.load({
|
|
|
339
337
|
: React.createElement(SelectMenu, { label: '筛选发件状态', value: outboxStatusFilter, options: [{ id: 'all', label: '全部发件状态' }, { id: 'confirmed', label: '已回读' }, { id: 'waiting', label: '待回读' }, { id: 'recalled', label: '已撤回' }], onChange: (value) => { setOutboxStatusFilter(value); setOutboxPage(1) } })))
|
|
340
338
|
const messagesTable = React.createElement(React.Fragment, null,
|
|
341
339
|
React.createElement('div', { style: { overflowX: 'auto' } }, React.createElement('table', { style: { width: '100%', minWidth: 820, borderCollapse: 'collapse', tableLayout: 'fixed' } },
|
|
342
|
-
React.createElement('thead', null, React.createElement('tr', { style: { background: colors.surface2, textAlign: 'left' } }, React.createElement('th', { style: { ...tableHeadCell, width:
|
|
340
|
+
React.createElement('thead', null, React.createElement('tr', { style: { background: colors.surface2, textAlign: 'left' } }, React.createElement('th', { style: { ...tableHeadCell, width: 104 } }, 'Agent 投递'), React.createElement('th', { style: { ...tableHeadCell, width: 160 } }, '发送人 / 时间'), React.createElement('th', { style: tableHeadCell }, '消息内容'), React.createElement('th', { style: { ...tableHeadCell, width: 150 } }, '消息'))),
|
|
343
341
|
React.createElement('tbody', null, ...(messageRows.length ? messageRows : [React.createElement('tr', { key: 'empty' }, React.createElement('td', { colSpan: 4, style: { ...tableBodyCell, padding: 36, textAlign: 'center', color: colors.muted } }, '暂无符合条件的群聊消息'))])))),
|
|
344
342
|
React.createElement('div', { style: tableFooter }, React.createElement('span', { style: { marginRight: 'auto', fontSize: 11, color: colors.muted } }, `${filteredMessages.length} 条 · 每页 ${pageSize} 条`), React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', disabled: currentMessagePage <= 1, onClick: () => setMessagePage((page) => Math.max(1, page - 1)) }, '上一页'), React.createElement('span', { style: { fontSize: 11, color: colors.muted } }, `${currentMessagePage} / ${pageCount}`), React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', disabled: currentMessagePage >= pageCount, onClick: () => setMessagePage((page) => Math.min(pageCount, page + 1)) }, '下一页')))
|
|
345
343
|
const outboxTable = React.createElement(React.Fragment, null,
|
|
346
344
|
React.createElement('div', { style: { overflowX: 'auto' } }, React.createElement('table', { style: { width: '100%', minWidth: 900, borderCollapse: 'collapse', tableLayout: 'fixed' } },
|
|
347
|
-
React.createElement('thead', null, React.createElement('tr', { style: { background: colors.surface2, textAlign: 'left' } }, React.createElement('th', { style: { ...tableHeadCell, width:
|
|
345
|
+
React.createElement('thead', null, React.createElement('tr', { style: { background: colors.surface2, textAlign: 'left' } }, React.createElement('th', { style: { ...tableHeadCell, width: 104 } }, '发送状态'), React.createElement('th', { style: tableHeadCell }, '消息内容'), React.createElement('th', { style: { ...tableHeadCell, width: 180 } }, '来源 / 回复目标'), React.createElement('th', { style: { ...tableHeadCell, width: 170 } }, '投递消息 ID'), React.createElement('th', { style: { ...tableHeadCell, width: 150 } }, '发信箱 ID'))),
|
|
348
346
|
React.createElement('tbody', null, ...(outboxRows.length ? outboxRows : [React.createElement('tr', { key: 'empty' }, React.createElement('td', { colSpan: 5, style: { ...tableBodyCell, padding: 36, textAlign: 'center', color: colors.muted } }, '暂无符合条件的 Agent 发件记录'))])))),
|
|
349
347
|
React.createElement('div', { style: tableFooter }, React.createElement('span', { style: { marginRight: 'auto', fontSize: 11, color: colors.muted } }, `${filteredOutbox.length} 条 · 每页 ${outboxPageSize} 条`), React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', disabled: currentOutboxPage <= 1, onClick: () => setOutboxPage((page) => Math.max(1, page - 1)) }, '上一页'), React.createElement('span', { style: { fontSize: 11, color: colors.muted } }, `${currentOutboxPage} / ${outboxPageCount}`), React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', disabled: currentOutboxPage >= outboxPageCount, onClick: () => setOutboxPage((page) => Math.min(outboxPageCount, page + 1)) }, '下一页')))
|
|
350
|
-
const groupsPage = React.createElement(React.
|
|
351
|
-
|
|
352
|
-
React.createElement('section', null, sectionHeader('消息记录', '收信箱与发信箱记录'), React.createElement('div', { style: tableFrame }, selectedGroupSummary, groupTableToolbar, groupTableView === 'messages' ? messagesTable : outboxTable)))
|
|
353
|
-
const tasksPage = React.createElement(React.Fragment, null, pageHeader('任务看板', '按执行阶段查看任务、叶子会话和目标进展。'), React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(4, minmax(300px, 1fr))', gap: 16, overflowX: 'auto', alignItems: 'start', paddingBottom: 8 } }, ...bucketColumns))
|
|
348
|
+
const groupsPage = React.createElement('section', null, React.createElement('div', { style: tableFrame }, selectedGroupSummary, groupTableToolbar, groupTableView === 'messages' ? messagesTable : outboxTable))
|
|
349
|
+
const tasksPage = React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(4, minmax(300px, 1fr))', gap: 16, overflowX: 'auto', alignItems: 'start', paddingBottom: 8 } }, ...bucketColumns)
|
|
354
350
|
const authorizationStatus = {
|
|
355
351
|
'pending-send': { label: '待发送', state: 'warning' },
|
|
356
352
|
'waiting-reply': { label: '待批复', state: 'warning' },
|
|
@@ -378,14 +374,14 @@ window.__ModuleLoader__.load({
|
|
|
378
374
|
const authorizationDetailField = (label, value) => React.createElement('div', { style: { display: 'grid', gap: 5 } },
|
|
379
375
|
React.createElement('strong', { style: { fontSize: 11, color: colors.muted } }, label),
|
|
380
376
|
React.createElement('div', { style: { fontSize: 13, lineHeight: 1.65, whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' } }, value || '—'))
|
|
381
|
-
const authorizationRows = visibleAuthorizationItems.map((item) => {
|
|
377
|
+
const authorizationRows = visibleAuthorizationItems.map((item, rowIndex) => {
|
|
382
378
|
const pending = item.status !== 'answered'
|
|
383
379
|
const status = pending ? authorizationStatus[item.status] : authorizationDecision[item.decision] || authorizationStatus.answered
|
|
384
380
|
const group = groupsById.get(item.groupId)
|
|
385
|
-
return React.createElement('div', { key: item.requestId, style: { width: '100%', minWidth: 0, boxSizing: 'border-box', display: 'grid', gridTemplateColumns: '
|
|
381
|
+
return React.createElement('div', { key: item.requestId, style: { width: '100%', minWidth: 0, boxSizing: 'border-box', display: 'grid', gridTemplateColumns: '104px minmax(220px, 1.1fr) minmax(280px, 1.5fr) 126px 52px', alignItems: 'center', gap: 16, borderTop: `1px solid ${colors.border}`, background: rowIndex % 2 ? `color-mix(in srgb, ${colors.surface2} 55%, transparent)` : colors.cardSurface, color: 'inherit', padding: '12px 16px' } },
|
|
386
382
|
React.createElement('div', { style: { justifySelf: 'start' } }, statusTag(status.label, status.state)),
|
|
387
|
-
React.createElement('span', { style: { minWidth: 0 } }, React.createElement('strong', { title: item.objective, style: { display: '
|
|
388
|
-
React.createElement('span', { style: { minWidth: 0 } }, React.createElement('span', { title: item.requestedAction, style: { display: '
|
|
383
|
+
React.createElement('span', { style: { minWidth: 0 } }, React.createElement('strong', { title: item.objective, style: { display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: 12.5, lineHeight: 1.5 } }, item.objective), React.createElement('span', { style: { display: 'block', marginTop: 3, color: colors.muted, fontSize: 10.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, group?.name || item.groupId)),
|
|
384
|
+
React.createElement('span', { style: { minWidth: 0 } }, React.createElement('span', { title: item.requestedAction, style: { display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: 11.5, lineHeight: 1.55, color: colors.muted } }, item.requestedAction), item.risk && item.risk !== '未单独说明' ? React.createElement('span', { style: { display: 'block', marginTop: 3, color: colors.danger, fontSize: 10.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, `风险 · ${item.risk}`) : null),
|
|
389
385
|
React.createElement('span', { style: { color: colors.muted, fontSize: 10.5, lineHeight: 1.5 } }, fmt(item.createdAt)),
|
|
390
386
|
React.createElement(Button, { variant: 'ghost', size: 'sm', type: 'button', onClick: () => setSelectedAuthorizationId(item.requestId) }, '查看'))
|
|
391
387
|
})
|
|
@@ -406,11 +402,10 @@ window.__ModuleLoader__.load({
|
|
|
406
402
|
React.createElement('input', { 'aria-label': `审批意见 ${selectedAuthorization.requestId}`, value: authorizationComments[selectedAuthorization.requestId] || '', onChange: (event) => setAuthorizationComments((current) => ({ ...current, [selectedAuthorization.requestId]: event.target.value })), placeholder: '审批意见(可选)', style: { minWidth: 0, border: `1px solid ${colors.border}`, borderRadius: 9, background: colors.surface2, color: 'inherit', padding: '9px 11px', fontFamily: 'inherit', fontSize: 12 } }),
|
|
407
403
|
React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', disabled: decidingAuthorizationId === selectedAuthorization.requestId, onClick: () => decideAuthorization(selectedAuthorization.requestId, 'rejected'), style: { color: colors.danger } }, '拒绝'),
|
|
408
404
|
React.createElement(Button, { variant: 'primary', size: 'sm', type: 'button', disabled: decidingAuthorizationId === selectedAuthorization.requestId, onClick: () => decideAuthorization(selectedAuthorization.requestId, 'approved') }, decidingAuthorizationId === selectedAuthorization.requestId ? '处理中…' : '批准')) : null)) : null
|
|
409
|
-
const authorizationsPage = React.createElement(React.Fragment, null,
|
|
410
|
-
sectionHeader('审批记录', `${authorizationItems.length} 条 · 每页 ${authorizationPageSize} 条`),
|
|
405
|
+
const authorizationsPage = React.createElement(React.Fragment, null, React.createElement('section', null,
|
|
411
406
|
React.createElement('div', { style: tableFrame },
|
|
412
|
-
React.createElement('div', { style: toolbar }, React.createElement('span', { style: { fontSize: 12, color: colors.muted } }, `当前显示 ${filteredAuthorizationItems.length} 条`), React.createElement(SelectMenu, { label: '筛选审批状态', value: authorizationFilter, options: [{ id: 'all', label: '全部审批状态' }, { id: 'pending', label: '待批复' }, { id: 'approved', label: '已批准' }, { id: 'rejected', label: '已拒绝' }], onChange: (value) => { setAuthorizationFilter(value); setAuthorizationPage(1) } })),
|
|
413
|
-
React.createElement('div', { style: { height:
|
|
407
|
+
React.createElement('div', { style: toolbar }, React.createElement('span', { style: { fontSize: 12, color: colors.muted } }, `当前显示 ${filteredAuthorizationItems.length} 条 · 每页 ${authorizationPageSize} 条`), React.createElement(SelectMenu, { label: '筛选审批状态', value: authorizationFilter, options: [{ id: 'all', label: '全部审批状态' }, { id: 'pending', label: '待批复' }, { id: 'approved', label: '已批准' }, { id: 'rejected', label: '已拒绝' }], onChange: (value) => { setAuthorizationFilter(value); setAuthorizationPage(1) } })),
|
|
408
|
+
React.createElement('div', { style: { height: 42, boxSizing: 'border-box', display: 'grid', gridTemplateColumns: '104px minmax(220px, 1.1fr) minmax(280px, 1.5fr) 126px 52px', alignItems: 'center', gap: 16, padding: '0 16px', background: colors.surface2, color: colors.muted, fontSize: 11, fontWeight: 500 } }, React.createElement('span', null, '状态'), React.createElement('span', null, '任务'), React.createElement('span', null, '申请摘要'), React.createElement('span', null, '申请时间'), React.createElement('span', null, '操作')),
|
|
414
409
|
React.createElement('div', null, ...(authorizationRows.length ? authorizationRows : [React.createElement('div', { key: 'empty', style: { padding: 36, textAlign: 'center', color: colors.muted, fontSize: 12 } }, '暂无授权申请')])),
|
|
415
410
|
React.createElement('div', { style: tableFooter },
|
|
416
411
|
React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', disabled: currentAuthorizationPage <= 1, onClick: () => setAuthorizationPage((page) => Math.max(1, page - 1)) }, '上一页'),
|
|
@@ -418,13 +413,9 @@ window.__ModuleLoader__.load({
|
|
|
418
413
|
React.createElement(Button, { variant: 'outline', size: 'sm', type: 'button', disabled: currentAuthorizationPage >= authorizationPageCount, onClick: () => setAuthorizationPage((page) => Math.min(authorizationPageCount, page + 1)) }, '下一页')))
|
|
419
414
|
), authorizationDetail)
|
|
420
415
|
const archivedTasks = (data?.tasks || []).filter((task) => task.state === 'completed' && task.archivedAt).sort((left, right) => String(right.archivedAt).localeCompare(String(left.archivedAt)))
|
|
421
|
-
const archivePage = React.createElement('section', null,
|
|
422
|
-
pageHeader('归档任务', '归档只影响看板展示,Task、Session、Goal 与历史证据仍完整保留。'),
|
|
423
|
-
React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: 12 } }, ...(archivedTasks.length ? archivedTasks.map(renderTaskCard) : [React.createElement(React.Fragment, { key: 'empty' }, emptyState('暂无归档任务'))]))
|
|
424
|
-
)
|
|
416
|
+
const archivePage = React.createElement('section', null, React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: 12 } }, ...(archivedTasks.length ? archivedTasks.map(renderTaskCard) : [React.createElement(React.Fragment, { key: 'empty' }, emptyState('暂无归档任务'))])))
|
|
425
417
|
const alertsPage = React.createElement(React.Fragment, null,
|
|
426
|
-
|
|
427
|
-
React.createElement('section', null, sectionHeader('告警记录', '按状态和类型筛选'), React.createElement('div', { style: tableFrame },
|
|
418
|
+
React.createElement('section', null, React.createElement('div', { style: tableFrame },
|
|
428
419
|
React.createElement('div', { style: toolbar },
|
|
429
420
|
React.createElement('div', { role: 'tablist', 'aria-label': '告警状态视图', style: { display: 'flex', alignSelf: 'stretch', gap: 20 } }, ...[{ id: 'active', label: `当前异常 ${filteredActiveAlerts.length}` }, { id: 'resolved', label: `恢复历史 ${filteredResolvedAlerts.length}` }].map((item) => React.createElement('button', { key: item.id, role: 'tab', 'aria-selected': alertView === item.id, type: 'button', onClick: () => setAlertView(item.id), style: { border: 0, borderBottom: alertView === item.id ? `2px solid ${colors.accent}` : '2px solid transparent', background: 'transparent', color: alertView === item.id ? colors.accent : colors.muted, padding: '0 2px', fontFamily: 'inherit', fontSize: 12, cursor: 'pointer' } }, item.label))),
|
|
430
421
|
React.createElement(SelectMenu, { label: '筛选告警类型', value: alertType, options: alertCategories.map((category) => ({ id: category.id, label: category.label })), onChange: (value) => { setAlertType(value); setResolvedAlertPage(1) } })),
|
|
@@ -433,7 +424,7 @@ window.__ModuleLoader__.load({
|
|
|
433
424
|
)
|
|
434
425
|
const pageContent = activePage === 'tasks' ? tasksPage : activePage === 'authorizations' ? authorizationsPage : activePage === 'archive' ? archivePage : activePage === 'alerts' ? alertsPage : groupsPage
|
|
435
426
|
const pageViewport = React.createElement('div', { style: { width: '100%', maxWidth: 1320, minHeight: 'calc(100dvh - 138px)', boxSizing: 'border-box', margin: '0 auto' } }, pageContent)
|
|
436
|
-
const main = React.createElement('main', { style: { width: '100%', minHeight: 'calc(100dvh - 90px)', boxSizing: 'border-box', padding: '24px 24px 32px', display: 'grid', alignContent: 'start', gap: 20, pointerEvents: 'auto' } },
|
|
427
|
+
const main = React.createElement('main', { style: { width: '100%', minHeight: 'calc(100dvh - 90px)', boxSizing: 'border-box', padding: activePage === 'tasks' ? '24px 24px 0' : '24px 24px 32px', display: 'grid', alignContent: 'start', gap: 20, pointerEvents: 'auto' } },
|
|
437
428
|
error ? React.createElement('div', { style: { ...card, borderColor: colors.danger, color: colors.danger } }, `无法连接 resident 插件:${error}`) : null,
|
|
438
429
|
navigationError ? React.createElement('div', { style: { ...card, borderColor: colors.danger, color: colors.danger } }, `无法打开 DSH Session:${navigationError}`) : null,
|
|
439
430
|
pageViewport
|