feat: 主题核心思路功能 - 每个主题可设定核心思路,AI分析和生成文章时自动引入
This commit is contained in:
@@ -23,6 +23,13 @@
|
||||
.material-item .mat-content { white-space: pre-wrap; word-break: break-word; font-size: 0.92rem; line-height: 1.5; max-height: 120px; overflow: hidden; }
|
||||
.material-item img { max-width: 100%; max-height: 200px; border-radius: 6px; margin-top: 6px; }
|
||||
.material-item .mat-meta { color: var(--text-muted); font-size: 0.8rem; margin-top: 6px; }
|
||||
.mat-note { color: var(--text-muted); font-size: 0.85rem; margin-top: 4px; padding: 4px 8px; background: rgba(88,166,255,0.05); border-radius: 4px; border-left: 2px solid var(--accent); }
|
||||
.mat-analysis { color: var(--text); font-size: 0.85rem; margin-top: 6px; padding: 8px 10px; background: rgba(63,185,80,0.06); border-radius: 6px; border-left: 3px solid var(--success); white-space: pre-wrap; word-break: break-word; line-height: 1.6; position: relative; }
|
||||
.mat-analysis-label { color: var(--success); font-size: 0.78rem; font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; gap: 4px; }
|
||||
.mat-analysis-actions { position: absolute; top: 6px; right: 6px; display: flex; gap: 4px; }
|
||||
.mat-analysis-actions .btn-link { padding: 0; font-size: 0.75rem; }
|
||||
.mat-note-edit { display: flex; gap: 6px; align-items: center; margin-top: 4px; }
|
||||
.mat-note-edit input { flex: 1; }
|
||||
.btn-accent { background: var(--accent); color: #fff; border: none; }
|
||||
.btn-accent:hover { background: var(--accent-hover); color: #fff; }
|
||||
.btn-outline-accent { border-color: var(--accent); color: var(--accent); }
|
||||
@@ -74,6 +81,33 @@
|
||||
.pill-option.selected-tag { background: rgba(63,185,80,0.15); border-color: var(--success); color: var(--success); }
|
||||
.tag-input-group { display: flex; gap: 6px; }
|
||||
.tag-input-group input { flex: 1; }
|
||||
|
||||
/* 素材选择开关 */
|
||||
.mat-select-toggle { position: relative; display: inline-block; width: 36px; height: 20px; flex-shrink: 0; }
|
||||
.mat-select-toggle input { opacity: 0; width: 0; height: 0; }
|
||||
.mat-select-toggle .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background: var(--border); border-radius: 20px; transition: 0.2s; }
|
||||
.mat-select-toggle .slider:before { content: ""; position: absolute; height: 14px; width: 14px; left: 3px; bottom: 3px; background: var(--text-muted); border-radius: 50%; transition: 0.2s; }
|
||||
.mat-select-toggle input:checked + .slider { background: var(--accent); }
|
||||
.mat-select-toggle input:checked + .slider:before { transform: translateX(16px); background: #fff; }
|
||||
.material-item.unselected { opacity: 0.45; }
|
||||
.material-item.unselected:hover { opacity: 0.7; }
|
||||
.select-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 0.82rem; }
|
||||
.select-toolbar .select-count { color: var(--text-muted); }
|
||||
.select-toolbar .btn-link { padding: 0; font-size: 0.82rem; text-decoration: none; }
|
||||
|
||||
/* 核心思路样式 */
|
||||
.core-idea-bar { padding: 10px 16px; background: rgba(210,153,34,0.08); border-bottom: 1px solid var(--border); display: flex; align-items: flex-start; gap: 10px; }
|
||||
.core-idea-bar .core-idea-icon { color: var(--warning); font-size: 1.1rem; flex-shrink: 0; margin-top: 2px; }
|
||||
.core-idea-bar .core-idea-content { flex: 1; }
|
||||
.core-idea-bar .core-idea-label { font-size: 0.78rem; font-weight: 600; color: var(--warning); margin-bottom: 2px; }
|
||||
.core-idea-bar .core-idea-text { font-size: 0.9rem; color: var(--text); line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
|
||||
.core-idea-bar .core-idea-empty { font-size: 0.85rem; color: var(--text-muted); font-style: italic; }
|
||||
.core-idea-bar .edit-btn { cursor: pointer; color: var(--text-muted); font-size: 0.8rem; flex-shrink: 0; }
|
||||
.core-idea-bar .edit-btn:hover { color: var(--accent); }
|
||||
.core-idea-edit-bar { padding: 10px 16px; background: rgba(210,153,34,0.08); border-bottom: 1px solid var(--border); display: none; }
|
||||
.core-idea-edit-bar .edit-row { display: flex; gap: 6px; align-items: flex-end; }
|
||||
.core-idea-edit-bar textarea { flex: 1; }
|
||||
.core-idea-edit-bar .btn-group { display: flex; gap: 4px; flex-shrink: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -105,6 +139,30 @@
|
||||
<span class="edit-btn ms-2" onclick="showEditCatTagModal()"><i class="bi bi-pencil"></i> 编辑</span>
|
||||
</div>
|
||||
|
||||
<!-- 核心思路显示 -->
|
||||
<div class="core-idea-bar" id="coreIdeaDisplay">
|
||||
<i class="bi bi-lightbulb core-idea-icon"></i>
|
||||
<div class="core-idea-content">
|
||||
<div class="core-idea-label">核心思路</div>
|
||||
{% if topic.core_idea %}
|
||||
<div class="core-idea-text" id="coreIdeaText">{{topic.core_idea}}</div>
|
||||
{% else %}
|
||||
<div class="core-idea-empty" id="coreIdeaText">尚未设定,点击编辑添加核心思路以指导AI分析和创作</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<span class="edit-btn" onclick="showEditCoreIdea()"><i class="bi bi-pencil"></i> 编辑</span>
|
||||
</div>
|
||||
<!-- 核心思路编辑区 -->
|
||||
<div class="core-idea-edit-bar" id="coreIdeaEdit">
|
||||
<div class="edit-row">
|
||||
<textarea class="form-control form-control-sm" id="coreIdeaInput" rows="3" placeholder="概括整体思路、文章风格、创作方向等,将指导AI分析和创作">{{topic.core_idea or ''}}</textarea>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-accent py-0 px-2" onclick="saveCoreIdea()"><i class="bi bi-check-lg"></i></button>
|
||||
<button class="btn btn-sm btn-secondary py-0 px-2" onclick="cancelEditCoreIdea()"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid px-4 py-3">
|
||||
<div class="row g-3">
|
||||
<!-- 左栏:素材 + Prompt -->
|
||||
@@ -126,6 +184,14 @@
|
||||
<div class="mb-2 small text-muted"><i class="bi bi-clock-history me-1"></i>历史Prompt(点击恢复)</div>
|
||||
<div id="promptHistoryList"></div>
|
||||
</div>
|
||||
<!-- Prompt模板选择 -->
|
||||
<div class="mb-2">
|
||||
<select class="form-select form-select-sm" id="topicPromptTemplate" onchange="applyTopicPromptTemplate(this)">
|
||||
<option value="">-- 选择Prompt模板 --</option>
|
||||
<option value="__custom__">自定义输入</option>
|
||||
</select>
|
||||
<div class="form-text">选择模板自动填充,也可手动编辑</div>
|
||||
</div>
|
||||
<textarea class="form-control" id="promptText" rows="4" placeholder="请根据以下素材撰写一篇结构清晰、内容丰富的文章:">{{topic.prompt or ''}}</textarea>
|
||||
{% if topic.description %}<div class="mt-2 text-muted small"><i class="bi bi-info-circle me-1"></i>主题说明:{{topic.description}}</div>{% endif %}
|
||||
</div>
|
||||
@@ -134,13 +200,23 @@
|
||||
<!-- 素材区 -->
|
||||
<div class="card-dark">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span class="section-title mb-0"><i class="bi bi-collection text-info"></i>素材库 <span class="badge bg-secondary ms-1">{{materials|length}}</span></span>
|
||||
<span class="section-title mb-0"><i class="bi bi-collection text-info"></i>素材库 <span class="badge bg-secondary ms-1" id="matCountBadge">{{materials|length}}</span></span>
|
||||
<div>
|
||||
<button class="btn btn-sm btn-outline-accent me-1" onclick="showAddText()"><i class="bi bi-type me-1"></i>文本</button>
|
||||
<button class="btn btn-sm btn-outline-accent" onclick="showAddImage()"><i class="bi bi-image me-1"></i>图片</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body" id="materialsList" style="max-height: 60vh; overflow-y: auto;">
|
||||
<!-- 选择工具栏 -->
|
||||
<div class="select-toolbar">
|
||||
<label class="mat-select-toggle" title="全选/取消全选">
|
||||
<input type="checkbox" id="selectAllToggle" onchange="toggleSelectAll(this.checked)">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span class="select-count" id="selectCount"></span>
|
||||
<span class="btn-link text-accent" onclick="selectAllMaterials(true)">全选</span>
|
||||
<span class="btn-link text-muted" onclick="selectAllMaterials(false)">取消全选</span>
|
||||
</div>
|
||||
<!-- 粘贴上传区 -->
|
||||
<div class="paste-zone mb-3" id="pasteZone" tabindex="0" onclick="document.getElementById('imageFile').click()">
|
||||
<i class="bi bi-clipboard"></i>
|
||||
@@ -148,17 +224,51 @@
|
||||
</div>
|
||||
{% if materials %}
|
||||
{% for m in materials %}
|
||||
<div class="material-item" id="mat-{{m.id}}">
|
||||
<div class="material-item {% if m.selected == 0 %}unselected{% endif %}" id="mat-{{m.id}}" data-selected="{{m.selected if m.selected is not none else 1}}">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<span class="badge {{'bg-info' if m.type=='text' else 'bg-warning'}}">{{'文本' if m.type=='text' else '图片'}}</span>
|
||||
<button class="btn btn-sm btn-link text-danger p-0" onclick="deleteMaterial('{{m.id}}')" title="删除"><i class="bi bi-x-lg"></i></button>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<label class="mat-select-toggle" title="选中/取消">
|
||||
<input type="checkbox" {% if m.selected != 0 %}checked{% endif %} onchange="toggleMaterialSelect('{{m.id}}', this.checked)">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span class="badge {{'bg-info' if m.type=='text' else 'bg-warning'}}">{{'文本' if m.type=='text' else '图片'}}</span>
|
||||
</div>
|
||||
<div class="d-flex gap-1">
|
||||
<button class="btn btn-sm btn-link text-success p-0" onclick="analyzeMaterial('{{m.id}}')" title="AI分析" id="analyze-btn-{{m.id}}"><i class="bi bi-stars"></i></button>
|
||||
{% if m.type == 'image' %}
|
||||
<button class="btn btn-sm btn-link text-accent p-0" onclick="editMatNote('{{m.id}}', '{{(m.content or "")|replace("'", "\\'")|replace("\n", "\\n")}}')" title="编辑备注"><i class="bi bi-pencil"></i></button>
|
||||
{% endif %}
|
||||
<button class="btn btn-sm btn-link text-danger p-0" onclick="deleteMaterial('{{m.id}}')" title="删除"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% if m.type == 'text' %}
|
||||
<div class="mat-content mt-1">{{m.content}}</div>
|
||||
{% else %}
|
||||
{% if m.content %}<div class="small text-muted mt-1">{{m.content}}</div>{% endif %}
|
||||
<img src="/static/{{m.file_path}}" alt="素材图片">
|
||||
<div id="mat-note-display-{{m.id}}">
|
||||
{% if m.content %}
|
||||
<div class="mat-note">{{m.content}}</div>
|
||||
{% else %}
|
||||
<div class="small text-muted mt-1" style="opacity:0.5;cursor:pointer;" onclick="editMatNote('{{m.id}}', '')"><i class="bi bi-plus-circle me-1"></i>添加备注</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="mat-note-edit-{{m.id}}" class="mat-note-edit" style="display:none;">
|
||||
<input type="text" class="form-control form-control-sm" id="mat-note-input-{{m.id}}" placeholder="输入图片备注..." onkeydown="if(event.key==='Enter')saveMatNote('{{m.id}}');if(event.key==='Escape')cancelMatNote('{{m.id}}');">
|
||||
<button class="btn btn-sm btn-accent py-0 px-2" onclick="saveMatNote('{{m.id}}')"><i class="bi bi-check-lg"></i></button>
|
||||
<button class="btn btn-sm btn-secondary py-0 px-2" onclick="cancelMatNote('{{m.id}}')"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="mat-analysis-{{m.id}}">
|
||||
{% if m.analysis %}
|
||||
<div class="mat-analysis">
|
||||
<div class="mat-analysis-label"><i class="bi bi-stars"></i>AI 分析</div>
|
||||
<div class="mat-analysis-actions">
|
||||
<button class="btn btn-link text-muted" onclick="clearAnalysis('{{m.id}}')" title="清除分析"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
{{m.analysis}}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="mat-meta">{{m.created_at}}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@@ -325,6 +435,31 @@
|
||||
const catTagModal = new bootstrap.Modal(document.getElementById('catTagModal'));
|
||||
let pastedBlob = null;
|
||||
|
||||
// Prompt模板数据缓存
|
||||
let topicPromptTemplatesCache = [];
|
||||
|
||||
// 页面加载时填充Prompt模板下拉
|
||||
(async function() {
|
||||
try {
|
||||
const res = await fetch('/api/prompt-templates');
|
||||
topicPromptTemplatesCache = await res.json();
|
||||
const sel = document.getElementById('topicPromptTemplate');
|
||||
sel.innerHTML = '<option value="">-- 选择Prompt模板 --</option><option value="__custom__">自定义输入</option>';
|
||||
topicPromptTemplatesCache.forEach(t => {
|
||||
sel.innerHTML += `<option value="${t.id}">${t.name}</option>`;
|
||||
});
|
||||
} catch(e) {}
|
||||
})();
|
||||
|
||||
function applyTopicPromptTemplate(sel) {
|
||||
const val = sel.value;
|
||||
if (!val || val === '__custom__') return;
|
||||
const tpl = topicPromptTemplatesCache.find(t => t.id === val);
|
||||
if (tpl) {
|
||||
document.getElementById('promptText').value = tpl.prompt;
|
||||
}
|
||||
}
|
||||
|
||||
// 当前主题的分类和标签
|
||||
const currentCategoryIds = [{% for c in topic.categories %}'{{c.id}}',{% endfor %}];
|
||||
const currentTagIds = [{% for tg in topic.tags %}'{{tg.id}}',{% endfor %}];
|
||||
@@ -492,6 +627,93 @@
|
||||
document.getElementById(`mat-${id}`).remove();
|
||||
}
|
||||
|
||||
// ===== AI分析素材 =====
|
||||
async function analyzeMaterial(id) {
|
||||
const btn = document.getElementById('analyze-btn-' + id);
|
||||
const orig = btn.innerHTML;
|
||||
btn.innerHTML = '<span class="spinner-generate" style="width:14px;height:14px;border-width:2px;"></span>';
|
||||
btn.style.pointerEvents = 'none';
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/materials/${id}/analyze`, {method: 'POST'});
|
||||
if (!res.ok) { const d = await res.json(); throw new Error(d.error || '分析失败'); }
|
||||
const data = await res.json();
|
||||
|
||||
// 更新分析结果显示区
|
||||
const container = document.getElementById('mat-analysis-' + id);
|
||||
if (container) {
|
||||
container.innerHTML = `<div class="mat-analysis">
|
||||
<div class="mat-analysis-label"><i class="bi bi-stars"></i>AI 分析</div>
|
||||
<div class="mat-analysis-actions">
|
||||
<button class="btn btn-link text-muted" onclick="clearAnalysis('${id}')" title="清除分析"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
${escapeHtml(data.analysis)}
|
||||
</div>`;
|
||||
}
|
||||
} catch(e) {
|
||||
alert('AI分析失败: ' + e.message);
|
||||
} finally {
|
||||
btn.innerHTML = orig;
|
||||
btn.style.pointerEvents = '';
|
||||
}
|
||||
}
|
||||
|
||||
async function clearAnalysis(id) {
|
||||
if (!confirm('确定清除AI分析结果?')) return;
|
||||
// 前端清空显示
|
||||
const container = document.getElementById('mat-analysis-' + id);
|
||||
if (container) container.innerHTML = '';
|
||||
// 后端清空数据
|
||||
await fetch(`/api/materials/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({analysis: ''})
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 图片备注编辑 =====
|
||||
function editMatNote(id, currentNote) {
|
||||
const displayEl = document.getElementById('mat-note-display-' + id);
|
||||
const editEl = document.getElementById('mat-note-edit-' + id);
|
||||
const inputEl = document.getElementById('mat-note-input-' + id);
|
||||
if (displayEl) displayEl.style.display = 'none';
|
||||
if (editEl) editEl.style.display = 'flex';
|
||||
if (inputEl) { inputEl.value = currentNote; inputEl.focus(); }
|
||||
}
|
||||
|
||||
function cancelMatNote(id) {
|
||||
const displayEl = document.getElementById('mat-note-display-' + id);
|
||||
const editEl = document.getElementById('mat-note-edit-' + id);
|
||||
if (displayEl) displayEl.style.display = '';
|
||||
if (editEl) editEl.style.display = 'none';
|
||||
}
|
||||
|
||||
async function saveMatNote(id) {
|
||||
const inputEl = document.getElementById('mat-note-input-' + id);
|
||||
const note = inputEl ? inputEl.value.trim() : '';
|
||||
const res = await fetch(`/api/materials/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({content: note})
|
||||
});
|
||||
if (res.ok) {
|
||||
// 更新显示区域
|
||||
const displayEl = document.getElementById('mat-note-display-' + id);
|
||||
if (displayEl) {
|
||||
if (note) {
|
||||
displayEl.innerHTML = `<div class="mat-note">${note}</div>`;
|
||||
} else {
|
||||
displayEl.innerHTML = `<div class="small text-muted mt-1" style="opacity:0.5;cursor:pointer;" onclick="editMatNote('${id}', '')"><i class="bi bi-plus-circle me-1"></i>添加备注</div>`;
|
||||
}
|
||||
displayEl.style.display = '';
|
||||
}
|
||||
const editEl = document.getElementById('mat-note-edit-' + id);
|
||||
if (editEl) editEl.style.display = 'none';
|
||||
} else {
|
||||
const d = await res.json(); alert(d.error || '保存失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function savePrompt() {
|
||||
const prompt = document.getElementById('promptText').value;
|
||||
const res = await fetch(`/api/topics/${topicId}`, {
|
||||
@@ -608,6 +830,98 @@
|
||||
function escapeAttr(text) {
|
||||
return text.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, '\\n');
|
||||
}
|
||||
|
||||
// ===== 素材选择 =====
|
||||
function updateSelectCount() {
|
||||
const items = document.querySelectorAll('.material-item');
|
||||
const total = items.length;
|
||||
let selected = 0;
|
||||
items.forEach(el => {
|
||||
if (el.dataset.selected === '1' || el.dataset.selected === undefined) selected++;
|
||||
});
|
||||
const countEl = document.getElementById('selectCount');
|
||||
if (countEl) countEl.textContent = `已选 ${selected}/${total}`;
|
||||
// 更新全选开关状态
|
||||
const toggleAll = document.getElementById('selectAllToggle');
|
||||
if (toggleAll) {
|
||||
toggleAll.checked = (total > 0 && selected === total);
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleMaterialSelect(id, checked) {
|
||||
const el = document.getElementById('mat-' + id);
|
||||
if (el) {
|
||||
el.dataset.selected = checked ? '1' : '0';
|
||||
el.classList.toggle('unselected', !checked);
|
||||
}
|
||||
await fetch(`/api/materials/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({selected: checked ? 1 : 0})
|
||||
});
|
||||
updateSelectCount();
|
||||
}
|
||||
|
||||
async function selectAllMaterials(selectAll) {
|
||||
const items = document.querySelectorAll('.material-item');
|
||||
const updates = [];
|
||||
items.forEach(el => {
|
||||
const id = el.id.replace('mat-', '');
|
||||
el.dataset.selected = selectAll ? '1' : '0';
|
||||
el.classList.toggle('unselected', !selectAll);
|
||||
const toggle = el.querySelector('.mat-select-toggle input');
|
||||
if (toggle) toggle.checked = selectAll;
|
||||
updates.push({id, selected: selectAll ? 1 : 0});
|
||||
});
|
||||
await fetch(`/api/topics/${topicId}/materials/select`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({materials: updates})
|
||||
});
|
||||
updateSelectCount();
|
||||
}
|
||||
|
||||
function toggleSelectAll(checked) {
|
||||
selectAllMaterials(checked);
|
||||
}
|
||||
|
||||
// ===== 核心思路编辑 =====
|
||||
function showEditCoreIdea() {
|
||||
document.getElementById('coreIdeaDisplay').style.display = 'none';
|
||||
document.getElementById('coreIdeaEdit').style.display = 'block';
|
||||
document.getElementById('coreIdeaInput').focus();
|
||||
}
|
||||
|
||||
function cancelEditCoreIdea() {
|
||||
document.getElementById('coreIdeaDisplay').style.display = '';
|
||||
document.getElementById('coreIdeaEdit').style.display = 'none';
|
||||
}
|
||||
|
||||
async function saveCoreIdea() {
|
||||
const coreIdea = document.getElementById('coreIdeaInput').value;
|
||||
const res = await fetch(`/api/topics/${topicId}`, {
|
||||
method: 'PUT',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({core_idea: coreIdea})
|
||||
});
|
||||
if (res.ok) {
|
||||
const textEl = document.getElementById('coreIdeaText');
|
||||
if (coreIdea.trim()) {
|
||||
textEl.className = 'core-idea-text';
|
||||
textEl.textContent = coreIdea;
|
||||
} else {
|
||||
textEl.className = 'core-idea-empty';
|
||||
textEl.textContent = '尚未设定,点击编辑添加核心思路以指导AI分析和创作';
|
||||
}
|
||||
document.getElementById('coreIdeaDisplay').style.display = '';
|
||||
document.getElementById('coreIdeaEdit').style.display = 'none';
|
||||
} else {
|
||||
const d = await res.json(); alert(d.error || '保存失败');
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化选择计数
|
||||
updateSelectCount();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user