This commit is contained in:
zlwu committed 2026-07-05 10:07:24 +08:00
1 parent 33c038b8d9
commit 54b27a3f0e
253 files changed
+30060 -14298

No files matched your search

+141
View File
@@ -0,0 +1,141 @@
const TOOLBAR_SELECTOR = '.page-container .list-toolbar, .console-container .list-toolbar'
const FILTER_AUTO_TOGGLE_CLASS = 'btn-filter-toggle-auto'
const FILTER_TOGGLE_ICON_CLASS = 'btn-list-filter-toggle'
const QUICK_SEARCH_GROUP_CLASS = 'quick-search-group'
const ensureQuickSearchGroup = (quickSearchInput: HTMLElement): HTMLElement => {
const parent = quickSearchInput.parentElement
if (parent?.classList.contains(QUICK_SEARCH_GROUP_CLASS)) {
return parent
}
const group = document.createElement('div')
group.className = QUICK_SEARCH_GROUP_CLASS
quickSearchInput.replaceWith(group)
group.appendChild(quickSearchInput)
return group
}
const findPrecedingFilterBlock = (toolbar: HTMLElement): HTMLElement | null => {
if (toolbar.closest('.el-dialog')) return null
let prev = toolbar.previousElementSibling as HTMLElement | null
while (prev) {
if (prev.classList.contains('filter-block')) return prev
if (
prev.classList.contains('list-body') ||
prev.classList.contains('list-toolbar') ||
prev.classList.contains('panel-top') ||
prev.classList.contains('stat-grid')
) {
return null
}
prev = prev.previousElementSibling as HTMLElement | null
}
return null
}
const setFilterBlockExpanded = (
filterBlock: HTMLElement,
button: HTMLButtonElement,
expanded: boolean
) => {
filterBlock.classList.toggle('is-filter-collapsed', !expanded)
filterBlock.classList.toggle('is-filter-expanded', expanded)
button.setAttribute('aria-expanded', expanded ? 'true' : 'false')
button.setAttribute('aria-label', expanded ? '收起检索' : '展开检索')
button.setAttribute('title', expanded ? '收起检索' : '展开检索')
}
const createToggleButton = (filterBlock: HTMLElement): HTMLButtonElement => {
const button = document.createElement('button')
button.type = 'button'
button.className = FILTER_TOGGLE_ICON_CLASS
button.setAttribute('aria-expanded', 'false')
button.setAttribute('aria-label', '展开检索')
button.setAttribute('title', '展开检索')
button.addEventListener('click', (event) => {
event.preventDefault()
event.stopPropagation()
const expanded = filterBlock.classList.contains('is-filter-expanded')
setFilterBlockExpanded(filterBlock, button, !expanded)
})
return button
}
const resolveFilterToggleAnchor = (
toolbar: HTMLElement
): { anchor: HTMLElement; quickSearchInput: HTMLElement | null } | null => {
const quickSearchInput = toolbar.querySelector<HTMLElement>('.quick-search-input')
if (quickSearchInput) {
return { anchor: ensureQuickSearchGroup(quickSearchInput), quickSearchInput }
}
const selectedAnchor = toolbar.querySelector<HTMLElement>('.list-toolbar-selected')
if (selectedAnchor) {
return { anchor: selectedAnchor, quickSearchInput: null }
}
const rowAnchor = toolbar.querySelector<HTMLElement>('.list-toolbar-row')
if (rowAnchor) {
return { anchor: rowAnchor, quickSearchInput: null }
}
return null
}
const ensureToolbarFilterToggle = (toolbar: HTMLElement, filterBlock: HTMLElement) => {
if (!filterBlock.classList.contains('is-filter-expanded')) {
filterBlock.classList.add('is-filter-collapsed')
}
const resolved = resolveFilterToggleAnchor(toolbar)
if (!resolved) return
const { anchor } = resolved
const existingToggle = toolbar.querySelector<HTMLButtonElement>(`.${FILTER_TOGGLE_ICON_CLASS}`)
if (existingToggle && existingToggle.parentElement !== anchor) {
existingToggle.remove()
}
let toggle = anchor.querySelector<HTMLButtonElement>(`:scope > .${FILTER_TOGGLE_ICON_CLASS}`)
if (!toggle) {
toggle = createToggleButton(filterBlock)
anchor.insertBefore(toggle, anchor.firstChild)
}
setFilterBlockExpanded(
filterBlock,
toggle,
filterBlock.classList.contains('is-filter-expanded')
)
}
const removeAutoFilterToggles = (): void => {
document.querySelectorAll<HTMLElement>(`.${FILTER_AUTO_TOGGLE_CLASS}`).forEach((node) => {
node.remove()
})
}
export const refreshFilterCollapse = (): void => {
removeAutoFilterToggles()
document.querySelectorAll<HTMLElement>(TOOLBAR_SELECTOR).forEach((toolbar) => {
const filterBlock = findPrecedingFilterBlock(toolbar)
if (!filterBlock) return
ensureToolbarFilterToggle(toolbar, filterBlock)
})
}
export const setupFilterCollapseObserver = (): MutationObserver => {
refreshFilterCollapse()
const observer = new MutationObserver(() => {
refreshFilterCollapse()
})
observer.observe(document.body, {
childList: true,
subtree: true
})
return observer
}
@@ -0,0 +1,29 @@
const INTERACTIVE_SELECTOR =
'button, a, .el-link, .el-dropdown, input, textarea, select, .el-switch, .el-radio, .el-select, .btn-op-item, .el-table__expand-icon'
/**
* 主列表行单击切换多选:点击行即选中/取消,点击链接、按钮、展开图标等交互元素时不触发。
*/
export function setupListTableRowSelect() {
const handler = (event: MouseEvent) => {
const target = event.target as HTMLElement | null
if (!target) return
if (target.closest('.el-table-column--selection')) return
const row = target.closest('.list-table .el-table__body-wrapper tbody tr.el-table__row')
if (!row) return
if (target.closest(INTERACTIVE_SELECTOR)) return
const checkboxInput = row.querySelector(
'.el-table-column--selection .el-checkbox__input'
) as HTMLElement | null
if (!checkboxInput) return
checkboxInput.click()
}
document.body.addEventListener('click', handler)
return () => document.body.removeEventListener('click', handler)
}