feat(prototype): add initial prototype for item database tool

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.
This commit is contained in:
xiaomai
2025-10-13 09:51:46 +08:00
parent c9a93bb52d
commit c0ba7ac0ff
11 changed files with 2711 additions and 0 deletions

346
prototype/index.html Normal file
View File

@@ -0,0 +1,346 @@
<!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>