提交
This commit is contained in:
1 parent
33c038b8d9
commit
54b27a3f0e
253 files changed
+30060
-14298
No files matched your search
@@ -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)
|
||||
}
|
||||
Reference in new issue
Block a user