Initial commit
This commit is contained in:
239
src/pages/ProcessDetailPage.tsx
Normal file
239
src/pages/ProcessDetailPage.tsx
Normal file
@@ -0,0 +1,239 @@
|
||||
import { useParams, Link, useLocation, useNavigate } from 'react-router-dom'
|
||||
import { motion } from 'framer-motion'
|
||||
import { ArrowLeft, ArrowRight, FileText, Wrench, FileOutput, LayoutGrid } from 'lucide-react'
|
||||
import { getProcessDetail, processes, artifactMap, toolMap } from '@/data'
|
||||
|
||||
export function ProcessDetailPage() {
|
||||
const { id } = useParams()
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
const processDetail = id ? getProcessDetail(id) : null
|
||||
|
||||
// 检查是否从矩阵页面来
|
||||
const fromMatrix = location.state?.from === 'matrix'
|
||||
|
||||
if (!processDetail) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-20">
|
||||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4">
|
||||
未找到该过程
|
||||
</h2>
|
||||
<Link
|
||||
to="/knowledge-areas"
|
||||
className="text-indigo-600 dark:text-indigo-400 hover:underline"
|
||||
>
|
||||
返回知识领域
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ka = processDetail.knowledgeArea
|
||||
const pg = processDetail.processGroup
|
||||
|
||||
// 获取前后过程
|
||||
const currentIndex = processes.findIndex(p => p.id === id)
|
||||
const prevProcess = currentIndex > 0 ? processes[currentIndex - 1] : null
|
||||
const nextProcess = currentIndex < processes.length - 1 ? processes[currentIndex + 1] : null
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* 返回按钮 + 面包屑 */}
|
||||
<div className="flex items-center gap-4">
|
||||
{fromMatrix && (
|
||||
<button
|
||||
onClick={() => navigate('/process-matrix')}
|
||||
className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-indigo-50 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400 hover:bg-indigo-100 dark:hover:bg-indigo-900/50 transition-colors text-sm font-medium"
|
||||
>
|
||||
<LayoutGrid size={16} />
|
||||
返回矩阵
|
||||
</button>
|
||||
)}
|
||||
<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>
|
||||
{ka && (
|
||||
<>
|
||||
<Link
|
||||
to={`/knowledge-areas/${ka.id}`}
|
||||
className="hover:text-indigo-600 dark:hover:text-indigo-400"
|
||||
>
|
||||
{ka.name}
|
||||
</Link>
|
||||
<span>/</span>
|
||||
</>
|
||||
)}
|
||||
<span className="text-gray-900 dark:text-white">{processDetail.name}</span>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
{/* 过程标题 */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="rounded-xl p-6 bg-white dark:bg-gray-800 shadow-sm border border-gray-100 dark:border-gray-700"
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<div
|
||||
className="flex h-16 w-16 items-center justify-center rounded-xl text-white font-bold text-xl shrink-0"
|
||||
style={{ backgroundColor: ka?.color || '#6366F1' }}
|
||||
>
|
||||
{processDetail.code}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
{processDetail.name}
|
||||
</h1>
|
||||
<p className="text-gray-500 dark:text-gray-400">{processDetail.nameEn}</p>
|
||||
<div className="flex items-center gap-3 mt-3">
|
||||
{ka && (
|
||||
<span
|
||||
className="px-3 py-1 rounded-full text-xs font-medium text-white"
|
||||
style={{ backgroundColor: ka.color }}
|
||||
>
|
||||
{ka.name}
|
||||
</span>
|
||||
)}
|
||||
{pg && (
|
||||
<span
|
||||
className="px-3 py-1 rounded-full text-xs font-medium text-white"
|
||||
style={{ backgroundColor: pg.color }}
|
||||
>
|
||||
{pg.name}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* ITTO表格 */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="grid lg:grid-cols-3 gap-6"
|
||||
>
|
||||
{/* 输入 */}
|
||||
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
||||
<div className="flex items-center gap-2 px-4 py-3 bg-blue-50 dark:bg-blue-900/30 border-b border-blue-100 dark:border-blue-800">
|
||||
<FileText size={18} className="text-blue-600 dark:text-blue-400" />
|
||||
<h3 className="font-semibold text-blue-900 dark:text-blue-100">
|
||||
输入 ({processDetail.inputs.length})
|
||||
</h3>
|
||||
</div>
|
||||
<ul className="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
{processDetail.inputs.map((inputId) => {
|
||||
const artifact = artifactMap.get(inputId)
|
||||
return (
|
||||
<li key={inputId} className="px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors">
|
||||
<div className="font-medium text-gray-900 dark:text-white">
|
||||
{artifact?.name || inputId}
|
||||
</div>
|
||||
{artifact && (
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
{artifact.nameEn}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 工具与技术 */}
|
||||
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
||||
<div className="flex items-center gap-2 px-4 py-3 bg-amber-50 dark:bg-amber-900/30 border-b border-amber-100 dark:border-amber-800">
|
||||
<Wrench size={18} className="text-amber-600 dark:text-amber-400" />
|
||||
<h3 className="font-semibold text-amber-900 dark:text-amber-100">
|
||||
工具与技术 ({processDetail.tools.length})
|
||||
</h3>
|
||||
</div>
|
||||
<ul className="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
{processDetail.tools.map((toolId) => {
|
||||
const tool = toolMap.get(toolId)
|
||||
return (
|
||||
<li key={toolId} className="px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors">
|
||||
<div className="font-medium text-gray-900 dark:text-white">
|
||||
{tool?.name || toolId}
|
||||
</div>
|
||||
{tool && (
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
{tool.nameEn}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 输出 */}
|
||||
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
||||
<div className="flex items-center gap-2 px-4 py-3 bg-emerald-50 dark:bg-emerald-900/30 border-b border-emerald-100 dark:border-emerald-800">
|
||||
<FileOutput size={18} className="text-emerald-600 dark:text-emerald-400" />
|
||||
<h3 className="font-semibold text-emerald-900 dark:text-emerald-100">
|
||||
输出 ({processDetail.outputs.length})
|
||||
</h3>
|
||||
</div>
|
||||
<ul className="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
{processDetail.outputs.map((outputId) => {
|
||||
const artifact = artifactMap.get(outputId)
|
||||
return (
|
||||
<li key={outputId} className="px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors">
|
||||
<div className="font-medium text-gray-900 dark:text-white">
|
||||
{artifact?.name || outputId}
|
||||
</div>
|
||||
{artifact && (
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
{artifact.nameEn}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* 前后导航 */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.2 }}
|
||||
className="flex items-center justify-between pt-6 border-t border-gray-200 dark:border-gray-700"
|
||||
>
|
||||
{prevProcess ? (
|
||||
<Link
|
||||
to={`/process/${prevProcess.id}`}
|
||||
className="flex items-center gap-2 text-gray-600 dark:text-gray-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
|
||||
>
|
||||
<ArrowLeft size={18} />
|
||||
<div>
|
||||
<div className="text-xs text-gray-400">上一个过程</div>
|
||||
<div className="font-medium">{prevProcess.code} {prevProcess.name}</div>
|
||||
</div>
|
||||
</Link>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
{nextProcess ? (
|
||||
<Link
|
||||
to={`/process/${nextProcess.id}`}
|
||||
className="flex items-center gap-2 text-gray-600 dark:text-gray-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors text-right"
|
||||
>
|
||||
<div>
|
||||
<div className="text-xs text-gray-400">下一个过程</div>
|
||||
<div className="font-medium">{nextProcess.code} {nextProcess.name}</div>
|
||||
</div>
|
||||
<ArrowRight size={18} />
|
||||
</Link>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user