|
|
@@ -1,17 +1,35 @@
|
|
|
import React, { useState, useEffect } from 'react'
|
|
|
import { View, Text, ScrollView, Button, Input, Textarea } from '@tarojs/components'
|
|
|
import Taro from '@tarojs/taro'
|
|
|
+import { useQuery } from '@tanstack/react-query'
|
|
|
import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar'
|
|
|
import { enterpriseOrderClient } from '../../api'
|
|
|
|
|
|
type OrderStatus = 'draft' | 'confirmed' | 'in_progress' | 'completed' | 'cancelled'
|
|
|
|
|
|
+interface OrderDetailData {
|
|
|
+ id: any
|
|
|
+ orderNumber: any
|
|
|
+ name: any
|
|
|
+ createdAt: string
|
|
|
+ updatedAt: string
|
|
|
+ status: any
|
|
|
+ statusLabel: string
|
|
|
+ statusClass: string
|
|
|
+ company: any
|
|
|
+ platform: any
|
|
|
+ channel: any
|
|
|
+ expectedPeople: any
|
|
|
+ actualPeople: any
|
|
|
+ expectedStartDate: string
|
|
|
+ actualStartDate: string
|
|
|
+ expectedEndDate: string
|
|
|
+ actualEndDate: string | null
|
|
|
+}
|
|
|
+
|
|
|
const OrderDetail: React.FC = () => {
|
|
|
const [orderStatus, setOrderStatus] = useState<OrderStatus>('in_progress')
|
|
|
const [note, setNote] = useState('')
|
|
|
- const [order, setOrder] = useState<any>(null)
|
|
|
- const [loading, setLoading] = useState(false)
|
|
|
- const [error, setError] = useState<string | null>(null)
|
|
|
const [orderId, setOrderId] = useState<number | null>(null)
|
|
|
const [persons, setPersons] = useState<any[]>([])
|
|
|
const [videos, setVideos] = useState<any[]>([])
|
|
|
@@ -37,58 +55,71 @@ const OrderDetail: React.FC = () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 获取订单详情
|
|
|
- const fetchOrderDetail = async (id: number) => {
|
|
|
- setLoading(true)
|
|
|
- setError(null)
|
|
|
- try {
|
|
|
- const response = await enterpriseOrderClient.detail[':id'].$get({
|
|
|
- param: { id: id }
|
|
|
- })
|
|
|
+ // 获取订单详情查询函数
|
|
|
+ const fetchOrderDetailQuery = async (id: number) => {
|
|
|
+ const response = await enterpriseOrderClient.detail[':id'].$get({
|
|
|
+ param: { id: id }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error(`获取订单详情失败: ${response.status}`)
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await response.json() as any
|
|
|
+ // 转换API数据到UI格式
|
|
|
+ return {
|
|
|
+ id: data.id,
|
|
|
+ orderNumber: data.orderNumber || `ORDER-${data.id}`,
|
|
|
+ name: data.orderName || '未命名订单',
|
|
|
+ createdAt: data.createTime ? new Date(data.createTime).toISOString().split('T')[0] : '未知日期',
|
|
|
+ updatedAt: data.updateTime ? new Date(data.updateTime).toISOString().split('T')[0] : '未知日期',
|
|
|
+ status: data.orderStatus || 'draft',
|
|
|
+ statusLabel: getStatusLabel(data.orderStatus),
|
|
|
+ statusClass: getStatusClass(data.orderStatus),
|
|
|
+ company: data.companyName || '未知公司',
|
|
|
+ platform: data.platformName || '未知平台',
|
|
|
+ channel: data.channelName || '未知渠道',
|
|
|
+ expectedPeople: data.expectedPersonCount || 0,
|
|
|
+ actualPeople: data.actualPersonCount || 0,
|
|
|
+ expectedStartDate: data.expectedStartDate ? new Date(data.expectedStartDate).toISOString().split('T')[0] : '未设置',
|
|
|
+ actualStartDate: data.actualStartDate ? new Date(data.actualStartDate).toISOString().split('T')[0] : '未设置',
|
|
|
+ expectedEndDate: data.expectedEndDate ? new Date(data.expectedEndDate).toISOString().split('T')[0] : '未设置',
|
|
|
+ actualEndDate: data.actualEndDate ? new Date(data.actualEndDate).toISOString().split('T')[0] : null,
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (response.ok) {
|
|
|
- const data = await response.json() as any
|
|
|
- // 转换API数据到UI格式
|
|
|
- const transformedOrder = {
|
|
|
- id: data.id,
|
|
|
- orderNumber: data.orderNumber || `ORDER-${data.id}`,
|
|
|
- name: data.orderName || '未命名订单',
|
|
|
- createdAt: data.createTime ? new Date(data.createTime).toISOString().split('T')[0] : '未知日期',
|
|
|
- updatedAt: data.updateTime ? new Date(data.updateTime).toISOString().split('T')[0] : '未知日期',
|
|
|
- status: data.orderStatus || 'draft',
|
|
|
- statusLabel: getStatusLabel(data.orderStatus),
|
|
|
- statusClass: getStatusClass(data.orderStatus),
|
|
|
- company: data.companyName || '未知公司',
|
|
|
- platform: data.platformName || '未知平台',
|
|
|
- channel: data.channelName || '未知渠道',
|
|
|
- expectedPeople: data.expectedPersonCount || 0,
|
|
|
- actualPeople: data.actualPersonCount || 0,
|
|
|
- expectedStartDate: data.expectedStartDate ? new Date(data.expectedStartDate).toISOString().split('T')[0] : '未设置',
|
|
|
- actualStartDate: data.actualStartDate ? new Date(data.actualStartDate).toISOString().split('T')[0] : '未设置',
|
|
|
- expectedEndDate: data.expectedEndDate ? new Date(data.expectedEndDate).toISOString().split('T')[0] : '未设置',
|
|
|
- actualEndDate: data.actualEndDate ? new Date(data.actualEndDate).toISOString().split('T')[0] : null,
|
|
|
- }
|
|
|
- setOrder(transformedOrder)
|
|
|
- setOrderStatus(data.orderStatus || 'draft')
|
|
|
+ // 使用React Query获取订单详情
|
|
|
+ const {
|
|
|
+ data: order,
|
|
|
+ isLoading,
|
|
|
+ error: queryError,
|
|
|
+ } = useQuery<OrderDetailData, Error>({
|
|
|
+ queryKey: ['order-detail', orderId],
|
|
|
+ queryFn: () => orderId ? fetchOrderDetailQuery(orderId) : Promise.reject(new Error('未找到订单ID')),
|
|
|
+ enabled: !!orderId,
|
|
|
+ })
|
|
|
|
|
|
- // TODO: 获取关联人才、视频、统计数据
|
|
|
- // 暂时使用空数组
|
|
|
- setPersons([])
|
|
|
- setVideos([])
|
|
|
- } else {
|
|
|
- throw new Error(`获取订单详情失败: ${response.status}`)
|
|
|
- }
|
|
|
- } catch (err) {
|
|
|
- console.error('获取订单详情错误:', err)
|
|
|
- setError(err instanceof Error ? err.message : '获取订单详情失败')
|
|
|
+ // 处理查询错误
|
|
|
+ useEffect(() => {
|
|
|
+ if (queryError) {
|
|
|
+ console.error('获取订单详情错误:', queryError)
|
|
|
Taro.showToast({
|
|
|
- title: '获取订单详情失败',
|
|
|
+ title: queryError.message.includes('未找到订单ID') ? '未找到订单ID' : '获取订单详情失败',
|
|
|
icon: 'none'
|
|
|
})
|
|
|
- } finally {
|
|
|
- setLoading(false)
|
|
|
}
|
|
|
- }
|
|
|
+ }, [queryError])
|
|
|
+
|
|
|
+ // 处理查询成功
|
|
|
+ useEffect(() => {
|
|
|
+ if (order) {
|
|
|
+ setOrderStatus(order.status || 'draft')
|
|
|
+ // TODO: 获取关联人才、视频、统计数据
|
|
|
+ // 暂时使用空数组
|
|
|
+ setPersons([])
|
|
|
+ setVideos([])
|
|
|
+ }
|
|
|
+ }, [order])
|
|
|
|
|
|
// 状态标签和样式辅助函数
|
|
|
const getStatusLabel = (status: string) => {
|
|
|
@@ -123,9 +154,6 @@ const OrderDetail: React.FC = () => {
|
|
|
|
|
|
if (id) {
|
|
|
setOrderId(id)
|
|
|
- fetchOrderDetail(id)
|
|
|
- } else {
|
|
|
- setError('未找到订单ID')
|
|
|
}
|
|
|
}, [])
|
|
|
|
|
|
@@ -168,6 +196,20 @@ const OrderDetail: React.FC = () => {
|
|
|
className="h-screen overflow-y-auto px-4 pb-4 pt-0"
|
|
|
scrollY
|
|
|
>
|
|
|
+ {isLoading ? (
|
|
|
+ <View className="flex items-center justify-center h-64">
|
|
|
+ <Text className="text-gray-500">加载中...</Text>
|
|
|
+ </View>
|
|
|
+ ) : queryError ? (
|
|
|
+ <View className="flex items-center justify-center h-64">
|
|
|
+ <Text className="text-red-500">{queryError.message}</Text>
|
|
|
+ </View>
|
|
|
+ ) : !order ? (
|
|
|
+ <View className="flex items-center justify-center h-64">
|
|
|
+ <Text className="text-gray-500">未找到订单数据</Text>
|
|
|
+ </View>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
{/* 顶部信息卡片 */}
|
|
|
<View className="card bg-white p-4 mb-4 mt-4">
|
|
|
<View className="flex justify-between items-start mb-3">
|
|
|
@@ -242,23 +284,23 @@ const OrderDetail: React.FC = () => {
|
|
|
<View className="bg-blue-50 rounded-lg p-2 text-center">
|
|
|
<Text className="text-xs text-gray-600">本月打卡</Text>
|
|
|
<Text className="text-sm font-bold text-gray-800">
|
|
|
- {order.checkinStats.current}/{order.checkinStats.total}
|
|
|
+ {checkinStats.current}/{checkinStats.total}
|
|
|
</Text>
|
|
|
- <Text className="text-xs text-gray-500">{order.checkinStats.percentage}%</Text>
|
|
|
+ <Text className="text-xs text-gray-500">{checkinStats.percentage}%</Text>
|
|
|
</View>
|
|
|
<View className="bg-green-50 rounded-lg p-2 text-center">
|
|
|
<Text className="text-xs text-gray-600">工资视频</Text>
|
|
|
<Text className="text-sm font-bold text-gray-800">
|
|
|
- {order.salaryVideoStats.current}/{order.salaryVideoStats.total}
|
|
|
+ {salaryVideoStats.current}/{salaryVideoStats.total}
|
|
|
</Text>
|
|
|
- <Text className="text-xs text-gray-500">{order.salaryVideoStats.percentage}%</Text>
|
|
|
+ <Text className="text-xs text-gray-500">{salaryVideoStats.percentage}%</Text>
|
|
|
</View>
|
|
|
<View className="bg-purple-50 rounded-lg p-2 text-center">
|
|
|
<Text className="text-xs text-gray-600">个税视频</Text>
|
|
|
<Text className="text-sm font-bold text-gray-800">
|
|
|
- {order.taxVideoStats.current}/{order.taxVideoStats.total}
|
|
|
+ {taxVideoStats.current}/{taxVideoStats.total}
|
|
|
</Text>
|
|
|
- <Text className="text-xs text-gray-500">{order.taxVideoStats.percentage}%</Text>
|
|
|
+ <Text className="text-xs text-gray-500">{taxVideoStats.percentage}%</Text>
|
|
|
</View>
|
|
|
</View>
|
|
|
<Button className="text-blue-500 text-sm">查看详细打卡记录</Button>
|
|
|
@@ -387,6 +429,7 @@ const OrderDetail: React.FC = () => {
|
|
|
</Button>
|
|
|
</View>
|
|
|
</View>
|
|
|
+ </>)}
|
|
|
</ScrollView>
|
|
|
</>
|
|
|
)
|