This commit introduces the initial prototype for an item database and build list tool. It establishes the foundational structure and core features of the application. Key components included: - **Documentation:** Initial design, interaction, and project structure documents (`design.md`, `interaction.md`, `outline.md`). - **Core Pages:** - `index.html`: Item management with CRUD operations. - `export.html`: CSV export configuration with drag-and-drop sorting. - `history.html`: Price history visualization with ECharts. - **Logic:** `main.js` and page-specific scripts handle client-side logic, including data management with `localStorage`, UI interactions, and animations. - **Features:** Implements core functionalities such as item creation, editing, deletion, data backup/restore, and sample data loading.
346 lines
19 KiB
HTML
346 lines
19 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>物品数据库管理工具</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/splide@4.1.4/dist/js/splide.min.js"></script>
|
||
<link href="https://cdn.jsdelivr.net/npm/splide@4.1.4/dist/css/splide.min.css" rel="stylesheet">
|
||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&family=Noto+Serif+SC:wght@400;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
body {
|
||
font-family: 'Noto Sans SC', sans-serif;
|
||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||
min-height: 100vh;
|
||
}
|
||
.hero-title {
|
||
font-family: 'Noto Serif SC', serif;
|
||
background: linear-gradient(135deg, #2C3E50, #3498DB);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
}
|
||
.card-hover {
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
.card-hover:hover {
|
||
transform: translateY(-4px);
|
||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||
}
|
||
.btn-primary {
|
||
background: linear-gradient(135deg, #3498DB, #2C3E50);
|
||
transition: all 0.3s ease;
|
||
}
|
||
.btn-primary:hover {
|
||
background: linear-gradient(135deg, #2C3E50, #3498DB);
|
||
transform: translateY(-1px);
|
||
}
|
||
.btn-secondary {
|
||
background: linear-gradient(135deg, #E67E22, #D35400);
|
||
transition: all 0.3s ease;
|
||
}
|
||
.btn-secondary:hover {
|
||
background: linear-gradient(135deg, #D35400, #E67E22);
|
||
transform: translateY(-1px);
|
||
}
|
||
.item-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||
gap: 1.5rem;
|
||
}
|
||
.item-card {
|
||
background: white;
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||
}
|
||
.item-image {
|
||
width: 100%;
|
||
height: 200px;
|
||
object-fit: cover;
|
||
background: linear-gradient(45deg, #f0f0f0, #e0e0e0);
|
||
}
|
||
.loading-skeleton {
|
||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||
background-size: 200% 100%;
|
||
animation: loading 1.5s infinite;
|
||
}
|
||
@keyframes loading {
|
||
0% { background-position: 200% 0; }
|
||
100% { background-position: -200% 0; }
|
||
}
|
||
.fade-in {
|
||
opacity: 0;
|
||
transform: translateY(20px);
|
||
}
|
||
.fade-in.visible {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
transition: all 0.6s ease;
|
||
}
|
||
.notification {
|
||
position: fixed;
|
||
top: 20px;
|
||
right: 20px;
|
||
z-index: 1000;
|
||
transform: translateX(400px);
|
||
transition: transform 0.3s ease;
|
||
}
|
||
.notification.show {
|
||
transform: translateX(0);
|
||
}
|
||
.search-input {
|
||
background: rgba(255, 255, 255, 0.9);
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid rgba(52, 152, 219, 0.2);
|
||
}
|
||
.search-input:focus {
|
||
border-color: #3498DB;
|
||
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- 导航栏 -->
|
||
<nav class="bg-white/90 backdrop-blur-md shadow-sm border-b border-gray-200 sticky top-0 z-50">
|
||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||
<div class="flex justify-between items-center h-16">
|
||
<div class="flex items-center space-x-3">
|
||
<img src="resources/database-icon.png" alt="Database Icon" class="w-8 h-8">
|
||
<h1 class="text-xl font-bold text-gray-800">物品数据库</h1>
|
||
</div>
|
||
<div class="flex space-x-4">
|
||
<a href="index.html" class="px-4 py-2 text-blue-600 bg-blue-50 rounded-lg font-medium">物品管理</a>
|
||
<a href="export.html" class="px-4 py-2 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
|
||
<img src="resources/export-icon.png" alt="Export" class="w-4 h-4 inline mr-2">导出配置
|
||
</a>
|
||
<a href="history.html" class="px-4 py-2 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
|
||
<img src="resources/chart-icon.png" alt="History" class="w-4 h-4 inline mr-2">历史记录
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- 主要内容区域 -->
|
||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||
<!-- 标题区域 -->
|
||
<div class="text-center mb-12 fade-in">
|
||
<h2 class="hero-title text-4xl md:text-5xl font-bold mb-4">智能物品管理系统</h2>
|
||
<p class="text-gray-600 text-lg max-w-2xl mx-auto">专业的物品数据库管理工具,支持图片记录、CSV导出和历史价格追踪</p>
|
||
</div>
|
||
|
||
<!-- 统计卡片 -->
|
||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8 fade-in">
|
||
<div class="bg-white rounded-xl p-6 shadow-sm border border-gray-100 card-hover">
|
||
<div class="flex items-center">
|
||
<div class="p-3 rounded-lg bg-blue-100">
|
||
<svg class="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"></path>
|
||
</svg>
|
||
</div>
|
||
<div class="ml-4">
|
||
<p class="text-sm font-medium text-gray-600">总物品数</p>
|
||
<p class="text-2xl font-bold text-gray-900" id="total-items">0</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="bg-white rounded-xl p-6 shadow-sm border border-gray-100 card-hover">
|
||
<div class="flex items-center">
|
||
<div class="p-3 rounded-lg bg-green-100">
|
||
<svg class="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||
</svg>
|
||
</div>
|
||
<div class="ml-4">
|
||
<p class="text-sm font-medium text-gray-600">本月新增</p>
|
||
<p class="text-2xl font-bold text-gray-900" id="monthly-items">0</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="bg-white rounded-xl p-6 shadow-sm border border-gray-100 card-hover">
|
||
<div class="flex items-center">
|
||
<div class="p-3 rounded-lg bg-orange-100">
|
||
<svg class="w-6 h-6 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z"></path>
|
||
</svg>
|
||
</div>
|
||
<div class="ml-4">
|
||
<p class="text-sm font-medium text-gray-600">历史记录</p>
|
||
<p class="text-2xl font-bold text-gray-900" id="history-records">0</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="bg-white rounded-xl p-6 shadow-sm border border-gray-100 card-hover">
|
||
<div class="flex items-center">
|
||
<div class="p-3 rounded-lg bg-purple-100">
|
||
<svg class="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||
</svg>
|
||
</div>
|
||
<div class="ml-4">
|
||
<p class="text-sm font-medium text-gray-600">图片总数</p>
|
||
<p class="text-2xl font-bold text-gray-900" id="total-images">0</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主要操作区域 -->
|
||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||
<!-- 添加物品表单 -->
|
||
<div class="lg:col-span-1">
|
||
<div class="bg-white rounded-xl p-6 shadow-sm border border-gray-100 fade-in">
|
||
<h3 class="text-xl font-bold text-gray-800 mb-6 flex items-center">
|
||
<svg class="w-6 h-6 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
|
||
</svg>
|
||
添加新物品
|
||
</h3>
|
||
<form id="add-item-form" class="space-y-4">
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">物品名称 *</label>
|
||
<input type="text" id="item-name" required
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||
placeholder="请输入物品名称">
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">图片 URL *</label>
|
||
<input type="url" id="item-image" required
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||
placeholder="https://example.com/image.jpg">
|
||
<p class="text-xs text-gray-500 mt-1">请粘贴您的图床图片链接</p>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">物品描述</label>
|
||
<textarea id="item-description" rows="3"
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||
placeholder="请输入物品描述(可选)"></textarea>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">分类标签</label>
|
||
<input type="text" id="item-tags"
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||
placeholder="用逗号分隔多个标签,如:古董,瓷器">
|
||
</div>
|
||
<button type="submit" class="w-full btn-primary text-white font-medium py-3 px-6 rounded-lg">
|
||
<svg class="w-5 h-5 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
|
||
</svg>
|
||
添加物品
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- 快速操作 -->
|
||
<div class="bg-white rounded-xl p-6 shadow-sm border border-gray-100 mt-6 fade-in">
|
||
<h3 class="text-lg font-bold text-gray-800 mb-4">快速操作</h3>
|
||
<div class="space-y-3">
|
||
<button id="export-data-btn" class="w-full flex items-center justify-center px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors">
|
||
<svg class="w-5 h-5 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||
</svg>
|
||
导出数据备份
|
||
</button>
|
||
<button id="import-data-btn" class="w-full flex items-center justify-center px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors">
|
||
<svg class="w-5 h-5 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3V10"></path>
|
||
</svg>
|
||
导入数据
|
||
</button>
|
||
<input type="file" id="import-file-input" accept=".json" class="hidden">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 物品列表 -->
|
||
<div class="lg:col-span-2">
|
||
<div class="bg-white rounded-xl p-6 shadow-sm border border-gray-100 fade-in">
|
||
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-6">
|
||
<h3 class="text-xl font-bold text-gray-800 mb-4 sm:mb-0">物品列表</h3>
|
||
<div class="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-3 w-full sm:w-auto">
|
||
<input type="text" id="search-input" placeholder="搜索物品名称..."
|
||
class="search-input px-4 py-2 rounded-lg focus:outline-none w-full sm:w-64">
|
||
<select id="filter-select" class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 w-full sm:w-auto">
|
||
<option value="">所有分类</option>
|
||
<option value="古董">古董</option>
|
||
<option value="艺术品">艺术品</option>
|
||
<option value="收藏品">收藏品</option>
|
||
<option value="珠宝">珠宝</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 物品网格 -->
|
||
<div id="items-grid" class="item-grid">
|
||
<!-- 动态生成的物品卡片将在这里显示 -->
|
||
</div>
|
||
|
||
<!-- 空状态 -->
|
||
<div id="empty-state" class="text-center py-12 hidden">
|
||
<svg class="w-16 h-16 text-gray-300 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"></path>
|
||
</svg>
|
||
<h3 class="text-lg font-medium text-gray-600 mb-2">暂无物品</h3>
|
||
<p class="text-gray-500">点击左侧添加您的第一个物品</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 通知组件 -->
|
||
<div id="notification" class="notification bg-white rounded-lg shadow-lg border border-gray-200 p-4 max-w-sm">
|
||
<div class="flex items-center">
|
||
<div id="notification-icon" class="flex-shrink-0">
|
||
<!-- 动态图标 -->
|
||
</div>
|
||
<div class="ml-3">
|
||
<p id="notification-message" class="text-sm font-medium text-gray-800"></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 编辑物品模态框 -->
|
||
<div id="edit-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
||
<div class="bg-white rounded-xl p-6 max-w-md w-full mx-4 transform transition-all">
|
||
<h3 class="text-xl font-bold text-gray-800 mb-4">编辑物品</h3>
|
||
<form id="edit-form" class="space-y-4">
|
||
<input type="hidden" id="edit-item-id">
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">物品名称</label>
|
||
<input type="text" id="edit-item-name" required
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">图片 URL</label>
|
||
<input type="url" id="edit-item-image" required
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">物品描述</label>
|
||
<textarea id="edit-item-description" rows="3"
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"></textarea>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">分类标签</label>
|
||
<input type="text" id="edit-item-tags"
|
||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
|
||
</div>
|
||
<div class="flex space-x-3 pt-4">
|
||
<button type="submit" class="flex-1 btn-primary text-white font-medium py-2 px-4 rounded-lg">
|
||
保存修改
|
||
</button>
|
||
<button type="button" id="cancel-edit" class="flex-1 bg-gray-200 text-gray-800 font-medium py-2 px-4 rounded-lg hover:bg-gray-300 transition-colors">
|
||
取消
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="main.js"></script>
|
||
</body>
|
||
</html> |