Add files via upload

This commit is contained in:
公明
2026-07-08 10:31:32 +08:00
committed by GitHub
parent dc541b91b5
commit 89264c9c1a
2 changed files with 284 additions and 13 deletions
+143 -2
View File
@@ -161,6 +161,8 @@ function initVulnerabilityStatusPickers(root) {
if (picker.classList.contains('is-disabled')) return;
const wasOpen = picker.classList.contains('open');
closeAllVulnerabilityStatusPickers();
closeAllVulnDetailProjectSelects();
closeAllVulnFilterCustomSelects();
if (!wasOpen) {
picker.classList.add('open');
menu.hidden = false;
@@ -770,6 +772,7 @@ function enhanceVulnFilterCustomSelect(selectId) {
if (typeof closeAllVulnerabilityStatusPickers === 'function') {
closeAllVulnerabilityStatusPickers();
}
closeAllVulnDetailProjectSelects();
const open = wrapper.classList.contains('open');
closeAllVulnFilterCustomSelects();
if (!open) {
@@ -806,6 +809,142 @@ function initVulnerabilityFilterSelects() {
syncAllVulnFilterCustomSelects();
}
const VULN_DETAIL_SELECT_CARET = '<svg class="vuln-detail-select-caret" width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
const vulnDetailProjectSelectMap = new WeakMap();
let vulnDetailProjectSelectDocBound = false;
function closeAllVulnDetailProjectSelects() {
document.querySelectorAll('.vuln-detail-select-ui.open').forEach(function (wrapper) {
wrapper.classList.remove('open');
const trigger = wrapper.querySelector('.vuln-detail-select-trigger');
if (trigger) trigger.setAttribute('aria-expanded', 'false');
});
}
function syncVulnDetailProjectSelect(select) {
const reg = vulnDetailProjectSelectMap.get(select);
if (!reg) return;
const dropdown = reg.dropdown;
const trigger = reg.trigger;
const valueSpan = trigger.querySelector('.vuln-detail-select-value');
dropdown.innerHTML = '';
Array.prototype.forEach.call(select.options, function (opt) {
const item = document.createElement('button');
item.type = 'button';
item.className = 'vuln-detail-select-option';
item.setAttribute('role', 'option');
item.setAttribute('data-value', opt.value);
if (opt.value === select.value) {
item.classList.add('is-selected');
item.setAttribute('aria-selected', 'true');
} else {
item.setAttribute('aria-selected', 'false');
}
const check = document.createElement('span');
check.className = 'vuln-detail-select-check';
check.setAttribute('aria-hidden', 'true');
check.textContent = '✓';
const label = document.createElement('span');
label.className = 'vuln-detail-select-label';
label.textContent = opt.textContent;
item.appendChild(check);
item.appendChild(label);
dropdown.appendChild(item);
});
const selectedOpt = select.options[select.selectedIndex];
if (valueSpan) {
valueSpan.textContent = selectedOpt ? selectedOpt.textContent : '';
}
trigger.disabled = !!select.disabled;
reg.wrapper.classList.toggle('is-disabled', !!select.disabled);
}
function enhanceVulnDetailProjectSelect(select) {
if (!select || !select.classList.contains('vulnerability-project-bind-select')) return;
if (select.dataset.vulnDetailCustomSelect === '1') {
syncVulnDetailProjectSelect(select);
return;
}
select.dataset.vulnDetailCustomSelect = '1';
select.classList.add('vuln-detail-native-select');
select.tabIndex = -1;
select.setAttribute('aria-hidden', 'true');
const wrapper = document.createElement('div');
wrapper.className = 'vuln-detail-select-ui';
const trigger = document.createElement('button');
trigger.type = 'button';
trigger.className = 'vuln-detail-select-trigger';
trigger.setAttribute('aria-haspopup', 'listbox');
trigger.setAttribute('aria-expanded', 'false');
const label = select.getAttribute('aria-label');
if (label) trigger.setAttribute('aria-label', label);
const valueSpan = document.createElement('span');
valueSpan.className = 'vuln-detail-select-value';
trigger.appendChild(valueSpan);
trigger.insertAdjacentHTML('beforeend', VULN_DETAIL_SELECT_CARET);
const dropdown = document.createElement('div');
dropdown.className = 'vuln-detail-select-dropdown';
dropdown.setAttribute('role', 'listbox');
const parent = select.parentNode;
parent.insertBefore(wrapper, select);
wrapper.appendChild(trigger);
wrapper.appendChild(dropdown);
wrapper.appendChild(select);
vulnDetailProjectSelectMap.set(select, { wrapper: wrapper, trigger: trigger, dropdown: dropdown, select: select });
trigger.addEventListener('click', function (e) {
e.stopPropagation();
if (select.disabled) return;
if (typeof closeAllVulnerabilityStatusPickers === 'function') {
closeAllVulnerabilityStatusPickers();
}
closeAllVulnFilterCustomSelects();
const open = wrapper.classList.contains('open');
closeAllVulnDetailProjectSelects();
if (!open) {
wrapper.classList.add('open');
trigger.setAttribute('aria-expanded', 'true');
}
});
dropdown.addEventListener('click', function (e) {
const opt = e.target.closest('.vuln-detail-select-option');
if (!opt) return;
e.stopPropagation();
const val = opt.getAttribute('data-value');
if (val === null) return;
if (select.value !== val) {
select.value = val;
select.dispatchEvent(new Event('change', { bubbles: true }));
}
wrapper.classList.remove('open');
trigger.setAttribute('aria-expanded', 'false');
syncVulnDetailProjectSelect(select);
});
syncVulnDetailProjectSelect(select);
}
function initVulnerabilityProjectBindSelects(root) {
if (!vulnDetailProjectSelectDocBound) {
document.addEventListener('click', closeAllVulnDetailProjectSelects);
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') closeAllVulnDetailProjectSelects();
});
vulnDetailProjectSelectDocBound = true;
}
const scope = root || document.getElementById('vulnerabilities-list');
if (!scope) return;
scope.querySelectorAll('select.vulnerability-project-bind-select').forEach(enhanceVulnDetailProjectSelect);
}
function countVulnerabilityAdvancedFiltersActive() {
const f = vulnerabilityFilters;
let n = 0;
@@ -1319,6 +1458,7 @@ function renderVulnerabilities(vulnerabilities, renderOptions) {
listContainer.innerHTML = html;
initVulnerabilityStatusPickers(listContainer);
initVulnerabilityProjectBindSelects(listContainer);
if (typeof window.applyTranslations === 'function') {
window.applyTranslations(listContainer);
}
@@ -1860,11 +2000,12 @@ function vulnDetailProjectField(vuln) {
return `<div class="vuln-detail-field">
<div class="vuln-detail-field__label">${escapeHtml(label)}</div>
<div class="vuln-detail-field__row">
<select class="vuln-detail-field-select vulnerability-project-bind-select" data-vuln-id="${escapeHtml(vuln.id)}"
onchange="bindVulnerabilityProject(this.dataset.vulnId, this.value, true)" onclick="event.stopPropagation();"
<select class="vulnerability-project-bind-select" data-vuln-id="${escapeHtml(vuln.id)}"
onchange="bindVulnerabilityProject(this.dataset.vulnId, this.value, true)"
title="${hint}" aria-label="${escapeHtml(label)}">
${buildVulnerabilityProjectOptionsHtml(vuln.project_id || '')}
</select>
<span class="vuln-detail-field__copy-spacer" aria-hidden="true"></span>
</div>
</div>`;
}