keywordmanage / index.html
oliverjim's picture
1.界面改为中文;2.每一行为一个主题,每个主题的关键词有多个,关键词框内可以增删单个关键词,关键词框内可以复制多个关键词;3.无需actions列; - Initial Deployment
cfcb94f verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Keyword Manager</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.fade-in {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.sidebar {
transition: all 0.3s ease;
}
.sidebar.collapsed {
width: 70px;
}
.sidebar.collapsed .sidebar-text {
display: none;
}
.sidebar.collapsed .menu-icon {
margin-right: 0;
}
</style>
</head>
<body class="bg-gray-100 font-sans">
<div class="flex h-screen overflow-hidden">
<!-- Sidebar -->
<div class="sidebar bg-indigo-800 text-white w-64 flex-shrink-0 flex flex-col">
<div class="p-4 flex items-center border-b border-indigo-700">
<i class="fas fa-keyboard text-2xl mr-3 menu-icon"></i>
<span class="text-xl font-bold sidebar-text">Keyword Manager</span>
</div>
<nav class="flex-1 overflow-y-auto">
<a href="#" class="block py-3 px-4 hover:bg-indigo-700 flex items-center active-nav-item" id="dashboard-nav">
<i class="fas fa-tachometer-alt mr-3 menu-icon"></i>
<span class="sidebar-text">Dashboard</span>
</a>
<a href="#" class="block py-3 px-4 hover:bg-indigo-700 flex items-center" id="keywords-nav">
<i class="fas fa-key mr-3 menu-icon"></i>
<span class="sidebar-text">Keywords</span>
</a>
<a href="#" class="block py-3 px-4 hover:bg-indigo-700 flex items-center" id="analytics-nav">
<i class="fas fa-chart-line mr-3 menu-icon"></i>
<span class="sidebar-text">Analytics</span>
</a>
<a href="#" class="block py-3 px-4 hover:bg-indigo-700 flex items-center" id="settings-nav">
<i class="fas fa-cog mr-3 menu-icon"></i>
<span class="sidebar-text">Settings</span>
</a>
</nav>
<div class="p-4 border-t border-indigo-700">
<button id="toggle-sidebar" class="w-full py-2 px-4 bg-indigo-700 hover:bg-indigo-600 rounded flex items-center justify-center">
<i class="fas fa-chevron-left menu-icon"></i>
<span class="ml-2 sidebar-text">Collapse</span>
</button>
</div>
</div>
<!-- Main Content -->
<div class="flex-1 overflow-auto">
<!-- Header -->
<header class="bg-white shadow-sm">
<div class="flex justify-between items-center p-4">
<h1 class="text-2xl font-semibold text-gray-800">Keyword Management</h1>
<div class="flex items-center space-x-4">
<div class="relative">
<input type="text" placeholder="Search..." class="pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
<i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
</div>
<div class="flex items-center space-x-2">
<div class="relative">
<i class="fas fa-bell text-xl text-gray-600 cursor-pointer"></i>
<span class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-4 w-4 flex items-center justify-center">3</span>
</div>
<div class="h-8 w-8 rounded-full bg-indigo-500 flex items-center justify-center text-white font-semibold">JD</div>
</div>
</div>
</div>
</header>
<!-- Content Area -->
<main class="p-6">
<!-- Stats Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500">Total Keywords</p>
<h3 class="text-2xl font-bold">1,248</h3>
</div>
<div class="p-3 rounded-full bg-indigo-100 text-indigo-600">
<i class="fas fa-key text-xl"></i>
</div>
</div>
<p class="text-sm text-green-500 mt-2"><i class="fas fa-arrow-up mr-1"></i> 12% from last month</p>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500">Active Topics</p>
<h3 class="text-2xl font-bold">42</h3>
</div>
<div class="p-3 rounded-full bg-blue-100 text-blue-600">
<i class="fas fa-tags text-xl"></i>
</div>
</div>
<p class="text-sm text-green-500 mt-2"><i class="fas fa-arrow-up mr-1"></i> 5% from last month</p>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500">Users</p>
<h3 class="text-2xl font-bold">8</h3>
</div>
<div class="p-3 rounded-full bg-green-100 text-green-600">
<i class="fas fa-users text-xl"></i>
</div>
</div>
<p class="text-sm text-gray-500 mt-2">No change from last month</p>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500">Recent Activity</p>
<h3 class="text-2xl font-bold">24</h3>
</div>
<div class="p-3 rounded-full bg-purple-100 text-purple-600">
<i class="fas fa-clock text-xl"></i>
</div>
</div>
<p class="text-sm text-red-500 mt-2"><i class="fas fa-arrow-down mr-1"></i> 3% from last week</p>
</div>
</div>
<!-- Keywords Table Section -->
<div class="bg-white rounded-lg shadow overflow-hidden">
<div class="p-4 border-b flex justify-between items-center">
<h2 class="text-lg font-semibold text-gray-800">Keywords List</h2>
<button id="add-keyword-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-plus mr-2"></i> Add Keyword
</button>
</div>
<!-- Filter and Search -->
<div class="p-4 border-b bg-gray-50">
<div class="flex flex-col md:flex-row md:items-center md:justify-between space-y-4 md:space-y-0">
<div class="flex items-center space-x-2">
<label class="text-sm text-gray-600">Filter by:</label>
<select class="border rounded px-3 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500">
<option>All Topics</option>
<option>Technology</option>
<option>Marketing</option>
<option>Business</option>
<option>Science</option>
</select>
<select class="border rounded px-3 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500">
<option>All Users</option>
<option>Admin</option>
<option>Editor</option>
<option>Viewer</option>
</select>
</div>
<div class="relative">
<input type="text" placeholder="Search keywords..." class="pl-8 pr-4 py-1 border rounded-lg focus:outline-none focus:ring-1 focus:ring-indigo-500">
<i class="fas fa-search absolute left-3 top-2 text-gray-400"></i>
</div>
</div>
</div>
<!-- Table -->
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Topic</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Keyword</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">User</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date Added</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200" id="keywords-table-body">
<!-- Sample data - will be populated by JavaScript -->
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">Technology</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Artificial Intelligence</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">admin</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">2023-05-15</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button class="text-indigo-600 hover:text-indigo-900 mr-2 edit-btn">Edit</button>
<button class="text-red-600 hover:text-red-900 delete-btn">Delete</button>
</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">Marketing</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">SEO Optimization</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">editor</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">2023-05-14</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button class="text-indigo-600 hover:text-indigo-900 mr-2 edit-btn">Edit</button>
<button class="text-red-600 hover:text-red-900 delete-btn">Delete</button>
</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">Business</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Market Analysis</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">viewer</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">2023-05-13</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button class="text-indigo-600 hover:text-indigo-900 mr-2 edit-btn">Edit</button>
<button class="text-red-600 hover:text-red-900 delete-btn">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Pagination -->
<div class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6">
<div class="flex-1 flex justify-between sm:hidden">
<a href="#" class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">Previous</a>
<a href="#" class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">Next</a>
</div>
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700">
Showing <span class="font-medium">1</span> to <span class="font-medium">10</span> of <span class="font-medium">97</span> results
</p>
</div>
<div>
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
<a href="#" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
<span class="sr-only">Previous</span>
<i class="fas fa-chevron-left"></i>
</a>
<a href="#" aria-current="page" class="z-10 bg-indigo-50 border-indigo-500 text-indigo-600 relative inline-flex items-center px-4 py-2 border text-sm font-medium">1</a>
<a href="#" class="bg-white border-gray-300 text-gray-500 hover:bg-gray-50 relative inline-flex items-center px-4 py-2 border text-sm font-medium">2</a>
<a href="#" class="bg-white border-gray-300 text-gray-500 hover:bg-gray-50 relative inline-flex items-center px-4 py-2 border text-sm font-medium">3</a>
<a href="#" class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
<span class="sr-only">Next</span>
<i class="fas fa-chevron-right"></i>
</a>
</nav>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<!-- Add/Edit Keyword Modal -->
<div id="keyword-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg shadow-xl w-full max-w-md fade-in">
<div class="p-4 border-b flex justify-between items-center">
<h3 class="text-lg font-semibold text-gray-800" id="modal-title">Add New Keyword</h3>
<button id="close-modal" class="text-gray-400 hover:text-gray-500">
<i class="fas fa-times"></i>
</button>
</div>
<form id="keyword-form" class="p-4">
<input type="hidden" id="keyword-id">
<div class="mb-4">
<label for="topic" class="block text-sm font-medium text-gray-700 mb-1">Topic</label>
<input type="text" id="topic" name="topic" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-1 focus:ring-indigo-500" required>
</div>
<div class="mb-4">
<label for="keyword" class="block text-sm font-medium text-gray-700 mb-1">Keyword</label>
<input type="text" id="keyword" name="keyword" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-1 focus:ring-indigo-500" required>
</div>
<div class="mb-4">
<label for="user" class="block text-sm font-medium text-gray-700 mb-1">User</label>
<select id="user" name="user" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-1 focus:ring-indigo-500" required>
<option value="">Select User</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="viewer">Viewer</option>
</select>
</div>
<div class="flex justify-end space-x-3 pt-4">
<button type="button" id="cancel-modal" class="px-4 py-2 border rounded-lg text-gray-700 hover:bg-gray-50">Cancel</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">Save</button>
</div>
</form>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div id="delete-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg shadow-xl w-full max-w-md fade-in">
<div class="p-4 border-b">
<h3 class="text-lg font-semibold text-gray-800">Confirm Deletion</h3>
</div>
<div class="p-4">
<p class="text-gray-700 mb-4">Are you sure you want to delete this keyword? This action cannot be undone.</p>
<div class="flex justify-end space-x-3">
<button id="cancel-delete" class="px-4 py-2 border rounded-lg text-gray-700 hover:bg-gray-50">Cancel</button>
<button id="confirm-delete" class="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700">Delete</button>
</div>
</div>
</div>
</div>
<script>
// Toggle sidebar
document.getElementById('toggle-sidebar').addEventListener('click', function() {
const sidebar = document.querySelector('.sidebar');
sidebar.classList.toggle('collapsed');
const icon = this.querySelector('i');
const text = this.querySelector('span');
if (sidebar.classList.contains('collapsed')) {
icon.classList.remove('fa-chevron-left');
icon.classList.add('fa-chevron-right');
text.textContent = 'Expand';
} else {
icon.classList.remove('fa-chevron-right');
icon.classList.add('fa-chevron-left');
text.textContent = 'Collapse';
}
});
// Navigation active state
const navItems = document.querySelectorAll('nav a');
navItems.forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
navItems.forEach(nav => nav.classList.remove('active-nav-item', 'bg-indigo-700'));
this.classList.add('active-nav-item', 'bg-indigo-700');
});
});
// Modal handling
const modal = document.getElementById('keyword-modal');
const deleteModal = document.getElementById('delete-modal');
const addKeywordBtn = document.getElementById('add-keyword-btn');
const closeModalBtn = document.getElementById('close-modal');
const cancelModalBtn = document.getElementById('cancel-modal');
const cancelDeleteBtn = document.getElementById('cancel-delete');
const confirmDeleteBtn = document.getElementById('confirm-delete');
const keywordForm = document.getElementById('keyword-form');
const modalTitle = document.getElementById('modal-title');
// Show add modal
addKeywordBtn.addEventListener('click', function() {
modalTitle.textContent = 'Add New Keyword';
keywordForm.reset();
document.getElementById('keyword-id').value = '';
modal.classList.remove('hidden');
});
// Close modal
closeModalBtn.addEventListener('click', function() {
modal.classList.add('hidden');
});
cancelModalBtn.addEventListener('click', function() {
modal.classList.add('hidden');
});
// Close modal when clicking outside
modal.addEventListener('click', function(e) {
if (e.target === modal) {
modal.classList.add('hidden');
}
});
deleteModal.addEventListener('click', function(e) {
if (e.target === deleteModal) {
deleteModal.classList.add('hidden');
}
});
// Edit button click
document.addEventListener('click', function(e) {
if (e.target.classList.contains('edit-btn')) {
const row = e.target.closest('tr');
const cells = row.querySelectorAll('td');
modalTitle.textContent = 'Edit Keyword';
document.getElementById('keyword-id').value = '1'; // In real app, this would be the ID from DB
document.getElementById('topic').value = cells[0].textContent.trim();
document.getElementById('keyword').value = cells[1].textContent.trim();
document.getElementById('user').value = cells[2].textContent.trim();
modal.classList.remove('hidden');
}
// Delete button click
if (e.target.classList.contains('delete-btn')) {
deleteModal.classList.remove('hidden');
}
});
// Cancel delete
cancelDeleteBtn.addEventListener('click', function() {
deleteModal.classList.add('hidden');
});
// Confirm delete
confirmDeleteBtn.addEventListener('click', function() {
// In a real app, you would send a request to delete the record
deleteModal.classList.add('hidden');
// Show a success message
alert('Keyword deleted successfully!');
});
// Form submission
keywordForm.addEventListener('submit', function(e) {
e.preventDefault();
const id = document.getElementById('keyword-id').value;
const topic = document.getElementById('topic').value;
const keyword = document.getElementById('keyword').value;
const user = document.getElementById('user').value;
// In a real app, you would send this data to the server
console.log('Form submitted:', { id, topic, keyword, user });
// Close the modal
modal.classList.add('hidden');
// Show a success message
alert(`Keyword ${id ? 'updated' : 'added'} successfully!`);
// In a real app, you would update the table with the new data
});
// Simulate loading data from the server
function loadKeywords(page = 1) {
// In a real app, this would be an AJAX call to your Flask backend
console.log(`Loading keywords for page ${page}`);
}
// Initial load
loadKeywords();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=oliverjim/keywordmanage" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>