Initial commit

This commit is contained in:
史悦
2026-02-02 18:30:58 +08:00
commit ae1ca8bfaa
40 changed files with 10900 additions and 0 deletions

View File

@@ -0,0 +1,190 @@
import { Link, useParams } from 'react-router-dom'
import { motion } from 'framer-motion'
import { ArrowRight, FileText, Wrench, FileOutput } from 'lucide-react'
import { knowledgeAreas, processesByKnowledgeArea, knowledgeAreaMap, processGroupMap } from '@/data'
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { staggerChildren: 0.05 },
},
}
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
}
export function KnowledgeAreasPage() {
const { id } = useParams()
const selectedKA = id ? knowledgeAreaMap.get(id) : null
const processes = id ? processesByKnowledgeArea.get(id) || [] : []
if (selectedKA) {
// 显示知识领域详情
return (
<div className="space-y-6">
{/* 面包屑 */}
<nav className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
<Link to="/knowledge-areas" className="hover:text-indigo-600 dark:hover:text-indigo-400">
</Link>
<span>/</span>
<span className="text-gray-900 dark:text-white">{selectedKA.name}</span>
</nav>
{/* 知识领域标题 */}
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
className="rounded-xl p-6"
style={{ backgroundColor: `${selectedKA.color}15` }}
>
<div className="flex items-center gap-4">
<div
className="flex h-14 w-14 items-center justify-center rounded-xl text-white font-bold text-xl"
style={{ backgroundColor: selectedKA.color }}
>
{selectedKA.order}
</div>
<div>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">
{selectedKA.name}
</h1>
<p className="text-gray-500 dark:text-gray-400">{selectedKA.nameEn}</p>
</div>
</div>
<p className="mt-4 text-gray-600 dark:text-gray-300">{selectedKA.description}</p>
</motion.div>
{/* 过程列表 */}
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
className="space-y-4"
>
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">
{processes.length}
</h2>
{processes.map((process) => {
const pg = processGroupMap.get(process.processGroupId)
return (
<motion.div key={process.id} variants={itemVariants}>
<Link
to={`/process/${process.id}`}
className="group block bg-white dark:bg-gray-800 rounded-xl p-5 shadow-sm border border-gray-100 dark:border-gray-700 hover:shadow-md hover:border-gray-200 dark:hover:border-gray-600 transition-all"
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<div
className="flex h-10 w-10 items-center justify-center rounded-lg text-white font-medium"
style={{ backgroundColor: selectedKA.color }}
>
{process.code}
</div>
<div>
<h3 className="font-semibold text-gray-900 dark:text-white">
{process.name}
</h3>
<p className="text-sm text-gray-500 dark:text-gray-400">
{process.nameEn}
</p>
</div>
</div>
<div className="flex items-center gap-4">
{pg && (
<span
className="px-3 py-1 rounded-full text-xs font-medium text-white"
style={{ backgroundColor: pg.color }}
>
{pg.name}
</span>
)}
<ArrowRight
size={20}
className="text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 group-hover:translate-x-1 transition-all"
/>
</div>
</div>
{/* ITTO统计 */}
<div className="mt-4 flex items-center gap-6 text-sm text-gray-500 dark:text-gray-400">
<span className="flex items-center gap-1">
<FileText size={14} />
{process.inputs.length}
</span>
<span className="flex items-center gap-1">
<Wrench size={14} />
{process.tools.length}
</span>
<span className="flex items-center gap-1">
<FileOutput size={14} />
{process.outputs.length}
</span>
</div>
</Link>
</motion.div>
)
})}
</motion.div>
</div>
)
}
// 显示知识领域列表
return (
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white"></h1>
<p className="text-gray-500 dark:text-gray-400 mt-1">
PMBOK第6版定义的10大项目管理知识领域
</p>
</div>
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
className="grid md:grid-cols-2 gap-4"
>
{knowledgeAreas.map((ka) => (
<motion.div key={ka.id} variants={itemVariants}>
<Link
to={`/knowledge-areas/${ka.id}`}
className="group block bg-white dark:bg-gray-800 rounded-xl p-5 shadow-sm border border-gray-100 dark:border-gray-700 hover:shadow-md transition-all"
style={{ borderLeftWidth: 4, borderLeftColor: ka.color }}
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<div
className="flex h-12 w-12 items-center justify-center rounded-lg text-white font-bold text-lg"
style={{ backgroundColor: ka.color }}
>
{ka.order}
</div>
<div>
<h3 className="font-semibold text-gray-900 dark:text-white">{ka.name}</h3>
<p className="text-sm text-gray-500 dark:text-gray-400">{ka.nameEn}</p>
</div>
</div>
<div className="flex items-center gap-2">
<span className="text-sm text-gray-500 dark:text-gray-400">
{ka.processCount}
</span>
<ArrowRight
size={20}
className="text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 group-hover:translate-x-1 transition-all"
/>
</div>
</div>
<p className="mt-3 text-sm text-gray-500 dark:text-gray-400 line-clamp-2">
{ka.description}
</p>
</Link>
</motion.div>
))}
</motion.div>
</div>
)
}