feat:添加日历展示任务及顶部按钮编排
This commit is contained in:
parent
97071b464b
commit
f76c460fd9
|
@ -12,6 +12,10 @@
|
||||||
2. 向左紧急
|
2. 向左紧急
|
||||||
|
|
||||||

|

|
||||||
|
## 日历
|
||||||
|
1. 月,周,日展示
|
||||||
|
2. 只有期望开始时间和期望结束时间都填写的时候才会在日历中展示
|
||||||
|
3.
|
||||||
## 项目启动
|
## 项目启动
|
||||||
### 后端服务启动
|
### 后端服务启动
|
||||||
1. 后端启动应用需求:docker,redis,mysql8。
|
1. 后端启动应用需求:docker,redis,mysql8。
|
||||||
|
|
|
@ -44,7 +44,7 @@ export type DataType ={
|
||||||
expectedTimeRange?:(string|Dayjs|undefined)[];
|
expectedTimeRange?:(string|Dayjs|undefined)[];
|
||||||
actualStartTime?:Date;
|
actualStartTime?:Date;
|
||||||
actualEndTime?:Date;
|
actualEndTime?:Date;
|
||||||
actualTimeRange?:(string|Dayjs)[]
|
actualTimeRange?:(string|Dayjs|undefined)[]
|
||||||
children: DataType[]|undefined;
|
children: DataType[]|undefined;
|
||||||
}
|
}
|
||||||
export type DictType={
|
export type DictType={
|
||||||
|
@ -54,3 +54,8 @@ export type DictType={
|
||||||
order:number;
|
order:number;
|
||||||
color:string;
|
color:string;
|
||||||
}
|
}
|
||||||
|
export type SearchObject={
|
||||||
|
name: string,
|
||||||
|
value: any,
|
||||||
|
operateType:string,
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {DownOutlined, QuestionCircleOutlined} from "@ant-design/icons";
|
||||||
import {DetailForm} from "@/ui/task/four/DetailForm";
|
import {DetailForm} from "@/ui/task/four/DetailForm";
|
||||||
import {commonUpdate, deleteTask, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
|
import {commonUpdate, deleteTask, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||||
|
|
||||||
export interface OperationButtonProps {
|
export interface OperationButtonProps {
|
||||||
itemId: number,
|
itemId: number,
|
||||||
|
@ -14,7 +15,7 @@ export interface OperationButtonProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OperationModelProps {
|
interface OperationModelProps {
|
||||||
operationId: number | undefined,
|
operationId: number,
|
||||||
pPid: number,
|
pPid: number,
|
||||||
pid: number,
|
pid: number,
|
||||||
openModal: boolean
|
openModal: boolean
|
||||||
|
@ -27,7 +28,7 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
||||||
this.state = {
|
this.state = {
|
||||||
pid: props.pid,
|
pid: props.pid,
|
||||||
pPid: props.pPid,
|
pPid: props.pPid,
|
||||||
operationId: undefined,
|
operationId: 0,
|
||||||
openModal: false
|
openModal: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -129,42 +130,16 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
||||||
</Space>
|
</Space>
|
||||||
</a>
|
</a>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Modal
|
<DetailModelForm
|
||||||
maskClosable={false}
|
haveButton={false}
|
||||||
destroyOnClose={true}
|
itemId={this.props.itemId}
|
||||||
open={this.state.openModal}
|
pPid={this.props.pPid}
|
||||||
title={this.state.operationId === OPERATION_BUTTON_TYPE.DETAIL ? '任务详情' :
|
operationId={this.state.operationId}
|
||||||
|
description={this.state.operationId === OPERATION_BUTTON_TYPE.DETAIL ? '任务详情' :
|
||||||
this.state.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? '添加支线任务' :
|
this.state.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? '添加支线任务' :
|
||||||
this.state.operationId === OPERATION_BUTTON_TYPE.UPDATE ? '修改任务' : '未知操作'}
|
this.state.operationId === OPERATION_BUTTON_TYPE.UPDATE ? '修改任务' : '未知操作'}
|
||||||
// open={open}
|
open={this.state.openModal}
|
||||||
// onOk={handleOk}
|
reloadData={handleCancel}/>
|
||||||
onCancel={handleCancel}
|
|
||||||
footer={[]}
|
|
||||||
width={800}
|
|
||||||
// footer={[
|
|
||||||
// <Button key="back" onClick={handleCancel}>
|
|
||||||
// Return
|
|
||||||
// </Button>,
|
|
||||||
// <Button key="submit" type="primary" loading={loading} onClick={handleOk}>
|
|
||||||
// Submit
|
|
||||||
// </Button>,
|
|
||||||
// <Button
|
|
||||||
// key="link"
|
|
||||||
// href="https://google.com"
|
|
||||||
// type="primary"
|
|
||||||
// loading={loading}
|
|
||||||
// onClick={handleOk}
|
|
||||||
// >
|
|
||||||
// Search on Google
|
|
||||||
// </Button>,
|
|
||||||
// ]}
|
|
||||||
>
|
|
||||||
<DetailForm itemId={this.props.itemId}
|
|
||||||
operationId={this.state.operationId}
|
|
||||||
handleCancel={handleCancel}
|
|
||||||
pPid={this.props.pPid}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, {useContext} from "react";
|
import React, {Fragment, useContext} from "react";
|
||||||
import {Button, DatePicker, Select, Space} from "antd";
|
import {Button, DatePicker, Select, Space} from "antd";
|
||||||
import {usePathname, useRouter} from "next/navigation";
|
import {usePathname, useRouter} from "next/navigation";
|
||||||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||||
|
@ -23,33 +23,39 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
console.log('usePathname()', usePathname());
|
console.log('usePathname()', usePathname());
|
||||||
const data = useContext(LocalContext);
|
const data = useContext(LocalContext);
|
||||||
const {RangePicker} = DatePicker;
|
const {RangePicker} = DatePicker;
|
||||||
const expectStartTimeParseResult:RequestDateType[] = data.expectedStartTime.length>0?JSON.parse(data.expectedStartTime):[undefined,undefined]
|
const expectStartTimeParseResult: RequestDateType[] = data.expectedStartTime.length > 0 ? JSON.parse(data.expectedStartTime) : [undefined, undefined]
|
||||||
expectStartTimeParseResult.map(item => item&&item.value ? dayjs(item.value.toString()) : undefined)
|
expectStartTimeParseResult.map(item => item && item.value ? dayjs(item.value.toString()) : undefined)
|
||||||
const defaultExpectStartTime:[start: Dayjs | null | undefined, end: Dayjs | null | undefined] = [
|
const defaultExpectStartTime: [start: Dayjs | null | undefined, end: Dayjs | null | undefined] = [
|
||||||
expectStartTimeParseResult[0]&&expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined,
|
expectStartTimeParseResult[0] && expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined,
|
||||||
expectStartTimeParseResult[1]&&expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
|
expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
|
||||||
];
|
];
|
||||||
return <Space style={{marginTop: 0 ,"height": "42px", "alignContent": "center"}}>
|
return <Space style={{marginTop: 0, "height": "42px", "alignContent": "center"}}>
|
||||||
<DetailModelForm operationId={OPERATION_BUTTON_TYPE.ADD} description='添加主线任务' reloadData={refreshData}/>
|
<DetailModelForm haveButton={true} open={false} operationId={OPERATION_BUTTON_TYPE.ADD}
|
||||||
{usePathname().startsWith("/task/project") ?
|
description='添加主线任务' reloadData={refreshData}/>
|
||||||
<>
|
{
|
||||||
<Button type="primary" onClick={() => {
|
!usePathname().startsWith("/task/project") &&
|
||||||
replace("/task/four");
|
<Button type="primary" onClick={() => {
|
||||||
// setCurrentPath("/task/four");
|
replace("/task/project");
|
||||||
}}>四象限显示</Button>
|
// setCurrentPath("/task/project")
|
||||||
<Button type="primary" onClick={() => {
|
}}>任务树</Button>
|
||||||
replace("/task/calendar");
|
}
|
||||||
// setCurrentPath("/task/project")
|
{
|
||||||
}}>日历显示</Button>
|
!usePathname().startsWith("/task/four") &&
|
||||||
</> : <>
|
<Button type="primary" onClick={() => {
|
||||||
<Button type="primary" onClick={() => {
|
replace("/task/four");
|
||||||
replace("/task/project");
|
// setCurrentPath("/task/four");
|
||||||
// setCurrentPath("/task/project")
|
}}>四象限显示</Button>
|
||||||
}}>任务树</Button>
|
}
|
||||||
<Button type="primary" onClick={() => {
|
{
|
||||||
replace("/task/calendar");
|
!usePathname().startsWith("/task/calendar") &&
|
||||||
// setCurrentPath("/task/project")
|
<Button type="primary" onClick={() => {
|
||||||
}}>日历显示</Button>
|
replace("/task/calendar");
|
||||||
|
// setCurrentPath("/task/project")
|
||||||
|
}}>日历显示</Button>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/*日历需要状态*/
|
||||||
|
!usePathname().startsWith("/task/project") && <Fragment>
|
||||||
<span style={{whiteSpace: 'nowrap'}}>任务状态:</span>
|
<span style={{whiteSpace: 'nowrap'}}>任务状态:</span>
|
||||||
<Select
|
<Select
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
|
@ -65,6 +71,11 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
return {label: item.name, value: item.code}
|
return {label: item.name, value: item.code}
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/*四相线需要状态时间*/
|
||||||
|
usePathname().startsWith("/task/four") && <Fragment>
|
||||||
<span style={{whiteSpace: 'nowrap'}}>期望开始时间范围:</span>
|
<span style={{whiteSpace: 'nowrap'}}>期望开始时间范围:</span>
|
||||||
<RangePicker
|
<RangePicker
|
||||||
placeholder={['开始时间', '结束时间']}
|
placeholder={['开始时间', '结束时间']}
|
||||||
|
@ -83,7 +94,7 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
'value': dates[0],
|
'value': dates[0],
|
||||||
'operateType': ">="
|
'operateType': ">="
|
||||||
});
|
});
|
||||||
}else{
|
} else {
|
||||||
expectStartTimeList.push(undefined)
|
expectStartTimeList.push(undefined)
|
||||||
}
|
}
|
||||||
if (dates[1]) {
|
if (dates[1]) {
|
||||||
|
@ -92,13 +103,15 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
'value': dates[1].add(1, 'day'),
|
'value': dates[1].add(1, 'day'),
|
||||||
'operateType': "<"
|
'operateType': "<"
|
||||||
})
|
})
|
||||||
}else{
|
} else {
|
||||||
expectStartTimeList.push(undefined)
|
expectStartTimeList.push(undefined)
|
||||||
}
|
}
|
||||||
setExpectedStartTime(JSON.stringify(expectStartTimeList))
|
setExpectedStartTime(JSON.stringify(expectStartTimeList))
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</Fragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
'use client'
|
'use client'
|
||||||
import React, {useEffect} from "react";
|
import React, {useCallback, useContext, useEffect, useMemo} from "react";
|
||||||
import {Calendar, dayjsLocalizer, Event, View} from 'react-big-calendar'
|
import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar'
|
||||||
// https://day.js.org/docs/zh-CN/get-set/get-set
|
// https://day.js.org/docs/zh-CN/get-set/get-set
|
||||||
import dayjs from 'dayjs'
|
import dayjs, {Dayjs} from 'dayjs'
|
||||||
import 'react-big-calendar/lib/css/react-big-calendar.css'
|
import 'react-big-calendar/lib/css/react-big-calendar.css'
|
||||||
import {getTaskTreeResult} from "@/lib/task/project/data";
|
import {getTaskTreeResult, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
|
||||||
import {useSearchParams} from "next/dist/client/components/navigation";
|
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";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/jquense/react-big-calendar?tab=readme-ov-file
|
* https://github.com/jquense/react-big-calendar?tab=readme-ov-file
|
||||||
|
@ -17,73 +20,121 @@ const CalShow: React.FC = () => {
|
||||||
const [view, setView] = React.useState<View>('month');
|
const [view, setView] = React.useState<View>('month');
|
||||||
const [date, setDate] = React.useState<Date>(new Date());
|
const [date, setDate] = React.useState<Date>(new Date());
|
||||||
// 展示在页面的任务,默认获取当前月的信息。
|
// 展示在页面的任务,默认获取当前月的信息。
|
||||||
const [events,setEvents] = React.useState<Event[]>([]);
|
const [events, setEvents] = React.useState<Event[]>([]);
|
||||||
const handleViewChange = (newView:View) => {
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const [description, setDescription] = React.useState('');
|
||||||
|
const [operationId, setOperationId] = React.useState(-1);
|
||||||
|
const [itemId,setItemId] = React.useState(-1);
|
||||||
|
const [expectedStartTime,setExpectedStartTime] = React.useState<Dayjs>();
|
||||||
|
const [expectedEndTime,setExpectedEndTime] = React.useState<Dayjs>();
|
||||||
|
let state:string=useContext(LocalContext).taskState
|
||||||
|
const handleViewChange = (newView: View) => {
|
||||||
setView(newView);
|
setView(newView);
|
||||||
};
|
};
|
||||||
var pid = useSearchParams().get('pid');
|
var pid = useSearchParams().get('pid');
|
||||||
useEffect(() => {
|
const handleNavigate = (newDate: Date) => {
|
||||||
const searchListE=[]
|
console.log('handleNavigate', newDate)
|
||||||
if (pid!=null) {
|
|
||||||
searchListE.push({name:"pid",value:pid,operateType:"="},{name:'TREE',value:"false",operateType: "TREE"});
|
|
||||||
}
|
|
||||||
if (view==='month'){
|
|
||||||
searchListE.push({name:'expectedStartTime',value:dayjs(date).startOf('month'),operateType:">="})
|
|
||||||
searchListE.push({name:'expectedStartTime',value:dayjs(date).endOf('month'),operateType:"<="})
|
|
||||||
}else {
|
|
||||||
searchListE.push({name:'expectedStartTime',value:dayjs(date).startOf('week'),operateType:">="})
|
|
||||||
searchListE.push({name:'expectedStartTime',value:dayjs(date).endOf('week'),operateType:"<="})
|
|
||||||
}
|
|
||||||
searchListE.push({name:'expectedEndTime',value:dayjs(date).endOf('month'),operateType:"NOT NULL"})
|
|
||||||
let request = JSON.stringify({
|
|
||||||
pageSize:9999,
|
|
||||||
pageNumber:1,
|
|
||||||
data: searchListE
|
|
||||||
})
|
|
||||||
const response = getTaskTreeResult(request)
|
|
||||||
response.then(responseD=>{
|
|
||||||
if(responseD.status.success){
|
|
||||||
setEvents(responseD.data.content.map(taskState=>{
|
|
||||||
return {
|
|
||||||
start:dayjs(taskState.expectedStartTime).toDate(),
|
|
||||||
end:dayjs(taskState.expectedEndTime).toDate(),
|
|
||||||
title:taskState.name
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleNavigate = (newDate:Date) => {
|
|
||||||
console.log('handleNavigate',newDate)
|
|
||||||
setDate(newDate);
|
setDate(newDate);
|
||||||
const searchList=[]
|
const searchList:SearchObject[] = []
|
||||||
if (pid!=null) {
|
if (pid != null) {
|
||||||
searchList.push({name:"pid",value:pid,operateType:"="},{name:'TREE',value:"false",operateType: "TREE"});
|
searchList.push({name: "pid", value: pid, operateType: "="}, {
|
||||||
|
name: 'TREE',
|
||||||
|
value: "false",
|
||||||
|
operateType: "TREE"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
searchList.push({name:'expectedStartTime',value:dayjs(newDate).startOf('month'),operateType:">="})
|
searchList.push({name: "expectedStartTime", value: dayjs(newDate).startOf('month'), operateType: ">="})
|
||||||
searchList.push({name:'expectedStartTime',value:dayjs(newDate).endOf('month'),operateType:"<="})
|
searchList.push({name: 'expectedStartTime', value: dayjs(newDate).endOf('month'), operateType: "<="})
|
||||||
searchList.push({name:'expectedEndTime',value:dayjs(newDate).endOf('month'),operateType:"NOT NULL"})
|
loadData(searchList);
|
||||||
let request = JSON.stringify({
|
|
||||||
pageSize:9999,
|
|
||||||
pageNumber:1,
|
|
||||||
data: searchList
|
|
||||||
})
|
|
||||||
const response = getTaskTreeResult(request)
|
|
||||||
response.then(responseD=>{
|
|
||||||
if(responseD.status.success){
|
|
||||||
setEvents(responseD.data.content.map(taskState=>{
|
|
||||||
return {
|
|
||||||
start:dayjs(taskState.expectedStartTime).toDate(),
|
|
||||||
end:dayjs(taskState.expectedEndTime).toDate(),
|
|
||||||
title:taskState.name
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return <div className="App" style={{ height: '90vh' }}>
|
useEffect(() => {
|
||||||
|
const searchListE = []
|
||||||
|
if (pid != null) {
|
||||||
|
searchListE.push({name: "pid", value: pid, operateType: "="}, {
|
||||||
|
name: 'TREE',
|
||||||
|
value: "false",
|
||||||
|
operateType: "TREE"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (view === 'month') {
|
||||||
|
searchListE.push({name: 'expectedStartTime', value: dayjs(date).startOf('month'), operateType: ">="})
|
||||||
|
searchListE.push({name: 'expectedStartTime', value: dayjs(date).endOf('month'), operateType: "<="})
|
||||||
|
} else {
|
||||||
|
searchListE.push({name: 'expectedStartTime', value: dayjs(date).startOf('week'), operateType: ">="})
|
||||||
|
searchListE.push({name: 'expectedStartTime', value: dayjs(date).endOf('week'), operateType: "<="})
|
||||||
|
}
|
||||||
|
loadData(searchListE);
|
||||||
|
}, [useContext(LocalContext)]);
|
||||||
|
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
|
||||||
|
})
|
||||||
|
getTaskTreeResult(request).then(responseD => {
|
||||||
|
if (responseD.status.success) {
|
||||||
|
setEvents(responseD.data.content.map(taskState => {
|
||||||
|
return {
|
||||||
|
start: dayjs(taskState.expectedStartTime).toDate(),
|
||||||
|
end: dayjs(taskState.expectedEndTime).toDate(),
|
||||||
|
title: taskState.name,
|
||||||
|
resource:taskState.id
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
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<HTMLElement>) => {
|
||||||
|
// window.alert(event.title);
|
||||||
|
console.log(event)
|
||||||
|
setOperationId(OPERATION_BUTTON_TYPE.DETAIL)
|
||||||
|
setDescription("任务详情")
|
||||||
|
setItemId(event.resource)
|
||||||
|
setOpen(true);
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
const {defaultDate, scrollToTime} = useMemo(
|
||||||
|
() => ({
|
||||||
|
defaultDate: new Date(2015, 3, 12),
|
||||||
|
scrollToTime: new Date(1970, 1, 1, 6),
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
return <div className="App" style={{height: '90vh'}}>
|
||||||
|
<DetailModelForm operationId={operationId} description={description} open={open} haveButton={false} itemId={itemId}
|
||||||
|
reloadData={reloadData} expectedStartTime={expectedStartTime} expectedEndTime={expectedEndTime}/>
|
||||||
<Calendar
|
<Calendar
|
||||||
localizer={localizer}
|
localizer={localizer}
|
||||||
events={events}
|
events={events}
|
||||||
|
@ -92,6 +143,13 @@ const CalShow: React.FC = () => {
|
||||||
// onRangeChange={rangeChange}
|
// onRangeChange={rangeChange}
|
||||||
date={date}
|
date={date}
|
||||||
onNavigate={handleNavigate}
|
onNavigate={handleNavigate}
|
||||||
|
messages={message}
|
||||||
|
// 点击任务
|
||||||
|
onSelectEvent={handleSelectEvent}
|
||||||
|
// 点击空白处添加任务
|
||||||
|
onSelectSlot={handleSelectSlot}
|
||||||
|
selectable
|
||||||
|
scrollToTime={scrollToTime}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,28 +7,66 @@ import {
|
||||||
ProFormText, ProFormTextArea, ProFormTreeSelect,
|
ProFormText, ProFormTextArea, ProFormTreeSelect,
|
||||||
} from '@ant-design/pro-components';
|
} from '@ant-design/pro-components';
|
||||||
import { Button, Form, message } from 'antd';
|
import { Button, Form, message } from 'antd';
|
||||||
import React, {useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import {
|
import {
|
||||||
addTask,
|
addTask, getTask,
|
||||||
getTaskTreeResult,
|
getTaskTreeResult,
|
||||||
OPERATION_BUTTON_TYPE,
|
OPERATION_BUTTON_TYPE,
|
||||||
taskPriorityList,
|
taskPriorityList,
|
||||||
taskStateList
|
taskStateList
|
||||||
} from "@/lib/task/project/data";
|
} from "@/lib/task/project/data";
|
||||||
import {DataType} from "@/lib/definitions";
|
import {DataType} from "@/lib/definitions";
|
||||||
import dayjs from "dayjs";
|
import dayjs, {Dayjs} from "dayjs";
|
||||||
|
|
||||||
export type DetailModelFormProps={
|
export type DetailModelFormProps={
|
||||||
|
// 当前内容id
|
||||||
itemId?: number,
|
itemId?: number,
|
||||||
|
// 父任务id
|
||||||
pPid?:number,
|
pPid?:number,
|
||||||
|
// 操作id
|
||||||
operationId: number,
|
operationId: number,
|
||||||
|
// 标题描述
|
||||||
description:string,
|
description:string,
|
||||||
|
// 是否打开界面,用于非按钮操作
|
||||||
|
open:boolean,
|
||||||
|
// 使用按钮操作
|
||||||
|
haveButton:boolean,
|
||||||
|
expectedStartTime?:Dayjs,
|
||||||
|
expectedEndTime?:Dayjs,
|
||||||
|
// 重新加载数据
|
||||||
reloadData?: () => void
|
reloadData?: () => void
|
||||||
}
|
}
|
||||||
export type PidSelectTree= { label: string; value: number;pPid:number; children?: PidSelectTree[] }
|
export type PidSelectTree= { label: string; value: number;pPid:number; children?: PidSelectTree[] }
|
||||||
|
|
||||||
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
|
console.log("DetailModelForm:props:",props,props.itemId!=undefined&&(
|
||||||
|
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE))
|
||||||
const [form] = Form.useForm<DataType>();
|
const [form] = Form.useForm<DataType>();
|
||||||
const [pPid, setPPid] = useState<number>(0);
|
const [pPid, setPPid] = useState<number>(0);
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.itemId!=undefined&&(
|
||||||
|
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
||||||
|
getTask(props.itemId).then(task => {
|
||||||
|
console.log('DetailModelForm:getTask(props.itemId)', props.itemId, task);
|
||||||
|
if (task.status.success) {
|
||||||
|
// setTaskMessage(task.data)
|
||||||
|
task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())?.name;
|
||||||
|
task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())?.name;
|
||||||
|
task.data.actualTimeRange = [task.data.actualStartTime ? dayjs(task.data.actualStartTime) : undefined,
|
||||||
|
task.data.actualEndTime ? dayjs(task.data.actualEndTime) : undefined];
|
||||||
|
task.data.expectedTimeRange = [task.data.expectedStartTime ? dayjs(task.data.expectedStartTime) : undefined,
|
||||||
|
task.data.expectedEndTime ? dayjs(task.data.expectedEndTime) : undefined];
|
||||||
|
form.setFieldsValue(task.data)
|
||||||
|
} else {
|
||||||
|
message.error(task.status.message);
|
||||||
|
props.reloadData?.()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else if(props.operationId === OPERATION_BUTTON_TYPE.ADD|| props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD){
|
||||||
|
let data={'expectedTimeRange':[props.expectedStartTime?props.expectedStartTime:dayjs(), props.expectedEndTime]};
|
||||||
|
form.setFieldsValue(data)
|
||||||
|
}
|
||||||
|
}, [props])
|
||||||
function childReduce(child:DataType[]):PidSelectTree[]{
|
function childReduce(child:DataType[]):PidSelectTree[]{
|
||||||
const result:PidSelectTree[] = [];
|
const result:PidSelectTree[] = [];
|
||||||
child.map(data=> {
|
child.map(data=> {
|
||||||
|
@ -40,26 +78,26 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
})
|
})
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
// 如果不是添加任务需要回显
|
||||||
return (
|
return (
|
||||||
<ModalForm<DataType>
|
<ModalForm<DataType>
|
||||||
title={
|
title={props.description}
|
||||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL ? "任务详情":
|
open={props.open&&!props.haveButton}
|
||||||
props.operationId === OPERATION_BUTTON_TYPE.ADD?"添加任务":
|
trigger={props.haveButton?
|
||||||
props.operationId === OPERATION_BUTTON_TYPE.ADD?"修改任务":''
|
|
||||||
}
|
|
||||||
trigger={
|
|
||||||
<Button type="primary">
|
<Button type="primary">
|
||||||
<PlusOutlined />
|
<PlusOutlined />
|
||||||
{props.description}
|
{props.description}
|
||||||
</Button>
|
</Button>:undefined
|
||||||
}
|
}
|
||||||
form={form}
|
form={form}
|
||||||
autoFocusFirstInput
|
autoFocusFirstInput
|
||||||
modalProps={{
|
modalProps={{
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
onCancel: () => console.log('run'),
|
onCancel: () => {
|
||||||
|
console.log('run');
|
||||||
|
props.reloadData?.();
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
// submitTimeout={2000}
|
|
||||||
onFinish={async (values) => {
|
onFinish={async (values) => {
|
||||||
console.log('Received values of form: ', values);
|
console.log('Received values of form: ', values);
|
||||||
if (values.pid===undefined){
|
if (values.pid===undefined){
|
||||||
|
@ -99,7 +137,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProFormText width="sm" name="id" hidden={true} label="主键" />
|
<ProFormText width="sm" name="id" hidden={true} label="主键" />
|
||||||
<ProFormText width="sm" name="code" hidden={true} label="任务编码" />
|
<ProFormText width="sm" name="code" initialValue={props.itemId} hidden={true} label="任务编码" />
|
||||||
<ProFormText width="sm" name="pPid" initialValue={props.pPid} hidden={true} label="祖宗id" />
|
<ProFormText width="sm" name="pPid" initialValue={props.pPid} hidden={true} label="祖宗id" />
|
||||||
<ProForm.Group>
|
<ProForm.Group>
|
||||||
<ProFormTreeSelect
|
<ProFormTreeSelect
|
||||||
|
|
Loading…
Reference in New Issue