Toolhub / Views /Admin /Tools.cshtml
unifare
Initial commit: ToolHub ASP.NET Core app
5fc700d
@model List<ToolHub.Models.Tool>
@{
ViewData["Title"] = "工具管理";
Layout = "_AdminLayout";
var categories = ViewBag.Categories as List<ToolHub.Models.Category> ?? new List<ToolHub.Models.Category>();
var currentCategory = ViewBag.CurrentCategory as int? ?? 0;
var currentPage = ViewBag.CurrentPage as int? ?? 1;
var totalPages = ViewBag.TotalPages as int? ?? 1;
var totalCount = ViewBag.TotalCount as int? ?? 0;
var pageSize = ViewBag.PageSize as int? ?? 20;
}
<!-- 页面头部 -->
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
<div>
<h2 style="font-size: 1.5rem; font-weight: 700; margin: 0; color: var(--dark);">工具管理</h2>
<p style="color: var(--dark-2); margin: 0.5rem 0 0;">管理平台上的所有工具,添加、编辑或删除工具</p>
</div>
<div style="display: flex; gap: 1rem;">
<a href="@Url.Action("Index", "Tag")" class="btn btn-secondary">
<i class="fas fa-tags"></i>
标签管理
</a>
<button class="btn btn-primary" onclick="openToolModal()">
<i class="fas fa-plus"></i>
添加工具
</button>
</div>
</div>
<!-- 筛选和搜索 -->
<div style="background: white; padding: 1.5rem; border-radius: var(--border-radius); box-shadow: var(--shadow-sm); margin-bottom: 2rem;">
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr auto; gap: 1rem; align-items: end;">
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem; font-size: 0.875rem;">分类筛选</label>
<select id="categoryFilter" onchange="filterTools()" style="width: 100%; padding: 0.75rem; border: 1px solid var(--light-2); border-radius: var(--border-radius);">
<option value="0">全部分类</option>
@foreach (var category in categories)
{
<option value="@category.Id" selected="@(currentCategory == category.Id)">@category.Name</option>
}
</select>
</div>
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem; font-size: 0.875rem;">状态筛选</label>
<select id="statusFilter" onchange="filterTools()" style="width: 100%; padding: 0.75rem; border: 1px solid var(--light-2); border-radius: var(--border-radius);">
<option value="">全部状态</option>
<option value="active">启用</option>
<option value="inactive">禁用</option>
<option value="hot">热门</option>
<option value="new">新品</option>
<option value="recommended">推荐</option>
</select>
</div>
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem; font-size: 0.875rem;">搜索工具</label>
<input type="text" id="searchInput" placeholder="输入工具名称..." onkeyup="filterTools()"
style="width: 100%; padding: 0.75rem; border: 1px solid var(--light-2); border-radius: var(--border-radius);" />
</div>
<button class="btn btn-outline" onclick="clearFilters()">
<i class="fas fa-undo"></i>
重置
</button>
</div>
</div>
<!-- 工具列表 -->
<div class="data-table">
<div style="padding: 1rem 1.5rem; border-bottom: 1px solid var(--light-2); display: flex; justify-content: space-between; align-items: center;">
<span style="font-weight: 600;">工具列表 (@totalCount)</span>
<div style="display: flex; gap: 0.5rem;">
<button class="btn btn-outline btn-sm" onclick="toggleView('table')" id="tableViewBtn">
<i class="fas fa-list"></i> 表格
</button>
<button class="btn btn-outline btn-sm" onclick="toggleView('grid')" id="gridViewBtn">
<i class="fas fa-th"></i> 网格
</button>
</div>
</div>
<!-- 表格视图 -->
<div id="tableView">
<table>
<thead>
<tr>
<th>工具信息</th>
<th>分类</th>
<th>统计</th>
<th>标签</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody id="toolsTableBody">
@foreach (var tool in Model)
{
<tr data-category="@tool.CategoryId" data-status="@(tool.IsActive ? "active" : "inactive")"
data-hot="@tool.IsHot.ToString().ToLower()" data-new="@tool.IsNew.ToString().ToLower()" data-recommended="@tool.IsRecommended.ToString().ToLower()">
<td>
<div style="display: flex; align-items: center;">
@if (!string.IsNullOrEmpty(tool.Image))
{
<img src="@tool.Image" alt="@tool.Name" style="width: 40px; height: 40px; border-radius: var(--border-radius); margin-right: 0.75rem; object-fit: cover;" />
}
else
{
<div style="width: 40px; height: 40px; background: linear-gradient(135deg, var(--primary), var(--secondary)); border-radius: var(--border-radius); display: flex; align-items: center; justify-content: center; margin-right: 0.75rem;">
<i class="@tool.Icon" style="color: white;"></i>
</div>
}
<div>
<strong class="tool-name">@tool.Name</strong>
@if (!string.IsNullOrEmpty(tool.Description))
{
<br><small style="color: var(--dark-2);">@(tool.Description.Length > 50 ? tool.Description.Substring(0, 50) + "..." : tool.Description)</small>
}
</div>
</div>
</td>
<td>
<span class="badge badge-primary">@tool.Category?.Name</span>
</td>
<td>
<div style="font-size: 0.875rem;">
<div style="margin-bottom: 0.25rem;">
<i class="fas fa-eye" style="color: var(--primary); margin-right: 0.25rem;"></i>
@(tool.ViewCount > 1000 ? (tool.ViewCount / 1000).ToString("F0") + "K" : tool.ViewCount.ToString())
</div>
@if (tool.Rating > 0)
{
<div>
<i class="fas fa-star" style="color: var(--warning); margin-right: 0.25rem;"></i>
@tool.Rating.ToString("F1")
</div>
}
</div>
</td>
<td>
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem;">
@if (tool.IsHot)
{
<span class="badge badge-danger">热门</span>
}
@if (tool.IsNew)
{
<span class="badge badge-warning">新品</span>
}
@if (tool.IsRecommended)
{
<span class="badge badge-success">推荐</span>
}
<button class="btn btn-outline btn-xs" onclick="manageToolTags(@tool.Id, '@tool.Name')" title="管理标签">
<i class="fas fa-tags"></i>
</button>
</div>
</td>
<td>
@if (tool.IsActive)
{
<span class="badge badge-success">启用</span>
}
else
{
<span class="badge badge-secondary">禁用</span>
}
</td>
<td style="color: var(--dark-2); font-size: 0.875rem;">
@tool.CreatedAt.ToString("yyyy-MM-dd")
</td>
<td>
<div style="display: flex; gap: 0.5rem;">
<button class="btn btn-outline btn-sm" onclick="editTool(@tool.Id)" title="编辑">
<i class="fas fa-edit"></i>
</button>
<a href="@Url.Action("Index", "ToolStatistics", new { toolId = tool.Id })" class="btn btn-outline btn-sm" title="统计">
<i class="fas fa-chart-bar"></i>
</a>
<button class="btn btn-outline btn-sm" onclick="toggleToolStatus(@tool.Id, @tool.IsActive.ToString().ToLower())"
style="color: @(tool.IsActive ? "var(--warning)" : "var(--success)");" title="@(tool.IsActive ? "禁用" : "启用")">
<i class="fas fa-@(tool.IsActive ? "pause" : "play")"></i>
</button>
<button class="btn btn-outline btn-sm" onclick="deleteTool(@tool.Id, '@tool.Name')"
style="color: var(--danger);" title="删除">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
@if (!Model.Any())
{
<div style="padding: 3rem; text-align: center; color: var(--dark-2);">
<i class="fas fa-tools" style="font-size: 3rem; margin-bottom: 1rem; display: block; opacity: 0.3;"></i>
<h3 style="margin-bottom: 0.5rem;">暂无工具</h3>
<p style="margin-bottom: 1.5rem;">还没有添加任何工具</p>
<button class="btn btn-primary" onclick="openToolModal()">
<i class="fas fa-plus"></i>
添加第一个工具
</button>
</div>
}
<!-- 分页控件 -->
@if (totalPages > 1)
{
<div style="padding: 1.5rem; border-top: 1px solid var(--light-2); display: flex; justify-content: center; align-items: center; gap: 0.5rem;">
<button class="btn btn-outline btn-sm" onclick="changePage(1)" @(currentPage == 1 ? "disabled" : "")>
<i class="fas fa-angle-double-left"></i>
</button>
<button class="btn btn-outline btn-sm" onclick="changePage(@(currentPage - 1))" @(currentPage == 1 ? "disabled" : "")>
<i class="fas fa-angle-left"></i>
</button>
@{
var startPage = Math.Max(1, currentPage - 2);
var endPage = Math.Min(totalPages, currentPage + 2);
}
@for (int i = startPage; i <= endPage; i++)
{
<button class="btn @(i == currentPage ? "btn-primary" : "btn-outline") btn-sm" onclick="changePage(@i)">
@i
</button>
}
<button class="btn btn-outline btn-sm" onclick="changePage(@(currentPage + 1))" @(currentPage == totalPages ? "disabled" : "")>
<i class="fas fa-angle-right"></i>
</button>
<button class="btn btn-outline btn-sm" onclick="changePage(@totalPages)" @(currentPage == totalPages ? "disabled" : "")>
<i class="fas fa-angle-double-right"></i>
</button>
</div>
}
</div>
<!-- 工具模态框 -->
<div id="toolModal" class="modal" style="display: none;">
<div class="modal-backdrop" onclick="closeToolModal()"></div>
<div class="modal-content" style="max-width: 600px;">
<div class="modal-header">
<h3 id="toolModalTitle">添加工具</h3>
<button onclick="closeToolModal()" style="background: none; border: none; font-size: 1.5rem; cursor: pointer;">×</button>
</div>
<form id="toolForm" onsubmit="submitTool(event)">
<div class="modal-body">
<input type="hidden" id="toolId" name="id" value="0" />
<div class="form-group">
<label>工具名称 *</label>
<input type="text" id="toolName" name="name" required placeholder="请输入工具名称" />
</div>
<div class="form-group">
<label>工具描述</label>
<textarea id="toolDescription" name="description" rows="3" placeholder="请输入工具描述"></textarea>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">
<div class="form-group">
<label>所属分类 *</label>
<select id="toolCategory" name="categoryId" required>
<option value="">请选择分类</option>
@foreach (var category in categories)
{
<option value="@category.Id">@category.Name</option>
}
</select>
</div>
<div class="form-group">
<label>图标选择</label>
<div style="display: flex; gap: 0.5rem;">
<input type="text" id="toolIcon" name="icon" placeholder="如: fas fa-file-pdf" readonly style="flex: 1;" />
<button type="button" class="btn btn-outline" onclick="openIconSelector()">
<i class="fas fa-icons"></i>
选择图标
</button>
</div>
</div>
</div>
<div class="form-group">
<label>工具链接</label>
<input type="url" id="toolUrl" name="url" placeholder="https://example.com" />
</div>
<div class="form-group">
<label>工具图片链接</label>
<input type="url" id="toolImage" name="image" placeholder="https://example.com/image.jpg" />
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem;">
<div class="form-group">
<label style="display: flex; align-items: center; gap: 0.5rem;">
<input type="checkbox" id="toolIsHot" name="isHot" />
<span>热门工具</span>
</label>
</div>
<div class="form-group">
<label style="display: flex; align-items: center; gap: 0.5rem;">
<input type="checkbox" id="toolIsNew" name="isNew" />
<span>新品工具</span>
</label>
</div>
<div class="form-group">
<label style="display: flex; align-items: center; gap: 0.5rem;">
<input type="checkbox" id="toolIsRecommended" name="isRecommended" />
<span>推荐工具</span>
</label>
</div>
</div>
<div class="form-group">
<label>排序顺序</label>
<input type="number" id="toolSort" name="sortOrder" min="0" value="0" placeholder="数字越小排序越靠前" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" onclick="closeToolModal()">取消</button>
<button type="submit" class="btn btn-primary">
<span id="toolSubmitText">保存</span>
</button>
</div>
</form>
</div>
</div>
<!-- 标签管理模态框 -->
<div id="tagModal" class="modal" style="display: none;">
<div class="modal-backdrop" onclick="closeTagModal()"></div>
<div class="modal-content" style="max-width: 500px;">
<div class="modal-header">
<h3 id="tagModalTitle">管理工具标签</h3>
<button onclick="closeTagModal()" style="background: none; border: none; font-size: 1.5rem; cursor: pointer;">×</button>
</div>
<div class="modal-body">
<div style="margin-bottom: 1rem;">
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">当前标签</label>
<div id="currentTags" style="display: flex; flex-wrap: wrap; gap: 0.5rem; min-height: 2rem; padding: 0.5rem; border: 1px solid var(--light-2); border-radius: var(--border-radius);">
<span style="color: var(--dark-2); font-style: italic;">加载中...</span>
</div>
</div>
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">添加标签</label>
<div style="display: flex; gap: 0.5rem;">
<select id="tagSelect" style="flex: 1; padding: 0.5rem; border: 1px solid var(--light-2); border-radius: var(--border-radius);">
<option value="">选择标签...</option>
</select>
<button class="btn btn-primary btn-sm" onclick="addToolTag()">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" onclick="closeTagModal()">关闭</button>
</div>
</div>
</div>
<!-- 图标选择器模态框 -->
<div id="iconSelectorModal" class="modal" style="display: none;">
<div class="modal-backdrop" onclick="closeIconSelector()"></div>
<div class="modal-content" style="max-width: 800px; max-height: 80vh;">
<div class="modal-header">
<h3>选择图标</h3>
<button onclick="closeIconSelector()" style="background: none; border: none; font-size: 1.5rem; cursor: pointer;">×</button>
</div>
<div class="modal-body" style="max-height: 60vh; overflow-y: auto;">
<div style="margin-bottom: 1rem;">
<input type="text" id="iconSearch" placeholder="搜索图标..."
style="width: 100%; padding: 0.75rem; border: 1px solid var(--light-2); border-radius: var(--border-radius);"
onkeyup="filterIcons()" />
</div>
<div id="iconGrid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 1rem;">
<!-- 图标将通过JavaScript动态加载 -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" onclick="closeIconSelector()">取消</button>
</div>
</div>
</div>
<script>
let currentView = 'table';
let isEditingTool = false;
let currentToolId = 0;
let currentToolName = '';
function changePage(page) {
const categoryFilter = document.getElementById('categoryFilter').value;
const searchInput = document.getElementById('searchInput').value;
let url = `@Url.Action("Index", "Tool")?page=${page}`;
if (categoryFilter !== '0') {
url += `&categoryId=${categoryFilter}`;
}
if (searchInput) {
url += `&search=${encodeURIComponent(searchInput)}`;
}
window.location.href = url;
}
function toggleView(view) {
currentView = view;
document.getElementById('tableView').style.display = view === 'table' ? 'block' : 'none';
document.getElementById('tableViewBtn').classList.toggle('btn-primary', view === 'table');
document.getElementById('tableViewBtn').classList.toggle('btn-outline', view !== 'table');
}
function filterTools() {
const categoryFilter = document.getElementById('categoryFilter').value;
const statusFilter = document.getElementById('statusFilter').value;
const searchInput = document.getElementById('searchInput').value.toLowerCase();
const tableRows = document.querySelectorAll('#toolsTableBody tr');
tableRows.forEach(row => {
const category = row.getAttribute('data-category');
const status = row.getAttribute('data-status');
const isHot = row.getAttribute('data-hot') === 'true';
const isNew = row.getAttribute('data-new') === 'true';
const isRecommended = row.getAttribute('data-recommended') === 'true';
const toolName = row.querySelector('.tool-name').textContent.toLowerCase();
let showRow = true;
// 分类筛选
if (categoryFilter !== '0' && category !== categoryFilter) {
showRow = false;
}
// 状态筛选
if (statusFilter) {
switch(statusFilter) {
case 'active':
if (status !== 'active') showRow = false;
break;
case 'inactive':
if (status !== 'inactive') showRow = false;
break;
case 'hot':
if (!isHot) showRow = false;
break;
case 'new':
if (!isNew) showRow = false;
break;
case 'recommended':
if (!isRecommended) showRow = false;
break;
}
}
// 搜索筛选
if (searchInput && !toolName.includes(searchInput)) {
showRow = false;
}
row.style.display = showRow ? '' : 'none';
});
}
function clearFilters() {
document.getElementById('categoryFilter').value = '0';
document.getElementById('statusFilter').value = '';
document.getElementById('searchInput').value = '';
filterTools();
}
function openToolModal(editMode = false) {
document.getElementById('toolModal').style.display = 'flex';
document.getElementById('toolModalTitle').textContent = editMode ? '编辑工具' : '添加工具';
document.getElementById('toolSubmitText').textContent = editMode ? '更新' : '保存';
isEditingTool = editMode;
if (!editMode) {
document.getElementById('toolForm').reset();
document.getElementById('toolId').value = '0';
}
}
function closeToolModal() {
document.getElementById('toolModal').style.display = 'none';
}
async function editTool(id) {
try {
const response = await fetch(`/Tool/Get?id=${id}`);
if (response.ok) {
const tool = await response.json();
openToolModal(true);
document.getElementById('toolId').value = tool.id;
document.getElementById('toolName').value = tool.name;
document.getElementById('toolDescription').value = tool.description || '';
document.getElementById('toolCategory').value = tool.categoryId;
document.getElementById('toolIcon').value = tool.icon || '';
document.getElementById('toolUrl').value = tool.url || '';
document.getElementById('toolImage').value = tool.image || '';
document.getElementById('toolIsHot').checked = tool.isHot;
document.getElementById('toolIsNew').checked = tool.isNew;
document.getElementById('toolIsRecommended').checked = tool.isRecommended;
document.getElementById('toolSort').value = tool.sortOrder;
}
} catch (error) {
console.error('获取工具信息失败:', error);
toolHub.showToast('获取工具信息失败', 'error');
}
}
async function submitTool(event) {
event.preventDefault();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData.entries());
// 处理复选框
data.isHot = document.getElementById('toolIsHot').checked;
data.isNew = document.getElementById('toolIsNew').checked;
data.isRecommended = document.getElementById('toolIsRecommended').checked;
try {
const response = await fetch('/Tool/Save', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
if (response.ok) {
toolHub.showToast(isEditingTool ? '工具更新成功' : '工具添加成功', 'success');
closeToolModal();
setTimeout(() => location.reload(), 1000);
} else {
toolHub.showToast('操作失败,请重试', 'error');
}
} catch (error) {
console.error('提交失败:', error);
toolHub.showToast('操作失败,请重试', 'error');
}
}
async function toggleToolStatus(id, currentStatus) {
try {
const response = await fetch('/Tool/ToggleStatus', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: id, isActive: !currentStatus })
});
if (response.ok) {
toolHub.showToast('状态更新成功', 'success');
setTimeout(() => location.reload(), 1000);
} else {
toolHub.showToast('操作失败,请重试', 'error');
}
} catch (error) {
console.error('操作失败:', error);
toolHub.showToast('操作失败,请重试', 'error');
}
}
async function deleteTool(id, name) {
if (!confirm(`确定要删除工具"${name}"吗?此操作不可恢复。`)) {
return;
}
try {
const response = await fetch('/Tool/Delete', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: id })
});
if (response.ok) {
toolHub.showToast('工具删除成功', 'success');
setTimeout(() => location.reload(), 1000);
} else {
toolHub.showToast('删除失败,请重试', 'error');
}
} catch (error) {
console.error('删除失败:', error);
toolHub.showToast('删除失败,请重试', 'error');
}
}
// 标签管理功能
async function manageToolTags(toolId, toolName) {
currentToolId = toolId;
currentToolName = toolName;
document.getElementById('tagModal').style.display = 'flex';
document.getElementById('tagModalTitle').textContent = `管理工具标签 - ${toolName}`;
await loadToolTags();
await loadAvailableTags();
}
function closeTagModal() {
document.getElementById('tagModal').style.display = 'none';
}
async function loadToolTags() {
try {
const response = await fetch(`/Tag/GetToolTags?toolId=${currentToolId}`);
const tags = await response.json();
const currentTagsDiv = document.getElementById('currentTags');
if (tags.length === 0) {
currentTagsDiv.innerHTML = '<span style="color: var(--dark-2); font-style: italic;">暂无标签</span>';
} else {
currentTagsDiv.innerHTML = tags.map(tag => `
<span class="badge" style="background: ${tag.color || 'var(--primary)'}; color: white; display: flex; align-items: center; gap: 0.25rem;">
${tag.name}
<button onclick="removeToolTag(${tag.id})" style="background: none; border: none; color: white; cursor: pointer; font-size: 0.75rem;">
<i class="fas fa-times"></i>
</button>
</span>
`).join('');
}
} catch (error) {
console.error('加载工具标签失败:', error);
toolHub.showToast('加载工具标签失败', 'error');
}
}
async function loadAvailableTags() {
try {
const response = await fetch('/Tag/GetList');
const tags = await response.json();
const tagSelect = document.getElementById('tagSelect');
tagSelect.innerHTML = '<option value="">选择标签...</option>';
tags.forEach(tag => {
const option = document.createElement('option');
option.value = tag.id;
option.textContent = tag.name;
tagSelect.appendChild(option);
});
} catch (error) {
console.error('加载可用标签失败:', error);
toolHub.showToast('加载可用标签失败', 'error');
}
}
async function addToolTag() {
const tagId = document.getElementById('tagSelect').value;
if (!tagId) {
toolHub.showToast('请选择要添加的标签', 'warning');
return;
}
try {
const response = await fetch('/Tag/AddToolTag', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ toolId: currentToolId, tagId: parseInt(tagId) })
});
const result = await response.json();
if (result.success) {
toolHub.showToast('标签添加成功', 'success');
document.getElementById('tagSelect').value = '';
await loadToolTags();
} else {
toolHub.showToast(result.message || '添加失败', 'error');
}
} catch (error) {
console.error('添加标签失败:', error);
toolHub.showToast('添加标签失败', 'error');
}
}
async function removeToolTag(tagId) {
if (!confirm('确定要移除这个标签吗?')) {
return;
}
try {
const response = await fetch('/Tag/RemoveToolTag', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ toolId: currentToolId, tagId: tagId })
});
const result = await response.json();
if (result.success) {
toolHub.showToast('标签移除成功', 'success');
await loadToolTags();
} else {
toolHub.showToast('移除失败', 'error');
}
} catch (error) {
console.error('移除标签失败:', error);
toolHub.showToast('移除标签失败', 'error');
}
}
// 图标选择器功能
const iconList = [
// 文件类型图标
{ name: 'PDF文件', class: 'fas fa-file-pdf', category: '文件' },
{ name: 'Word文档', class: 'fas fa-file-word', category: '文件' },
{ name: 'Excel表格', class: 'fas fa-file-excel', category: '文件' },
{ name: 'PowerPoint', class: 'fas fa-file-powerpoint', category: '文件' },
{ name: '文本文件', class: 'fas fa-file-alt', category: '文件' },
{ name: '图片文件', class: 'fas fa-file-image', category: '文件' },
{ name: '压缩文件', class: 'fas fa-file-archive', category: '文件' },
{ name: '代码文件', class: 'fas fa-file-code', category: '文件' },
{ name: '音频文件', class: 'fas fa-file-audio', category: '文件' },
{ name: '视频文件', class: 'fas fa-file-video', category: '文件' },
// 工具类图标
{ name: '工具', class: 'fas fa-tools', category: '工具' },
{ name: '扳手', class: 'fas fa-wrench', category: '工具' },
{ name: '锤子', class: 'fas fa-hammer', category: '工具' },
{ name: '螺丝刀', class: 'fas fa-screwdriver', category: '工具' },
{ name: '齿轮', class: 'fas fa-cog', category: '工具' },
{ name: '设置', class: 'fas fa-cogs', category: '工具' },
// 媒体图标
{ name: '图片', class: 'fas fa-image', category: '媒体' },
{ name: '视频', class: 'fas fa-video', category: '媒体' },
{ name: '音乐', class: 'fas fa-music', category: '媒体' },
{ name: '相机', class: 'fas fa-camera', category: '媒体' },
{ name: '麦克风', class: 'fas fa-microphone', category: '媒体' },
{ name: '播放', class: 'fas fa-play', category: '媒体' },
{ name: '暂停', class: 'fas fa-pause', category: '媒体' },
{ name: '停止', class: 'fas fa-stop', category: '媒体' },
// 网络图标
{ name: '网络', class: 'fas fa-network-wired', category: '网络' },
{ name: 'WiFi', class: 'fas fa-wifi', category: '网络' },
{ name: '链接', class: 'fas fa-link', category: '网络' },
{ name: '下载', class: 'fas fa-download', category: '网络' },
{ name: '上传', class: 'fas fa-upload', category: '网络' },
{ name: '云存储', class: 'fas fa-cloud', category: '网络' },
{ name: '服务器', class: 'fas fa-server', category: '网络' },
{ name: '数据库', class: 'fas fa-database', category: '网络' },
// 设计图标
{ name: '画笔', class: 'fas fa-paint-brush', category: '设计' },
{ name: '调色板', class: 'fas fa-palette', category: '设计' },
{ name: '设计', class: 'fas fa-drafting-compass', category: '设计' },
{ name: '图层', class: 'fas fa-layer-group', category: '设计' },
{ name: '裁剪', class: 'fas fa-crop', category: '设计' },
{ name: '滤镜', class: 'fas fa-magic', category: '设计' },
// 开发图标
{ name: '代码', class: 'fas fa-code', category: '开发' },
{ name: '终端', class: 'fas fa-terminal', category: '开发' },
{ name: '调试', class: 'fas fa-bug', category: '开发' },
{ name: 'Git', class: 'fab fa-git-alt', category: '开发' },
{ name: 'GitHub', class: 'fab fa-github', category: '开发' },
{ name: 'HTML', class: 'fab fa-html5', category: '开发' },
{ name: 'CSS', class: 'fab fa-css3-alt', category: '开发' },
{ name: 'JavaScript', class: 'fab fa-js-square', category: '开发' },
{ name: 'React', class: 'fab fa-react', category: '开发' },
{ name: 'Node.js', class: 'fab fa-node-js', category: '开发' },
{ name: 'Python', class: 'fab fa-python', category: '开发' },
{ name: 'Java', class: 'fab fa-java', category: '开发' },
{ name: 'PHP', class: 'fab fa-php', category: '开发' },
// 通用图标
{ name: '主页', class: 'fas fa-home', category: '通用' },
{ name: '用户', class: 'fas fa-user', category: '通用' },
{ name: '用户组', class: 'fas fa-users', category: '通用' },
{ name: '设置', class: 'fas fa-cog', category: '通用' },
{ name: '搜索', class: 'fas fa-search', category: '通用' },
{ name: '编辑', class: 'fas fa-edit', category: '通用' },
{ name: '删除', class: 'fas fa-trash', category: '通用' },
{ name: '添加', class: 'fas fa-plus', category: '通用' },
{ name: '保存', class: 'fas fa-save', category: '通用' },
{ name: '关闭', class: 'fas fa-times', category: '通用' },
{ name: '检查', class: 'fas fa-check', category: '通用' },
{ name: '警告', class: 'fas fa-exclamation-triangle', category: '通用' },
{ name: '信息', class: 'fas fa-info-circle', category: '通用' },
{ name: '问号', class: 'fas fa-question-circle', category: '通用' },
{ name: '星标', class: 'fas fa-star', category: '通用' },
{ name: '心形', class: 'fas fa-heart', category: '通用' },
{ name: '点赞', class: 'fas fa-thumbs-up', category: '通用' },
{ name: '分享', class: 'fas fa-share', category: '通用' },
{ name: '邮件', class: 'fas fa-envelope', category: '通用' },
{ name: '电话', class: 'fas fa-phone', category: '通用' },
{ name: '日历', class: 'fas fa-calendar', category: '通用' },
{ name: '时钟', class: 'fas fa-clock', category: '通用' },
{ name: '地图', class: 'fas fa-map-marker-alt', category: '通用' },
{ name: '购物车', class: 'fas fa-shopping-cart', category: '通用' },
{ name: '钱包', class: 'fas fa-wallet', category: '通用' },
{ name: '信用卡', class: 'fas fa-credit-card', category: '通用' },
{ name: '锁', class: 'fas fa-lock', category: '通用' },
{ name: '钥匙', class: 'fas fa-key', category: '通用' },
{ name: '盾牌', class: 'fas fa-shield-alt', category: '通用' },
{ name: '眼睛', class: 'fas fa-eye', category: '通用' },
{ name: '眼睛斜杠', class: 'fas fa-eye-slash', category: '通用' },
{ name: '打印', class: 'fas fa-print', category: '通用' },
{ name: '扫描', class: 'fas fa-scanner', category: '通用' },
{ name: '传真', class: 'fas fa-fax', category: '通用' },
{ name: '计算器', class: 'fas fa-calculator', category: '通用' },
{ name: '图表', class: 'fas fa-chart-bar', category: '通用' },
{ name: '饼图', class: 'fas fa-chart-pie', category: '通用' },
{ name: '折线图', class: 'fas fa-chart-line', category: '通用' },
{ name: '表格', class: 'fas fa-table', category: '通用' },
{ name: '列表', class: 'fas fa-list', category: '通用' },
{ name: '网格', class: 'fas fa-th', category: '通用' },
{ name: '标签', class: 'fas fa-tags', category: '通用' },
{ name: '书签', class: 'fas fa-bookmark', category: '通用' },
{ name: '文件夹', class: 'fas fa-folder', category: '通用' },
{ name: '文件', class: 'fas fa-file', category: '通用' },
{ name: '剪贴板', class: 'fas fa-clipboard', category: '通用' },
{ name: '复制', class: 'fas fa-copy', category: '通用' },
{ name: '粘贴', class: 'fas fa-paste', category: '通用' },
{ name: '剪切', class: 'fas fa-cut', category: '通用' },
{ name: '撤销', class: 'fas fa-undo', category: '通用' },
{ name: '重做', class: 'fas fa-redo', category: '通用' },
{ name: '刷新', class: 'fas fa-sync', category: '通用' },
{ name: '旋转', class: 'fas fa-sync-alt', category: '通用' },
{ name: '箭头', class: 'fas fa-arrow-right', category: '通用' },
{ name: '左箭头', class: 'fas fa-arrow-left', category: '通用' },
{ name: '上箭头', class: 'fas fa-arrow-up', category: '通用' },
{ name: '下箭头', class: 'fas fa-arrow-down', category: '通用' },
{ name: '外部链接', class: 'fas fa-external-link-alt', category: '通用' },
{ name: '返回', class: 'fas fa-arrow-circle-left', category: '通用' },
{ name: '前进', class: 'fas fa-arrow-circle-right', category: '通用' },
{ name: '展开', class: 'fas fa-chevron-down', category: '通用' },
{ name: '收起', class: 'fas fa-chevron-up', category: '通用' },
{ name: '菜单', class: 'fas fa-bars', category: '通用' },
{ name: '汉堡菜单', class: 'fas fa-hamburger', category: '通用' },
{ name: '更多', class: 'fas fa-ellipsis-h', category: '通用' },
{ name: '垂直更多', class: 'fas fa-ellipsis-v', category: '通用' }
];
function openIconSelector() {
document.getElementById('iconSelectorModal').style.display = 'flex';
loadIconGrid();
}
function closeIconSelector() {
document.getElementById('iconSelectorModal').style.display = 'none';
document.getElementById('iconSearch').value = '';
}
function loadIconGrid() {
const iconGrid = document.getElementById('iconGrid');
iconGrid.innerHTML = '';
iconList.forEach(icon => {
const iconDiv = document.createElement('div');
iconDiv.className = 'icon-item';
iconDiv.style.cssText = `
display: flex;
flex-direction: column;
align-items: center;
padding: 1rem;
border: 1px solid var(--light-2);
border-radius: var(--border-radius);
cursor: pointer;
transition: all 0.2s;
background: white;
`;
iconDiv.onmouseover = () => {
iconDiv.style.borderColor = 'var(--primary)';
iconDiv.style.backgroundColor = 'var(--light-1)';
};
iconDiv.onmouseout = () => {
iconDiv.style.borderColor = 'var(--light-2)';
iconDiv.style.backgroundColor = 'white';
};
iconDiv.onclick = () => selectIcon(icon.class);
iconDiv.innerHTML = `
<i class="${icon.class}" style="font-size: 2rem; color: var(--primary); margin-bottom: 0.5rem;"></i>
<div style="font-size: 0.75rem; text-align: center; color: var(--dark-2);">${icon.name}</div>
<div style="font-size: 0.625rem; text-align: center; color: var(--dark-3); margin-top: 0.25rem;">${icon.class}</div>
`;
iconGrid.appendChild(iconDiv);
});
}
function selectIcon(iconClass) {
document.getElementById('toolIcon').value = iconClass;
closeIconSelector();
toolHub.showToast('图标已选择', 'success');
}
function filterIcons() {
const searchTerm = document.getElementById('iconSearch').value.toLowerCase();
const iconItems = document.querySelectorAll('.icon-item');
iconItems.forEach(item => {
const iconName = item.querySelector('div').textContent.toLowerCase();
const iconClass = item.querySelector('div:last-child').textContent.toLowerCase();
if (iconName.includes(searchTerm) || iconClass.includes(searchTerm)) {
item.style.display = 'flex';
} else {
item.style.display = 'none';
}
});
}
</script>