203 lines
6.6 KiB
JavaScript
203 lines
6.6 KiB
JavaScript
import { useState, useEffect } from 'react'
|
||
import { Card, Row, Col, Calendar, List, Badge, Empty, Typography, Spin } from 'antd'
|
||
import { FileTextOutlined, ClockCircleOutlined } from '@ant-design/icons'
|
||
import { useNavigate } from 'react-router-dom'
|
||
import { getDocumentActivityDates, getDocumentActivity } from '@/api/dashboard'
|
||
import Toast from '@/components/Toast/Toast'
|
||
import dayjs from 'dayjs'
|
||
import './Desktop.css'
|
||
|
||
const { Text } = Typography
|
||
|
||
function Desktop() {
|
||
const navigate = useNavigate()
|
||
const [loading, setLoading] = useState(false)
|
||
const [activityDates, setActivityDates] = useState([])
|
||
const [selectedDate, setSelectedDate] = useState(dayjs())
|
||
const [activityLogs, setActivityLogs] = useState([])
|
||
const [currentMonth, setCurrentMonth] = useState(dayjs())
|
||
|
||
useEffect(() => {
|
||
loadActivityDates(currentMonth.year(), currentMonth.month() + 1)
|
||
loadActivityLogs(selectedDate.format('YYYY-MM-DD'))
|
||
}, [])
|
||
|
||
// 加载指定月份有活动的日期
|
||
const loadActivityDates = async (year, month) => {
|
||
try {
|
||
const res = await getDocumentActivityDates(year, month)
|
||
if (res.data && res.data.dates) {
|
||
setActivityDates(res.data.dates)
|
||
}
|
||
} catch (error) {
|
||
console.error('Load activity dates error:', error)
|
||
}
|
||
}
|
||
|
||
// 加载指定日期的活动日志
|
||
const loadActivityLogs = async (date) => {
|
||
setLoading(true)
|
||
try {
|
||
const res = await getDocumentActivity(date)
|
||
if (res.data && res.data.logs) {
|
||
setActivityLogs(res.data.logs)
|
||
} else {
|
||
setActivityLogs([])
|
||
}
|
||
} catch (error) {
|
||
console.error('Load activity logs error:', error)
|
||
Toast.error('加载失败', '获取文档活动记录失败')
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
// 日历单元格渲染
|
||
const dateCellRender = (value) => {
|
||
const dateStr = value.format('YYYY-MM-DD')
|
||
const activity = activityDates.find(item => item.date === dateStr)
|
||
|
||
if (activity && activity.count > 0) {
|
||
return (
|
||
<div style={{ textAlign: 'center' }}>
|
||
<Badge
|
||
count={activity.count}
|
||
style={{ backgroundColor: '#1890ff' }}
|
||
overflowCount={99}
|
||
/>
|
||
</div>
|
||
)
|
||
}
|
||
return null
|
||
}
|
||
|
||
// 日期选择事件
|
||
const onSelect = (date) => {
|
||
setSelectedDate(date)
|
||
loadActivityLogs(date.format('YYYY-MM-DD'))
|
||
}
|
||
|
||
// 月份切换事件
|
||
const onPanelChange = (date) => {
|
||
setCurrentMonth(date)
|
||
loadActivityDates(date.year(), date.month() + 1)
|
||
}
|
||
|
||
// 点击文档打开
|
||
const handleDocumentClick = (log) => {
|
||
// 如果文件不存在,提示无法打开
|
||
if (!log.file_exists) {
|
||
Toast.warning('无法打开', '文件不存在或已被删除/移动/重命名')
|
||
return
|
||
}
|
||
|
||
// 如果没有项目ID,提示无法打开
|
||
if (!log.project_id) {
|
||
Toast.error('无法打开', '找不到对应的项目')
|
||
return
|
||
}
|
||
|
||
// 跳转到文档页面
|
||
navigate(`/projects/${log.project_id}/docs?file=${encodeURIComponent(log.file_path)}`)
|
||
}
|
||
|
||
return (
|
||
<div className="desktop-page">
|
||
<h1 className="page-title">个人桌面</h1>
|
||
|
||
<Row gutter={24}>
|
||
{/* 左侧日历 */}
|
||
<Col xs={24} lg={12}>
|
||
<Card className="calendar-card">
|
||
<Calendar
|
||
fullscreen={false}
|
||
value={selectedDate}
|
||
onSelect={onSelect}
|
||
onPanelChange={onPanelChange}
|
||
cellRender={dateCellRender}
|
||
/>
|
||
</Card>
|
||
</Col>
|
||
|
||
{/* 右侧活动列表 */}
|
||
<Col xs={24} lg={12}>
|
||
<Card
|
||
className="activity-card"
|
||
title={
|
||
<div>
|
||
<FileTextOutlined style={{ marginRight: 8 }} />
|
||
{selectedDate.format('YYYY年MM月DD日')} 的文档活动
|
||
</div>
|
||
}
|
||
>
|
||
<Spin spinning={loading}>
|
||
{activityLogs.length > 0 ? (
|
||
<List
|
||
dataSource={activityLogs}
|
||
renderItem={(item) => (
|
||
<List.Item
|
||
key={item.id}
|
||
onClick={() => handleDocumentClick(item)}
|
||
className={item.file_exists ? 'activity-item-clickable' : 'activity-item-disabled'}
|
||
style={{ cursor: item.file_exists ? 'pointer' : 'default' }}
|
||
>
|
||
<List.Item.Meta
|
||
avatar={
|
||
<ClockCircleOutlined
|
||
style={{
|
||
fontSize: 20,
|
||
color: item.file_exists ? '#1890ff' : '#d9d9d9'
|
||
}}
|
||
/>
|
||
}
|
||
title={
|
||
<div>
|
||
<Text strong style={{ color: item.file_exists ? undefined : '#999' }}>
|
||
{item.project_name}
|
||
</Text>
|
||
<Text
|
||
type="secondary"
|
||
style={{ marginLeft: 8, color: item.file_exists ? undefined : '#bbb' }}
|
||
>
|
||
{item.operation_type}
|
||
</Text>
|
||
{!item.file_exists && (
|
||
<Text type="danger" style={{ marginLeft: 8, fontSize: 12 }}>
|
||
(已失效)
|
||
</Text>
|
||
)}
|
||
</div>
|
||
}
|
||
description={
|
||
<div>
|
||
<div style={{ marginBottom: 4 }}>
|
||
<Text type="secondary">文件:</Text>
|
||
<Text code style={{ color: item.file_exists ? undefined : '#999' }}>
|
||
{item.file_path}
|
||
</Text>
|
||
</div>
|
||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||
{new Date(item.created_at).toLocaleTimeString('zh-CN')}
|
||
</Text>
|
||
</div>
|
||
}
|
||
/>
|
||
</List.Item>
|
||
)}
|
||
/>
|
||
) : (
|
||
<Empty
|
||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||
description="该日期暂无文档活动记录"
|
||
/>
|
||
)}
|
||
</Spin>
|
||
</Card>
|
||
</Col>
|
||
</Row>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default Desktop
|