673 lines
27 KiB
JavaScript
673 lines
27 KiB
JavaScript
// 2. 多语言核心功能
|
|
let currentLang = 'en'; // 默认语言
|
|
|
|
// 切换语言
|
|
function switchLanguage(lang) {
|
|
if (lang === currentLang) return;
|
|
currentLang = lang;
|
|
const resources = i18nResources[lang];
|
|
|
|
// 替换普通文本(data-i18n 属性)
|
|
document.querySelectorAll('[data-i18n]').forEach(el => {
|
|
const key = el.getAttribute('data-i18n');
|
|
if (resources[key]) el.textContent = resources[key];
|
|
});
|
|
|
|
// 替换占位符(data-i18n-placeholder 属性)
|
|
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
|
|
const key = el.getAttribute('data-i18n-placeholder');
|
|
if (resources[key]) el.placeholder = resources[key];
|
|
});
|
|
|
|
// 替换标题属性(data-i18n-title 属性)
|
|
document.querySelectorAll('[data-i18n-title]').forEach(el => {
|
|
const key = el.getAttribute('data-i18n-title');
|
|
if (resources[key]) el.title = resources[key];
|
|
});
|
|
|
|
// 替换下拉选项文本(data-i18n 属性)
|
|
document.querySelectorAll('option[data-i18n]').forEach(el => {
|
|
const key = el.getAttribute('data-i18n');
|
|
if (resources[key]) el.textContent = resources[key];
|
|
});
|
|
|
|
// 更新语言切换按钮状态(桌面端)
|
|
document.getElementById('lang-en').className = `lang-switch-btn ${lang === 'en' ? 'active' : 'inactive'}`;
|
|
document.getElementById('lang-zh').className = `lang-switch-btn ${lang === 'zh' ? 'active' : 'inactive'}`;
|
|
|
|
// 更新语言切换按钮状态(移动端)
|
|
document.getElementById('mobile-lang-en').className = `lang-switch-btn ${lang === 'en' ? 'active' : 'inactive'} text-xs`;
|
|
document.getElementById('mobile-lang-zh').className = `lang-switch-btn ${lang === 'zh' ? 'active' : 'inactive'} text-xs`;
|
|
|
|
// 更新HTML文档语言属性
|
|
document.documentElement.lang = lang;
|
|
|
|
// 重新渲染Markdown预览(语言切换后保持预览状态)
|
|
updateAllMarkdownPreviews();
|
|
}
|
|
|
|
// 3. Markdown编辑器功能
|
|
function initMarkdownEditors() {
|
|
// 为所有编辑器标签绑定切换事件
|
|
document.querySelectorAll('.editor-tab').forEach(tab => {
|
|
tab.addEventListener('click', function() {
|
|
const editor = this.closest('.markdown-editor');
|
|
const tabType = this.getAttribute('data-tab');
|
|
const textarea = editor.querySelector('textarea');
|
|
const preview = editor.querySelector('.preview-content');
|
|
const tabs = editor.querySelectorAll('.editor-tab');
|
|
|
|
// 更新标签状态
|
|
tabs.forEach(t => {
|
|
t.classList.remove('active', 'text-neutral');
|
|
t.classList.add(t.getAttribute('data-tab') === tabType ? 'active' : 'text-neutral');
|
|
});
|
|
|
|
// 切换编辑/预览模式
|
|
if (tabType === 'edit') {
|
|
textarea.classList.remove('hidden');
|
|
preview.classList.add('hidden');
|
|
} else {
|
|
textarea.classList.add('hidden');
|
|
preview.classList.remove('hidden');
|
|
// 渲染Markdown
|
|
preview.innerHTML = marked.parse(textarea.value);
|
|
// 代码高亮
|
|
Prism.highlightAllUnder(preview);
|
|
}
|
|
});
|
|
});
|
|
|
|
// 为所有Markdown文本域绑定输入事件(实时预览)
|
|
document.querySelectorAll('.editor-content').forEach(textarea => {
|
|
textarea.addEventListener('input', function() {
|
|
const editor = this.closest('.markdown-editor');
|
|
const preview = editor.querySelector('.preview-content');
|
|
const activeTab = editor.querySelector('.editor-tab.active');
|
|
|
|
// 如果当前是预览模式,实时更新预览
|
|
if (activeTab.getAttribute('data-tab') === 'preview') {
|
|
preview.innerHTML = marked.parse(this.value);
|
|
Prism.highlightAllUnder(preview);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// 更新所有Markdown预览
|
|
function updateAllMarkdownPreviews() {
|
|
document.querySelectorAll('.markdown-editor').forEach(editor => {
|
|
const textarea = editor.querySelector('textarea');
|
|
const preview = editor.querySelector('.preview-content');
|
|
const activeTab = editor.querySelector('.editor-tab.active');
|
|
|
|
if (activeTab.getAttribute('data-tab') === 'preview') {
|
|
preview.innerHTML = marked.parse(textarea.value);
|
|
Prism.highlightAllUnder(preview);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 4. CVSS评分计算功能
|
|
function initCvssCalculator() {
|
|
// CVSS v3.1 评分权重映射
|
|
const cvssWeights = {
|
|
AV: { N: 0.85, A: 0.62, L: 0.55, P: 0.2 },
|
|
AC: { L: 0.77, H: 0.44 },
|
|
PR: { N: 0.85, L: 0.62, H: 0.27 },
|
|
UI: { N: 0.85, R: 0.62 },
|
|
S: { U: 6.42, C: 7.52 },
|
|
C: { N: 0, L: 0.22, H: 0.56 },
|
|
I: { N: 0, L: 0.22, H: 0.56 },
|
|
A: { N: 0, L: 0.22, H: 0.56 }
|
|
};
|
|
|
|
// 计算CVSS基础评分
|
|
function calculateCvssScore() {
|
|
// 获取所有CVSS指标值
|
|
const AV = document.querySelector('select[name="cvssAV"]').value;
|
|
const AC = document.querySelector('select[name="cvssAC"]').value;
|
|
const PR = document.querySelector('select[name="cvssPR"]').value;
|
|
const UI = document.querySelector('select[name="cvssUI"]').value;
|
|
const S = document.querySelector('select[name="cvssS"]').value;
|
|
const C = document.querySelector('select[name="cvssC"]').value;
|
|
const I = document.querySelector('select[name="cvssI"]').value;
|
|
const A = document.querySelector('select[name="cvssA"]').value;
|
|
|
|
// 计算利用向量评分 (Exploitability Score)
|
|
const exploitabilityScore = 8.22 * cvssWeights.AV[AV] * cvssWeights.AC[AC] * cvssWeights.PR[PR] * cvssWeights.UI[UI];
|
|
|
|
// 计算影响评分 (Impact Score)
|
|
const impactSubScore = 1 - ((1 - cvssWeights.C[C]) * (1 - cvssWeights.I[I]) * (1 - cvssWeights.A[A]));
|
|
const impactScore = cvssWeights.S[S] * impactSubScore;
|
|
|
|
// 计算基础评分 (Base Score)
|
|
let baseScore;
|
|
if (impactScore <= 0) {
|
|
baseScore = 0;
|
|
} else if (S === 'U') {
|
|
baseScore = Math.min(impactScore + exploitabilityScore, 10);
|
|
} else {
|
|
baseScore = Math.min(1.08 * (impactScore + exploitabilityScore), 10);
|
|
}
|
|
|
|
// 四舍五入到一位小数
|
|
baseScore = Math.round(baseScore * 10) / 10;
|
|
|
|
// 确定严重级别
|
|
let severity, severityColor;
|
|
if (baseScore >= 9.0) {
|
|
severity = 'CRITICAL';
|
|
severityColor = 'bg-danger/10 text-danger';
|
|
} else if (baseScore >= 7.0) {
|
|
severity = 'HIGH';
|
|
severityColor = 'bg-danger/10 text-danger';
|
|
} else if (baseScore >= 4.0) {
|
|
severity = 'MEDIUM';
|
|
severityColor = 'bg-warning/10 text-warning';
|
|
} else if (baseScore >= 0.1) {
|
|
severity = 'LOW';
|
|
severityColor = 'bg-success/10 text-success';
|
|
} else {
|
|
severity = 'NONE';
|
|
severityColor = 'bg-neutral/10 text-neutral';
|
|
}
|
|
|
|
// 更新UI显示
|
|
document.getElementById('cvssScore').textContent = baseScore;
|
|
document.getElementById('cvssSeverity').textContent = severity;
|
|
document.getElementById('cvssSeverity').className = `px-2 py-1 rounded-full ${severityColor} text-xs font-medium`;
|
|
|
|
// 更新CVSS向量字符串
|
|
const vectorString = `CVSS:3.1/AV:${AV}/AC:${AC}/PR:${PR}/UI:${UI}/S:${S}/C:${C}/I:${I}/A:${A}`;
|
|
document.getElementById('cvssVector').textContent = vectorString;
|
|
|
|
return {
|
|
score: baseScore,
|
|
severity: severity,
|
|
vector: vectorString
|
|
};
|
|
}
|
|
|
|
// 初始化时计算一次
|
|
calculateCvssScore();
|
|
|
|
// 绑定指标变更事件
|
|
document.querySelectorAll('.cvss-metric').forEach(select => {
|
|
select.addEventListener('change', calculateCvssScore);
|
|
});
|
|
|
|
// 暴露计算函数供其他功能使用
|
|
window.calculateCvssScore = calculateCvssScore;
|
|
}
|
|
|
|
// 5. 动态表单功能(添加/删除条目)
|
|
function initDynamicForms() {
|
|
// 产品条目:添加
|
|
document.getElementById('addProductBtn').addEventListener('click', function() {
|
|
const productsList = document.getElementById('productsList');
|
|
const productItem = productsList.querySelector('.product-item').cloneNode(true);
|
|
|
|
// 清空输入值
|
|
productItem.querySelectorAll('input').forEach(input => {
|
|
input.value = '';
|
|
});
|
|
|
|
// 添加删除事件
|
|
productItem.querySelector('.removeProductBtn').addEventListener('click', function() {
|
|
if (productsList.querySelectorAll('.product-item').length > 1) {
|
|
this.closest('.product-item').remove();
|
|
} else {
|
|
// 至少保留一个条目,清空值
|
|
productItem.querySelectorAll('input').forEach(input => {
|
|
input.value = '';
|
|
});
|
|
}
|
|
});
|
|
|
|
productsList.appendChild(productItem);
|
|
});
|
|
|
|
// 产品条目:删除
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.closest('.removeProductBtn')) {
|
|
const productItem = e.target.closest('.product-item');
|
|
const productsList = document.getElementById('productsList');
|
|
|
|
if (productsList.querySelectorAll('.product-item').length > 1) {
|
|
productItem.remove();
|
|
} else {
|
|
// 至少保留一个条目,清空值
|
|
productItem.querySelectorAll('input').forEach(input => {
|
|
input.value = '';
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// 参考资料:添加
|
|
document.getElementById('addReferenceBtn').addEventListener('click', function() {
|
|
const referencesList = document.getElementById('referencesList');
|
|
const referenceItem = referencesList.querySelector('.reference-item').cloneNode(true);
|
|
|
|
// 清空输入值
|
|
referenceItem.querySelectorAll('input').forEach(input => {
|
|
input.value = '';
|
|
});
|
|
|
|
// 添加删除事件
|
|
referenceItem.querySelector('.removeReferenceBtn').addEventListener('click', function() {
|
|
if (referencesList.querySelectorAll('.reference-item').length > 1) {
|
|
this.closest('.reference-item').remove();
|
|
} else {
|
|
// 至少保留一个条目,清空值
|
|
referenceItem.querySelectorAll('input').forEach(input => {
|
|
input.value = '';
|
|
});
|
|
}
|
|
});
|
|
|
|
referencesList.appendChild(referenceItem);
|
|
});
|
|
|
|
// 参考资料:删除
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.closest('.removeReferenceBtn')) {
|
|
const referenceItem = e.target.closest('.reference-item');
|
|
const referencesList = document.getElementById('referencesList');
|
|
|
|
if (referencesList.querySelectorAll('.reference-item').length > 1) {
|
|
referenceItem.remove();
|
|
} else {
|
|
// 至少保留一个条目,清空值
|
|
referenceItem.querySelectorAll('input').forEach(input => {
|
|
input.value = '';
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// 相关SVE:添加
|
|
document.getElementById('addRelatedSveBtn').addEventListener('click', function() {
|
|
const relatedSveList = document.getElementById('relatedSveList');
|
|
const relatedSveItem = document.createElement('div');
|
|
relatedSveItem.className = 'related-sve-item flex items-center gap-3 p-3 border border-gray-200 rounded-lg';
|
|
|
|
relatedSveItem.innerHTML = `
|
|
<input type="text" name="relatedSveId[]" placeholder="SVE-YYYY-XXXXXX" class="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary/50 focus:border-secondary" data-i18n-placeholder="related_sve_id_placeholder">
|
|
<select name="relatedSveRelation[]" class="w-40 px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary/50 focus:border-secondary">
|
|
<option value="same_product" data-i18n="related_same_product">Same Product</option>
|
|
<option value="similar_vuln" data-i18n="related_similar_vuln">Similar Vulnerability</option>
|
|
<option value="same_vendor" data-i18n="related_same_vendor">Same Vendor</option>
|
|
<option value="other" data-i18n="related_other">Other Relationship</option>
|
|
</select>
|
|
<button type="button" class="removeRelatedSveBtn text-danger hover:text-danger/80 p-2" data-i18n-title="remove_related_sve">
|
|
<i class="fa fa-times"></i>
|
|
</button>
|
|
`;
|
|
|
|
// 添加删除事件
|
|
relatedSveItem.querySelector('.removeRelatedSveBtn').addEventListener('click', function() {
|
|
relatedSveItem.remove();
|
|
});
|
|
|
|
relatedSveList.appendChild(relatedSveItem);
|
|
});
|
|
|
|
// 相关SVE:删除
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.closest('.removeRelatedSveBtn')) {
|
|
const relatedSveItem = e.target.closest('.related-sve-item');
|
|
// 可以删除所有相关SVE条目,没有数量限制
|
|
relatedSveItem.remove();
|
|
}
|
|
});
|
|
}
|
|
|
|
// 6. JSON导入导出功能
|
|
function initJsonImportExport() {
|
|
// 导出JSON
|
|
document.getElementById('exportJson').addEventListener('click', function() {
|
|
// 收集表单数据
|
|
const sveData = collectFormData();
|
|
|
|
// 转换为JSON字符串
|
|
const jsonString = JSON.stringify(sveData, null, 2);
|
|
|
|
// 创建下载链接
|
|
const blob = new Blob([jsonString], { type: 'application/json' });
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = `${sveData.sveId || 'new-sve'}.json`;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
|
|
// 清理
|
|
setTimeout(() => {
|
|
document.body.removeChild(a);
|
|
URL.revokeObjectURL(url);
|
|
}, 0);
|
|
});
|
|
|
|
// 导入JSON
|
|
document.getElementById('importJson').addEventListener('change', function(e) {
|
|
const file = e.target.files[0];
|
|
if (!file) return;
|
|
|
|
const reader = new FileReader();
|
|
reader.onload = function(event) {
|
|
try {
|
|
const sveData = JSON.parse(event.target.result);
|
|
populateFormData(sveData);
|
|
|
|
// 重置文件输入,允许重复选择同一文件
|
|
e.target.value = '';
|
|
} catch (error) {
|
|
alert('Failed to import JSON: Invalid format');
|
|
console.error('JSON import error:', error);
|
|
}
|
|
};
|
|
reader.readAsText(file);
|
|
});
|
|
}
|
|
|
|
// 收集表单数据
|
|
function collectFormData() {
|
|
// 基础信息
|
|
const sveYear = document.getElementById('sveYear').value;
|
|
const sveNumber = document.getElementById('sveNumber').value;
|
|
const sveId = `SVE-${sveYear}-${sveNumber}`;
|
|
|
|
// CVSS评分
|
|
const cvss = window.calculateCvssScore();
|
|
|
|
// 受影响产品
|
|
const products = [];
|
|
document.querySelectorAll('.product-item').forEach(item => {
|
|
products.push({
|
|
name: item.querySelector('input[name="productName[]"]').value,
|
|
version: item.querySelector('input[name="productVersion[]"]').value,
|
|
fixedVersion: item.querySelector('input[name="productFixedVersion[]"]').value
|
|
});
|
|
});
|
|
|
|
// 参考资料
|
|
const references = [];
|
|
document.querySelectorAll('.reference-item').forEach(item => {
|
|
references.push({
|
|
type: item.querySelector('select[name="referenceType[]"]').value,
|
|
title: item.querySelector('input[name="referenceTitle[]"]').value,
|
|
url: item.querySelector('input[name="referenceUrl[]"]').value
|
|
});
|
|
});
|
|
|
|
// 相关SVE
|
|
const relatedSves = [];
|
|
document.querySelectorAll('.related-sve-item').forEach(item => {
|
|
const sveId = item.querySelector('input[name="relatedSveId[]"]').value;
|
|
if (sveId) { // 只收集有值的相关SVE
|
|
relatedSves.push({
|
|
sveId: sveId,
|
|
relation: item.querySelector('select[name="relatedSveRelation[]"]').value
|
|
});
|
|
}
|
|
});
|
|
|
|
return {
|
|
sveId: sveId,
|
|
sveYear: sveYear,
|
|
sveNumber: sveNumber,
|
|
publishDate: document.getElementById('publishDate').value,
|
|
vulnTitle: document.getElementById('vulnTitle').value,
|
|
vulnStatus: document.getElementById('vulnStatus').value,
|
|
vulnDescription: document.getElementById('vulnDescription').value,
|
|
products: products,
|
|
cvss: {
|
|
av: document.querySelector('select[name="cvssAV"]').value,
|
|
ac: document.querySelector('select[name="cvssAC"]').value,
|
|
pr: document.querySelector('select[name="cvssPR"]').value,
|
|
ui: document.querySelector('select[name="cvssUI"]').value,
|
|
s: document.querySelector('select[name="cvssS"]').value,
|
|
c: document.querySelector('select[name="cvssC"]').value,
|
|
i: document.querySelector('select[name="cvssI"]').value,
|
|
a: document.querySelector('select[name="cvssA"]').value,
|
|
score: cvss.score,
|
|
severity: cvss.severity,
|
|
vector: cvss.vector
|
|
},
|
|
solutions: document.getElementById('solutions').value,
|
|
references: references,
|
|
relatedSves: relatedSves,
|
|
createdAt: new Date().toISOString()
|
|
};
|
|
}
|
|
|
|
// 填充表单数据
|
|
function populateFormData(sveData) {
|
|
if (!sveData) return;
|
|
|
|
// 基础信息
|
|
if (sveData.sveYear) document.getElementById('sveYear').value = sveData.sveYear;
|
|
if (sveData.sveNumber) document.getElementById('sveNumber').value = sveData.sveNumber;
|
|
if (sveData.publishDate) document.getElementById('publishDate').value = sveData.publishDate;
|
|
if (sveData.vulnTitle) document.getElementById('vulnTitle').value = sveData.vulnTitle;
|
|
if (sveData.vulnStatus) document.getElementById('vulnStatus').value = sveData.vulnStatus;
|
|
|
|
// 漏洞描述
|
|
if (sveData.vulnDescription) {
|
|
document.getElementById('vulnDescription').value = sveData.vulnDescription;
|
|
// 更新预览
|
|
const preview = document.getElementById('vulnDescriptionPreview');
|
|
if (!preview.classList.contains('hidden')) {
|
|
preview.innerHTML = marked.parse(sveData.vulnDescription);
|
|
Prism.highlightAllUnder(preview);
|
|
}
|
|
}
|
|
|
|
// 受影响产品
|
|
const productsList = document.getElementById('productsList');
|
|
// 清空现有条目(保留一个)
|
|
const productItems = productsList.querySelectorAll('.product-item');
|
|
for (let i = 1; i < productItems.length; i++) {
|
|
productItems[i].remove();
|
|
}
|
|
// 填充数据
|
|
if (sveData.products && sveData.products.length > 0) {
|
|
sveData.products.forEach((product, index) => {
|
|
let productItem;
|
|
if (index === 0) {
|
|
productItem = productsList.querySelector('.product-item');
|
|
} else {
|
|
// 添加新条目
|
|
document.getElementById('addProductBtn').click();
|
|
productItem = productsList.querySelectorAll('.product-item')[index];
|
|
}
|
|
|
|
productItem.querySelector('input[name="productName[]"]').value = product.name || '';
|
|
productItem.querySelector('input[name="productVersion[]"]').value = product.version || '';
|
|
productItem.querySelector('input[name="productFixedVersion[]"]').value = product.fixedVersion || '';
|
|
});
|
|
}
|
|
|
|
// CVSS指标
|
|
if (sveData.cvss) {
|
|
if (sveData.cvss.av) document.querySelector('select[name="cvssAV"]').value = sveData.cvss.av;
|
|
if (sveData.cvss.ac) document.querySelector('select[name="cvssAC"]').value = sveData.cvss.ac;
|
|
if (sveData.cvss.pr) document.querySelector('select[name="cvssPR"]').value = sveData.cvss.pr;
|
|
if (sveData.cvss.ui) document.querySelector('select[name="cvssUI"]').value = sveData.cvss.ui;
|
|
if (sveData.cvss.s) document.querySelector('select[name="cvssS"]').value = sveData.cvss.s;
|
|
if (sveData.cvss.c) document.querySelector('select[name="cvssC"]').value = sveData.cvss.c;
|
|
if (sveData.cvss.i) document.querySelector('select[name="cvssI"]').value = sveData.cvss.i;
|
|
if (sveData.cvss.a) document.querySelector('select[name="cvssA"]').value = sveData.cvss.a;
|
|
|
|
// 重新计算评分
|
|
window.calculateCvssScore();
|
|
}
|
|
|
|
// 解决方案
|
|
if (sveData.solutions) {
|
|
document.getElementById('solutions').value = sveData.solutions;
|
|
// 更新预览
|
|
const preview = document.getElementById('solutionsPreview');
|
|
if (!preview.classList.contains('hidden')) {
|
|
preview.innerHTML = marked.parse(sveData.solutions);
|
|
Prism.highlightAllUnder(preview);
|
|
}
|
|
}
|
|
|
|
// 参考资料
|
|
const referencesList = document.getElementById('referencesList');
|
|
// 清空现有条目(保留一个)
|
|
const referenceItems = referencesList.querySelectorAll('.reference-item');
|
|
for (let i = 1; i < referenceItems.length; i++) {
|
|
referenceItems[i].remove();
|
|
}
|
|
// 填充数据
|
|
if (sveData.references && sveData.references.length > 0) {
|
|
sveData.references.forEach((reference, index) => {
|
|
let referenceItem;
|
|
if (index === 0) {
|
|
referenceItem = referencesList.querySelector('.reference-item');
|
|
} else {
|
|
// 添加新条目
|
|
document.getElementById('addReferenceBtn').click();
|
|
referenceItem = referencesList.querySelectorAll('.reference-item')[index];
|
|
}
|
|
|
|
if (reference.type) referenceItem.querySelector('select[name="referenceType[]"]').value = reference.type;
|
|
referenceItem.querySelector('input[name="referenceTitle[]"]').value = reference.title || '';
|
|
referenceItem.querySelector('input[name="referenceUrl[]"]').value = reference.url || '';
|
|
});
|
|
}
|
|
|
|
// 相关SVE
|
|
const relatedSveList = document.getElementById('relatedSveList');
|
|
// 清空现有条目
|
|
relatedSveList.innerHTML = '';
|
|
// 填充数据
|
|
if (sveData.relatedSves && sveData.relatedSves.length > 0) {
|
|
sveData.relatedSves.forEach((relatedSve, index) => {
|
|
// 添加新条目
|
|
document.getElementById('addRelatedSveBtn').click();
|
|
const relatedSveItem = relatedSveList.querySelectorAll('.related-sve-item')[index];
|
|
|
|
relatedSveItem.querySelector('input[name="relatedSveId[]"]').value = relatedSve.sveId || '';
|
|
if (relatedSve.relation) relatedSveItem.querySelector('select[name="relatedSveRelation[]"]').value = relatedSve.relation;
|
|
});
|
|
} else {
|
|
// 至少保留一个空条目
|
|
document.getElementById('addRelatedSveBtn').click();
|
|
}
|
|
}
|
|
|
|
// 7. 表单提交处理
|
|
function initFormSubmit() {
|
|
document.getElementById('sveForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
// 收集表单数据
|
|
const sveData = collectFormData();
|
|
|
|
console.log('SVE Data to submit:', sveData);
|
|
fetch('/API/Write.api', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(sveData),
|
|
}).then(response => response.json()).then(data => {
|
|
if (!data.code) {
|
|
alert(data.msg);
|
|
} else {
|
|
alert(data.error);
|
|
}
|
|
console.log('Success:', data);
|
|
}).catch((error) => {
|
|
alert(data.error);
|
|
console.error('Error:', error);
|
|
});
|
|
|
|
// 重置表单(可选)
|
|
// this.reset();
|
|
});
|
|
|
|
// 保存草稿
|
|
document.querySelector('button[data-i18n="save_draft"]').addEventListener('click', function() {
|
|
// 收集表单数据
|
|
const sveData = collectFormData();
|
|
|
|
// 在实际应用中,这里会保存草稿到服务器或本地存储
|
|
console.log('SVE Draft saved:', sveData);
|
|
|
|
// 显示成功消息
|
|
alert('Draft saved successfully!');
|
|
});
|
|
}
|
|
|
|
// 8. 移动端菜单切换
|
|
function initMobileMenu() {
|
|
document.getElementById('mobile-menu-btn').addEventListener('click', function() {
|
|
const mobileMenu = document.getElementById('mobile-menu');
|
|
const mobileLangSwitch = document.getElementById('mobile-lang-switch');
|
|
|
|
// 切换菜单显示/隐藏,并同步显示语言切换按钮
|
|
mobileMenu.classList.toggle('hidden');
|
|
mobileLangSwitch.classList.toggle('hidden');
|
|
});
|
|
}
|
|
|
|
// 9. 导航栏滚动效果
|
|
function initScrollEffects() {
|
|
window.addEventListener('scroll', function() {
|
|
const header = document.querySelector('header');
|
|
if (window.scrollY > 10) {
|
|
header.classList.add('shadow');
|
|
header.classList.remove('shadow-sm');
|
|
} else {
|
|
header.classList.remove('shadow');
|
|
header.classList.add('shadow-sm');
|
|
}
|
|
});
|
|
}
|
|
|
|
// 10. 初始化所有功能
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// 设置当前年份为默认年份
|
|
const currentYear = new Date().getFullYear().toString();
|
|
document.getElementById('sveYear').value = currentYear;
|
|
|
|
// 绑定语言切换事件(桌面端)
|
|
document.getElementById('lang-en').addEventListener('click', () => switchLanguage('en'));
|
|
document.getElementById('lang-zh').addEventListener('click', () => switchLanguage('zh'));
|
|
|
|
// 绑定语言切换事件(移动端)
|
|
document.getElementById('mobile-lang-en').addEventListener('click', () => switchLanguage('en'));
|
|
document.getElementById('mobile-lang-zh').addEventListener('click', () => switchLanguage('zh'));
|
|
|
|
// 初始化其他功能
|
|
initMarkdownEditors();
|
|
initCvssCalculator();
|
|
initDynamicForms();
|
|
initJsonImportExport();
|
|
initFormSubmit();
|
|
initMobileMenu();
|
|
initScrollEffects();
|
|
|
|
SVEID = window.location.search.split("SVEID=")[1];
|
|
if (SVEID) {
|
|
fetch(`/API/GetInformation.api?SVEID=${SVEID}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (!data.code) {
|
|
populateFormData(data);
|
|
} else {
|
|
alert("获取SVE详情失败");
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error("网络错误:", error);
|
|
alert("网络原因获取SVE详情失败");
|
|
});
|
|
}
|
|
}); |