dsh-model-doctor 0.5.0 → 0.5.2
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/lib/client/index.js +37 -8
- package/package.json +1 -1
package/lib/client/index.js
CHANGED
|
@@ -80,7 +80,7 @@ window.__ModuleLoader__.load({
|
|
|
80
80
|
.dmd-chip.is-warn{color:#d08700;background:color-mix(in srgb,#d08700 16%,transparent)}
|
|
81
81
|
.dmd-allbar{display:flex;align-items:center;gap:8px;padding:6px 12px;margin:2px 6px;font-size:11px;border-radius:8px;background:color-mix(in srgb,currentColor 6%,transparent)}
|
|
82
82
|
.dmd-allbar button{font:inherit;font-size:11px;line-height:16px;padding:2px 9px;border-radius:6px;border:1px solid color-mix(in srgb,currentColor 25%,transparent);background:transparent;color:inherit;cursor:pointer}
|
|
83
|
-
.dmd-allbar button:disabled{opacity:.45;cursor:default}
|
|
83
|
+
.dmd-allbar button:disabled,.dmd-allbar button.is-busy{opacity:.45;cursor:default}
|
|
84
84
|
.dmd-allbar .dmd-status{opacity:.65}
|
|
85
85
|
.dmd-allbar .dmd-balance{color:#2fa96e}
|
|
86
86
|
`
|
|
@@ -560,8 +560,17 @@ window.__ModuleLoader__.load({
|
|
|
560
560
|
if (result && result.ok === true) {
|
|
561
561
|
deletedKeys.add(keyOf(provider, model))
|
|
562
562
|
const section = row.closest('section')
|
|
563
|
+
// 焦点若在被删行上,移除后焦点会落到 body → 官方 onBlur 会关闭菜单,
|
|
564
|
+
// 所以先把焦点转移到相邻的模型行再移除。
|
|
565
|
+
const hadFocus = row === document.activeElement
|
|
566
|
+
const neighbour = row.nextElementSibling ?? row.previousElementSibling
|
|
563
567
|
row.remove()
|
|
564
568
|
if (section !== null && section.querySelectorAll(ROW_SEL).length === 0) section.remove()
|
|
569
|
+
if (hadFocus) {
|
|
570
|
+
const target = (neighbour !== null && neighbour.isConnected ? neighbour : null)
|
|
571
|
+
?? document.querySelector('[role="menuitemradio"]')
|
|
572
|
+
if (target !== null && typeof target.focus === 'function') target.focus()
|
|
573
|
+
}
|
|
565
574
|
fetchDirectory(true)
|
|
566
575
|
} else {
|
|
567
576
|
const message = result && typeof result.error === 'string' ? result.error : '删除失败'
|
|
@@ -683,11 +692,21 @@ window.__ModuleLoader__.load({
|
|
|
683
692
|
status.className = 'dmd-status'
|
|
684
693
|
const balance = document.createElement('span')
|
|
685
694
|
balance.className = 'dmd-balance'
|
|
695
|
+
// 忙碌用标记而不是 disabled:被禁用的聚焦元素会把焦点丢给 body,
|
|
696
|
+
// 而官方菜单在根节点上监听 onBlur(portal 的事件仍走 React 树冒泡),
|
|
697
|
+
// 焦点一离开菜单就会 setOpen(false) —— 表现就是「点全部检测菜单被关掉」。
|
|
698
|
+
let busy = false
|
|
699
|
+
const setBusy = (value) => {
|
|
700
|
+
busy = value
|
|
701
|
+
button.classList.toggle('is-busy', value)
|
|
702
|
+
button.setAttribute('aria-busy', value ? 'true' : 'false')
|
|
703
|
+
button.style.pointerEvents = value ? 'none' : ''
|
|
704
|
+
}
|
|
686
705
|
button.addEventListener('click', (event) => {
|
|
687
706
|
event.stopPropagation()
|
|
688
707
|
event.preventDefault()
|
|
689
|
-
if (doctor === null ||
|
|
690
|
-
|
|
708
|
+
if (doctor === null || busy) return
|
|
709
|
+
setBusy(true)
|
|
691
710
|
barBusy = true
|
|
692
711
|
status.textContent = '探测中…'
|
|
693
712
|
balance.textContent = ''
|
|
@@ -696,7 +715,7 @@ window.__ModuleLoader__.load({
|
|
|
696
715
|
})
|
|
697
716
|
doctor.checkAll().then((result) => {
|
|
698
717
|
if (disposed) return
|
|
699
|
-
|
|
718
|
+
setBusy(false)
|
|
700
719
|
barBusy = false
|
|
701
720
|
if (!result || result.ok === false || !isRecord(result.results)) {
|
|
702
721
|
status.textContent = `失败:${result && typeof result.error === 'string' ? result.error : '通道异常'}`
|
|
@@ -726,7 +745,12 @@ window.__ModuleLoader__.load({
|
|
|
726
745
|
}
|
|
727
746
|
})
|
|
728
747
|
})
|
|
729
|
-
|
|
748
|
+
// preventDefault 阻止焦点转移到本按钮:焦点一旦离开菜单,官方 onBlur 就会关闭菜单
|
|
749
|
+
button.addEventListener('mousedown', (event) => {
|
|
750
|
+
event.preventDefault()
|
|
751
|
+
event.stopPropagation()
|
|
752
|
+
})
|
|
753
|
+
button.addEventListener('pointerdown', (event) => event.stopPropagation())
|
|
730
754
|
bar.appendChild(button)
|
|
731
755
|
bar.appendChild(status)
|
|
732
756
|
bar.appendChild(balance)
|
|
@@ -746,6 +770,8 @@ window.__ModuleLoader__.load({
|
|
|
746
770
|
|
|
747
771
|
let reportSignature = ''
|
|
748
772
|
let reportAt = 0
|
|
773
|
+
/** 最近一次写入的报告是否包含「菜单已打开」的现场。 */
|
|
774
|
+
let lastReportHadMenu = false
|
|
749
775
|
|
|
750
776
|
function describe(el) {
|
|
751
777
|
if (el === null || el === undefined) return null
|
|
@@ -754,16 +780,19 @@ window.__ModuleLoader__.load({
|
|
|
754
780
|
return { tag: el.tagName, role: el.getAttribute('role') ?? '', cls, text }
|
|
755
781
|
}
|
|
756
782
|
|
|
757
|
-
function reportDiagnostics(state,
|
|
783
|
+
function reportDiagnostics(state, menuVisible = false) {
|
|
758
784
|
if (doctor === null) return
|
|
759
785
|
const { at, ...rest } = state
|
|
760
786
|
const signature = JSON.stringify(rest)
|
|
761
787
|
const now = Date.now()
|
|
762
|
-
|
|
763
|
-
|
|
788
|
+
const isError = typeof state.error === 'string'
|
|
789
|
+
// 报告里已经留下「菜单打开」的现场时,不要被随后「菜单关闭」的空扫描覆盖(错误除外)
|
|
790
|
+
if (!menuVisible && !isError && lastReportHadMenu) return
|
|
791
|
+
if (!isError && signature === reportSignature && now - reportAt < (menuVisible ? 5000 : 1200)) return
|
|
764
792
|
if (now - reportAt < 400) return
|
|
765
793
|
reportSignature = signature
|
|
766
794
|
reportAt = now
|
|
795
|
+
lastReportHadMenu = menuVisible
|
|
767
796
|
void doctor.clientReport(state)
|
|
768
797
|
}
|
|
769
798
|
|
package/package.json
CHANGED