From 24c01d4dc872048d5fbf3be248b2f3511bf545a0 Mon Sep 17 00:00:00 2001 From: 1708-huayu <57060237+1708-huayu@users.noreply.github.com> Date: Thu, 24 Jul 2025 18:40:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E7=AA=97=E5=8F=A3=E5=8F=98=E5=8A=A8?= =?UTF-8?q?=E5=90=8E=E6=97=A5=E5=BF=97=E9=AB=98=E5=BA=A6=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DiaryOption.tsx | 157 +++++++++++++++++++----- src/components/service/Diary.tsx | 6 + src/hooks/useWindowSize.ts | 21 ++++ src/ui/task/project/DetailModelForm.tsx | 29 ++++- 4 files changed, 178 insertions(+), 35 deletions(-) create mode 100644 src/hooks/useWindowSize.ts diff --git a/src/components/DiaryOption.tsx b/src/components/DiaryOption.tsx index 156434c..df5987d 100644 --- a/src/components/DiaryOption.tsx +++ b/src/components/DiaryOption.tsx @@ -1,13 +1,17 @@ -import React, {useEffect, useRef, useState} from 'react'; -import {Avatar, Dropdown, Input, List, MenuProps, message} from 'antd'; +import React, {Fragment, useEffect, useRef, useState} from 'react'; +import {Dropdown, List, MenuProps, message, Popconfirm} from 'antd'; import VirtualList from 'rc-virtual-list'; import {Button, Drawer} from 'antd'; import {ListDiary, SelectDiary} from "@/components/type/Diary"; import TextArea from "antd/es/input/TextArea"; import style from "@/components/DiaryOption.module.css" import dayjs from "dayjs"; -import {addTaskLogAPI} from "@/components/service/Diary"; +import {addTaskLogAPI, deleteTaskLogByIdAPI, editEnableFlagAPI} from "@/components/service/Diary"; import {ListRef} from "rc-virtual-list/lib/List"; +import {copyToClipboard} from "@/lib/copyToClipboard"; +import {useWindowSize} from "@/hooks/useWindowSize"; +import {DetailModelForm} from "@/ui/task/project/DetailModelForm"; +import {OPERATION_BUTTON_TYPE} from "@/lib/task/project/data"; const DiaryOption = (props: SelectDiary) => { // 抽屉 start @@ -19,9 +23,13 @@ const DiaryOption = (props: SelectDiary) => { setOpen(false); }; // 抽屉 end - const [shouldScroll,setShouldScroll] = React.useState(true); + const [shouldScroll, setShouldScroll] = React.useState(true); // 设置高度 start + const { height } = useWindowSize(); const [containerHeight, setContainerHeight] = useState(400); + useEffect(() => { + setDiaryList([]) + }, []); useEffect(() => { if (!open) return; // 使用 setTimeout 确保 Drawer 内容已渲染 @@ -47,7 +55,7 @@ const DiaryOption = (props: SelectDiary) => { // observer.observe(contentRef.current); // // return () => observer.disconnect(); - }, [open]); + }, [open,height]); // 设置高度 end // 头按钮设置 start @@ -91,6 +99,9 @@ const DiaryOption = (props: SelectDiary) => { } const appendData = (showMessage = true) => { + if (!open){ + return + } const fakeDataUrl = process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/message/diary/select`; fetch(fakeDataUrl, { method: 'POST', headers: { @@ -118,9 +129,7 @@ const DiaryOption = (props: SelectDiary) => { useEffect(() => { appendData(false); - // 视口高度 - window.innerHeight - }, []); + }, [open]); useEffect(() => { console.log("处理日志集合", diaryList) @@ -171,13 +180,13 @@ const DiaryOption = (props: SelectDiary) => { // 条件滚动 useEffect(() => { - console.log({shouldScroll},{listRef}) + console.log({shouldScroll}, {listRef}) if (shouldScroll && listRef.current) { listRef.current.scrollTo({ top: 99999, }); } - }, [diaryList, shouldScroll,open]); + }, [diaryList, shouldScroll, open]); // 滚动处理 end // 点击操作 start const [clickTaskDiary, setClickTaskDiary] = useState() @@ -188,34 +197,103 @@ const DiaryOption = (props: SelectDiary) => { setClickTaskDiary(item) } } - const items: MenuProps['items'] = [ + // 删除操作 + const [popConfirmOpen, setPopConfirmOpen] = useState(false); + const [popConfirmLoading, setPopConfirmLoading] = useState(false); + const popConfirmOk = () => { + setPopConfirmLoading(true) + if (clickTaskDiary){ + deleteTaskLogByIdAPI(clickTaskDiary.id).then(res=>{ + if (res.data.status.success){ + setDiaryList(diaryList.filter(taskLog => taskLog.id != clickTaskDiary.id)) + message.info("删除成功") + setPopConfirmLoading(false) + setPopConfirmOpen(false) + }else { + message.error(res.data.status.message) + } + }) + } + } + const handleCancel = () =>{ + setPopConfirmOpen(false) + } + + const editEnableFlag = (enableFlag:string) => { + if (clickTaskDiary){ + editEnableFlagAPI(clickTaskDiary.id,enableFlag).then(res=>{ + if (res.data.status.success){ + setDiaryList(diaryList.map(taskLog => { + if(taskLog.id == clickTaskDiary.id){ + taskLog.enableFlag = enableFlag; + } + return taskLog; + })) + message.info("设置成功") + }else { + message.error(res.data.status.message) + } + }) + } + } + + const [addTaskOpen,setAddTaskOpen] = useState(false) + + const commonItems: MenuProps['items'] = [ { label: '复制', key: '1', onClick: () => { + copyToClipboard(clickTaskDiary!.description) } }, - { - label: '失效', - key: '2', - }, { label: '创建计划', key: '3', + onClick:()=>{ + // 打开添加任务窗口 + setAddTaskOpen(true) + } }, { label: '删除', key: '4', + onClick: () => { + setPopConfirmOpen(true) + } }, { label: '取消', key: '5', + onClick:()=>{ + setClickTaskDiary(undefined) + } }, + ] + const items: MenuProps['items'] = [ ]; + items.push(...commonItems) + items.splice(1,0,{ + label: '失效', + key: '2', + onClick:()=>{ + editEnableFlag("0") + }, + }) + const itemsEnable: MenuProps['items'] = [ + ]; + itemsEnable.push(...commonItems) + itemsEnable.splice(1,0,{ + label: '生效', + key: '2', + onClick:()=>{ + editEnableFlag("1") + }, + }) // 点击操作 end return ( - <> + @@ -309,26 +387,45 @@ const DiaryOption = (props: SelectDiary) => { :
- -
onClickTAskDiary(item, "L")} - onContextMenu={() => onClickTAskDiary(item, "R")}> - - {item.description} - -
+ + 5 ? item.description.substring(0, 5) + '...' : item.description}?`} + open={popConfirmOpen&&clickTaskDiary?.id==item.id} + onConfirm={popConfirmOk} + okButtonProps={{loading: popConfirmLoading}} + onCancel={handleCancel} + okText="Yes" + cancelText="No" + > +
onClickTAskDiary(item, "L")} + onContextMenu={() => onClickTAskDiary(item, "R")}> + + {item.description} + +
+
)} - + {addTaskOpen&&setAddTaskOpen(false)} + />} +
); }; export default DiaryOption; \ No newline at end of file diff --git a/src/components/service/Diary.tsx b/src/components/service/Diary.tsx index 9659fa6..13273f9 100644 --- a/src/components/service/Diary.tsx +++ b/src/components/service/Diary.tsx @@ -7,3 +7,9 @@ export const addTaskLogAPI= (data:AddDiary):Promise { + return httpReq.delete( process.env.NEXT_PUBLIC_TODO_REQUEST_URL+`/task/message/diary?id=${id}`); +} +export const editEnableFlagAPI = (id:string,enableFlag:string) => { + return httpReq.put( process.env.NEXT_PUBLIC_TODO_REQUEST_URL+`/task/message/diary/enable?id=${id}&enableFlag=${enableFlag}`); +} diff --git a/src/hooks/useWindowSize.ts b/src/hooks/useWindowSize.ts new file mode 100644 index 0000000..b457b81 --- /dev/null +++ b/src/hooks/useWindowSize.ts @@ -0,0 +1,21 @@ +import { useState, useEffect } from 'react'; + +export function useWindowSize() { + const [windowSize, setWindowSize] = useState({ + width: window.innerWidth, + height: window.innerHeight, + }); + + useEffect(() => { + const handleResize = () => { + setWindowSize({ + width: window.innerWidth, + height: window.innerHeight, + }); + }; + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + return windowSize; +} diff --git a/src/ui/task/project/DetailModelForm.tsx b/src/ui/task/project/DetailModelForm.tsx index f3866c2..b55fd30 100644 --- a/src/ui/task/project/DetailModelForm.tsx +++ b/src/ui/task/project/DetailModelForm.tsx @@ -2,7 +2,7 @@ import {PlusOutlined, QuestionCircleOutlined} from '@ant-design/icons'; import { ModalForm, ProForm, - ProFormDateRangePicker, ProFormDateTimeRangePicker, + ProFormDateTimeRangePicker, ProFormSelect, ProFormText, ProFormTextArea, ProFormTreeSelect, } from '@ant-design/pro-components'; @@ -29,6 +29,8 @@ export type DetailModelFormProps = { operationId: OPERATION_BUTTON_TYPE, // 标题描述 description: string, + // 任务内容描述 + taskContent?:string, // 是否打开界面,用于非按钮操作 open: boolean, // 使用按钮操作 @@ -42,12 +44,14 @@ export type PidSelectTree = { label: string; value: string; pid: string; childre export const DetailModelForm: React.FC = (props) => { console.log("DetailModelForm:props:", props) + const [closeButton,setCloseButton] =useState(false) const [form] = Form.useForm(); const [requestTask,setRequestTask]=useState() const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL) // 团队第一层 pid必须为0 const [taskType, setTaskType] = useState('0') useEffect(() => { + setCloseButton(false) if (props.itemId != undefined && ( props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) { getTask(props.itemId).then(task => { @@ -100,7 +104,7 @@ export const DetailModelForm: React.FC = (props) => { return ( title={props.description} - open={props.open && !props.haveButton} + open={props.open && !props.haveButton&&!closeButton} trigger={props.haveButton ? ) + } + return result; }, } : undefined} onFinish={async (values) => {