Initial commit: 传感器实验课件系统
- 基于 React 19 + Vite 7 + Tailwind CSS 4 - 实现拖拽排序功能 (@dnd-kit) - 5个传感器实验项目展示 - 响应式设计和现代化 UI - 修复拖拽释放到空白区域时的潜在 bug 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
21a48c948c
16 files changed
+2877
No files matched your search
+111
@@ -0,0 +1,111 @@
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from '@dnd-kit/core';
|
||||
import {
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
sortableKeyboardCoordinates,
|
||||
verticalListSortingStrategy,
|
||||
} from '@dnd-kit/sortable';
|
||||
import { DraggableItem } from './components/DraggableItem';
|
||||
import { Cpu, Thermometer, Gauge, Radio, Zap, Droplets } from 'lucide-react';
|
||||
|
||||
function App() {
|
||||
const [experiments, setExperiments] = useState([
|
||||
{ id: '1', name: '温度传感器实验', icon: Thermometer, description: '学习温度传感器的工作原理及应用' },
|
||||
{ id: '2', name: '压力传感器实验', icon: Gauge, description: '了解压力传感器的测量原理与特性' },
|
||||
{ id: '3', name: '位移传感器实验', icon: Radio, description: '掌握位移传感器的检测方法' },
|
||||
{ id: '4', name: '光电传感器实验', icon: Zap, description: '探索光电传感器的光电转换原理' },
|
||||
{ id: '5', name: '湿度传感器实验', icon: Droplets, description: '研究湿度传感器的测量技术' },
|
||||
]);
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
})
|
||||
);
|
||||
|
||||
function handleDragEnd(event) {
|
||||
const { active, over } = event;
|
||||
|
||||
if (over && active.id !== over.id) {
|
||||
setExperiments((items) => {
|
||||
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||
const newIndex = items.findIndex((item) => item.id === over.id);
|
||||
return arrayMove(items, oldIndex, newIndex);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<header className="text-center mb-12">
|
||||
<div className="flex items-center justify-center gap-3 mb-4">
|
||||
<Cpu className="w-10 h-10 text-indigo-600" />
|
||||
<h1 className="text-4xl font-bold text-gray-800">
|
||||
传感器及检测技术
|
||||
</h1>
|
||||
</div>
|
||||
<p className="text-gray-600 text-lg">实验课件交互式平台</p>
|
||||
</header>
|
||||
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<div className="bg-white rounded-xl shadow-lg p-6 mb-6">
|
||||
<h2 className="text-2xl font-semibold text-gray-800 mb-4">
|
||||
实验项目列表
|
||||
</h2>
|
||||
<p className="text-gray-600 mb-6">
|
||||
拖动实验项目可以调整顺序,规划您的学习路径
|
||||
</p>
|
||||
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<SortableContext
|
||||
items={experiments}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
{experiments.map((experiment, index) => {
|
||||
const Icon = experiment.icon;
|
||||
return (
|
||||
<DraggableItem key={experiment.id} id={experiment.id}>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex-shrink-0 w-12 h-12 bg-indigo-100 rounded-full flex items-center justify-center">
|
||||
<Icon className="w-6 h-6 text-indigo-600" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-semibold text-gray-800">
|
||||
{index + 1}. {experiment.name}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600">
|
||||
{experiment.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</DraggableItem>
|
||||
);
|
||||
})}
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
</div>
|
||||
|
||||
<div className="text-center text-gray-600 text-sm">
|
||||
<p>使用现代化技术构建 • React + Vite + Tailwind CSS</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
Reference in new issue
Block a user