feat(app): 添加图片采集器功能并修复粘贴问题
- 集成 dexie 和 dexie-react-hooks 实现本地数据库存储 - 创建 TestPage 组件实现图片粘贴采集功能 - 修复重复粘贴问题,添加事件监听器清理机制 - 修复删除按钮触发增加的事件冒泡问题 - 为电子木鱼页面添加顶部边距样式 - 更新导航项标签为中文显示 - 添加图片网格展示和删除功能
This commit is contained in:
Generated
+19
@@ -12,6 +12,8 @@
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.1",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"dexie": "^4.2.1",
|
||||
"dexie-react-hooks": "^4.2.0",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"react-markdown": "^10.1.0",
|
||||
@@ -6703,6 +6705,23 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/dexie": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/dexie/-/dexie-4.2.1.tgz",
|
||||
"integrity": "sha512-Ckej0NS6jxQ4Po3OrSQBFddayRhTCic2DoCAG5zacOfOVB9P2Q5Xc5uL/nVa7ZVs+HdMnvUPzLFCB/JwpB6Csg==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/dexie-react-hooks": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/dexie-react-hooks/-/dexie-react-hooks-4.2.0.tgz",
|
||||
"integrity": "sha512-u7KqTX9JpBQK8+tEyA9X0yMGXlSCsbm5AU64N6gjvGk/IutYDpLBInMYEAEC83s3qhIvryFS+W+sqLZUBEvePQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=16",
|
||||
"dexie": ">=4.2.0-alpha.1 <5.0.0",
|
||||
"react": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/didyoumean": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.1",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"dexie": "^4.2.1",
|
||||
"dexie-react-hooks": "^4.2.0",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"react-markdown": "^10.1.0",
|
||||
|
||||
+3
-1
@@ -4,13 +4,15 @@ import TimestampPage from './pages/TimestampPage';
|
||||
import ElectronicWoodenFishPage from "./pages/ElectronicWoodenFishPage";
|
||||
import TodoListPage from "./pages/TodoListPage";
|
||||
import './App.css';
|
||||
import TestPage from "./pages/TestPage";
|
||||
|
||||
// 导航项配置数组,便于后续添加
|
||||
// 为了测试折叠功能,我们添加更多导航项
|
||||
const navItems = [
|
||||
{path: '/', label: 'Timestamp', element: <TimestampPage/>},
|
||||
{path: '/', label: '时间戳', element: <TimestampPage/>},
|
||||
{path: '/dzmy', label: '电子木鱼', element: <ElectronicWoodenFishPage/>},
|
||||
{path: '/todo', label: '待办', element: <TodoListPage/>},
|
||||
{path: '/test', label: '测试', element: <TestPage/>}
|
||||
];
|
||||
|
||||
function App() {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
overflow: hidden;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* 添加装饰性背景元素 */
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import {db} from '../utils/db';
|
||||
import {useLiveQuery} from 'dexie-react-hooks';
|
||||
|
||||
// 样式简单写一下,实际可以用 styled-components 或 css modules
|
||||
const styles = {
|
||||
container: {padding: '20px', fontFamily: 'sans-serif', maxWidth: '600px', margin: '0 auto'},
|
||||
uploadBox: {
|
||||
border: '2px dashed #aaa',
|
||||
padding: '40px',
|
||||
textAlign: 'center',
|
||||
background: '#f9f9f9',
|
||||
marginBottom: '20px',
|
||||
borderRadius: '8px'
|
||||
},
|
||||
grid: {display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))', gap: '10px'},
|
||||
card: {border: '1px solid #eee', borderRadius: '8px', overflow: 'hidden', position: 'relative'},
|
||||
img: {width: '100%', height: '120px', objectFit: 'cover', display: 'block'},
|
||||
delBtn: {
|
||||
position: 'absolute',
|
||||
top: '5px',
|
||||
right: '5px',
|
||||
background: 'red',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
padding: '2px 8px',
|
||||
borderRadius: '4px'
|
||||
}
|
||||
};
|
||||
|
||||
const TestPage = () => {
|
||||
const images = useLiveQuery(() => db.images.orderBy('created').reverse().toArray());
|
||||
|
||||
// --- FIX 2: 修复重复粘贴问题 ---
|
||||
useEffect(() => {
|
||||
const handlePaste = async (event) => {
|
||||
// 1. 获取剪贴板数据
|
||||
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
||||
|
||||
// 2. 找到第一个图片文件 (防止一次粘贴循环出多个格式)
|
||||
let foundImage = false;
|
||||
|
||||
for (let item of items) {
|
||||
if (!foundImage && item.kind === 'file' && item.type.includes('image/')) {
|
||||
const blob = item.getAsFile();
|
||||
foundImage = true; // 标记已找到,避免重复处理
|
||||
|
||||
// 3. 阻止默认行为(防止浏览器把图片直接贴到页面上)
|
||||
event.preventDefault();
|
||||
|
||||
await db.images.add({
|
||||
blob: blob,
|
||||
created: new Date(),
|
||||
source: 'Paste'
|
||||
});
|
||||
|
||||
console.log('图片已添加');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 添加监听
|
||||
window.addEventListener('paste', handlePaste);
|
||||
|
||||
// ★★★ 关键:必须返回一个清理函数,组件刷新时移除旧的监听器 ★★★
|
||||
return () => {
|
||||
window.removeEventListener('paste', handlePaste);
|
||||
};
|
||||
}, []); // ★★★ 关键:依赖数组必须为空 [],保证只在挂载时绑定一次
|
||||
|
||||
|
||||
// --- FIX 1: 修复删除变增加的问题 ---
|
||||
const handleDelete = async (event, id) => {
|
||||
// ★★★ 关键:阻止事件冒泡,防止触发父级的点击或粘贴逻辑
|
||||
event.stopPropagation();
|
||||
|
||||
try {
|
||||
await db.images.delete(id);
|
||||
console.log('删除成功 ID:', id);
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<h2>React 图片采集器 (已修复)</h2>
|
||||
<p>点击任意处粘贴 (Ctrl+V)</p>
|
||||
|
||||
<div style={styles.grid}>
|
||||
{images?.map((img) => (
|
||||
<div key={img.id} style={styles.card}>
|
||||
<img src={URL.createObjectURL(img.blob)} alt="screenshot" style={styles.img}/>
|
||||
|
||||
{/* 传递 event 对象给 handleDelete */}
|
||||
<button
|
||||
style={styles.delBtn}
|
||||
onClick={(e) => handleDelete(e, img.id)}
|
||||
>
|
||||
删除
|
||||
</button>
|
||||
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TestPage;
|
||||
@@ -0,0 +1,7 @@
|
||||
import Dexie from "dexie";
|
||||
|
||||
export const db = new Dexie("testImagesDb");
|
||||
|
||||
db.version(1).stores({
|
||||
images: '++id, created, source'
|
||||
});
|
||||
Reference in New Issue
Block a user