'use client' import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from "react"; import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar' import dayjs, {Dayjs} from 'dayjs' import 'react-big-calendar/lib/css/react-big-calendar.css' import 'react-big-calendar/lib/sass/styles.scss' import 'react-big-calendar/lib/addons/dragAndDrop/styles.scss' import '@/ui/task/calendar/index.modules.css' import {commonUpdate, getTaskTreeResult, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data"; import {useSearchParams} from "next/dist/client/components/navigation"; import {DetailModelForm} from "@/ui/task/project/DetailModelForm"; import {SearchObject} from "@/lib/definitions"; import LocalContext from "@/ui/LocalContent"; import withDragAndDrop, {EventInteractionArgs} from "react-big-calendar/lib/addons/dragAndDrop"; import {TaskEvent} from "@/lib/task/calendar/data"; import {number} from "prop-types"; import {DATE_TIME} from "@/lib/constants"; /** * https://github.com/jquense/react-big-calendar?tab=readme-ov-file * @constructor */ const localizer = dayjsLocalizer(dayjs) const DragAndDropCalendar = withDragAndDrop(Calendar) const CalShow: React.FC = () => { dayjs.locale('zh-cn') const [view, setView] = useState('week'); const [date, setDate] = useState(new Date()); const clickRef = useRef(null) // 展示在页面的任务,默认获取当前月的信息。 const [events, setEvents] = useState([]); const [open, setOpen] = useState(false); const [description, setDescription] = useState(''); const [operationId, setOperationId] = useState(-1); const [itemId, setItemId] = useState('-1'); const [expectedStartTime, setExpectedStartTime] = useState(); const [expectedEndTime, setExpectedEndTime] = useState(); const [range, setRange] = useState<{start: Date; end: Date}>({ start: dayjs(date).startOf('week').toDate(), end: dayjs(date).endOf('week').toDate() }); const state=useContext(LocalContext).taskState; const handleViewChange = (newView: View) => { setView(newView); }; var pid = useSearchParams().get('pid'); function clearClickTimeout(){ clickRef && typeof clickRef.current=== 'number' &&!isNaN(clickRef.current) && isFinite(clickRef.current)&&window.clearTimeout(clickRef.current) } const handleNavigate = (newDate: Date) => { console.log('handleNavigate', newDate) setDate(newDate); const searchList: SearchObject[] = [] if (pid != null) { searchList.push({name: "pid", value: pid, operateType: "="}, {name: 'ALL-CHILD', value: "true", operateType: "ALL-CHILD"}, {name: 'TREE-FILTER', value: "true", operateType: "TREE-FILTER"}, ); } loadData(searchList); }; useEffect(() => { console.log("CalShow:useEffect:range",range) const searchListE = [] if (pid != null) { searchListE.push( {name: "pid", value: pid, operateType: "="}, {name: 'ALL-CHILD', value: "true", operateType: "ALL-CHILD"}, {name: 'TREE-FILTER', value: "true", operateType: "TREE-FILTER"}, ); } // searchListE.push({name: 'expectedStartTime', value: range.start, operateType: ">="}) // searchListE.push({name: 'expectedStartTime', value: range.end, operateType: "<="}) loadData(searchListE); /** * What Is This? * This is to prevent a memory leak, in the off chance that you * teardown your interface prior to the timed method being called. */ return () => { clearClickTimeout() } }, [useContext(LocalContext),range]); const message = { week: '周', work_week: '工作周', day: '天', month: '月', previous: '前', next: '后', today: '当下', agenda: '日程' } const loadData = (searchList: SearchObject[]) => { if (state.length > 0) { searchList.push({name: 'state', value: state, operateType: "IN"}) } // searchList.push({name: 'expectedEndTime', value: dayjs(date).endOf('month'), operateType: "NOT NULL"}) let request = JSON.stringify({ pageSize: 9999, pageNumber: 1, data: searchList, startTime:range.start, // startTime:dayjs(range.start).format('YYYY-MM-DD HH:mm:ss'), endTime:range.end, // endTime:dayjs(range.end).format('YYYY-MM-DD HH:mm:ss'), startColumn:"expected_start_time", endColumn:"expected_end_time" }) getTaskTreeResult(request).then(responseD => { if (responseD.status.success) { let result:TaskEvent[] =responseD.data.content.map(taskState => { return { start: dayjs(taskState.expectedStartTime).toDate(), end: dayjs(taskState.expectedEndTime).toDate(), title: taskState.name, resource: taskState.id, id:taskState.id, state:taskState.state, priority:taskState.priority } }); console.log('responseD.data.content:',result) setEvents([...result]) } }) } const reloadData = () => { setOpen(false) handleNavigate(expectedStartTime ? expectedStartTime.toDate() : date) } const handleSelectSlot = useCallback( ({start, end}: SlotInfo) => { setExpectedEndTime(dayjs(end)) setExpectedStartTime(dayjs(start)) setOperationId(OPERATION_BUTTON_TYPE.ADD) setDescription("添加任务") setOpen(true); }, [setEvents] ) const handleSelectEvent = useCallback( (event: Event, e: React.SyntheticEvent) => { clearClickTimeout() clickRef.current = window.setTimeout(()=> { // window.alert(event.title); console.log(event) setOperationId(OPERATION_BUTTON_TYPE.DETAIL) setDescription("任务详情") setItemId(event.resource) setOpen(true); },250) }, [] ) const {defaultDate, scrollToTime} = useMemo( () => ({ defaultDate: new Date(2015, 3, 12), scrollToTime: new Date(1970, 1, 1, 6), }), [] ) const doubleClick = (event: TaskEvent, e: React.SyntheticEvent) => { clearClickTimeout() clickRef.current = window.setTimeout(()=>{ // 数据落库 commonUpdate({ updateColumnList: [{ name: '任务状态', code: 'state', value: 7 }], conditionColumnList: [{ name: 'id', code: 'id', operateType: '=', value: event.resource }] }) setEvents((prev: TaskEvent[]) => { const existing: TaskEvent | undefined = prev.find((ev: TaskEvent) => ev.resource === event.resource); const filtered: TaskEvent[] | undefined = prev.filter((ev: TaskEvent) => ev.resource !== event.resource); let result: TaskEvent[] = []; if (existing !== undefined&&filtered !== undefined) { result= [...filtered, {...existing, state:7}]; } let strings = state.split(","); console.log('result',result,strings) return result.filter((ev: TaskEvent) => strings.indexOf(ev.state.toString())>=0); }) },250) } const moveEvent = useCallback( ({event, start, end, isAllDay: droppedOnAllDaySlot = false}: EventInteractionArgs) => { console.log("onEventResize || onEventDrop :",start,end) const {allDay} = event if (!allDay && droppedOnAllDaySlot) { event.allDay = true } // 数据落库 commonUpdate({ updateColumnList: [{ name: 'expectedStartTime', code: '', value: start.toLocaleString() }, { name: 'expectedEndTime', code: '', value: end.toLocaleString() }], conditionColumnList: [{ name: 'id', code: 'id', operateType: '=', value: event.resource }] }) setEvents((prev: TaskEvent[]) => { const existing: TaskEvent | undefined = prev.find((ev: TaskEvent) => ev.resource === event.resource); const filtered: TaskEvent[] | undefined = prev.filter((ev: TaskEvent) => ev.resource !== event.resource); if (start instanceof Date && end instanceof Date && existing !== undefined) { return [...filtered, {...existing, start, end, allDay}]; } if (filtered !== undefined) { return [...filtered]; } return []; }) }, [setEvents] ) const eventPropGetter = useCallback( (event:TaskEvent) => ({ ...(event.state===7 ? { className: 'completeTask' } : event.priority===3?{ className: 'importantUrgentTask' }: event.priority===2?{ className: 'importantNotUrgentTask' }: event.priority===1?{ className: 'notImportantUrgentTask' }: { className: 'notImportantNotUrgentTask' }), }), [setEvents] ) const rangeChange = (rangeLet: Date[]|{ start: Date; end: Date },current?:View|undefined)=>{ console.log("rangeChange:",rangeLet,(current?current:view)) // view 为天的时候类型为数组,index:0为当天 if ((current?current:view)==="day"&&Array.isArray(rangeLet)) { if (range.start.valueOf()>rangeLet[0].valueOf()){ setRange({...range,start:rangeLet[0]}) }else if (range.end.valueOf()rangeLet[0].valueOf()){ setRange({...range,start:rangeLet[0]}) } if (range.end.valueOf()rangeLet.start.valueOf()){ setRange({...range,start:rangeLet.start}) } if (range.end.valueOf() {open && } } export default CalShow;