|
@@ -57,6 +57,9 @@
|
|
|
<div class="flex justify-between items-center mb-4">
|
|
<div class="flex justify-between items-center mb-4">
|
|
|
<label class="text-gray-400 text-sm font-bold">3. 采集结果橱窗</label>
|
|
<label class="text-gray-400 text-sm font-bold">3. 采集结果橱窗</label>
|
|
|
<div class="flex gap-2 items-center">
|
|
<div class="flex gap-2 items-center">
|
|
|
|
|
+ <button onclick="openManualModal()" class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-1 rounded text-sm transition-colors">
|
|
|
|
|
+ <i class="fas fa-plus"></i> 手动入库
|
|
|
|
|
+ </button>
|
|
|
<span id="result-count" class="text-gray-500 text-sm"></span>
|
|
<span id="result-count" class="text-gray-500 text-sm"></span>
|
|
|
<button onclick="toggleSelectAll()" id="btn-select-all" class="hidden bg-gray-600 hover:bg-gray-500 text-white px-3 py-1 rounded text-sm transition-colors">
|
|
<button onclick="toggleSelectAll()" id="btn-select-all" class="hidden bg-gray-600 hover:bg-gray-500 text-white px-3 py-1 rounded text-sm transition-colors">
|
|
|
<i class="fas fa-check-double"></i> 全选
|
|
<i class="fas fa-check-double"></i> 全选
|
|
@@ -380,5 +383,135 @@
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ function openManualModal() {
|
|
|
|
|
+ $('#manual-modal').removeClass('hidden');
|
|
|
|
|
+ $('#manual-link').val('');
|
|
|
|
|
+ $('#manual-title').val('');
|
|
|
|
|
+ $('#manual-abstract').val('');
|
|
|
|
|
+ $('#manual-source').val('');
|
|
|
|
|
+ $('#manual-cover').val('');
|
|
|
|
|
+ $('#manual-date').val('');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function closeManualModal() {
|
|
|
|
|
+ $('#manual-modal').addClass('hidden');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function addManualEntry() {
|
|
|
|
|
+ const link = $('#manual-link').val().trim();
|
|
|
|
|
+ if (!link) {
|
|
|
|
|
+ alert('链接地址为必填项');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const item = {
|
|
|
|
|
+ title: $('#manual-title').val().trim(),
|
|
|
|
|
+ abstract: $('#manual-abstract').val().trim(),
|
|
|
|
|
+ source: $('#manual-source').val().trim(),
|
|
|
|
|
+ cover: $('#manual-cover').val().trim(),
|
|
|
|
|
+ link: link,
|
|
|
|
|
+ published_at: $('#manual-date').val().trim()
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ $.ajax({
|
|
|
|
|
+ url: '/collection/api/manual-save',
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ contentType: 'application/json',
|
|
|
|
|
+ data: JSON.stringify({ items: [item] }),
|
|
|
|
|
+ success: function(response) {
|
|
|
|
|
+ const msg = response.added > 0 ? `新增 ${response.added} 条` : `更新 ${response.updated} 条`;
|
|
|
|
|
+ alert('保存成功!' + msg);
|
|
|
|
|
+ closeManualModal();
|
|
|
|
|
+ // Add to showcase display
|
|
|
|
|
+ const idx = currentResults.length;
|
|
|
|
|
+ currentResults.push(item);
|
|
|
|
|
+ const container = $('#results-container');
|
|
|
|
|
+ // Remove placeholder if exists
|
|
|
|
|
+ if (container.find('.col-span-full').length > 0) {
|
|
|
|
|
+ container.empty();
|
|
|
|
|
+ }
|
|
|
|
|
+ const coverHtml = item.cover ?
|
|
|
|
|
+ `<img src="${item.cover}" class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105" onerror="this.src='https://via.placeholder.com/300x200?text=No+Image'">` :
|
|
|
|
|
+ `<div class="w-full h-full bg-gray-700 flex items-center justify-center text-gray-500"><i class="fas fa-image text-3xl"></i></div>`;
|
|
|
|
|
+ const html = `
|
|
|
|
|
+ <div id="result-card-${idx}" class="result-card bg-gray-700 rounded-lg border border-gray-600 cursor-pointer hover:shadow-xl transition-all flex flex-col group relative"
|
|
|
|
|
+ onclick="toggleSelection(${idx}, this)">
|
|
|
|
|
+ <div class="h-40 w-full flex-none overflow-hidden rounded-t-lg relative">
|
|
|
|
|
+ ${coverHtml}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="p-4 flex flex-col flex-1">
|
|
|
|
|
+ <h3 class="text-white font-bold mb-2 text-sm md:text-base break-words hover:text-blue-400"
|
|
|
|
|
+ style="display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.5em; max-height: 3em;"
|
|
|
|
|
+ title="${item.title || ''}"
|
|
|
|
|
+ onclick="event.stopPropagation(); window.open('${item.link}', '_blank')">
|
|
|
|
|
+ ${item.title || '<span class="text-gray-500 italic">(无标题)</span>'}
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ <div class="mt-auto pt-2 border-t border-gray-600 flex justify-between items-center text-xs text-gray-400">
|
|
|
|
|
+ <span class="truncate max-w-[120px]" title="${item.source || ''}">
|
|
|
|
|
+ <i class="fas fa-globe mr-1 text-blue-400"></i>${item.source || '未知来源'}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span class="whitespace-nowrap ml-2">
|
|
|
|
|
+ <i class="far fa-clock mr-1 text-green-400"></i>${item.published_at || '未知时间'}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ `;
|
|
|
|
|
+ container.append(html);
|
|
|
|
|
+ $('#btn-save').removeClass('hidden');
|
|
|
|
|
+ $('#result-count').text(`共 ${currentResults.length} 条数据`);
|
|
|
|
|
+ },
|
|
|
|
|
+ error: function(xhr) {
|
|
|
|
|
+ alert('保存失败: ' + (xhr.responseJSON?.error || '未知错误'));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
</script>
|
|
</script>
|
|
|
|
|
+
|
|
|
|
|
+<!-- Manual Input Modal -->
|
|
|
|
|
+<div id="manual-modal" class="hidden fixed inset-0 bg-black/60 z-50 flex items-center justify-center">
|
|
|
|
|
+ <div class="bg-gray-800 rounded-lg shadow-xl p-6 w-full max-w-lg mx-4 border border-gray-700">
|
|
|
|
|
+ <div class="flex justify-between items-center mb-4">
|
|
|
|
|
+ <h2 class="text-xl font-bold text-white"><i class="fas fa-plus text-purple-500 mr-2"></i>手动入库</h2>
|
|
|
|
|
+ <button onclick="closeManualModal()" class="text-gray-400 hover:text-white">
|
|
|
|
|
+ <i class="fas fa-times text-xl"></i>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="space-y-4">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <label class="block text-gray-400 text-sm mb-1 font-bold">链接地址 <span class="text-red-500">*</span></label>
|
|
|
|
|
+ <input type="text" id="manual-link" class="w-full bg-gray-700 text-white rounded p-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="https://...">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <label class="block text-gray-400 text-sm mb-1 font-bold">标题</label>
|
|
|
|
|
+ <input type="text" id="manual-title" class="w-full bg-gray-700 text-white rounded p-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="文章标题">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <label class="block text-gray-400 text-sm mb-1 font-bold">摘要</label>
|
|
|
|
|
+ <textarea id="manual-abstract" rows="3" class="w-full bg-gray-700 text-white rounded p-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="内容摘要"></textarea>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex gap-4">
|
|
|
|
|
+ <div class="flex-1">
|
|
|
|
|
+ <label class="block text-gray-400 text-sm mb-1 font-bold">来源</label>
|
|
|
|
|
+ <input type="text" id="manual-source" class="w-full bg-gray-700 text-white rounded p-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="来源网站">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex-1">
|
|
|
|
|
+ <label class="block text-gray-400 text-sm mb-1 font-bold">发布日期</label>
|
|
|
|
|
+ <input type="text" id="manual-date" class="w-full bg-gray-700 text-white rounded p-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="2026-05-20">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <label class="block text-gray-400 text-sm mb-1 font-bold">封面图片 URL</label>
|
|
|
|
|
+ <input type="text" id="manual-cover" class="w-full bg-gray-700 text-white rounded p-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="https://...">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex justify-end gap-3 mt-6">
|
|
|
|
|
+ <button onclick="closeManualModal()" class="bg-gray-600 hover:bg-gray-500 text-white px-6 py-2 rounded transition-colors">取消</button>
|
|
|
|
|
+ <button onclick="addManualEntry()" class="bg-purple-600 hover:bg-purple-700 text-white px-6 py-2 rounded transition-colors">
|
|
|
|
|
+ <i class="fas fa-save mr-1"></i>保存入库
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</div>
|
|
|
{% endblock %}
|
|
{% endblock %}
|