Files
x-server-mobile/frontend/src/modules/approval/components/ApprovalDetail.tsx
T
root 8d78e18267 Initial commit: X-Server Mobile enterprise tool system
- Frontend: React 18 + TypeScript + Vite + Ant Design Mobile
- Backend: PHP 8.5 + Webman 2.x + MySQL + Redis
- i18n support: Chinese, English, Russian, Spanish, French
- Approval workflow engine
- Docker development environment
- Feishu integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:57:25 +08:00

109 lines
3.6 KiB
TypeScript

import { useQuery } from '@tanstack/react-query'
import { getApprovalDetail } from '../services/approval'
import ApprovalFlow from './ApprovalFlow'
import ApprovalAction from './ApprovalAction'
import styles from './ApprovalDetail.module.css'
interface ApprovalDetailProps {
id: string
}
export default function ApprovalDetail({ id }: ApprovalDetailProps) {
const { data, isLoading, error } = useQuery({
queryKey: ['approval-detail', id],
queryFn: () => getApprovalDetail(id),
})
if (isLoading) {
return <div className={styles.loading}>加载中...</div>
}
if (error) {
return <div className={styles.error}>加载失败: {error.message}</div>
}
const order = data?.data
if (!order) {
return <div className={styles.empty}>未找到审批详情</div>
}
const getStatusText = (status: string) => {
const statusMap: Record<string, string> = {
draft: '草稿',
pending: '审批中',
approved: '已通过',
rejected: '已拒绝',
cancelled: '已撤销',
}
return statusMap[status] || status
}
return (
<div className={styles.detail}>
{/* 标题 */}
<div className={styles.header}>
<h1 className={styles.title}>{order.title}</h1>
<span className={styles.status}>{getStatusText(order.status)}</span>
</div>
{/* 审批流程 */}
{order.flow && (
<div className={styles.section}>
<h2 className={styles.sectionTitle}>审批流程</h2>
<ApprovalFlow nodes={order.flow.nodes || []} />
</div>
)}
{/* 表单数据 */}
{order.formData && Object.keys(order.formData).length > 0 && (
<div className={styles.section}>
<h2 className={styles.sectionTitle}>申请内容</h2>
<div className={styles.formData}>
{Object.entries(order.formData).map(([key, value]) => (
<div key={key} className={styles.formRow}>
<span className={styles.formLabel}>{key}:</span>
<span className={styles.formValue}>{String(value)}</span>
</div>
))}
</div>
</div>
)}
{/* 审批记录 */}
{order.timeline && order.timeline.length > 0 && (
<div className={styles.section}>
<h2 className={styles.sectionTitle}>审批记录</h2>
<div className={styles.timeline}>
{order.timeline.map((record: any) => (
<div key={record.id} className={styles.timelineItem}>
<div className={styles.timelineDot} />
<div className={styles.timelineContent}>
<div className={styles.timelineHeader}>
<span className={styles.timelineUser}>{record.approver?.name}</span>
<span className={styles.timelineAction}>
{record.action === 'approve' && '通过'}
{record.action === 'reject' && '拒绝'}
{record.action === 'submit' && '提交'}
{record.action === 'cancel' && '撤销'}
</span>
</div>
{record.comment && (
<div className={styles.timelineComment}>{record.comment}</div>
)}
<div className={styles.timelineTime}>
{new Date(record.createdAt).toLocaleString('zh-CN')}
</div>
</div>
</div>
))}
</div>
</div>
)}
{/* 操作按钮 */}
<ApprovalAction orderId={order.id} status={order.status} />
</div>
)
}