diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts index 69f7b91..e07bb9a 100644 --- a/src/app/lib/definitions.ts +++ b/src/app/lib/definitions.ts @@ -29,12 +29,25 @@ export type ResponseVO={ export type DataType ={ key: React.ReactNode; id: number; + pid:number; + pPid:number; code: string; name: string; description: string; - state: number; - priority: number; + state: number|string|undefined; + priority: number|string|undefined; type:number; action?:React.ReactNode; - children: DataType[]; + expectedStartTime?:Date; + expectedEndTime?:Date; + actualStartTime?:Date; + actualEndTime?:Date; + children: DataType[]|undefined; +} +export type DictType={ + id:number; + code:string + name:string; + order:number; + color:string; } diff --git a/src/app/lib/task/project/data.tsx b/src/app/lib/task/project/data.tsx index 6f999eb..12b4a70 100644 --- a/src/app/lib/task/project/data.tsx +++ b/src/app/lib/task/project/data.tsx @@ -1,8 +1,8 @@ import {unstable_noStore as noStore} from 'next/cache'; import axios, {AxiosResponse} from "axios"; -import {DataType, ResponseVO, ResultPage} from "@/app/lib/definitions"; +import {DataType, DictType, ResponseVO, ResultPage} from "@/app/lib/definitions"; -export async function taskTreeResult():Promise>> { +export async function taskTreeResult(): Promise>> { noStore(); try { // 使用 Axios 发送 POST 请求获取数据 @@ -19,3 +19,207 @@ export async function taskTreeResult():Promise>> throw new Error('Failed to fetch data'); } } +export async function getTask(id:number): Promise> { + noStore(); + try { + // 使用 Axios 发送 GET 请求获取数据 + const response: AxiosResponse> = await axios.get('http://localhost:8090/task/'+id); + // 从响应中提取数据并返回 + return response.data; + } catch (error) { + // 处理错误 + console.error('Error fetching data:', error); + // 返回一个默认值或者抛出错误 + throw new Error('Failed to fetch data'); + } +} + +export async function addTask(task:DataType): Promise> { + noStore(); + try { + // 使用 Axios 发送 POST 请求添加数据 + const response: AxiosResponse> = await axios.post('http://localhost:8090/task', task); + // 从响应中提取数据并返回 + return response.data; + } catch (error) { + // 处理错误 + console.error('Error fetching data:', error); + // 返回一个默认值或者抛出错误 + throw new Error('Failed to fetch data'); + } +} +export async function updateTask(task:DataType): Promise> { + noStore(); + try { + // 使用 Axios 发送 PUT 请求修改数据 + const response: AxiosResponse> = await axios.put('http://localhost:8090/task', task); + // 从响应中提取数据并返回 + return response.data; + } catch (error) { + // 处理错误 + console.error('Error fetching data:', error); + // 返回一个默认值或者抛出错误 + throw new Error('Failed to fetch data'); + } +} +export async function deleteTask(id:number): Promise> { + noStore(); + try { + // 使用 Axios 发送 DELETE 删除数据 + const response: AxiosResponse> = await axios.delete('http://localhost:8090/task/'+id); + // 从响应中提取数据并返回 + return response.data; + } catch (error) { + // 处理错误 + console.error('Error fetching data:', error); + // 返回一个默认值或者抛出错误 + throw new Error('Failed to fetch data'); + } +} + +export async function editState(id:number,state:number): Promise> { + noStore(); + try { + // 使用 Axios 发送 DELETE 删除数据 + const response: AxiosResponse> = await axios.patch('http://localhost:8090/task/'+id); + // 从响应中提取数据并返回 + return response.data; + } catch (error) { + // 处理错误 + console.error('Error fetching data:', error); + // 返回一个默认值或者抛出错误 + throw new Error('Failed to fetch data'); + } +} + +export async function editPriority(id:number,priority:number): Promise> { + noStore(); + try { + // 使用 Axios 发送 DELETE 删除数据 + const response: AxiosResponse> = await axios.patch('http://localhost:8090/task/'+id); + // 从响应中提取数据并返回 + return response.data; + } catch (error) { + // 处理错误 + console.error('Error fetching data:', error); + // 返回一个默认值或者抛出错误 + throw new Error('Failed to fetch data'); + } +} + + +//0,重要紧急红色,1,重要不紧急黄色,2,不重要紧急灰色,3不重要,不紧急绿色 +export const taskPriorityList: DictType[] = [ + { + id: 0, + code: '0', + name: '重要紧急', + order: 0, + color: 'red' + }, { + id: 1, + code: '1', + name: '重要不紧急', + order: 1, + color: 'yellow' + }, { + id: 2, + code: '2', + name: '不重要紧急', + order: 2, + color: 'gary' + }, { + id: 3, + code: '3', + name: '不重要不紧急', + order: 3, + color: 'green' + } +] +export const TASK_PRIORITY_LIST: DictType[] = [ + { + id: 0, + code: '0', + name: '重要紧急', + order: 0, + color: 'red' + }, { + id: 1, + code: '1', + name: '重要不紧急', + order: 1, + color: 'yellow' + }, { + id: 2, + code: '2', + name: '不重要紧急', + order: 2, + color: 'gary' + }, { + id: 3, + code: '3', + name: '不重要不紧急', + order: 3, + color: 'green' + } +] +// 0,暂存,1,提交,2,审核,3通过4拒绝5排期中,6进行中,7完成,8bug修复,9修复完成,10确认,11,上线运行 +export const taskStateList: DictType[] = [ + { + id: 0, + code: '0', + name: '暂存', + order: 1, + color: 'red' + }, { + id: 1, + code: '1', + name: '提交', + order: 1, + color: 'red' + }, { + id: 2, + code: '2', + name: '审核', + order: 2, + color: 'red' + }, { + id: 3, + code: '3', + name: '通过', + order: 3, + color: 'red' + }, { + id: 4, + code: '4', + name: '拒绝', + order: 4, + color: 'red' + }, { + id: 5, + code: '5', + name: '排期中', + order: 5, + color: 'red' + }, { + id: 6, + code: '6', + name: '排期中', + order: 6, + color: 'red' + }, { + id: 7, + code: '7', + name: '完成', + order: 7, + color: 'red' + } +] +export enum OPERATION_BUTTON_TYPE { + DETAIL, + ADD_CHILD, + UPDATE, + DELETE, + COMPLETE, + SHOW_FOUR +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 1a2455e..c2c6def 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,52 +1,57 @@ +'use client' import AcmeLogo from '@/app/ui/acme-logo'; import { ArrowRightIcon } from '@heroicons/react/24/outline'; import Link from 'next/link'; import Image from 'next/image'; +import {useRouter} from "next/navigation"; export default function Home() { + const { replace } = useRouter(); + replace("/task/project") return ( +
-
- -
-
-
-

- Welcome to Acme. This is the example for the{' '} - - Next.js Learn Course - - , brought to you by Vercel. -

- - Log in - {/**/} - -
-
- {/* Add Hero Images Here */} - Screenshots of the dashboard project showing desktop version - Screenshot of the dashboard project showing mobile version -
-
+ {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + {/*
*/} + {/* */} + {/* Welcome to Acme. This is the example for the{' '}*/} + {/* */} + {/* Next.js Learn Course*/} + {/* */} + {/* , brought to you by Vercel.*/} + {/*

*/} + {/* */} + {/* Log in*/} + {/* /!**!/*/} + {/* */} + {/*
*/} + {/*
*/} + {/* /!* Add Hero Images Here *!/*/} + {/* */} + {/* */} + {/*
*/} + {/*
*/}
); } diff --git a/src/app/task/error.tsx b/src/app/task/error.tsx new file mode 100644 index 0000000..9a18a57 --- /dev/null +++ b/src/app/task/error.tsx @@ -0,0 +1,31 @@ +'use client'; + +import { useEffect } from 'react'; + +export default function Error({ + error, + reset, + }: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + // Optionally log the error to an error reporting service + console.error(error); + }, [error]); + + return ( +
+

Something went wrong!

+ +
+ ); +} diff --git a/src/app/task/not-found.tsx b/src/app/task/not-found.tsx new file mode 100644 index 0000000..29f31a3 --- /dev/null +++ b/src/app/task/not-found.tsx @@ -0,0 +1,18 @@ +import Link from 'next/link'; +import { FaceFrownIcon } from '@heroicons/react/24/outline'; + +export default function NotFound() { + return ( +
+ +

404 Not Found

+

Could not find the requested invoice.

+ + Go Back + +
+ ); +} diff --git a/src/app/task/project/page.tsx b/src/app/task/project/page.tsx index c86c7ad..a3965d8 100644 --- a/src/app/task/project/page.tsx +++ b/src/app/task/project/page.tsx @@ -1,12 +1,10 @@ import TreeTable from "@/app/ui/task/project/TreeTable"; -import {DetailForm} from "@/app/ui/task/project/DetailForm"; const Page: React.FC = () => { return ( <> - ); }; diff --git a/src/app/ui/task/project/DetailForm.tsx b/src/app/ui/task/project/DetailForm.tsx index c6caa60..f4239a1 100644 --- a/src/app/ui/task/project/DetailForm.tsx +++ b/src/app/ui/task/project/DetailForm.tsx @@ -1,6 +1,6 @@ 'use client' -import React, { useState } from 'react'; -import { PlusOutlined } from '@ant-design/icons'; +import React, {useEffect, useState} from 'react'; +import {PlusOutlined} from '@ant-design/icons'; import { Button, Cascader, @@ -9,123 +9,312 @@ import { DatePicker, Form, Input, - InputNumber, + InputNumber, message, Radio, Select, - Slider, + Slider, Space, Switch, TreeSelect, Upload, } from 'antd'; +import {RangePickerProps} from "antd/es/date-picker"; +import dayjs from "dayjs"; +import { + addTask, + getTask, + OPERATION_BUTTON_TYPE, + taskPriorityList, + taskStateList, + updateTask +} from "@/app/lib/task/project/data"; +import {DataType, DictType} from "@/app/lib/definitions"; + export interface DetailFormProps { itemId: number, - operationId: string, + pPid:number, + operationId: number|undefined, + handleCancel: () => void } export const DetailForm: React.FC = (props) => { - - - const [componentDisabled, setComponentDisabled] = - useState(props.operationId==='1'); - - const { RangePicker } = DatePicker; - const { TextArea } = Input; - - const normFile = (e: any) => { - if (Array.isArray(e)) { - return e; - } - return e?.fileList; + const [form] = Form.useForm(); + const [componentDisabled, setComponentDisabled] = + useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL); + const {RangePicker} = DatePicker; + const {TextArea} = Input; + // const [taskMessage,setTaskMessage]=useState({name:"useState没效果吗,是这样的"}); + let taskMessage; + useEffect(() => { + if (props.operationId === OPERATION_BUTTON_TYPE.DETAIL||props.operationId === OPERATION_BUTTON_TYPE.UPDATE) { + getTask(props.itemId).then(task => { + console.log('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; + form.setFieldsValue(task.data) + }else{ + message.error(task.status.message); + props.handleCancel() + } + }) + } + },[]) + const normFile = (e: any) => { + if (Array.isArray(e)) { + return e; + } + return e?.fileList; + }; + const range = (start: number, end: number) => { + const result = []; + for (let i = start; i < end; i++) { + result.push(i); + } + return result; + }; + const disabledDate: RangePickerProps['disabledDate'] = (current) => { + // return current && current < dayjs().endOf('day'); + console.log('current', current, current && current < dayjs().endOf('day'), current < dayjs().endOf('day')) + return current < dayjs().startOf('day'); + }; + const disabledRangeTime: RangePickerProps['disabledTime'] = (_, type) => { + console.log('current', _) + if (type === 'start') { + return { + disabledHours: () => range(0, 60).splice(4, 20), + disabledMinutes: () => range(30, 60), + disabledSeconds: () => [55, 56], + }; + } + return { + disabledHours: () => range(0, 60).splice(20, 4), + disabledMinutes: () => range(0, 31), + disabledSeconds: () => [55, 56], }; - return ( - <> - setComponentDisabled(e.target.checked)} - > - Form disabled - -
- - Checkbox - - - - Apple - Pear - - - - - - - - - - - - - - - - - - - - - - - - -